#!/usr/local/bin/perl5
#
# usage: make-forms <file> [<cpp flags>]
#
# function: converts .h and .c files from fdesign into classes derived from the
# Forms class in Forms.cc. Uses <file>.fd+ to add menus and other extra info.
#

sub parseSource();
sub parseHeader();

$forms_file = shift;

for ($i = 0; $i <= $#ARGV; $i++)
{
    $flags = $flags . ' ' . $ARGV[$i];
}
print "options = $flags\n";

print "Creating ${forms_file}Forms.h and ${forms_file}Forms.cc ...\n";

# create header file and constructor methods
parseHeader();
# create InitForm methods
parseSource();

print "Done.\n";

exit(0);


sub parseSource()
# purpose: parse an fdesign .c file and recast the 
# create-form functions found there as methods of the appropriate Forms class.
{
	my $insub = 0;
	
	open(SOURCE, "<${forms_file}.c") || die "can't open ${forms_file}.c";
	open(SOURCE_OUT, ">>${forms_file}Forms.cc");

	print SOURCE_OUT "\n";
	print SOURCE_OUT "// --- InitForm declarations for the Forms classes ---------------------------\n";
	print SOURCE_OUT "\n\n";

	print "\nParsing ${forms_file}.c ...\n\n";
	while (<SOURCE>)
	{
		chomp;
		split;
#		print "READ: $_\n";
#		print "READ: $_[0]\n";

		if ($insub)
		{
			if ($_[0] eq "return")
			{ ; } # omit return
			elsif (substr($_[0], 0, 3) eq "FD_")
			{ ; } # omit declaration of fdui variable.
			elsif ($_[0] eq 'fdui->'.$form.'->fdui')
			{ ; } # omit final assignment of fdui
			elsif (substr($_[0], 0, 6) eq "fdui->")
			{
				# strip use of fdui-> qualifier.

				$_[0] = substr($_[0], 6, length($_[0]) - 6);
				if ($_[0] eq $form)
				{
					$_[0] = "form";
				}
				$_ = join(" ", @_);

				print SOURCE_OUT "    $_\n";
			}
			else	
			{
				print SOURCE_OUT "$_\n";
			}
		}

		if (/^FD_/)
		{
#			print "MATCHED\n";
			$form = substr($_[0], 3, length($_[0]) - 3);
		    $name = "${form}Form";
			print SOURCE_OUT "void ${name}::InitForm()\n"; 
		    $insub = 1;
		}
		elsif ($_[0] eq "}")
		{
#			print "END\n";
			
			$insub = 0;
			print SOURCE_OUT "\n";
		}
	}
	close(SOURCE);
	close(SOURCE_OUT);
}

sub parseHeader()
{
	my $extfile = "$forms_file.fd+";
	my $extcmd;
	
#	print "CPP = $ENV{CPP}\n";
	if ($ENV{CPP} ne '')
	{
	    $extcmd = "$ENV{CPP} -P $flags $extfile |";
	}
	else
	{
	    $extcmd = "cpp -P $flags $extfile |";
	}
#	print "PROCESSOR = $extcmd\n";

	open(SOURCE_OUT, "> ${forms_file}Forms.cc");
	open(HEADER_OUT, "> ${forms_file}Forms.h");

	# parse fd+ file...

	open(FD_FILE, $extcmd) || die "can't open $extfile";

	print "\nParsing $extfile ...\n\n";
	while (<FD_FILE>)
	{
		chomp;
		split;

#		print "READ: $_\n";
		
	    if ($_[0] eq 'c' || $_[0] eq 'cz' || $_[0] eq 'm')
	    {
			if ($_[2] eq '')
			{
		    	$current_menu = $_[1];
			}
			else
			{
			    $current_menu = $_[2];  
			}

			# strip leading '.' prefixes
			$current_menu =~ /([^.]*)$/;

			$current_menu = $1;
			$menu{$current_menu} = 0;

			# count of items in menu
			print "menu $current_menu\n";
			if ($_[0] eq 'm')
			{
			    $menu_type{$current_menu} = 'menu';
			}
			else
			{
			    $menu_type{$current_menu} = 'choice';
			}
	    }
	    elsif ($_[0] =~ /^i(.*)/ && $current_menu ne '')
	    {
			if ($_[0] ne 'i')
			{
			    print "  (button $_[1])\n";
			    $_[1] = '';
			    $item_suffix = "\%$1";
			}
			else
			{
			    $item_suffix = '';
			}
			$_[0] = '';
			$_ = join(" ", @_);
			# strip leading whitespace
			$_ =~ /^[ \t]*(.*)$/;

			print "  item $menu{$current_menu}:$1:\n";
			# store for later.
			$last_item = $menu{$current_menu};
			$menu_item{$current_menu, $menu{$current_menu}++} = "$1$item_suffix";
			$item_prefix = '';
	    }
	    elsif ($_[0] eq 'sp')
	    {
			$menu_item{$current_menu, $last_item} 
				= $menu_item{$current_menu, $last_item} . '%l';
	    }
	}
	close(FD_FILE);

	print HEADER_OUT "/* This file automatically generated from ${forms_file}.h */\n\n";
	print HEADER_OUT "#ifndef __${forms_file}__\n";
	print HEADER_OUT "#define __${forms_file}__\n\n";
	print HEADER_OUT "#include \"Forms.h\"\n\n"; 

	print SOURCE_OUT "/* This file automatically generated from ${forms_file}.h */\n\n";
	print SOURCE_OUT "#include \"${forms_file}Forms.h\"\n\n"; 

	open(HEADER, "<${forms_file}.h") || die "can't open ${forms_file}.h";
	
	print "\nParsing ${forms_file}.h ...\n\n";
	while (<HEADER>)
	{
	    chomp;
		split;
	    if ($_[0] eq 'FL_FORM')
	    {
			# Form definition...

			# close off previous class if there was one.
			if ($form ne '')
			{
			    print HEADER_OUT "};\n\n";
			    print SOURCE_OUT "};\n\n";
			}

			# Start new form class...
			$form = substr($_[1], 1, length($_[1]) - 2);
			$formclass = $form . 'Form';

			print HEADER_OUT "class $formclass : public Form\n";
			print HEADER_OUT "{\n";
			print HEADER_OUT "public:\n";
			print HEADER_OUT "    ${formclass}();\n";
			print HEADER_OUT "\n";
			print HEADER_OUT "    void InitForm();\n";
			print HEADER_OUT "\n";

			print SOURCE_OUT "${formclass}::${formclass}()\n";
			print SOURCE_OUT "{\n";
			print SOURCE_OUT "    InitForm();\n\n";
			print SOURCE_OUT "    RegisterForm(form);\n";
	    }

	    if ($_[0] eq 'FL_OBJECT')
	    {
			$name = substr($_[1], 1, length($_[1]) - 2);
			print HEADER_OUT "    FL_OBJECT  *$name;\n";
			print SOURCE_OUT "    RegisterObj($name);\n";

			if ($menu{$name})
			{
			    for ($i = 0; $i < $menu{$name}; $i++)
			    {
					print SOURCE_OUT
					"    fl_addto_$menu_type{$name}($name, \"$menu_item{$name, $i}\");\n";
			    }
			}
	    }
	}
	close(HEADER);
	
	print HEADER_OUT "};\n\n#endif\n";
	print SOURCE_OUT "}\n";

	close(HEADER_OUT);
	close(SOURCE_OUT);
}
