makestrs.c revision a773ec55
1/*
2
3Copyright (c) 1991, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27/* Constructs string definitions */
28
29#include <stdio.h>
30#include <string.h>
31#include <stdlib.h>
32#include <unistd.h>
33
34typedef struct _TableEnt {
35    struct _TableEnt *next;
36    char *left;
37    char *right;
38    size_t offset;
39} TableEnt;
40
41typedef struct _Table {
42    struct _Table *next;
43    TableEnt *tableent;
44    TableEnt *tableentcurrent;
45    TableEnt **tableenttail;
46    char *name;
47    size_t offset;
48} Table;
49
50typedef struct _File {
51    struct _File *next;
52    FILE *tmpl;
53    char *name;
54    Table *table;
55    Table *tablecurrent;
56    Table **tabletail;
57} File;
58
59static File *file = NULL;
60static File *filecurrent = NULL;
61static File **filetail = &file;
62static char *conststr;
63static char *prefixstr = NULL;
64static char *featurestr = NULL;
65static char *ctmplstr = NULL;
66static char *fileprotstr;
67static char *externrefstr;
68static char *externdefstr;
69
70#ifndef FALSE
71#define FALSE 0
72#define TRUE  !(FALSE)
73#endif
74
75static int solaris_abi_names = FALSE;
76
77#define X_DEFAULT_ABI   0
78#define X_ARRAYPER_ABI  1
79#define X_INTEL_ABI     2
80#define X_INTEL_ABI_BC  3
81#define X_SPARC_ABI     4
82#define X_FUNCTION_ABI  5
83
84#define X_MAGIC_STRING "<<<STRING_TABLE_GOES_HERE>>>"
85
86/* Wrapper for fopen()
87 * Prepend filename with an includedir which can be specified on the
88 * commandline. Needed to separate source and build directories.
89 */
90static char *includedir = NULL;
91static FILE *
92ifopen(const char *myfile, const char *mode)
93{
94#ifndef HAVE_ASPRINTF
95    size_t len;
96#endif
97    char *buffer;
98    FILE *ret;
99
100    if (includedir == NULL)
101        return fopen(myfile, mode);
102
103#ifdef HAVE_ASPRINTF
104    if (asprintf(&buffer, "%s/%s", includedir, myfile) == -1)
105        return NULL;
106#else
107    len = strlen(myfile) + strlen(includedir) + 1;
108    buffer = (char *) malloc(len + 1);
109    if (buffer == NULL)
110        return NULL;
111
112    snprintf(buffer, len + 1, "%s/%s", includedir, myfile);
113#endif
114
115    ret = fopen(buffer, mode);
116
117    free(buffer);
118    return ret;
119}
120
121static void
122WriteHeaderProlog(FILE * f, File * phile)
123{
124    Table *t;
125    TableEnt *te;
126
127    (void) fprintf(f, "#ifdef %s\n", featurestr);
128    for (t = phile->table; t; t = t->next) {
129        for (te = t->tableent; te; te = te->next) {
130            if (strcmp(te->left, "RAtom") == 0) {
131                (void) fprintf(f,
132                               "#ifndef %s%s\n#define %s%s \"%s\"\n#endif\n",
133                               prefixstr, te->left, prefixstr, te->left,
134                               te->right);
135            }
136            else {
137                (void) fprintf(f,
138                               "#define %s%s \"%s\"\n",
139                               prefixstr, te->left, te->right);
140            }
141        }
142    }
143    (void) fprintf(f, "%s", "#else\n");
144}
145
146static void
147IntelABIWriteHeader(FILE * f, File * phile)
148{
149    Table *t;
150    TableEnt *te;
151
152    WriteHeaderProlog(f, phile);
153
154    for (t = phile->table; t; t = t->next) {
155        (void) fprintf(f, "%s %sConst char %s[];\n",
156                       externrefstr, conststr ? conststr : fileprotstr,
157                       t->name);
158        for (te = t->tableent; te; te = te->next) {
159            (void) fprintf(f,
160                           "#ifndef %s%s\n#define %s%s ((String)&%s[%lu])\n#endif\n",
161                           prefixstr, te->left, prefixstr, te->left, t->name,
162                           (unsigned long) te->offset);
163        }
164    }
165
166    (void) fprintf(f, "#endif /* %s */\n", featurestr);
167}
168
169static void
170SPARCABIWriteHeader(FILE * f, File * phile)
171{
172    Table *t;
173    TableEnt *te;
174
175    for (t = phile->table; t; t = t->next) {
176        for (te = t->tableent; te; te = te->next) {
177            (void) fprintf(f, "#define %s%s \"%s\"\n",
178                           prefixstr, te->left, te->right);
179        }
180    }
181}
182
183static void
184FunctionWriteHeader(FILE * f, File * phile)
185{
186    Table *t;
187    TableEnt *te;
188
189    WriteHeaderProlog(f, phile);
190
191    (void) fprintf(f, "%s %sConst char* %s();\n",
192                   externrefstr, conststr ? conststr : fileprotstr,
193                   phile->table->name);
194
195    for (t = phile->table; t; t = t->next) {
196        for (te = t->tableent; te; te = te->next) {
197            (void) fprintf(f,
198                           "#ifndef %s%s\n#define %s%s (%s(%lu))\n#endif\n",
199                           prefixstr, te->left, prefixstr, te->left,
200                           phile->table->name, (unsigned long) te->offset);
201        }
202    }
203
204    (void) fprintf(f, "#endif /* %s */\n", featurestr);
205}
206
207static void
208ArrayperWriteHeader(FILE * f, File * phile)
209{
210    Table *t;
211    TableEnt *te;
212
213    WriteHeaderProlog(f, phile);
214
215    for (t = phile->table; t; t = t->next) {
216        for (te = t->tableent; te; te = te->next) {
217            (void) fprintf(f,
218                           "#ifndef %s%s\n%s %sConst char %s%s[];\n#endif\n",
219                           prefixstr, te->left,
220                           externrefstr, conststr ? conststr : fileprotstr,
221                           prefixstr, te->left);
222        }
223    }
224
225    (void) fprintf(f, "#endif /* %s */\n", featurestr);
226}
227
228static void
229DefaultWriteHeader(FILE * f, File * phile)
230{
231    Table *t;
232    TableEnt *te;
233
234    WriteHeaderProlog(f, phile);
235
236    (void) fprintf(f, "%s %sConst char %s[];\n",
237                   externrefstr, conststr ? conststr : fileprotstr,
238                   phile->table->name);
239
240    for (t = phile->table; t; t = t->next) {
241        for (te = t->tableent; te; te = te->next) {
242            (void) fprintf(f,
243                           "#ifndef %s%s\n#define %s%s ((String)&%s[%lu])\n#endif\n",
244                           prefixstr, te->left, prefixstr, te->left,
245                           phile->table->name, (unsigned long) te->offset);
246        }
247    }
248
249    (void) fprintf(f, "#endif /* %s */\n", featurestr);
250}
251
252static void
253CopyTmplProlog(FILE * tmpl, FILE * f)
254{
255    char buf[1024];
256    static const char *magic_string = X_MAGIC_STRING;
257    size_t magic_string_len = strlen(magic_string);
258
259    while (fgets(buf, sizeof buf, tmpl)) {
260        if (strncmp(buf, magic_string, magic_string_len) == 0) {
261            return;
262        }
263        (void) fputs(buf, f);
264    }
265}
266
267static void
268CopyTmplEpilog(FILE * tmpl, FILE * f)
269{
270    char buf[1024];
271
272    while (fgets(buf, sizeof buf, tmpl))
273        (void) fputs(buf, f);
274}
275
276static const char *abistring[] = {
277    "Default", "Array per string", "Intel", "Intel BC", "SPARC", "Function"
278};
279
280static void
281WriteHeader(char *tagline, File * phile, int abi)
282{
283    FILE *f;
284    char *tmp;
285
286    static void (*headerproc[]) (FILE * f, File * phile) = {
287    DefaultWriteHeader, ArrayperWriteHeader,
288            IntelABIWriteHeader, IntelABIWriteHeader,
289            SPARCABIWriteHeader, FunctionWriteHeader};
290
291    if ((f = fopen(phile->name, "w+")) == NULL)
292        exit(1);
293
294    if (phile->tmpl)
295        CopyTmplProlog(phile->tmpl, f);
296
297    (void) fprintf(f,
298                   "%s\n%s\n/* %s ABI version -- Do not edit */\n",
299                   "/* $Xorg: makestrs.c,v 1.6 2001/02/09 02:03:17 xorgcvs Exp $ */",
300                   "/* This file is automatically generated. */",
301                   abistring[abi]);
302
303    if (tagline)
304        (void) fprintf(f, "/* %s */\n\n", tagline);
305
306    /* do the right thing for Motif, i.e. avoid _XmXmStrDefs_h_ */
307    if (strcmp(prefixstr, "Xm") == 0) {
308#ifdef HAVE_ASPRINTF
309        if (asprintf(&fileprotstr, "_%s_", phile->name) == -1)
310            exit(1);
311#else
312        if ((fileprotstr = malloc(strlen(phile->name) + 3)) == NULL)
313            exit(1);
314        (void) sprintf(fileprotstr, "_%s_", phile->name);
315#endif
316    }
317    else {
318#ifdef HAVE_ASPRINTF
319        if (asprintf(&fileprotstr, "_%s%s_", prefixstr, phile->name) == -1)
320            exit(1);
321#else
322        if ((fileprotstr =
323             malloc(strlen(phile->name) + strlen(prefixstr) + 3)) == NULL)
324            exit(1);
325        (void) sprintf(fileprotstr, "_%s%s_", prefixstr, phile->name);
326#endif
327    }
328
329    for (tmp = fileprotstr; *tmp; tmp++)
330        if (*tmp == '.')
331            *tmp = '_';
332
333    (*headerproc[abi]) (f, phile);
334
335    if (phile->tmpl)
336        CopyTmplEpilog(phile->tmpl, f);
337
338    (void) free(fileprotstr);
339    (void) fclose(phile->tmpl);
340    (void) fclose(f);
341}
342
343static void
344WriteSourceLine(TableEnt * te, int abi, int fudge)
345{
346    char *c;
347
348    (void) abi;
349    for (c = te->right; *c; c++)
350        (void) printf("'%c',", *c);
351    (void) printf("%c", '0');
352    if (te->next || fudge)
353        (void) printf("%c", ',');
354    (void) printf("%s", "\n");
355}
356
357#define const_string "%s %sConst char %s[] = {\n"
358
359static void
360IntelABIWriteSource(int abi)
361{
362    File *phile;
363
364    for (phile = file; phile; phile = phile->next) {
365        Table *t;
366        TableEnt *te;
367
368        for (t = phile->table; t; t = t->next) {
369            (void) printf(const_string, externdefstr,
370                          conststr ? conststr : "", t->name);
371            for (te = t->tableent; te; te = te->next) {
372                WriteSourceLine(te, abi, 0);
373            }
374            (void) printf("%s\n\n", "};");
375        }
376    }
377}
378
379static void
380IntelABIBCWriteSource(int abi)
381{
382    File *phile;
383
384    for (phile = file; phile; phile = phile->next) {
385        Table *t;
386        TableEnt *te;
387
388        (void) printf(const_string, externdefstr,
389                      conststr ? conststr : "", phile->table->name);
390
391        for (t = phile->table; t; t = t->next) {
392            for (te = t->tableent; te; te = te->next) {
393                WriteSourceLine(te, abi, t->next ? 1 : 0);
394            }
395        }
396        (void) printf("%s\n\n", "};");
397
398        if (phile->table->next) {
399            (void) printf(const_string, externdefstr,
400                          conststr ? conststr : "", phile->table->next->name);
401            for (t = phile->table->next; t; t = t->next) {
402                for (te = t->tableent; te; te = te->next) {
403                    WriteSourceLine(te, abi, 0);
404                }
405            }
406            (void) printf("%s\n\n", "};");
407        }
408    }
409}
410
411static void
412FunctionWriteSource(int abi)
413{
414    File *phile;
415
416    for (phile = file; phile; phile = phile->next) {
417        Table *t;
418        TableEnt *te;
419
420        (void) printf("static %sConst char _%s[] = {\n",
421                      conststr ? conststr : "", phile->table->name);
422
423        for (t = phile->table; t; t = t->next) {
424            for (te = t->tableent; te; te = te->next) {
425                WriteSourceLine(te, abi, t->next ? 1 : 0);
426            }
427        }
428        (void) printf("%s\n\n", "};");
429
430        (void)
431            printf
432            ("%sConst char* %s(index)\n    int index;\n{\n    return &_%s[index];\n}\n\n",
433             conststr ? conststr : "", phile->table->name, phile->table->name);
434    }
435}
436
437static void
438ArrayperWriteSource(int abi)
439{
440    File *phile;
441    static int done_atom;
442
443    (void) abi;
444    for (phile = file; phile; phile = phile->next) {
445        Table *t;
446        TableEnt *te;
447
448        for (t = phile->table; t; t = t->next) {
449            for (te = t->tableent; te; te = te->next) {
450                if (strcmp(te->left, "RAtom") == 0) {
451                    if (done_atom)
452                        return;
453                    done_atom = 1;
454                }
455                (void) printf("%s %sConst char %s%s[] = \"%s\";\n",
456                              externdefstr, conststr ? conststr : "",
457                              prefixstr, te->left, te->right);
458            }
459        }
460    }
461}
462
463static void
464DefaultWriteSource(int abi)
465{
466    File *phile;
467
468    for (phile = file; phile; phile = phile->next) {
469        Table *t;
470        TableEnt *te;
471
472        (void) printf(const_string, externdefstr, conststr ? conststr : "",
473                      phile->table->name);
474
475        for (t = phile->table; t; t = t->next) {
476            for (te = t->tableent; te; te = te->next) {
477                WriteSourceLine(te, abi, t->next ? 1 : 0);
478            }
479        }
480        (void) printf("%s\n\n", "};");
481    }
482}
483
484static void
485WriteSource(char *tagline, int abi)
486{
487    static void (*sourceproc[]) (int) = {
488    DefaultWriteSource, ArrayperWriteSource,
489            IntelABIWriteSource, IntelABIBCWriteSource,
490            DefaultWriteSource, FunctionWriteSource};
491
492    FILE *tmpl;
493
494    if (ctmplstr) {
495        tmpl = ifopen(ctmplstr, "r");
496
497        if (tmpl)
498            CopyTmplProlog(tmpl, stdout);
499        else {
500            (void) fprintf(stderr, "Expected template %s, not found\n",
501                           ctmplstr);
502            exit(1);
503        }
504    }
505    else
506        tmpl = NULL;
507
508    (void) printf("/* *%s* */\n", "INDENT-OFF");
509    (void) printf("%s\n%s\n/* %s ABI version -- Do not edit */\n",
510                  "/* $Xorg: makestrs.c,v 1.6 2001/02/09 02:03:17 xorgcvs Exp $ */",
511                  "/* This file is automatically generated. */",
512                  abistring[abi]);
513
514    if (tagline)
515        (void) printf("/* %s */\n\n", tagline);
516
517    (*sourceproc[abi]) (abi);
518
519    if (tmpl) {
520        CopyTmplEpilog(tmpl, stdout);
521        fclose(tmpl);
522    }
523    (void) printf("/* *%s* */\n", "INDENT-ON");
524}
525
526static void
527DoLine(char *buf)
528{
529#define X_NO_TOKEN 0
530#define X_FILE_TOKEN 1
531#define X_TABLE_TOKEN 2
532#define X_PREFIX_TOKEN 3
533#define X_FEATURE_TOKEN 4
534#define X_EXTERNREF_TOKEN 5
535#define X_EXTERNDEF_TOKEN 6
536#define X_CTMPL_TOKEN 7
537#define X_HTMPL_TOKEN 8
538#define X_CONST_TOKEN 9
539
540    int token;
541    char lbuf[1024];
542    static const char *file_str = "#file";
543    static const char *table_str = "#table";
544    static const char *prefix_str = "#prefix";
545    static const char *feature_str = "#feature";
546    static const char *externref_str = "#externref";
547    static const char *externdef_str = "#externdef";
548    static const char *ctmpl_str = "#ctmpl";
549    static const char *htmpl_str = "#htmpl";
550    static const char *const_str = "#const";
551
552    if (strncmp(buf, file_str, strlen(file_str)) == 0)
553        token = X_FILE_TOKEN;
554    else if (strncmp(buf, table_str, strlen(table_str)) == 0)
555        token = X_TABLE_TOKEN;
556    else if (strncmp(buf, prefix_str, strlen(prefix_str)) == 0)
557        token = X_PREFIX_TOKEN;
558    else if (strncmp(buf, feature_str, strlen(feature_str)) == 0)
559        token = X_FEATURE_TOKEN;
560    else if (strncmp(buf, externref_str, strlen(externref_str)) == 0)
561        token = X_EXTERNREF_TOKEN;
562    else if (strncmp(buf, externdef_str, strlen(externdef_str)) == 0)
563        token = X_EXTERNDEF_TOKEN;
564    else if (strncmp(buf, ctmpl_str, strlen(ctmpl_str)) == 0)
565        token = X_CTMPL_TOKEN;
566    else if (strncmp(buf, htmpl_str, strlen(htmpl_str)) == 0)
567        token = X_HTMPL_TOKEN;
568    else if (strncmp(buf, const_str, strlen(const_str)) == 0)
569        token = X_CONST_TOKEN;
570    else
571        token = X_NO_TOKEN;
572
573    switch (token) {
574    case X_FILE_TOKEN:
575    {
576        File *phile;
577
578        if ((phile = (File *) malloc(sizeof(File))) == NULL)
579            exit(1);
580        if ((phile->name = strdup(buf + strlen(file_str) + 1)) == NULL)
581            exit(1);
582        phile->table = NULL;
583        phile->tablecurrent = NULL;
584        phile->tabletail = &phile->table;
585        phile->next = NULL;
586        phile->tmpl = NULL;
587
588        *filetail = phile;
589        filetail = &phile->next;
590        filecurrent = phile;
591    }
592        break;
593    case X_TABLE_TOKEN:
594    {
595        Table *table;
596
597        if ((table = (Table *) malloc(sizeof(Table))) == NULL)
598            exit(1);
599        if ((table->name = strdup(buf + strlen(table_str) + 1)) == NULL)
600            exit(1);
601        if (solaris_abi_names) {
602            if (strcmp(table->name, "XtStringsR6") == 0) {
603                strcpy(table->name, "XtR6Strings");
604            }
605            else if (strcmp(table->name, "XtShellStringsR6") == 0) {
606                strcpy(table->name, "XtR6ShellStrings");
607            }
608        }
609        table->tableent = NULL;
610        table->tableentcurrent = NULL;
611        table->tableenttail = &table->tableent;
612        table->next = NULL;
613        table->offset = 0;
614
615        *filecurrent->tabletail = table;
616        filecurrent->tabletail = &table->next;
617        filecurrent->tablecurrent = table;
618    }
619        break;
620    case X_PREFIX_TOKEN:
621        if ((prefixstr = strdup(buf + strlen(prefix_str) + 1)) == NULL)
622            exit(1);
623        break;
624    case X_FEATURE_TOKEN:
625        if ((featurestr = strdup(buf + strlen(feature_str) + 1)) == NULL)
626            exit(1);
627        break;
628    case X_EXTERNREF_TOKEN:
629        if ((externrefstr = strdup(buf + strlen(externref_str) + 1)) == NULL)
630            exit(1);
631        break;
632    case X_EXTERNDEF_TOKEN:
633        if ((externdefstr = strdup(buf + strlen(externdef_str) + 1)) == NULL)
634            exit(1);
635        break;
636    case X_CTMPL_TOKEN:
637        if ((ctmplstr = strdup(buf + strlen(ctmpl_str) + 1)) == NULL)
638            exit(1);
639        break;
640    case X_HTMPL_TOKEN:
641        if ((filecurrent->tmpl =
642             ifopen(buf + strlen(htmpl_str) + 1, "r")) == NULL) {
643            (void) fprintf(stderr, "Expected template %s, not found\n",
644                           htmpl_str);
645            exit(1);
646        }
647        break;
648    case X_CONST_TOKEN:
649        if ((conststr = strdup(buf + strlen(const_str) + 1)) == NULL)
650            exit(1);
651        break;
652    default:
653    {
654        char *right;
655        TableEnt *tableent;
656        size_t llen;
657        size_t rlen;
658        size_t len;
659
660        if ((right = strchr(buf, ' ')))
661            *right++ = 0;
662        else
663            right = buf + 1;
664        if (buf[0] == 'H') {
665            snprintf(lbuf, sizeof(lbuf), "%s%s", prefixstr, right);
666            right = lbuf;
667        }
668
669        llen = len = strlen(buf) + 1;
670        rlen = strlen(right) + 1;
671        if (right != buf + 1)
672            len += rlen;
673        tableent = (TableEnt *) calloc(sizeof(TableEnt) + len, 1);
674        if (tableent == NULL)
675            exit(1);
676        tableent->left = (char *) (tableent + 1);
677        strcpy(tableent->left, buf);
678        if (llen != len) {
679            tableent->right = tableent->left + llen;
680            strcpy(tableent->right, right);
681        }
682        else {
683            tableent->right = tableent->left + 1;
684        }
685        tableent->next = NULL;
686
687        *filecurrent->tablecurrent->tableenttail = tableent;
688        filecurrent->tablecurrent->tableenttail = &tableent->next;
689        filecurrent->tablecurrent->tableentcurrent = tableent;
690    }
691        break;
692    }
693}
694
695static void
696IntelABIIndexEntries(File * myfile)
697{
698    Table *t;
699    TableEnt *te;
700
701    for (t = myfile->table; t; t = t->next) {
702        for (te = t->tableent; te; te = te->next) {
703            te->offset = t->offset;
704            t->offset += strlen(te->right);
705            t->offset++;
706        }
707    }
708}
709
710static void
711DefaultIndexEntries(File * myfile)
712{
713    Table *t;
714    TableEnt *te;
715    size_t offset = 0;
716
717    for (t = myfile->table; t; t = t->next) {
718        for (te = t->tableent; te; te = te->next) {
719            te->offset = offset;
720            offset += strlen(te->right);
721            offset++;
722        }
723    }
724}
725
726static void
727IndexEntries(File * myfile, int abi)
728{
729    switch (abi) {
730    case X_SPARC_ABI:
731        break;
732    case X_INTEL_ABI:
733    case X_INTEL_ABI_BC:
734        IntelABIIndexEntries(myfile);
735        break;
736    default:
737        DefaultIndexEntries(myfile);
738        break;
739    }
740}
741
742static char *
743DoComment(char *line)
744{
745    char *tag;
746    char *eol;
747    char *ret;
748    size_t len;
749
750    /* assume that the first line with two '$' in it is the RCS tag line */
751    if ((tag = strchr(line, '$')) == NULL)
752        return NULL;
753    if ((eol = strchr(tag + 1, '$')) == NULL)
754        return NULL;
755    len = (size_t) (eol - tag);
756    if ((ret = malloc(len)) == NULL)
757        exit(1);
758    (void) strncpy(ret, tag + 1, len - 1);
759    ret[len - 2] = 0;
760    return ret;
761}
762
763int
764main(int argc, char *argv[])
765{
766    size_t len;
767    char *tagline = NULL;
768    File *phile;
769    FILE *f;
770    char buf[1024];
771    int abi =
772#ifndef ARRAYPERSTR
773        X_DEFAULT_ABI;
774#else
775        X_ARRAYPER_ABI;
776#endif
777
778    f = stdin;
779    if (argc > 1) {
780        int i;
781
782        for (i = 1; i < argc; i++) {
783            if (strcmp(argv[i], "-f") == 0) {
784                if (++i < argc)
785                    f = fopen(argv[i], "r");
786                else
787                    return 1;
788            }
789            if (strcmp(argv[i], "-i") == 0) {
790                if (++i < argc) {
791                    includedir = argv[i];
792                }
793                else {
794                    if (f != 0 && f != stdin)
795                        fclose(f);
796                    return 1;
797                }
798            }
799            if (strcmp(argv[i], "-sparcabi") == 0)
800                abi = X_SPARC_ABI;
801            if (strcmp(argv[i], "-intelabi") == 0)
802                abi = X_INTEL_ABI;
803            if (strcmp(argv[i], "-functionabi") == 0)
804                abi = X_FUNCTION_ABI;
805            if (strcmp(argv[i], "-earlyR6bc") == 0 && abi == X_INTEL_ABI)
806                abi = X_INTEL_ABI_BC;
807            if (strcmp(argv[i], "-arrayperabi") == 0)
808                abi = X_ARRAYPER_ABI;
809#ifdef ARRAYPERSTR
810            if (strcmp(argv[i], "-defaultabi") == 0)
811                abi = X_DEFAULT_ABI;
812#endif
813            if (strcmp(argv[i], "-solarisabinames") == 0)
814                solaris_abi_names = TRUE;
815        }
816    }
817
818    if (f == NULL)
819        return 1;
820    while (fgets(buf, sizeof buf, f)) {
821        if (!buf[0] || buf[0] == '\n')
822            continue;
823        if (buf[0] == '!') {
824            if (tagline)
825                continue;
826            tagline = DoComment(buf);
827            continue;
828        }
829        if (buf[(len = strlen(buf) - 1)] == '\n')
830            buf[len] = '\0';
831        DoLine(buf);
832    }
833    for (phile = file; phile; phile = phile->next) {
834        if (abi != X_ARRAYPER_ABI)
835            IndexEntries(phile, abi);
836        WriteHeader(tagline, phile, abi);
837    }
838    WriteSource(tagline, abi);
839    return 0;
840}
841