<?php

// Copyright (C) 2007 Cygnus <cygnus2 at post.cz>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA

define ("CTRY","\033[1;34;40m -\033[0m ");
define ("COK","\033[1;32;40m *\033[0m ");
define ("CWARN","\033[1;33;40m ?\033[0m ");
define ("CFAIL","\033[1;31;40m !\033[0m ");
define ("CDEB","\033[1;37;40m >\033[0m ");
define ("CWHITE","\033[1;37;40m");
define ("CDEF","\033[0m");

// configuration
$cfg_infile	= './test_unfinished_source.za';
$cfg_outfile	= './test_reformated_source.za';

$cgf_max_lines	= 200;	// 0 = infinite

$debug		= 1;

// --------------------------------------------------------------------------------------

function is_hex_address($out)
{
	$r = 1;
	if (strlen($out) != 4)
		$r = 0;

	if ($out[0] == 'A' && $out[1] == '_')
		$r = 0;

	for ($i = 0; $i < strlen($out); $i++)
	{
		if ($out[$i] != '0' && $out[$i] != '1' && $out[$i] != '2' && $out[$i] != '3' && $out[$i] != '4' && $out[$i] != '5' && $out[$i] != '6' && $out[$i] != '7' && $out[$i] != '8' && $out[$i] != '9' && $out[$i] != 'a' && $out[$i] != 'b' && $out[$i] != 'c' && $out[$i] != 'd' && $out[$i] != 'e' && $out[$i] != 'f')
			$r = 0;
	}
	return ($r);
}

function reformat ($in)
{
	global $debug;

	$out = '';

	$i = 0;
	$s = 'n';

	while ($i < strlen ($in)-1)
	{
		$c = $in[$i];

		switch ($s)
		{
			case 'n':
				// undetermined
				if ($c == ' ')
				{
					$s = 'fb';
					if ($debug) echo CDEB."f bytes";
				}
				if ($c == "\t")
				{
					$s = 'fi';
					if ($debug) echo CDEB."f instr";
				}
				if ($c == ';')
				{
					$s = 'c';
					$out .= $c;
					if ($debug) echo CDEB."comment";
				}
				if ($c != ' ' && $c != "\t" && $c != ';')
				{
					$s = 'a';
					$out .= $c;
					if ($debug) echo CDEB."addr";
				}
				break;
			case 'a':
				// address or label
				if ($c == ' ')
				{
					$s = 'fb';
					if (is_hex_address($out))
					{
						$out = '';
						if ($debug) echo CDEB."del addr";
					}
					if ($debug) echo CDEB."f bytes";
				}
				if ($c == "\t")
				{
					$s = 'fi';
					if (is_hex_address($out))
					{
						$out = '';
						if ($debug) echo CDEB."del addr";
					}
					if ($debug) echo CDEB."f instr";
				}
				if ($c == ';')
				{
					$s = 'c';
					$out .= $c;
					if ($debug) echo CDEB."comment";
				}
				if ($c != ' ' && $c != "\t" && $c != ';')
				{
					$out .= $c;
				}
				break;
			case 'fb':
				// hexadecimal bytes before instruction
				if ($c == ' ') break;
				if ($c == "\t") break;
				if ($c != ' ' && $c != "\t" && $c != ';' && ($c == '0' || $c == '1' || $c == '2' || $c == '3' || $c == '4' || $c == '5' || $c == '6' || $c == '7' || $c == '8' || $c == '9' || $c == 'a' || $c == 'b' || $c == 'c' || $c == 'd' || $c == 'e' || $c == 'f'))
				{
					$s = 'b';
					if ($debug) echo CDEB."bytes";
				}
				if  ($c != ' ' && $c != "\t" && $c != ';' && $c != ';'  && $c != '0' && $c != '1' && $c != '2' && $c != '3' && $c != '4' && $c != '5' && $c != '6' && $c != '7' && $c != '8' && $c != '9' && $c != 'a' && $c != 'b' && $c != 'c' && $c != 'd' && $c != 'e' && $c != 'f')
				{
					$s = 'i';
					$out .= $c;
					if ($debug) echo CDEB."instr";
				}
				if ($c == ';')
				{
					$s = 'c';
					$out .= $c;
					if ($debug) echo CDEB."comment";
				}
				break;
			case 'b':
				// hexadecimal bytes before instruction
				if ($c == ' ' || $c == "\t")
				{
					$s = 'fi';
					if ($debug) echo CDEB."f instr";
				}
				if ($c != ' ' && $c != "\t" && $c != ';' && $c != '0' && $c != '1' && $c != '2' && $c != '3' && $c != '4' && $c != '5' && $c != '6' && $c != '7' && $c != '8' && $c != '9' && $c != 'a' && $c != 'b' && $c != 'c' && $c != 'd' && $c != 'e' && $c != 'f')
				{
					$s = 'i';
					$out .= $c;
					if ($debug) echo CDEB."instr";
				}
				if ($c == ';')
				{
					$s = 'c';
					$out .= "\t".$c;
					if ($debug) echo CDEB."comment";
				}
				break;
			case 'fi':
				// find instruction
				if ($c != ' ' && $c != "\t" && $c != ';')
				{
					$s = 'i';
					$out .= "\t\t".$c;
				}
				if ($c == ';')
				{
					$s = 'c';
					$out .= "\t".$c;
					if ($debug) echo CDEB."comment";
				}
				break;
			case 'i':
				// instruction
				if ($c == ' ' || $c == "\t")
				{
					$s = 'fo';
					if ($debug) echo CDEB."f operand $c";
				}
				else
					$out .= $c;
				break;
			case 'fo':
				// operands
				if ($c != ' ' && $c != "\t")
				{
					// instruction found
					$s = 'o';
					$out .= "\t".$c;
					if ($debug) echo CDEB."operand";
				}
				break;
			case 'o':
				// operands
				if ($c != ';')
					$out .= $c;
				if ($c == ';')
				{
					// comment detected
					$s = 'c';
					$out .= $c;
					if ($debug) echo CDEB."comment";
				}
				break;
			case 'c':
				// comment
				$out .= $c;
				break;
		}

		$i++;
	}

	if ($debug) echo "\n".$out;
	return ($out."\n");
}

