#!/usr/bin/perl -w
# 
# Copyright (C) 2005-2009 FAUmachine Team <info@faumachine.org>.
# This program is free software. You can redistribute it and/or modify it
# under the terms of the GNU General Public License, either version 2 of
# the License, or (at your option) any later version. See COPYING.
#

$DEBUG = 0;
$DELETE_TMPS = 1;

$PROGRAM = "gcc.pl";
$compiled_ext = "compiled";
$patched_ext = "patched";
$asmpatched_ext = "s";

$PREASM_PATCHER = "../../scripts/preasm_patcher.pl";
$PREASM_PROC = "../../scripts/preasm_proc.pl";
$RM = "rm -f ";
$CP = "cp";

$old_CC = shift(@ARGV);
@old_CC_args = @ARGV;

@args_tmp = @old_CC_args;

# Analyze and patch arguments
$obj_final = undef;
$mode = "link";
$input_file = undef;
$sec_prefix = undef;
for ($i = 0; $i <= $#args_tmp; $i++) {

	# get output file and delete that arguments 
	if ($args_tmp[$i] =~ /^-o$/) {
		$obj_final = $args_tmp[$i + 1];
		$args_tmp[$i] = "";
		$args_tmp[$i + 1] = "";
		$i++;

	# erase -c 
	} elsif ($args_tmp[$i] =~ /^-c$/) {
		$mode = "compile";
		$args_tmp[$i] = "";

	# Detect input file 
	} elsif (($args_tmp[$i] =~ /^.*\.c$/)
		|| ($args_tmp[$i] =~ /^.*\.S$/)) {

		$input_file = $args_tmp[$i];
		$args_tmp[$i] = "";

	# Detect section prefix argument
	} elsif ($args_tmp[$i] =~ /^--sec-prefix=(.*)$/) {
		$sec_prefix = $1;
		$args_tmp[$i] = "";
	}
}

$newargs = join(" ", @args_tmp);
$oldargs = join(" ", @old_CC_args);
if ($DEBUG) {
	print "OLD ARGS: $oldargs\n\n";
}

# C source compilation
if ($mode eq "compile") {

	if (!defined($input_file)) {
		die "no input file";
	}

	if (!defined($obj_final)) {
		die "no output file";
	}

	$obj_final =~ /^(.*)\.(\S*)$/;
	$obj_name = $1;
	$obj_ext = $2;


	if ($DEBUG) {
		print "$obj_final\n";
		print "$obj_name\n";
		print "$obj_ext\n";
	}


	# Generate ASM output 
	if ($input_file =~ /^.*\.S/) {
		$compile_cmd = "$old_CC $newargs $input_file -S > ${obj_name}.${compiled_ext} \n\n"; 
	} else {
		$compile_cmd = "$old_CC $newargs $input_file -S -o ${obj_name}.${compiled_ext} \n\n"; 
	}
	if ($DEBUG) { print "COMPILE_CMD: $compile_cmd\n\n"; }
	if (system $compile_cmd) {
		die "$PROGRAM: asm output generation failed\n";
	}

	# Patch ASM output of C files
	if ($input_file =~ /^.*\.c/) {
		$patch_cmd = "$PREASM_PATCHER ${obj_name}.${compiled_ext} ${obj_name}.${patched_ext}";
		if (defined($sec_prefix)) {
			$patch_cmd .= " --sec-prefix=$sec_prefix"; 
		}
		if ($DEBUG) { print "CPATCH_CMD: $patch_cmd\n\n"; }
		if (system $patch_cmd) {
			die "$PROGRAM: patching of asm output failed\n";
		}
	} else {
		$cpy_cmd = "$CP ${obj_name}.${compiled_ext} ${obj_name}.${patched_ext}";
		if ($DEBUG) { print "CPY_CMD: $cpy_cmd\n\n"; }
		if (system $cpy_cmd) {
			die "$PROGRAM: copying of asm output failed\n";
		}
	}

	# Patch ASM output
	$asmpatch_cmd = "$PREASM_PROC ${obj_name}.${patched_ext} ${obj_name}.${asmpatched_ext}"; 
	if ($DEBUG) { print "ASMPATCH_CMD: $asmpatch_cmd\n\n"; }
	if (system $asmpatch_cmd) {
		die "$PROGRAM: processing of patched asm output failed\n";
	}

	## Assemble patched output
	$assemble_cmd = "$old_CC ${newargs} ${obj_name}.${asmpatched_ext} -c -o ${obj_name}.${obj_ext} "; 
	if ($DEBUG) { print "ASSEMBLE_CMD: $assemble_cmd\n\n"; }
	if (system $assemble_cmd) {
		die "$PROGRAM: assemble of final asm output failed\n";
	}

	# Remove temporary files
	if ($DELETE_TMPS) {
		$rm_cmd = "${RM} ${obj_name}.${compiled_ext} ${obj_name}.${patched_ext} ${obj_name}.${asmpatched_ext}";
		system $rm_cmd;
	}
	
} else {

	# Do the same
	$same_cmd = "$old_CC $oldargs";
	if ($DEBUG) {
		print "SAME_CMD: $same_cmd"; 
	}
	system "${same_cmd}";
}




