#!/usr/bin/perl
#  gendoc
#
#  This is a partial rewrite of the gensig program in PERL.
#  The perceps script doesn't like a number of notations that appear
#  in our gen_h files, so it is necessary to do at least a partial
#  processing into a header file.
#
#  Copyright 1998, Karl Nelson
#

# What type of widget wrapper is it
$LOCAL_WIDGET=0;
$GNOME_WIDGET=0;
$GTKMM_WIDGET=0;
$PERCEPS=1;

# Filenames
$SOURCE="";
$TARGET="";
$TARGET_BASENAME="";
 
# Output Flags
$COND_ACTIVE=0;
$COND_OUTPUT=1;
$COND_BEEN=0;
$LINE_NUM=0;

$BASE="";
$BASE_PREFIX="";
$UNAME="";
$PARENT="";

$VERSION=`gtk-config --version`;
chop $VERSION;
($MAJ,$MIN,$MIC)=split(/\./,$VERSION);

##############################################################
# parse_error(message,rest)
##############################################################
sub parse_error
  {$message=shift;
   $rest=shift;
   printf STDERR "$LINE_NUM : Parse error $message \nAt: -$rest\n";
   exit(-1); 
  }
   
##############################################################
# cond_*_func
##############################################################
# these hand the preprocessor symbols #ifgtk, #elsegtk, #endifgtk

sub cond_start_func
  {$comp=shift;
   $version=shift;
   ($maj,$min,$mic)=split(/\./,$version);
   $COND_OUTPUT=0;
   if ($comp eq "==")
     {
      ($MAJ==$maj) && ($min=~/^$/) && ($COND_OUTPUT=1);
      ($MAJ==$maj) && ($MIN==$min) && ($mic=~/^$/) && ($COND_OUTPUT=1);
      ($MAJ==$maj) && ($MIN==$min) && ($MIC==$mic) && ($COND_OUTPUT=1);
     }
   if ($comp eq ">=")
     {($MAJ>$maj) && ($MIN>$min) && ($MIC>$mic) && ($COND_OUTPUT=1);
     }
   if ($comp eq ">")
     {($MAJ>$maj) && ($MIN>$min) && ($MIC>$mic) && ($COND_OUTPUT=1);
     }
   $COND_BEEN|=$COND_OUTPUT;
   $COND_ACTIVE=1;
  }

sub cond_else_func
  {parse_error("#elsegtk without #ifgtk",$line) 
     if !$COND_ACTIVE;
   $COND_OUTPUT=!$COND_BEEN;
  }

sub cond_end_func
  {parse_error("#endifgtk without #ifgtk",$line) 
     if !$COND_ACTIVE;
   $COND_OUTPUT=1;
   $COND_ACTIVE=0;
   $COND_BEEN=0;
  }

##############################################################
# keyword functions
##############################################################

sub class_start_func
  {
#   close(out);
#   open(out,">.gtkmmheader1$$");
  }

sub signalstart_func
  {$arg=shift;
   ($UNAME,$PARENT)=split(",",$arg);
   $BASE_PREFIX="Gtk_" 		if $GTKMM_WIDGET;
   $BASE_PREFIX="Gnome_" 	if $GNOME_WIDGET;
   $PREFIX="Gtk_" 		if $GTKMM_WIDGET;
   $PREFIX="Gnome_" 		if $GNOME_WIDGET;
  }

sub signalspec_func
  {$signal=shift;
   $signal=~/(.*) +(.*)\((.*)\)/;
   print out "signal $signal;\n";
   print out "protected:\n"; 
   print out "  virtual $1 $2_impl($3); \n";
   print out "public: \n";
  }

