Added Nitfol and Frotz source code.
[rodin/chimara.git] / interpreters / nitfol / opt2glkc.pl
diff --git a/interpreters/nitfol/opt2glkc.pl b/interpreters/nitfol/opt2glkc.pl
new file mode 100644 (file)
index 0000000..6f60a64
--- /dev/null
@@ -0,0 +1,1055 @@
+#!/usr/local/bin/perl -w
+use strict;
+
+my $header = "nitfol.h";
+my $appname = "nitfol";
+my $appmajor = "NITFOL_MAJOR";
+my $appminor = "NITFOL_MINOR";
+my $texinfo = "nitfol.texi";
+my $author = "Evin Robertson";
+my $email = "nitfol\@my-deja.com";
+my $search_path = "INFOCOM_PATH";
+my @man_see_also = ( "frotz (6)", "txd (1)" );
+my $mac_creator = "niTf";
+my $mac_savefile = "IFZS";
+my $mac_datafile = "ZipD";
+my @mac_gamefile = ( "ZCOD", "IFRS", $mac_savefile );
+
+# The following are modified by make_glk_* as appropriate
+my $dirsep = "/";
+my $configdir = "configdir = n_strdup(getenv(\"HOME\"));";
+my $configname = "configname = \"${dirsep}.${appname}rc\";";
+
+
+# opt2glkc.pl - Generates Glk startup code and some documentation
+# Copyright (C) 1999  Evin Robertson
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+#
+#  The author can be reached at nitfol@my-deja.com
+
+my @LoL;
+my $argtype;
+my $systemtype;
+
+my %optionlist = ( unix => [ "startunix.c",  \&make_glk_unix ],
+                  dos  => [ "startdos.c",   \&make_glk_dos ],
+                  win  => [ "startwin.c",   \&make_glk_win ],
+                  mac  => [ "startmac.c",   \&make_glk_mac ],
+                  info => [ "options.texi", \&make_info ],
+                  man  => [ "$appname.6",   \&make_man ]
+                  );
+
+$_ = $ARGV[0];
+
+if(/^-(.*)$/) {
+    $systemtype = $1;
+    shift;
+} else {
+    $systemtype = "unix";
+}
+
+read_in_optfile();
+
+$optionlist{$systemtype} || die "Unknown switch '-$systemtype'\n";
+
+open("MYOUTPUT", ">$optionlist{$systemtype}[0]") || die "cannot write to $optionlist{$systemtype}[0]\n";
+
+select "MYOUTPUT";
+&{ $optionlist{$systemtype}[1] }();
+
+close "MYOUTPUT";
+
+
+
+
+sub read_in_optfile
+{
+    my $longdesc;
+    my $i = 1;
+    while(<>) {
+       if(/^\#/ || /^$/) {
+           ;
+       }
+       #             1          2      3         4         5       6                     9
+       elsif(/^\s*\"(.*?)\"\s+(\S+)\s+(\S)\s+\"(.*?)\"\s+(\S+)\s+((\S+)|(\".*?\"))\s+(\{.*)$/) {
+           $longdesc = <>;
+           push @LoL, [ ( $1, $2, $3, $4, $5, $6, $9, $i, $ARGV, $longdesc ) ];
+           $i++;
+       } else {
+           die "Error in file $ARGV line $i.";
+       }
+       $i++;
+    }
+}
+
+
+
+sub make_info
+{
+    foreach my $soption (@LoL) {
+       my @option = @{ $soption };
+       if($option[4] eq "flag") {
+           print "\@item -$option[1]\n";
+           print "\@itemx -no-$option[1]\n";
+           if($option[2] ne "-") {
+               print "\@itemx -$option[2]\n";
+           }
+       } else {
+           print "\@item -$option[1] \@var{$option[4]}\n";
+           if($option[2] ne "-") {
+               print "\@itemx -$option[2] \@var{$option[4]}\n";
+           }
+       }
+       print "$option[3].  $option[9]\n";
+    }
+}
+
+sub texi2roff
+{
+    $_ = $_[0];
+    s/\@itemize \@minus\n//;
+    s/\@end itemize/.PP/;
+    s/\@item /.IP \\\(bu\n/;
+
+    s/\@code\{(.*?)\}/\\fB$1\\fP/g;
+    s/\@samp\{(.*?)\}/\`$1\'/g;
+    s/\@var\{(.*?)\}/\\fI$1\\fP/g;
+    s/\@kbd\{(.*?)\}/\`$1\'/g;
+    s/\@file\{(.*?)\}/\`$1\'/g;
+    s/\@cite\{(.*?)\}/\\fI$1\\fP/g;
+    s/\@uref\{(.*?)(, (.*?))\}/$3 \<$1\>/g;
+    s/\@uref\{(.*?)\}/\<$1\>/g;
+    s/\@email\{(.*?)\}/\<$1\>/g;
+    s/\@sc\{(.*?)\}/$1/g;
+    s/\@\@/\@/g;
+
+    return $_;
+}
+
+sub texi2txt
+{
+    $_ = $_[0];
+    s/\@code\{(.*?)\}/\'$1\'/g;
+    s/\@file\{(.*?)\}/\'$1\'/g;
+    s/\@\@/\@/g;
+    return $_;
+}
+
+
+sub make_man
+{
+    open("MYTEXINFO", "<$texinfo") || die "unable to read '$texinfo'\n";
+    print ".TH ", uc $appname, " 6\n";
+    print ".SH NAME\n";
+    while(($_ = <MYTEXINFO>) !~ /^\* $appname: \($appname\). *.*/i) {
+       ;
+    }
+    /^\* $appname: \($appname\). *(.*)/i;
+    print "$appname \\- $1\n";
+    print ".SH SYNOPSIS\n";
+    print ".B $appname\n";
+    print ".I \"[options] file\"\n";
+    print ".SH DESCRIPTION\n";
+    print "This manpage was generated from bits of the info page.  See the info page for complete documentation.\n";
+    while(<MYTEXINFO> !~ /^\@chapter introduction/i) {
+       ;
+    }
+    while(($_ = <MYTEXINFO>) !~ /^(\@node)|(\@bye)|(\@menu)/) {
+       if($_ !~ /^\@.*/) {
+           print texi2roff($_);
+       }
+    }
+    print ".SH OPTIONS\n";
+    foreach my $soption (@LoL) {
+       my @option = @{ $soption };
+       print ".TP\n";
+       print ".B";
+       if($option[4] eq "flag") {
+           print " \\-$option[1]";
+           print ", \\-no\\-$option[1]";
+           if($option[2] ne "-") {
+               print ", \\-$option[2]";
+           }
+       } else {
+           print " \\-$option[1] \\fI$option[4]\\fB";
+           if($option[2] ne "-") {
+               print ", \\-$option[2] \\fI$option[4]";
+           }
+       }
+       print "\n";
+       print texi2roff($option[3]), ".  ", texi2roff($option[9]);
+    }
+
+    print ".SH BUGS\n";
+    while(<MYTEXINFO> !~ /^\@chapter bugs/i) {
+       ;
+    }
+    while(($_ = <MYTEXINFO>) !~ /^(\@node)|(\@bye)/) {
+       print texi2roff($_);
+    }
+
+    print ".SH \"SEE ALSO\"\n";
+    print ".RB \"`\\|\" $appname \"\\|'\"\n";
+    print "entry in\n";
+    print ".B\n";
+    print "info;\n";
+
+    my $flag = 0;
+    foreach my $also (@man_see_also) {
+       if($flag) {
+           print ",\n";
+       }
+       $flag = 1;
+       print ".BR $also";
+    }
+    print ".\n";
+
+    print ".SH AUTHOR\n";
+    print "$appname was written by $author, who can be reached at $email.\n";
+    close("MYTEXINFO");
+}
+
+sub make_glk_unix
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+#ifdef DEBUGGING
+#include <signal.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <limits.h>
+#include \"$header\"
+#include \"glkstart.h\"
+
+static char *game_filename = NULL;
+
+static void set_game_filename(const char *name)
+{
+  n_free(game_filename);
+  game_filename = 0;
+
+#if defined(_GNU_SOURCE)
+  game_filename = canonicalize_file_name(name);
+#else
+#if defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
+  game_filename = (char *) n_malloc(PATH_MAX);
+  if(!realpath(name, game_filename)) {
+    n_free(game_filename);
+    game_filename = 0;
+  }
+#else
+#ifdef __DJGPP__
+  game_filename = (char *) n_malloc(FILENAME_MAX);
+  _fixpath(name, game_filename);
+#endif
+#endif
+#endif
+
+  if(!game_filename)
+    game_filename = n_strdup(name);
+}
+
+
+strid_t startup_findfile(void)
+{
+  static DIR *dir = NULL;
+  static char *pathstart = NULL;
+  static char *path = NULL;
+  strid_t stream;
+  struct dirent *d;
+  char *name = NULL;
+
+  if(!pathstart) {
+    char *p = search_path;
+    if(!p)
+      return 0;
+    pathstart = n_strdup(p);
+    if(!(path = n_strtok(pathstart, \":\"))) {
+      n_free(pathstart);
+      pathstart = 0;
+      return 0;
+    }
+  }
+
+  do {
+    if(!dir) {
+      dir = opendir(path);
+      if(!dir) {
+       n_free(pathstart);
+       pathstart = 0;
+       return 0;
+      }
+    }
+    d = readdir(dir);
+    if(!d) {
+      closedir(dir);
+      dir = NULL;
+      if(!(path = n_strtok(NULL, \":\"))) {
+       n_free(pathstart);
+       pathstart = 0;
+       return 0;
+      }
+    }
+  } while(!dir);
+
+  name = (char *) n_malloc(n_strlen(path) + n_strlen(d->d_name) + 2);
+  n_strcpy(name, path);
+  n_strcat(name, \"$dirsep\");
+  n_strcat(name, d->d_name);
+  stream = glkunix_stream_open_pathname(name, fileusage_Data |
+                                       fileusage_BinaryMode, 0);
+  if(stream)
+    set_game_filename(name);
+  n_free(name);
+  return stream;
+}
+
+
+strid_t intd_filehandle_open(strid_t savefile, glui32 operating_id,
+                             glui32 contents_id, glui32 interp_id,
+                             glui32 length)
+{
+  char *name;
+  strid_t str;
+  if(operating_id != ", string_to_iff("UNIX"), ")
+    return 0;
+  if(contents_id != 0)
+    return 0;
+  if(interp_id != ", string_to_iff("    "), ")
+    return 0;
+
+  name = (char *) n_malloc(length+1);
+  glk_get_buffer_stream(savefile, name, length);
+  name[length] = 0;
+  str = glkunix_stream_open_pathname(name, fileusage_Data |
+                                    fileusage_BinaryMode, 0);
+  if(str)
+    set_game_filename(name);
+  n_free(name);
+  return str;
+}
+
+void intd_filehandle_make(strid_t savefile)
+{
+  if(!game_filename)
+    return;
+  w_glk_put_string_stream(savefile, \"UNIX\");
+  glk_put_char_stream(savefile, b00000010); /* Flags */
+  glk_put_char_stream(savefile, 0);         /* Contents ID */
+  glk_put_char_stream(savefile, 0);         /* Reserved */
+  glk_put_char_stream(savefile, 0);         /* Reserved */
+  w_glk_put_string_stream(savefile, \"    \"); /* Interpreter ID */
+  w_glk_put_string_stream(savefile, game_filename);
+}
+
+glui32 intd_get_size(void)
+{
+  if(!game_filename)
+    return 0;
+  return n_strlen(game_filename) + 12;
+}
+
+strid_t startup_open(const char *name)
+{
+  strid_t str;
+
+  str = glkunix_stream_open_pathname((char *) name, fileusage_Data | fileusage_BinaryMode, 0);
+  if(str) {
+    set_game_filename(name);
+  } else {
+    char *path = search_path;
+    if(path) {
+      char *p;
+      char *newname = (char *) n_malloc(strlen(path) + strlen(name) + 2);
+      path = n_strdup(path);
+      for(p = n_strtok(path, \":\"); p; p = n_strtok(NULL, \":\")) {
+       n_strcpy(newname, p);
+       n_strcat(newname, \"$dirsep\");
+       n_strcat(newname, name);
+       str = glkunix_stream_open_pathname((char *) newname, fileusage_Data |
+                                          fileusage_BinaryMode, 0);
+       if(str) {
+         set_game_filename(newname);
+         break;
+        }
+      }
+      n_free(path);
+    }
+  }
+
+  if(!str)
+    fprintf(stderr, \"Cannot open '%s'\\n\", name);
+
+  return str;
+}
+
+";
+
+    make_generic_startup_wopen();
+    make_useless_command_structure();
+    make_functions();
+    make_useful_command_structure();
+    make_default_setter();
+    make_textpref_reader();
+    make_help_printer();
+    make_command_parser();
+
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+
+#ifdef DEBUGGING
+static void sighandle(int unused);
+
+static void sighandle(int unused)
+{
+/*  signal(SIGINT, sighandle); */ /* SysV resets default behaviour - foil it */
+  enter_debugger = TRUE;
+}
+#endif
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+int glkunix_startup_code(glkunix_startup_t *data)
+{
+  strid_t pref;
+  const char *configname;
+  char *configdir, *prefname;
+  char *execname;
+  char *p;
+  username = getenv(\"LOGNAME\");   /* SysV */
+  if(!username)
+    username = getenv(\"USER\");    /* BSD */
+
+#ifdef DEBUGGING
+/*  signal(SIGINT, sighandle); */
+#endif
+
+  execname = n_strrchr(data->argv[0], '$dirsep');
+
+  if(execname)
+    execname++;
+  else
+    execname = data->argv[0];
+  
+  set_defaults();
+  $configdir
+  $configname
+  prefname = n_malloc(n_strlen(configdir) + n_strlen(configname) + 1);
+  n_strcpy(prefname, configdir);
+  n_strcat(prefname, configname);
+  pref = glkunix_stream_open_pathname(prefname, fileusage_Data | fileusage_TextMode, 0);
+  n_free(configdir);
+  n_free(prefname);
+  read_textpref(pref, execname);
+  
+  p = getenv(\"$search_path\");
+  if(p) {
+    free(search_path);
+    search_path = n_strdup(p);
+  }
+
+  return parse_commands(data->argc, data->argv);
+}
+#ifdef __cplusplus
+}
+#endif
+";
+}
+
+sub make_glk_dos
+{
+    $dirsep = "/";
+    $configdir = "configdir = n_strdup(data->argv[0]); if(n_strrchr(configdir, '$dirsep')) *n_strrchr(configdir, '$dirsep') = 0;";
+    $configname = "configname = \"${dirsep}${appname}.cfg\";";
+    make_glk_unix();
+}
+
+
+sub make_glk_win
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+#include \"$header\"
+#include \"WinGlk.h\"
+
+";
+    make_generic_intd();
+    make_generic_findfile();
+    make_generic_startup_open();
+    make_generic_startup_wopen();
+    make_functions();
+    make_useful_command_structure();
+    make_default_setter();
+    make_help_printer();
+    make_command_parser();
+
+
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+void shift_string_left(char *str)
+{
+  int len = strlen(str);
+  int i;
+  for(i = 0; i < len; i++)
+    str[i] = str[i+1];
+}
+
+int winglk_startup_code(void)
+{
+  BOOL status;
+  char *commandline = strdup(GetCommandLine());
+  char **argv = (char **) n_malloc(sizeof(char *) * strlen(commandline));
+  int argc = 0;
+
+  int i;
+
+  while(*commandline) {
+    while(*commandline && isspace(*commandline))
+      commandline++;
+    
+    argv[argc++] =  commandline;
+    
+    while(*commandline && !isspace(*commandline)) {
+      if(*commandline == '\"') {
+       shift_string_left(commandline);
+       while(*commandline && *commandline != '\"')
+         commandline++;
+       shift_string_left(commandline);
+      } else {
+       commandline++;
+      }
+    }
+    
+    *commandline++ = 0;
+  }
+
+  argv[argc] = NULL;
+  
+  status = parse_commands(argc, argv);
+
+  n_free(argv);
+  n_free(commandline);
+
+  winglk_app_set_name(\"$appname\");
+  winglk_window_set_title(\"$appname\");
+  set_defaults();
+
+  return status;
+}
+";
+}
+
+
+
+sub string_to_iff
+{
+    my ($id) = @_;
+    my $i;
+    my $val;
+    $val = 0;
+    for($i=0; $i < length $id; $i++) {
+       $val = $val * 0x100 + ord substr $id, $i, 1;
+    }
+    return sprintf("0x%x /* '$id' */", $val);
+}
+
+
+
+sub make_glk_mac
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+#include \"$header\"
+#include \"macglk_startup.h\"
+
+static strid_t mac_gamefile;
+
+static BOOL hashandle = FALSE;
+static AliasHandle gamehandle;
+";
+    make_generic_findfile();
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+strid_t intd_filehandle_open(strid_t savefile, glui32 operating_id,
+                             glui32 contents_id, glui32 interp_id,
+                             glui32 length)
+{
+  FSSpec file;
+  Boolean wasChanged;
+  if(operating_id != ", string_to_iff("MACS"), ")
+    return 0;
+  if(contents_id != 0)
+    return 0;
+  if(interp_id != ", string_to_iff("    "), ")
+    return 0;
+
+  gamehandle = NewHandle(length);
+  glk_get_buffer_stream(savefile, *gamehandle, length);
+  hashandle = TRUE;
+  ResolveAlias(NULL, gamehandle, &file, &wasChanged);
+  return macglk_stream_open_fsspec(&file, 0, 0);  
+}
+
+void intd_filehandle_make(strid_t savefile)
+{
+  if(!hashandle)
+    return;
+  glk_put_string_stream(savefile, \"MACS\");
+  glk_put_char_stream(savefile, b00000010); /* Flags */
+  glk_put_char_stream(savefile, 0);         /* Contents ID */
+  glk_put_char_stream(savefile, 0);         /* Reserved */
+  glk_put_char_stream(savefile, 0);         /* Reserved */
+  glk_put_string_stream(savefile, \"    \");/* Interpreter ID */
+  glk_put_buffer_stream(savefile, *gamehandle, *gamehandle->aliasSize);
+}
+
+glui32 intd_get_size(void)
+{
+  if(!hashandle)
+    return 0;
+  return *gamehandle->aliasSize + 12;
+}
+
+static Boolean mac_whenselected(FSSpec *file, OSType filetype)
+{
+  NewAlias(NULL, file, &gamehandle);
+  hashandle = TRUE;
+  return game_use_file(mac_gamefile);
+}
+
+static Boolean mac_whenbuiltin()
+{
+  return game_use_file(mac_gamefile);
+}
+
+Boolean macglk_startup_code(macglk_startup_t *data)
+{
+  OSType mac_gamefile_types[] = { ";
+
+    my $flag = 0;
+    foreach my $filetype (@mac_gamefile) {
+       if($flag) {
+           print ", ";
+        }
+        $flag = 1;
+        print string_to_iff($filetype);
+    }
+
+    print " };
+
+  data->startup_model  = macglk_model_ChooseOrBuiltIn;
+  data->app_creator    = ", string_to_iff($mac_creator), ";
+  data->gamefile_types = mac_gamefile_types;
+  data->num_gamefile_types = sizeof(mac_gamefile_types) / sizeof(*mac_gamefile_types);
+  data->savefile_type  = ", string_to_iff($mac_savefile), ";
+  data->datafile_type  = ", string_to_iff($mac_datafile), ";
+  data->gamefile       = &mac_gamefile;
+  data->when_selected  = mac_whenselected;
+  data->when_builtin   = mac_whenbuiltin;
+
+  return TRUE;
+}
+";
+}
+
+sub make_generic_intd
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+strid_t intd_filehandle_open(strid_t savefile, glui32 operating_id,
+                             glui32 contents_id, glui32 interp_id,
+                             glui32 length)
+{
+  return 0;
+}
+
+void intd_filehandle_make(strid_t savefile)
+{
+  ;
+}
+
+glui32 intd_get_size(void)
+{
+  return 0;
+}
+";
+}
+
+
+sub make_generic_findfile
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+strid_t startup_findfile(void)
+{
+  ;
+}
+";
+}
+
+
+sub make_generic_startup_open
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+strid_t startup_open(const char *name)
+{
+  return n_file_name(fileusage_Data | fileusage_BinaryMode,
+                    filemode_Read, name);
+}
+";
+}
+
+
+sub make_generic_startup_wopen
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+static strid_t startup_wopen(const char *name)
+{
+  return n_file_name(fileusage_Data | fileusage_BinaryMode,
+                    filemode_Write, name);
+}
+";
+}
+
+
+
+sub make_functions
+{
+    foreach my $soption (@LoL) {
+       my @option = @{ $soption };
+       if($option[4] eq "flag") {
+           $argtype = "int flag";
+       }
+       if($option[4] eq "file" || $option[4] eq "wfile") {
+           $argtype = "strid_t stream";
+       }
+       if($option[4] eq "number") {
+           $argtype = "int number";
+       }
+       if($option[4] eq "string") {
+           $argtype = "const char *string";
+       }
+       
+       print "static void code_$option[1]($argtype)\n";
+       print "#line $option[7] \"$option[8]\"\n";
+       print "$option[6]\n\n";
+    }
+}
+
+
+
+sub make_useful_command_structure
+{
+    #
+    # Write structure so we can actually parse the options
+    #
+    my ( $int_func, $defint, $str_func, $defstr, $string_func, $defstring );
+
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"';
+    print "\ntypedef enum { option_flag, option_file, option_wfile, option_number, option_string } option_type;\n";
+    print "typedef struct { const char *longname; char shortname; const char *description; option_type type; void (*int_func)(int); int defint; void (*str_func)(strid_t); strid_t defstream; void (*string_func)(const char *); const char *defstring; } option_option;\n\n";
+
+    print "static option_option options[] = {\n";
+
+    my $flag = 0;
+    foreach my $soption (@LoL) {
+       my @option = @{ $soption };
+       if($flag) {
+           print ",\n";
+       }
+       $flag = 1;
+
+       $int_func = "NULL";
+       $defint = "0";
+
+       $str_func = "NULL";
+       $defstr = "NULL";
+
+       $string_func = "NULL";
+       $defstring = "NULL";
+       
+       if($option[4] eq "flag") {
+           $defint = $option[5];
+           $int_func = "code_" . $option[1];
+       }
+       if($option[4] eq "file" || $option[4] eq "wfile") {
+           $defstr = $option[5];
+           $str_func = "code_" . $option[1];
+       }
+       if($option[4] eq "number") {
+           $defint = $option[5];
+           $int_func = "code_" . $option[1];
+       }
+       if($option[4] eq "string") {
+           $defstring = $option[5];
+           $string_func = "code_" . $option[1];
+       }
+       
+       print "  { \"$option[1]\", '$option[2]', \"", texi2txt($option[3]), "\", option_$option[4], $int_func, $defint, $str_func, $defstr, $string_func, $defstring }";
+    }
+    
+    print "\n};\n\n";
+
+}
+
+
+
+sub make_default_setter
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+static void set_defaults(void)
+{
+  unsigned n;
+  for(n = 0; n < sizeof(options) / sizeof(*options); n++) {
+    if(options[n].int_func)
+      options[n].int_func(options[n].defint);
+    if(options[n].str_func)
+      options[n].str_func(options[n].defstream);
+    if(options[n].string_func)
+      options[n].string_func(options[n].defstring);
+  }
+}
+\n";
+}
+
+sub make_textpref_reader
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+static void read_textpref(strid_t pref, const char *progname)
+{
+  unsigned n;
+  char buffer[1024];
+  int prognamelen = n_strlen(progname);
+  if(!pref)
+    return;
+  while(glk_get_line_stream(pref, buffer, sizeof(buffer))) {
+    char *optname;
+    char *optval;
+    long int optnum;
+
+    if(buffer[0] == '#')
+      continue;
+    while(buffer[0] == '[') {
+      if(n_strncasecmp(buffer+1, progname, prognamelen) != 0
+        || buffer[1+prognamelen] != ']') {
+       while(glk_get_line_stream(pref, buffer, sizeof(buffer)))
+         if(buffer[0] == '[')
+           break;
+      } else {
+       glk_get_line_stream(pref, buffer, sizeof(buffer));
+      }
+    }
+
+    optname = buffer;
+    while(isspace(*optname))
+      optname++;
+    if((optval = n_strchr(optname, '=')) != NULL) {
+      char *p;
+      *optval = 0;
+      optval++;
+
+      if((p = n_strchr(optname, ' ')) != NULL)
+       *p = 0;
+      
+      while(isspace(*optval))
+       optval++;
+
+      while(isspace(optval[strlen(optval)-1]))
+        optval[strlen(optval)-1] = 0;
+
+      optnum = n_strtol(optval, NULL, 0);
+      if(n_strcasecmp(optval, \"false\") == 0
+        || n_strcasecmp(optval, \"f\") == 0)
+       optnum = FALSE;
+      if(n_strcasecmp(optval, \"true\") == 0
+        || n_strcasecmp(optval, \"t\") == 0)
+       optnum = TRUE;
+
+      for(n = 0; n < sizeof(options) / sizeof(*options); n++) {
+       if(n_strcmp(options[n].longname, optname) == 0) {
+         switch(options[n].type) {
+         case option_flag:
+         case option_number:
+           options[n].int_func(optnum);
+           break;
+         case option_file:
+           options[n].str_func(startup_open(optval));
+           break;
+         case option_wfile:
+           options[n].str_func(startup_wopen(optval));
+           break;
+         case option_string:
+           options[n].string_func(optval);
+           break;
+         }
+          break;
+       }
+      }
+    }
+  }
+  glk_stream_close(pref, NULL);
+}
+\n";
+}
+
+
+sub make_help_printer
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+static void show_help(void)
+{
+  unsigned n;
+  printf(\"Usage: $appname [OPTIONS] gamefile\\n\");
+  for(n = 0; n < sizeof(options) / sizeof(*options); n++) {
+    if(options[n].shortname != '-')
+      printf(\" -%c, \", options[n].shortname);
+    else
+      printf(\"     \");
+    printf(\"-%-15s %s\\n\", options[n].longname, options[n].description);
+  }
+}
+\n";
+}
+
+sub make_command_parser
+{
+    print "#line " . (__LINE__+1) . ' "' . __FILE__ . '"' . "
+static BOOL parse_commands(int argc, char **argv)
+{
+  int i;
+  unsigned n;
+
+  for(i = 1; i < argc; i++) {
+    BOOL flag = TRUE;
+
+    const char *p = argv[i];
+    
+    if(p[0] == '-') {
+      BOOL found = FALSE;
+
+      while(*p == '-')
+       p++;
+      if(n_strncmp(p, \"no-\", 3) == 0) {
+       flag = FALSE;
+       p+=3;
+      }
+
+      if(n_strcasecmp(p, \"help\") == 0) {
+       show_help();
+       exit(0);
+      }
+      if(n_strcasecmp(p, \"version\") == 0) {
+       printf(\"$appname version %d.%d\\n\", $appmajor, $appminor);
+       exit(0);
+      }
+      
+      for(n = 0; n < sizeof(options) / sizeof(*options); n++) {
+       if((n_strlen(p) == 1 && *p == options[n].shortname) ||
+          n_strcmp(options[n].longname, p) == 0) {
+         found = TRUE;
+
+         switch(options[n].type) {
+         case option_flag:
+           options[n].int_func(flag);
+           break;
+
+         case option_file:
+           i++;
+           options[n].str_func(startup_open(argv[i]));
+           break;
+
+         case option_wfile:
+           i++;
+           options[n].str_func(startup_wopen(argv[i]));
+           break;
+
+         case option_number:
+            i++;
+            options[n].int_func(n_strtol(argv[i], NULL, 0));
+           break;
+
+         case option_string:
+           i++;
+           options[n].string_func(argv[i]);
+           break;
+         }
+       }
+      }
+
+      if(!found)
+       return FALSE;
+
+    } else {
+      strid_t s = startup_open(argv[i]);
+      if(!s)
+       return FALSE;
+      if(!game_use_file(s))
+       return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+\n";
+}
+
+
+
+
+sub make_useless_command_structure
+{
+    print "glkunix_argumentlist_t glkunix_arguments[] = {\n";
+    
+    print "  { (char *) \"\", glkunix_arg_ValueCanFollow, (char *) \"filename\tfile to load\" },\n";
+
+    print "  { (char *) \"-help\", glkunix_arg_NoValue, (char *) \"list command-line options\" },\n";
+    print "  { (char *) \"--help\", glkunix_arg_NoValue, (char *) \"list command-line options\" },\n";
+    print "  { (char *) \"-version\", glkunix_arg_NoValue, (char *) \"get version number\" },\n";
+    print "  { (char *) \"--version\", glkunix_arg_NoValue, (char *) \"get version number\" },\n";
+
+    
+    foreach my $soption (@LoL) {
+       my @option = @{ $soption };
+       if($option[4] eq "flag") {
+           $argtype = "glkunix_arg_NoValue";
+       }
+       if($option[4] eq "file" || $option[4] eq "wfile") {
+           $argtype = "glkunix_arg_ValueFollows";
+       }
+       if($option[4] eq "number") {
+           $argtype = "glkunix_arg_NumberValue";
+       }
+       if($option[4] eq "string") {
+          $argtype = "glkunix_arg_ValueFollows";
+       }
+       
+       if($option[2] ne "-") {
+           print "  { (char *) \"-$option[2]\", $argtype, (char *) \"-$option[2]\" },\n";
+       }
+       
+       if($option[4] eq "flag") {
+           print "  { (char *) \"-no-$option[1]\", $argtype, (char *) \"-no-$option[1]\" },\n";
+           print "  { (char *) \"--no-$option[1]\", $argtype, (char *) \"--no-$option[1]\" },\n";
+       }
+       
+       print "  { (char *) \"-$option[1]\", $argtype, (char *) \"-$option[1]\" },\n";
+       print "  { (char *) \"--$option[1]\", $argtype, (char *) \"--$option[1]\t$option[3]\" },\n";
+    }
+
+    print "  { NULL, glkunix_arg_End, NULL }\n";
+    print "};\n\n";
+
+}
+
+