// --------------------------------------------------------------------------------------

function convert ($in, $out)
{
	global $cgf_max_lines;
	global $debug;

	// convert
	$error = 0;
	$error_msg = '';

	$ln['number'] = 1;
	$ln['in'] = '';
	$ln['out'] = '';

	while (1)
	{
		$ln['in'] = fgets($in);

		if (feof($in))
		{
			echo COK."All done\n";
			break;
		}

		if ($cgf_max_lines > 0 && $ln['number'] > $cgf_max_lines)
		{
			echo COK."Limited by max. line\n";
			break;
		}

		if ($debug) echo CTRY."Processing line ".$ln['number'];
		if ($debug) echo "\n".$ln['in'];

		$copy = 0;

		if ($ln['in'][0] == ';') $copy = 1;
		if ($ln['in'][0] == "\t") $copy = 1;
		if ($ln['in'] == '' || $ln['in'] == "\n") $copy = 1;

		if ($copy == 0)
		{
			$ln['out'] = reformat($ln['in']);
		}
		else
		{
			$ln['out'] = $ln['in'];
		}

		fputs($out, $ln['out']);

		echo "\n";
		$ln['number']++;
		$ln['in'] = '';
		$ln['out'] = '';
	}

	if ($error) echo $error_msg;
}

// --------------------------------------------------------------------------------------

$in = fopen ($cfg_infile, "r");
$out = fopen ($cfg_outfile, "w");

if ($in && $out)
{
	convert ($in, $out);
}
else
{
	if (!$in) echo CFAIL."Warning: opening input file \"$cfg_infile\" failed.\n";
	if (!$out) echo CFAIL."Warning: opening output file  \"$cfg_outfile\" failed.\n";
}

if ($in) fclose ($in);
if ($out) fclose ($out);

return (0);

?>