##############################################################
# parser
##############################################################
sub parser
  {open(infile,"$SOURCE");
   while ($line=<infile>)
     {$LINE_NUM++;

      # check for conditionals
      $hit=0;
      ($line=~/^#ifgtk/)		&& ($hit=1) ;
      ($line=~/^#ifgtk +(\S+) +(\S+)/)	&& ($hit=1) && cond_start_func($1,$2);
      ($line=~/^#elsegtk/)		&& ($hit=1) && cond_else_func;
      ($line=~/^#endifgtk/)		&& ($hit=1) && cond_end_func; 
      ($line=~/^#/)			&& ($hit=1);#Perceps doesn't like # 
      if ($hit)
        {print out "#line $LINE_NUM \"$SOURCE\"\n" if $COND_OUTPUT && !$PERCEPS;
         next;
        }
      next if !$COND_OUTPUT;

      # check for our keywords (only one keyword may be per line)
      $hit=0;
      $line =~ /SIGNAL_START\((.*)\);/	&& ($hit=1) && signalstart_func($1);
      $line =~ /SIGNAL_SPEC\((.*)\);/ 	&& ($hit=1) && signalspec_func($1);
      $line =~ /SIGNAL_SHORT_SPEC\((.*)\);/ && ($hit=1) && signalspec_func($1);
      $line =~ /SIGNAL_VFUNC_SPEC\((.*)\);/ && ($hit=1) && signalspec_func($1);
      $line =~ /SIGNAL_END/ 		&& ($hit=1) ;# && signalend_func;
      $line =~ /CPP_CLASS_INIT_HOOK/	&& ($hit=1) ;# && signalstart_func;
      $line =~ /CLASS_START;/ 		&& ($hit=1) && class_start_func;
      $line =~ /IMPL_START;/	 	&& ($hit=1) && last;
      $line =~ /BASE_PREFIX\((\S+)\)/ 	&& ($hit=1) && ($BASE_PREFIX=$1);
      $line =~ /PREFIX\((\S+)\)/ 	&& ($hit=1) && ($PREFIX=$1);
      $line =~ /Signal_proxy/		&& ($hit=1); #remove signal_proxies
      if ($hit)
        {
         next;
        } 

      print out $line;
     }
  }

##############################################################
# usage(reason)
##############################################################
# Prints program usage
sub usage
  {$reason=shift;
    print "$reason\n";
    print "Usage: $0 [-h] [-l] source dest\n";
    print "    -h = help\n";
    print "    -l = generate local files -- use this flag for non-gtk-- widgets\n";
    print "    -g = generate a Gnome widget\n";
    print "    -p = generate a perceps header\n";
    print "\nNote: This will read source.gen_h file and generates dest.cc dest.h files.\n";
    exit(-1);
}

##############################################################
# parse_argv 
##############################################################
sub parse_argv
  {$SOURCE="";
   $TARGET="";
   while (@ARGV)
     { last if ($ARGV[0] !~ /^-/ );
       $option = shift @ARGV;
       if    ($option eq "-h") {usage;}
       elsif ($option eq "-l") {$LOCAL_WIDGET=1;}
       elsif ($option eq "-g") {$GNOME_WIDGET=1;}
       else
         {usage("Unknown option $option");}
       shift @argv;
     }
   usage("Incorrect number of arguments.") if $#ARGV!=1;
   $SOURCE=$ARGV[0];
   $TARGET=$ARGV[1];
   $TARGET_BASENAME=$TARGET;
   $TARGET_BASENAME=~ s/^.*\///;
   $GTKMM_WIDGET=1 if !$LOCAL_WIDGET && !$GNOME_WIDGET;
  }

##############################################################
# process_file
##############################################################
sub process_file
  {# open all output files for writing
   open(out,">$TARGET.h");
   #open(out,">.gtkmmheader$$");
   #open(out2,">.gtkmmsource$$");
   #open(out3,">.gtkmmextraheader$$");
  
   # output preambles 
   print out "// -*- c++ -*-\n";
   print out "/*\n";
   print out "   This file has been generated by gtksig from $SOURCE. DO NOT MODIFY!!!\n";
   print out "*/\n";

   #print out2 "/*\n";
   #print out2 "   This file has been generated by gtksig from $SOURCE. DO NOT MODIFY!!!\n";
   #print out2 "*/\n";

   #print out2 "#include <gnome--/$TARGET_BASENAME.h>\n" 
   #  if $GNOME_WIDGET;
   #print out2 "#include <gtk--/$TARGET_BASENAME.h>\n" 
   #  if $GTKMM_WIDGET;
   #print out2 "#include \"$TARGET_BASENAME.h\"\n"
   #  if $LOCAL_WIDGET;

   # some Gnome basenames have - in them
   $TEMP=$TARGET_BASENAME;
   $TEMP=~ s/-/_/;
   $TEMP=~ tr/[a-z]/[A-Z]/;
   if ($GNOME_WIDGET)
     {
      print out "#ifndef GNOMEMM_${TEMP}_HEADER\n";
      print out "#define GNOMEMM_${TEMP}_HEADER\n\n";
     }
    else
     {
      print out "#ifndef GTKMM_${TEMP}_HEADER\n";
      print out "#define GTKMM_${TEMP}_HEADER\n\n";
     }
     
   parser;   
   close(out);
   #close(out2);
   #close(out3);

   #system("cat .gtkmmheader$$ .gtkmmextraheader$$ .gtkmmheader1$$ > $TARGET.h");
   #system("cat .gtkmmsource$$ .gtkmmsource1$$ > $TARGET.c");
   #system("rm .gtkmmheader$$ .gtkmmextraheader$$ .gtkmmheader1$$");
   #system("rm .gtkmmsource$$ .gtkmmsource1$$");
   exit(0);
  }

##############################################################
# Main
##############################################################
parse_argv;
process_file;

