Minimal (i.e., lame) update to Loopy documentation to match reality -- it's
[sgt/puzzles] / mkfiles.pl
index b93e4fa..a107737 100755 (executable)
 #  - special-define objects (foo.o[PREPROCSYMBOL]) are not
 #    supported in the mac or vcproj makefiles.
 
-use FileHandle;
+use IO::Handle;
 use Cwd;
 
-open IN, "Recipe" or do {
+@filestack = ();
+$in = new IO::Handle;
+open $in, "Recipe" or do {
     # We want to deal correctly with being run from one of the
     # subdirs in the source tree. So if we can't find Recipe here,
     # try one level up.
     chdir "..";
-    open IN, "Recipe" or die "unable to open Recipe file\n";
+    open $in, "Recipe" or die "unable to open Recipe file\n";
 };
+push @filestack, $in;
 
 # HACK: One of the source files in `charset' is auto-generated by
 # sbcsgen.pl. We need to generate that _now_, before attempting
@@ -45,13 +48,20 @@ $project_name = "project"; # this is a good enough default
 
 @allobjs = (); # all object file names
 
-while (<IN>) {
+readinput: while (1) {
+  while (not defined ($_ = <$in>)) {
+    close $in;
+    last readinput if 0 == scalar @filestack;
+    $in = pop @filestack;
+  }
+
+  chomp;
+  split;
+
   # Skip comments (unless the comments belong, for example because
   # they're part of a diversion).
   next if /^\s*#/ and !defined $divert;
 
-  chomp;
-  split;
   if ($_[0] eq "!begin" and $_[1] eq "help") { $divert = \$help; next; }
   if ($_[0] eq "!end") { $divert = undef; next; }
   if ($_[0] eq "!name") { $project_name = $_[1]; next; }
@@ -59,13 +69,27 @@ while (<IN>) {
   if ($_[0] eq "!makefile" and &mfval($_[1])) { $makefiles{$_[1]}=$_[2]; next;}
   if ($_[0] eq "!specialobj" and &mfval($_[1])) { $specialobj{$_[1]}->{$_[2]} = 1; next;}
   if ($_[0] eq "!begin") {
-      if (&mfval($_[1])) {
+      if ($_[1] =~ /^>(.*)/) {
+         $divert = \$auxfiles{$1};
+      } elsif (&mfval($_[1])) {
          $divert = \$makefile_extra{$_[1]};
-      } else {
-         $divert = \$dummy;
       }
       next;
   }
+  if ($_[0] eq "!include") {
+      @newfiles = ();
+      for ($i = 1; $i <= $#_; $i++) {
+         push @newfiles, (sort glob $_[$i]);
+      }
+      for ($i = $#newfiles; $i >= 0; $i--) {
+         $file = $newfiles[$i];
+         $f = new IO::Handle;
+         open $f, "<$file" or die "unable to open include file '$file'\n";
+         push @filestack, $f;
+      }
+      $in = $filestack[$#filestack];
+      next;
+  }
   # If we're gathering help text, keep doing so.
   if (defined $divert) { ${$divert} .= "$_\n"; next; }
   # Ignore blank lines.
@@ -80,6 +104,11 @@ while (<IN>) {
     $prog = undef;
     die "$.: unexpected + line\n" if !defined $lastlistref;
   } elsif ($_[1] eq "=") {
+    $groups{$_[0]} = [];
+    $listref = $groups{$_[0]};
+    $prog = undef;
+    shift @objs; # eat the group name
+  } elsif ($_[1] eq "+=") {
     $groups{$_[0]} = [] if !defined $groups{$_[0]};
     $listref = $groups{$_[0]};
     $prog = undef;
@@ -89,7 +118,7 @@ while (<IN>) {
     $prog = $_[0];
     shift @objs; # eat the program name
   } else {
-    die "$.: unrecognised line type\n";
+    die "$.: unrecognised line type: '$_'\n";
   }
   shift @objs; # eat the +, the = or the :
 
@@ -113,7 +142,11 @@ while (<IN>) {
   $lastlistref = $listref;
 }
 
-close IN;
+foreach $aux (sort keys %auxfiles) {
+    open AUX, ">$aux";
+    print AUX $auxfiles{$aux};
+    close AUX;
+}
 
 # Find object file names with predefines (in square brackets after
 # the module name), and decide on actual object names for them.
@@ -325,7 +358,8 @@ sub splitline {
   $splitchar = (defined $splitchar ? $splitchar : '\\');
   while (length $line > $len) {
     $line =~ /^(.{0,$len})\s(.*)$/ or $line =~ /^(.{$len,}?\s(.*)$/;
-    $result .= $1 . " ${splitchar}\n\t\t";
+    $result .= $1;
+    $result .= " ${splitchar}\n\t\t" if $2 ne '';
     $line = $2;
     $len = 60;
   }