#!/usr/bin/perl -w
#
# Copyright (C)1997-1998 Alligator Descartes <descart@arcana.co.uk>
#
# $Id$
#
# Generates demos for both the demo harness ( applications using the Frame
# class ) and applets from a Java class containing preprocessing directives.
#
# $Log$
#

*USAGE = \"Usage: generateDemo <app|applet> <file>\n";
*MODE_APP = \0;
*MODE_APPLET = \1;
*MODE_SWING_APP = \2;

my $mode = -1;

if ( $#ARGV != 1 ) {
    die "$USAGE";
  }

my $infileId =
    open INFILE, "$ARGV[1]";
if ( !defined $infileId ) {
    die "Cannot open input file $ARGV[1] for reading: $!\n";
  }

### Setup the modes
if ( $ARGV[0] eq "app" ) {
    $mode = $MODE_APP;
  } elsif ( $ARGV[0] eq "applet" ) {
    $mode = $MODE_APPLET;
  } elsif ( $ARGV[0] eq "swingapp" ) {
    $mode = $MODE_SWING_APP;
  } else {
    die "Invalid mode!\n$USAGE";
  }

### Slurp the input file into one big long string for munging
my $fileData = "";
while ( <INFILE> ) {
    my $tmpline = $_;

    $fileData .= $tmpline;
  }

### Extract some key information points from the file. Firstly, the name
if ( $fileData !~ /\/\*\*\#name\:((\w)+)\ *\*\// ) {
    die "Cannot locate demo name within preprocessor file!\n";
  } else {
    $demoName = $1;

    ### Alter the demo name as needed
    if ( $mode == $MODE_APPLET ) {
        $demoName = $demoName . "app";
      }

#    print "Demo Name: $demoName\n";

    ### Substitute the name back into the file
    $fileData =~ s/\/\*\*\#name\:((\w)+)\ *\*\//$demoName/g;
  }

### Open the output file
my $outfileId =
    open OUTFILE, ">$demoName" . ".java";
if ( !defined $outfileId ) {
    die "Cannot open output file $demoName.java for writing: $!\n";
  }

### Parse the file for substitution targets.
#
### The parent class for the demo
if ( $fileData =~ /\/\*\*\#parent\ *\*\// ) {
    SWITCH: {
        if ( $mode == $MODE_APP ) {
            $fileData =~ s/\/\*\*\#parent\ *\*\//Frame/g;
            last SWITCH;
          }
        if ( $mode == $MODE_APPLET ) {
            $fileData =~ s/\/\*\*\#parent\ *\*\//Applet/g;
            last SWITCH;
          }
        if ( $mode == $MODE_SWING_APP ) {
            $fileData =~ s/\/\*\*\#parent\ *\*\//Frame/g;
            last SWITCH;
          }
      }
  }

### The initialization method, ie, constructor or 'init()' method
if ( $fileData =~ /\/\*\*\#initializer\ *\*\// ) {
    SWITCH: {
        if ( $mode == $MODE_APP || $mode == $MODE_SWING_APP ) {
            $fileData =~ s/\/\*\*\#initializer\ *\*\//$demoName\(\)/g;
            last SWITCH;
          }
        if ( $mode == $MODE_APPLET ) {
            $fileData =~ s/\/\*\*\#initializer\ *\*\//void init\(\)/g;
            last SWITCH;
          }
      }
  }

### If we're generating an applet, parse for the /**#start */ directive to call
### startDemo()
if ( $mode == $MODE_APPLET ) {
    if ( $fileData =~ /\/\*\*\#start\ *\*\// ) {
        $fileData =~ s/\/\*\*\#start\ *\*\//startDemo\(\)\;/g;
      }
  }

### If we're generating an application, parse for the /**#layout */ directive
### to call 'pack(); show();'
if ( $mode == $MODE_APP || $mode == $MODE_SWING_APP ) {
    if ( $fileData =~ /\/\*\*\#layout\ *\*\// ) {
        $fileData =~ s/\/\*\*\#layout\ *\*\//pack\(\)\; show\(\)\;/g;
      }
  }

### Parse for the /**#dispose */ directive if we're an application
if ( $mode == $MODE_APP || $mode == $MODE_SWING_APP ) {
    if ( $fileData =~ /\/\*\*\#dispose\ *\*\// ) {
        $fileData =~ s/\/\*\*\#dispose\ *\*\//dispose\(\)\;\n        if ( callExit ) {\n            System.exit( 0 );\n          }\n/g;
      }
  }

### Parse for the /**#windowListener */ directive if we're an application
if ( $mode == $MODE_APP || $mode == $MODE_SWING_APP ) {
    if ( $fileData =~ /\/\*\*\#windowListener\ *\*\// ) {
        $fileData =~ s/\/\*\*\#windowListener\ *\*\//this.addWindowListener\(\ this\ \)\;/g;
      }
  }

### Parse for the /**#main */ directive if we're an application
if ( $mode == $MODE_APP || $mode == $MODE_SWING_APP ) {
    if ( $fileData =~ /\/\*\*\#main\ *\*\// ) {
        $fileData =~ s/\/\*\*\#main\ *\*\//\/\*\* Regulates the calling of System.exit() \*\/\n    private boolean callExit = true;\n\n    public static void main\( String argv\[\] \) \{\n        $demoName d = new $demoName\(\)\;\n        d.setTitle\( d.getName\(\) \);\n        System.err.println\( "\\n" + d.getName\(\) + " -- " + d.getOriginalAuthor\(\) \);\n        for ( int i = 0 ; i < ( d.getName().length() + d.getOriginalAuthor().length() + 4 ) ; i++ ) {\n            System.err.print\( "=" \)\;\n          \}\n        System.err.println\( "\\n" \)\;\n        System.err.println\( d.getDescription\(\) + "\\n" )\;\n        d.startDemo\(\)\;\n      \}/g;
      }
  } else {
    if ( $fileData =~ /\/\*\*\#main\ *\*\// ) {
        $fileData =~ s/\/\*\*\#main\ *\*\//\/\*\* Regulates the calling of System.exit() \*\/\n    private boolean callExit = true;\n\n/g;;
      }
  }

### Write the modified file data to the output file
print OUTFILE $fileData;

close INFILE;
close OUTFILE;

exit 0;
