#!/usr/bin/perl

#
# rfo_line_changer.pl
#
# This is a script used to to convert vintage/classic basic programs w/ line numbers
# to RFO BASIC! for Android.  It is not universal, and needs to be customized for each
# program you want to convert.  The output will also need tweaking by hand, since there
# are lots of specifics that this script will miss. The PERL used is pretty quick and dirty.  
# I'm not good with regular expressions, but perl has a lot of good string functions and
# is available on most Linux systems by default, so I used perl, even though it's not 
# my first choice of a language. Please forgive the "un-perlness" of the code.
#
# run the script from the shell as:
#
# rfo_line_changer.pl source_file > output_file
#
# By default, the script will output to stdout.  Redirect that output to a file
#

#OK, we have to load the file and look for GOTO/GOSUB targets as well as any arrays
#this program has two spaces after each command, so we must compensate for it.

$filename = @ARGV[0];
open (filename) or die "Can't open the file!";

$counter = 0;
@fileinput = <filename>;

while ($line = @fileinput[$counter++]) {
	#find GOTO's and GOSUBS and store their targets in an array
	#we are only going to convert important line numbers to labels
	@commands=("GOTO", "GOSUB");	
	
	foreach $keyword(@commands){
		$goto_position = index($line,$keyword);
		if ($goto_position > -1) {
			$goto_line_no = substr($line, $goto_position + length($keyword) + 2); 			
			push(@goto_targets, sprintf("%04d",$goto_line_no));		
			#print "$goto_line_no";			
			}
		}

	#now find arrays
	$dim_position = index ($line, "DIM");
	if ($dim_position > -1) {
		#will now split line into array
		@line_array = split(" ",$line);
		#now, split the mantissa again to deal with commas in the DIM statement
		@dimvar_array = split('\),',@line_array[2]);

		foreach $var(@dimvar_array) {
			push(@dim_array,substr($var, 0, 2));
			#print substr($var, 0, 2); print "\n";
			}
		}
	}

while ($line = <>) {
	#change line numbers to labels

	$subline = substr($line,1,4);
	if (grep $_ eq $subline, @goto_targets){
		$changed_line0 = substr($line,0,1,"L");
		$changed_line = substr($line,5,2,":\n");
		}
		else	{
			$changed_line = substr($line,0,5,"");
		}
	

	#now fix line numbers in GOTO and GOSUB statements
	@commands=("GOTO", "GOSUB");	
	
	foreach $keyword(@commands){
		$goto_position = index($line,$keyword);
		if ($goto_position > -1) {
			$first_substring = substr($line,0,$goto_position + length($keyword));
			$second_substring = substr($line, $goto_position + length($keyword) + 2); 			

			#check to see if there is an IF statement in the line first
			#all if statements are folowed by GOTO's in this program
			$IF_position = index($line,"IF");
			if ($IF_position > -1) {
				$first_substring = substr($line,0,$goto_position);
				$first_substring = "$first_substring" . "THEN GOTO";				
				}

			
			#$line = "$first_substring L$second_substring";
			$line = sprintf("%s L%04d\n",$first_substring,$second_substring);
			}
		}

	#find all the array variables and convert parentheses to brackets
	$dim_position = index($line, "DIM");
	if ($dim_position == -1){	
		foreach $array_val(@dim_array) {
			$array_position = index($line,$array_val);
			while ($array_position > -1) {
				#first parenthesis will be $array_position + 1
				#now to find the second parenthesis
				$second_half_string = substr($line, $array_position);
				$close_paren_position = index($second_half_string, ")");
				
				#now make substitutions
				$dummy_string = substr($line,$array_position + 1, 1, "[");
				$dummy_string2 = substr($line,$array_position + $close_paren_position, 1, "]");
				
				$array_position = index($line,$array_val);
				}
			}							
		}

	#now substitute for  FNA(X)= INT ( RND ( 0)*X)+1
	$def_position = index($line,"DEF");
	if ($def_position > -1) {
		$line = "REM ***LINE REMOVED***: $line";
		}
	else {
		$fna_position = index($line,"FNA");
		if ($fna_position > -1) {
			$first_substring = substr($line,0,$fna_position);
			$second_substring = substr($line, $fna_position + 4);
			$line = "$first_substring" . "ROUND(0.5+RND(0)*$second_substring";
			}
	}

	#substitute for all other INT()'s as well--may be more than one int in a line
	$int_position = index($line,"INT (");
	while ($int_position > -1) {
		$first_substring = substr($line,0,$int_position);
		$second_substring = substr($line, $int_position + 5);
		$line = "$first_substring" . "ROUND (-0.5+$second_substring";
		$int_position = index($line,"INT (");		
		}

	#all decimal values must have leading zero or an error will result
	#can only do first and last to avoid infinate loop
	$dec_position = index($line, '.');
	for ($i = 0; $i < 2; $i++) {
		if ($dec_position > -1) {
			$num_check = substr($line, $dec_position-1, 1);		
			if (!(($num_check ge '0' && $num_check le '9') || ($num_check ge 'A' && $num_check le 'Z'))) {
				#print "XXX=$num_check";
				$first_substring = substr($line, 0, $dec_position);
				$second_substring = substr($line, $dec_position);
				$line = "$first_substring" . "0$second_substring";		
				}			
			}		
		$dec_position = rindex($line, "."); 
		}	

	#change all INPUT statements to allow for inkey$ press before input occurs
	$inp_position = index($line, "INPUT");
	if ($inp_position > -1) { 
		$first_substring = substr($line, 0, $inp_position + 6);
		$second_substring = substr($line, $inp_position + 6);
		$line = "  PRINT \"PRESS ANY BUTTON TO CONTINUE\"\n  DO\n  INKEY\$ KBD\$\n  UNTIL KBD\$<>\"@\"\n$first_substring\"\", $second_substring";
		}

	#last thing--warn for functions that are not supported:
	@unsupported=("SGN", "STOP", "RANDOMIZE", "DATA", "READ");	
	
	foreach $keyword(@unsupported){
		$unsupported_pos = index($line,$keyword);
		if ($unsupported_pos > -1) {
			$line = "$line REM ***WARNING*** '$keyword' IS UNSUPPORTED IN RFO BASIC!\n"; 
			}
		}	

	print "$line";
} 

close(filename);
