#!/usr/bin/perl
$version="0.01";
$count_of_args=@ARGV;
if( !($count_of_args >= 1 && $count_of_args <= 3) ) {
    print "Made by Alexander Chernov in 2010\n";
    print $0." version $version. Under 'New' BSD License.\n\t";
    print $0." <input> [<output>] [<macros>]\n";
}
my %converting_structure;

$converting_structure{input} =$ARGV[0];
$converting_structure{output}=$ARGV[1] if $count_of_args > 1;
$converting_structure{macros}=$ARGV[2] if $count_of_args > 2;

$converting_structure{data}="DATA\n";
$converting_structure{code}="CODE\n\tcall main\n\tmov eax, -1\n\tint 0x40\n";

open my $input, "<", $converting_structure{input} or die "Error opening ".$converting_structure{input}."!\n$!\n";
while( my $line = <$input> ) {
    if( $converting_structure{object_flag} == 1 && $line=~/$converting_structure{type_name}\:/) {
	$converting_structure{object_flag}=2;
	$converting_structure{data}=$converting_structure{data}."".$line; next;
    }
    if( $converting_structure{object_flag} == 2) { 
	$converting_structure{data}=$converting_structure{data}."".ConvertToIntel($line);
	$converting_structure{object_flag}=false; next;
    }
    if( $converting_structure{function_flag} == 1 && $line=~/$converting_structure{type_name}\:/) {
	$converting_structure{function_flag}=2;
	$converting_structure{code}=$converting_structure{code}."".$line; next;
    }
    if( $converting_structure{function_flag} == 2) {
	$converting_structure{function_flag}=false if $line=~/ret/;
	next if $line=~/\#/;
	next if $line=~/\.size/;
	next if $line=~/\.ident/;
	next if $line=~/\.section/;
	
	$converting_structure{code}=$converting_structure{code}."".ConvertToIntel($line); next;
    }
    
    $converting_structure{cfilename}=GetFileName( $line ) if $line=~/\.file/;
    if( $line=~/\.type/ ) {
	my $type=GetType( $line );
	$converting_structure{type_name}=GetTypeName( $line );
	$converting_structure{object_flag}=1 if $type=~/object/;
	$converting_structure{function_flag}=1 if $type=~/function/;
    }
}
close $input or die "Error closing ".$converting_structure{input}."\n$!\n";

$converting_structure{programm}=";Created by kcc $version\ninclude \"macros.inc\"\n\nMEOS_APP_START\n\n".$converting_structure{code}.
"\n".$converting_structure{data}."\nUDATA\n\nMEOS_APP_END\n";

my $output;
if( $count_of_args > 1 ) {
    open $output, ">", $converting_structure{output} or die "Error writing ".$converting_structure{output}."!\n$!\n";
} else {
    $out_file=$converting_structure{input};
    chop($out_file);
    open $output, ">", $out_file."asm" or die "Error writing ".$out_file."!\n$!\n";
}
print $output $converting_structure{programm};
close $output;

sub GetFileName {
    $_[0]=~/\w{1,}.c/;
    return $&;
}

sub GetType {
    $_[0]=~/\@\w{1,}/;
    return $&;
}

sub GetTypeName {
    $_[0]=~/\w{1,}\,/;
    my $name=$&;
    chop($name);
    return $name;
}

sub ConvertToIntel {
    $ATT=$_[0];
    $ATT=~s/\.long/dw/;
    $ATT=~s/\"\s/\"\,0\n/ if $ATT=~/.string/;
    $ATT=~s/\.string/db/;
    $ATT=~s/movl/mov/;
    $ATT=~s/pushl/push/;
    $ATT=~s/popl/pop/;
    $ATT=~s/leal/lea/;
    $ATT=~s/andl/and/;
    $ATT=~s/subl/sub/;
    $ATT=~s/addl/add/;
    $ATT=~s/cmpl/cmp/;
    $ATT=~s/sall/sal/;
    
    $ATT=~s/\$//;
    $ATT=~s/\%//;
    $ATT=~s/\%//;
    
    $ATT=MoveLeftToRight($ATT) if $ATT=~/\,/;
    
    $ATT=~s/\(/\[/;
    $ATT=~s/\)/\]/;
    
    if( $ATT=~/\s[-]{0,1}\d{1,}\[/ ) {
	$founded=$&;
	chop($founded);
	$founded=~/\s/;
	$founded=$';
	$ATT=~s/$founded//;
	if( $founded=~/\-/ ) {
	    $ATT=~s/\]/$founded\]/;
	} else {
	    $ATT=~s/\]/\+$founded\]/;
	}
    }
    if( $ATT=~/\[/ ) {
	$ATT=~s/push\s/push dword /;
	#$ATT=~s/cmp\s/cmp dword /;
    }
    if( $ATT=~/\s\[[-\+0-9A-Za-z]{1,}\]\,\s[-]{0,1}\d{1,}/ ) {
	$ATT=~s/\[/dword \[/;
    }
    
    if( $ATT=~/movb/ ) {
	$ATT=~s/movb/mov/;
	#$ATT=~s/\,/\, byte ptr/;
    }
    
    return $ATT;
}

sub MoveLeftToRight {
    return $_[0] if $_[0]=~/mcall/;
    return $_[0] if $_[0]=~/\sdb\s/;
    $_[0]=~/[-()0-9A-Za-z]{1,}\,/;
    $first=$&;
    chop($first);
    $_[0]=~/\,\s[-()0-9A-Za-z]{1,}/;
    $&=~/\,\s/;
    $second=$';
    
    $ATT=$_[0];
    $ATT=~s/[-()0-9A-Za-z]{1,}\,/1\,/;
    $ATT=~s/\,\s[-()0-9A-Za-z]{1,}/\, 2/;
    
    $ATT=~s/1\,/$second\,/;
    $ATT=~s/\, 2/\, $first/;
    
    return $ATT;
}