Fixing installed headers and directories
[projects/chimara/chimara.git] / interpreters / nitfol / startdos.c
1 #line 228 "opt2glkc.pl"
2 #ifdef DEBUGGING
3 #include <signal.h>
4 #endif
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <ctype.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <dirent.h>
11 #include <limits.h>
12 #include "nitfol.h"
13 #include <libchimara/glkstart.h>
14
15 static char *game_filename = NULL;
16
17 static void set_game_filename(const char *name)
18 {
19   n_free(game_filename);
20   game_filename = 0;
21
22 #if defined(_GNU_SOURCE)
23   game_filename = canonicalize_file_name(name);
24 #else
25 #if defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE)
26   game_filename = (char *) n_malloc(PATH_MAX);
27   if(!realpath(name, game_filename)) {
28     n_free(game_filename);
29     game_filename = 0;
30   }
31 #else
32 #ifdef __DJGPP__
33   game_filename = (char *) n_malloc(FILENAME_MAX);
34   _fixpath(name, game_filename);
35 #endif
36 #endif
37 #endif
38
39   if(!game_filename)
40     game_filename = n_strdup(name);
41 }
42
43
44 strid_t startup_findfile(void)
45 {
46   static DIR *dir = NULL;
47   static char *pathstart = NULL;
48   static char *path = NULL;
49   strid_t stream;
50   struct dirent *d;
51   char *name = NULL;
52
53   if(!pathstart) {
54     char *p = search_path;
55     if(!p)
56       return 0;
57     pathstart = n_strdup(p);
58     if(!(path = n_strtok(pathstart, ":"))) {
59       n_free(pathstart);
60       pathstart = 0;
61       return 0;
62     }
63   }
64
65   do {
66     if(!dir) {
67       dir = opendir(path);
68       if(!dir) {
69         n_free(pathstart);
70         pathstart = 0;
71         return 0;
72       }
73     }
74     d = readdir(dir);
75     if(!d) {
76       closedir(dir);
77       dir = NULL;
78       if(!(path = n_strtok(NULL, ":"))) {
79         n_free(pathstart);
80         pathstart = 0;
81         return 0;
82       }
83     }
84   } while(!dir);
85
86   name = (char *) n_malloc(n_strlen(path) + n_strlen(d->d_name) + 2);
87   n_strcpy(name, path);
88   n_strcat(name, "/");
89   n_strcat(name, d->d_name);
90   stream = glkunix_stream_open_pathname(name, fileusage_Data |
91                                         fileusage_BinaryMode, 0);
92   if(stream)
93     set_game_filename(name);
94   n_free(name);
95   return stream;
96 }
97
98
99 strid_t intd_filehandle_open(strid_t savefile, glui32 operating_id,
100                              glui32 contents_id, glui32 interp_id,
101                              glui32 length)
102 {
103   char *name;
104   strid_t str;
105   if(operating_id != 0x554e4958 /* 'UNIX' */)
106     return 0;
107   if(contents_id != 0)
108     return 0;
109   if(interp_id != 0x20202020 /* '    ' */)
110     return 0;
111
112   name = (char *) n_malloc(length+1);
113   glk_get_buffer_stream(savefile, name, length);
114   name[length] = 0;
115   str = glkunix_stream_open_pathname(name, fileusage_Data |
116                                      fileusage_BinaryMode, 0);
117   if(str)
118     set_game_filename(name);
119   n_free(name);
120   return str;
121 }
122
123 void intd_filehandle_make(strid_t savefile)
124 {
125   if(!game_filename)
126     return;
127   w_glk_put_string_stream(savefile, "UNIX");
128   glk_put_char_stream(savefile, b00000010); /* Flags */
129   glk_put_char_stream(savefile, 0);         /* Contents ID */
130   glk_put_char_stream(savefile, 0);         /* Reserved */
131   glk_put_char_stream(savefile, 0);         /* Reserved */
132   w_glk_put_string_stream(savefile, "    "); /* Interpreter ID */
133   w_glk_put_string_stream(savefile, game_filename);
134 }
135
136 glui32 intd_get_size(void)
137 {
138   if(!game_filename)
139     return 0;
140   return n_strlen(game_filename) + 12;
141 }
142
143 strid_t startup_open(const char *name)
144 {
145   strid_t str;
146
147   str = glkunix_stream_open_pathname((char *) name, fileusage_Data | fileusage_BinaryMode, 0);
148   if(str) {
149     set_game_filename(name);
150   } else {
151     char *path = search_path;
152     if(path) {
153       char *p;
154       char *newname = (char *) n_malloc(strlen(path) + strlen(name) + 2);
155       path = n_strdup(path);
156       for(p = n_strtok(path, ":"); p; p = n_strtok(NULL, ":")) {
157         n_strcpy(newname, p);
158         n_strcat(newname, "/");
159         n_strcat(newname, name);
160         str = glkunix_stream_open_pathname((char *) newname, fileusage_Data |
161                                            fileusage_BinaryMode, 0);
162         if(str) {
163           set_game_filename(newname);
164           break;
165         }
166       }
167       n_free(path);
168     }
169   }
170
171   if(!str)
172     fprintf(stderr, "Cannot open '%s'\n", name);
173
174   return str;
175 }
176
177 #line 717 "opt2glkc.pl"
178 static strid_t startup_wopen(const char *name)
179 {
180   return n_file_name(fileusage_Data | fileusage_BinaryMode,
181                      filemode_Write, name);
182 }
183 glkunix_argumentlist_t glkunix_arguments[] = {
184   { (char *) "", glkunix_arg_ValueCanFollow, (char *) "filename file to load" },
185   { (char *) "-help", glkunix_arg_NoValue, (char *) "list command-line options" },
186   { (char *) "--help", glkunix_arg_NoValue, (char *) "list command-line options" },
187   { (char *) "-version", glkunix_arg_NoValue, (char *) "get version number" },
188   { (char *) "--version", glkunix_arg_NoValue, (char *) "get version number" },
189   { (char *) "-i", glkunix_arg_NoValue, (char *) "-i" },
190   { (char *) "-no-ignore", glkunix_arg_NoValue, (char *) "-no-ignore" },
191   { (char *) "--no-ignore", glkunix_arg_NoValue, (char *) "--no-ignore" },
192   { (char *) "-ignore", glkunix_arg_NoValue, (char *) "-ignore" },
193   { (char *) "--ignore", glkunix_arg_NoValue, (char *) "--ignore        Ignore Z-machine strictness errors" },
194   { (char *) "-f", glkunix_arg_NoValue, (char *) "-f" },
195   { (char *) "-no-fullname", glkunix_arg_NoValue, (char *) "-no-fullname" },
196   { (char *) "--no-fullname", glkunix_arg_NoValue, (char *) "--no-fullname" },
197   { (char *) "-fullname", glkunix_arg_NoValue, (char *) "-fullname" },
198   { (char *) "--fullname", glkunix_arg_NoValue, (char *) "--fullname    For running under Emacs or DDD" },
199   { (char *) "-x", glkunix_arg_ValueFollows, (char *) "-x" },
200   { (char *) "-command", glkunix_arg_ValueFollows, (char *) "-command" },
201   { (char *) "--command", glkunix_arg_ValueFollows, (char *) "--command Read commands from this file" },
202   { (char *) "-P", glkunix_arg_NoValue, (char *) "-P" },
203   { (char *) "-no-pirate", glkunix_arg_NoValue, (char *) "-no-pirate" },
204   { (char *) "--no-pirate", glkunix_arg_NoValue, (char *) "--no-pirate" },
205   { (char *) "-pirate", glkunix_arg_NoValue, (char *) "-pirate" },
206   { (char *) "--pirate", glkunix_arg_NoValue, (char *) "--pirate        Aye, matey" },
207   { (char *) "-q", glkunix_arg_NoValue, (char *) "-q" },
208   { (char *) "-no-quiet", glkunix_arg_NoValue, (char *) "-no-quiet" },
209   { (char *) "--no-quiet", glkunix_arg_NoValue, (char *) "--no-quiet" },
210   { (char *) "-quiet", glkunix_arg_NoValue, (char *) "-quiet" },
211   { (char *) "--quiet", glkunix_arg_NoValue, (char *) "--quiet  Do not print introductory messages" },
212   { (char *) "-no-spell", glkunix_arg_NoValue, (char *) "-no-spell" },
213   { (char *) "--no-spell", glkunix_arg_NoValue, (char *) "--no-spell" },
214   { (char *) "-spell", glkunix_arg_NoValue, (char *) "-spell" },
215   { (char *) "--spell", glkunix_arg_NoValue, (char *) "--spell  Perform spelling correction" },
216   { (char *) "-no-expand", glkunix_arg_NoValue, (char *) "-no-expand" },
217   { (char *) "--no-expand", glkunix_arg_NoValue, (char *) "--no-expand" },
218   { (char *) "-expand", glkunix_arg_NoValue, (char *) "-expand" },
219   { (char *) "--expand", glkunix_arg_NoValue, (char *) "--expand        Expand one letter abbreviations" },
220   { (char *) "-s", glkunix_arg_ValueFollows, (char *) "-s" },
221   { (char *) "-symbols", glkunix_arg_ValueFollows, (char *) "-symbols" },
222   { (char *) "--symbols", glkunix_arg_ValueFollows, (char *) "--symbols Specify symbol file for game" },
223   { (char *) "-t", glkunix_arg_NoValue, (char *) "-t" },
224   { (char *) "-no-tandy", glkunix_arg_NoValue, (char *) "-no-tandy" },
225   { (char *) "--no-tandy", glkunix_arg_NoValue, (char *) "--no-tandy" },
226   { (char *) "-tandy", glkunix_arg_NoValue, (char *) "-tandy" },
227   { (char *) "--tandy", glkunix_arg_NoValue, (char *) "--tandy  Censors some Infocom games" },
228   { (char *) "-T", glkunix_arg_ValueFollows, (char *) "-T" },
229   { (char *) "-transcript", glkunix_arg_ValueFollows, (char *) "-transcript" },
230   { (char *) "--transcript", glkunix_arg_ValueFollows, (char *) "--transcript   Write transcript to this file" },
231   { (char *) "-d", glkunix_arg_NoValue, (char *) "-d" },
232   { (char *) "-no-debug", glkunix_arg_NoValue, (char *) "-no-debug" },
233   { (char *) "--no-debug", glkunix_arg_NoValue, (char *) "--no-debug" },
234   { (char *) "-debug", glkunix_arg_NoValue, (char *) "-debug" },
235   { (char *) "--debug", glkunix_arg_NoValue, (char *) "--debug  Enter debugger immediatly" },
236   { (char *) "-prompt", glkunix_arg_ValueFollows, (char *) "-prompt" },
237   { (char *) "--prompt", glkunix_arg_ValueFollows, (char *) "--prompt   Specify debugging prompt" },
238   { (char *) "-path", glkunix_arg_ValueFollows, (char *) "-path" },
239   { (char *) "--path", glkunix_arg_ValueFollows, (char *) "--path       Look for games in this directory" },
240   { (char *) "-no-autoundo", glkunix_arg_NoValue, (char *) "-no-autoundo" },
241   { (char *) "--no-autoundo", glkunix_arg_NoValue, (char *) "--no-autoundo" },
242   { (char *) "-autoundo", glkunix_arg_NoValue, (char *) "-autoundo" },
243   { (char *) "--autoundo", glkunix_arg_NoValue, (char *) "--autoundo    Ensure @code{@@save_undo} is called every turn" },
244   { (char *) "-S", glkunix_arg_NumberValue, (char *) "-S" },
245   { (char *) "-stacklimit", glkunix_arg_NumberValue, (char *) "-stacklimit" },
246   { (char *) "--stacklimit", glkunix_arg_NumberValue, (char *) "--stacklimit    Exit when the stack is this deep" },
247   { (char *) "-a", glkunix_arg_ValueFollows, (char *) "-a" },
248   { (char *) "-alias", glkunix_arg_ValueFollows, (char *) "-alias" },
249   { (char *) "--alias", glkunix_arg_ValueFollows, (char *) "--alias     Specify an alias" },
250   { (char *) "-ralias", glkunix_arg_ValueFollows, (char *) "-ralias" },
251   { (char *) "--ralias", glkunix_arg_ValueFollows, (char *) "--ralias   Specify an recursive alias" },
252   { (char *) "-unalias", glkunix_arg_ValueFollows, (char *) "-unalias" },
253   { (char *) "--unalias", glkunix_arg_ValueFollows, (char *) "--unalias Remove an alias" },
254   { (char *) "-r", glkunix_arg_NumberValue, (char *) "-r" },
255   { (char *) "-random", glkunix_arg_NumberValue, (char *) "-random" },
256   { (char *) "--random", glkunix_arg_NumberValue, (char *) "--random    Set random seed" },
257   { (char *) "-mapsym", glkunix_arg_ValueFollows, (char *) "-mapsym" },
258   { (char *) "--mapsym", glkunix_arg_ValueFollows, (char *) "--mapsym   Specify mapping glyphs" },
259   { (char *) "-mapsize", glkunix_arg_NumberValue, (char *) "-mapsize" },
260   { (char *) "--mapsize", glkunix_arg_NumberValue, (char *) "--mapsize  Specify map size" },
261   { (char *) "-maploc", glkunix_arg_ValueFollows, (char *) "-maploc" },
262   { (char *) "--maploc", glkunix_arg_ValueFollows, (char *) "--maploc   Specify map location" },
263   { (char *) "-terpnum", glkunix_arg_NumberValue, (char *) "-terpnum" },
264   { (char *) "--terpnum", glkunix_arg_NumberValue, (char *) "--terpnum  Specify interpreter number" },
265   { (char *) "-terpver", glkunix_arg_ValueFollows, (char *) "-terpver" },
266   { (char *) "--terpver", glkunix_arg_ValueFollows, (char *) "--terpver Specify interpreter version" },
267   { NULL, glkunix_arg_End, NULL }
268 };
269
270 static void code_ignore(int flag)
271 #line 6 "nitfol.opt"
272 { ignore_errors = flag; }
273
274 static void code_fullname(int flag)
275 #line 9 "nitfol.opt"
276 { fullname = flag; }
277
278 static void code_command(strid_t stream)
279 #line 12 "nitfol.opt"
280 { if(stream) input_stream1 = stream; }
281
282 static void code_pirate(int flag)
283 #line 15 "nitfol.opt"
284 { aye_matey = flag; }
285
286 static void code_quiet(int flag)
287 #line 18 "nitfol.opt"
288 { quiet = flag; }
289
290 static void code_spell(int flag)
291 #line 21 "nitfol.opt"
292 { do_spell_correct = flag; }
293
294 static void code_expand(int flag)
295 #line 24 "nitfol.opt"
296 { do_expand = flag; }
297
298 static void code_symbols(strid_t stream)
299 #line 27 "nitfol.opt"
300 { if(stream) init_infix(stream); }
301
302 static void code_tandy(int flag)
303 #line 30 "nitfol.opt"
304 { do_tandy = flag; }
305
306 static void code_transcript(strid_t stream)
307 #line 33 "nitfol.opt"
308 { if(stream) set_transcript(stream); }
309
310 static void code_debug(int flag)
311 #line 36 "nitfol.opt"
312 { enter_debugger = flag; do_check_watches = flag; }
313
314 static void code_prompt(const char *string)
315 #line 39 "nitfol.opt"
316 { n_free(db_prompt); db_prompt = n_strdup(string); }
317
318 static void code_path(const char *string)
319 #line 42 "nitfol.opt"
320 { n_free(search_path); search_path = n_strdup(string); }
321
322 static void code_autoundo(int flag)
323 #line 45 "nitfol.opt"
324 { auto_save_undo = flag; }
325
326 static void code_stacklimit(int number)
327 #line 52 "nitfol.opt"
328 { stacklimit = number; }
329
330 static void code_alias(const char *string)
331 #line 55 "nitfol.opt"
332 { if(string) parse_new_alias(string, FALSE); }
333
334 static void code_ralias(const char *string)
335 #line 58 "nitfol.opt"
336 { if(string) parse_new_alias(string, TRUE); }
337
338 static void code_unalias(const char *string)
339 #line 61 "nitfol.opt"
340 { if(string) remove_alias(string); }
341
342 static void code_random(int number)
343 #line 64 "nitfol.opt"
344 { faked_random_seed = number; }
345
346 static void code_mapsym(const char *string)
347 #line 67 "nitfol.opt"
348 { n_free(roomsymbol); roomsymbol = n_strdup(string); }
349
350 static void code_mapsize(int number)
351 #line 70 "nitfol.opt"
352 { automap_size = number; }
353
354 static void code_maploc(const char *string)
355 #line 73 "nitfol.opt"
356 { switch(glk_char_to_lower(*string)) { case 'a': case 't': case 'u': automap_split = winmethod_Above; break; case 'b': case 'd': automap_split = winmethod_Below; break; case 'l': automap_split = winmethod_Left; break; case 'r': automap_split = winmethod_Right; } }
357
358 static void code_terpnum(int number)
359 #line 76 "nitfol.opt"
360 { interp_num = number; }
361
362 static void code_terpver(const char *string)
363 #line 79 "nitfol.opt"
364 { if(string) { if(n_strlen(string) == 1) interp_ver = *string; else interp_ver = n_strtol(string, NULL, 10); } }
365
366 #line 760 "opt2glkc.pl"
367 typedef enum { option_flag, option_file, option_wfile, option_number, option_string } option_type;
368 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;
369
370 static option_option options[] = {
371   { "ignore", 'i', "Ignore Z-machine strictness errors", option_flag, code_ignore, 0, NULL, NULL, NULL, NULL },
372   { "fullname", 'f', "For running under Emacs or DDD", option_flag, code_fullname, 0, NULL, NULL, NULL, NULL },
373   { "command", 'x', "Read commands from this file", option_file, NULL, 0, code_command, NULL, NULL, NULL },
374   { "pirate", 'P', "Aye, matey", option_flag, code_pirate, 0, NULL, NULL, NULL, NULL },
375   { "quiet", 'q', "Do not print introductory messages", option_flag, code_quiet, 1, NULL, NULL, NULL, NULL },
376   { "spell", '-', "Perform spelling correction", option_flag, code_spell, 1, NULL, NULL, NULL, NULL },
377   { "expand", '-', "Expand one letter abbreviations", option_flag, code_expand, 1, NULL, NULL, NULL, NULL },
378   { "symbols", 's', "Specify symbol file for game", option_file, NULL, 0, code_symbols, NULL, NULL, NULL },
379   { "tandy", 't', "Censors some Infocom games", option_flag, code_tandy, 0, NULL, NULL, NULL, NULL },
380   { "transcript", 'T', "Write transcript to this file", option_wfile, NULL, 0, code_transcript, NULL, NULL, NULL },
381   { "debug", 'd', "Enter debugger immediatly", option_flag, code_debug, 0, NULL, NULL, NULL, NULL },
382   { "prompt", '-', "Specify debugging prompt", option_string, NULL, 0, NULL, NULL, code_prompt, "(nitfol) " },
383   { "path", '-', "Look for games in this directory", option_string, NULL, 0, NULL, NULL, code_path, NULL },
384   { "autoundo", '-', "Ensure '@save_undo' is called every turn", option_flag, code_autoundo, 1, NULL, NULL, NULL, NULL },
385   { "stacklimit", 'S', "Exit when the stack is this deep", option_number, code_stacklimit, 0, NULL, NULL, NULL, NULL },
386   { "alias", 'a', "Specify an alias", option_string, NULL, 0, NULL, NULL, code_alias, NULL },
387   { "ralias", '-', "Specify an recursive alias", option_string, NULL, 0, NULL, NULL, code_ralias, NULL },
388   { "unalias", '-', "Remove an alias", option_string, NULL, 0, NULL, NULL, code_unalias, NULL },
389   { "random", 'r', "Set random seed", option_number, code_random, 0, NULL, NULL, NULL, NULL },
390   { "mapsym", '-', "Specify mapping glyphs", option_string, NULL, 0, NULL, NULL, code_mapsym, "*udb@UDB+" },
391   { "mapsize", '-', "Specify map size", option_number, code_mapsize, 12, NULL, NULL, NULL, NULL },
392   { "maploc", '-', "Specify map location", option_string, NULL, 0, NULL, NULL, code_maploc, "above" },
393   { "terpnum", '-', "Specify interpreter number", option_number, code_terpnum, 2, NULL, NULL, NULL, NULL },
394   { "terpver", '-', "Specify interpreter version", option_string, NULL, 0, NULL, NULL, code_terpver, "N" }
395 };
396
397 #line 811 "opt2glkc.pl"
398 static void set_defaults(void)
399 {
400   unsigned n;
401   for(n = 0; n < sizeof(options) / sizeof(*options); n++) {
402     if(options[n].int_func)
403       options[n].int_func(options[n].defint);
404     if(options[n].str_func)
405       options[n].str_func(options[n].defstream);
406     if(options[n].string_func)
407       options[n].string_func(options[n].defstring);
408   }
409 }
410
411 #line 829 "opt2glkc.pl"
412 static void read_textpref(strid_t pref, const char *progname)
413 {
414   unsigned n;
415   char buffer[1024];
416   int prognamelen = n_strlen(progname);
417   if(!pref)
418     return;
419   while(glk_get_line_stream(pref, buffer, sizeof(buffer))) {
420     char *optname;
421     char *optval;
422     long int optnum;
423
424     if(buffer[0] == '#')
425       continue;
426     while(buffer[0] == '[') {
427       if(n_strncasecmp(buffer+1, progname, prognamelen) != 0
428          || buffer[1+prognamelen] != ']') {
429         while(glk_get_line_stream(pref, buffer, sizeof(buffer)))
430           if(buffer[0] == '[')
431             break;
432       } else {
433         glk_get_line_stream(pref, buffer, sizeof(buffer));
434       }
435     }
436
437     optname = buffer;
438     while(isspace(*optname))
439       optname++;
440     if((optval = n_strchr(optname, '=')) != NULL) {
441       char *p;
442       *optval = 0;
443       optval++;
444
445       if((p = n_strchr(optname, ' ')) != NULL)
446         *p = 0;
447       
448       while(isspace(*optval))
449         optval++;
450
451       while(isspace(optval[strlen(optval)-1]))
452         optval[strlen(optval)-1] = 0;
453
454       optnum = n_strtol(optval, NULL, 0);
455       if(n_strcasecmp(optval, "false") == 0
456          || n_strcasecmp(optval, "f") == 0)
457         optnum = FALSE;
458       if(n_strcasecmp(optval, "true") == 0
459          || n_strcasecmp(optval, "t") == 0)
460         optnum = TRUE;
461
462       for(n = 0; n < sizeof(options) / sizeof(*options); n++) {
463         if(n_strcmp(options[n].longname, optname) == 0) {
464           switch(options[n].type) {
465           case option_flag:
466           case option_number:
467             options[n].int_func(optnum);
468             break;
469           case option_file:
470             options[n].str_func(startup_open(optval));
471             break;
472           case option_wfile:
473             options[n].str_func(startup_wopen(optval));
474             break;
475           case option_string:
476             options[n].string_func(optval);
477             break;
478           }
479           break;
480         }
481       }
482     }
483   }
484   glk_stream_close(pref, NULL);
485 }
486
487 #line 910 "opt2glkc.pl"
488 static void show_help(void)
489 {
490   unsigned n;
491   printf("Usage: nitfol [OPTIONS] gamefile\n");
492   for(n = 0; n < sizeof(options) / sizeof(*options); n++) {
493     if(options[n].shortname != '-')
494       printf(" -%c, ", options[n].shortname);
495     else
496       printf("     ");
497     printf("-%-15s %s\n", options[n].longname, options[n].description);
498   }
499 }
500
501 #line 928 "opt2glkc.pl"
502 static BOOL parse_commands(int argc, char **argv)
503 {
504   int i;
505   unsigned n;
506
507   for(i = 1; i < argc; i++) {
508     BOOL flag = TRUE;
509
510     const char *p = argv[i];
511     
512     if(p[0] == '-') {
513       BOOL found = FALSE;
514
515       while(*p == '-')
516         p++;
517       if(n_strncmp(p, "no-", 3) == 0) {
518         flag = FALSE;
519         p+=3;
520       }
521
522       if(n_strcasecmp(p, "help") == 0) {
523         show_help();
524         exit(0);
525       }
526       if(n_strcasecmp(p, "version") == 0) {
527         printf("nitfol version %d.%d\n", NITFOL_MAJOR, NITFOL_MINOR);
528         exit(0);
529       }
530       
531       for(n = 0; n < sizeof(options) / sizeof(*options); n++) {
532         if((n_strlen(p) == 1 && *p == options[n].shortname) ||
533            n_strcmp(options[n].longname, p) == 0) {
534           found = TRUE;
535
536           switch(options[n].type) {
537           case option_flag:
538             options[n].int_func(flag);
539             break;
540
541           case option_file:
542             i++;
543             options[n].str_func(startup_open(argv[i]));
544             break;
545
546           case option_wfile:
547             i++;
548             options[n].str_func(startup_wopen(argv[i]));
549             break;
550
551           case option_number:
552             i++;
553             options[n].int_func(n_strtol(argv[i], NULL, 0));
554             break;
555
556           case option_string:
557             i++;
558             options[n].string_func(argv[i]);
559             break;
560           }
561         }
562       }
563
564       if(!found)
565         return FALSE;
566
567     } else {
568       strid_t s = startup_open(argv[i]);
569       if(!s)
570         return FALSE;
571       if(!game_use_file(s))
572         return FALSE;
573     }
574   }
575
576   return TRUE;
577 }
578
579 #line 415 "opt2glkc.pl"
580
581 #ifdef DEBUGGING
582 static void sighandle(int unused);
583
584 static void sighandle(int unused)
585 {
586 /*  signal(SIGINT, sighandle); */ /* SysV resets default behaviour - foil it */
587   enter_debugger = TRUE;
588 }
589 #endif
590
591 #ifdef __cplusplus
592 extern "C" {
593 #endif
594 int glkunix_startup_code(glkunix_startup_t *data)
595 {
596   strid_t pref;
597   const char *configname;
598   char *configdir, *prefname;
599   char *execname;
600   char *p;
601   username = getenv("LOGNAME");   /* SysV */
602   if(!username)
603     username = getenv("USER");    /* BSD */
604
605 #ifdef DEBUGGING
606 /*  signal(SIGINT, sighandle); */
607 #endif
608
609   execname = n_strrchr(data->argv[0], '/');
610
611   if(execname)
612     execname++;
613   else
614     execname = data->argv[0];
615   
616   set_defaults();
617   configdir = n_strdup(data->argv[0]); if(n_strrchr(configdir, '/')) *n_strrchr(configdir, '/') = 0;
618   configname = "/nitfol.cfg";
619   prefname = n_malloc(n_strlen(configdir) + n_strlen(configname) + 1);
620   n_strcpy(prefname, configdir);
621   n_strcat(prefname, configname);
622   pref = glkunix_stream_open_pathname(prefname, fileusage_Data | fileusage_TextMode, 0);
623   n_free(configdir);
624   n_free(prefname);
625   read_textpref(pref, execname);
626   
627   p = getenv("INFOCOM_PATH");
628   if(p) {
629     free(search_path);
630     search_path = n_strdup(p);
631   }
632
633   return parse_commands(data->argc, data->argv);
634 }
635 #ifdef __cplusplus
636 }
637 #endif