makestrs.c revision 72af6995
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 *ifopen(const char *myfile, const char *mode)
92{
93#ifndef HAVE_ASPRINTF
94    size_t len;
95#endif
96    char *buffer;
97    FILE *ret;
98
99    if (includedir == NULL)
100        return fopen(myfile, mode);
101
102#ifdef HAVE_ASPRINTF
103    if (asprintf(&buffer, "%s/%s", includedir, myfile) == -1)
104        return NULL;
105#else
106    len = strlen(myfile) + strlen(includedir) + 1;
107    buffer = (char*)malloc(len + 1);
108    if (buffer == NULL)
109        return NULL;
110
111    snprintf(buffer, len + 1, "%s/%s", includedir, myfile);
112#endif
113
114    ret = fopen(buffer, mode);
115
116    free(buffer);
117    return ret;
118}
119
120static void WriteHeaderProlog (FILE *f, File *phile)
121{
122    Table* t;
123    TableEnt* te;
124
125    (void) fprintf (f, "#ifdef %s\n", featurestr);
126    for (t = phile->table; t; t = t->next) {
127	for (te = t->tableent; te; te = te->next) {
128	    if (strcmp (te->left, "RAtom") == 0) {
129		(void) fprintf (f,
130			"#ifndef %s%s\n#define %s%s \"%s\"\n#endif\n",
131			prefixstr, te->left, prefixstr, te->left, te->right);
132	    } else {
133		(void) fprintf (f,
134			"#define %s%s \"%s\"\n",
135			prefixstr, te->left, te->right);
136	    }
137	}
138    }
139    (void) fprintf (f, "%s", "#else\n");
140}
141
142static void IntelABIWriteHeader (FILE *f, File *phile)
143{
144    Table* t;
145    TableEnt* te;
146
147    WriteHeaderProlog (f, phile);
148
149    for (t = phile->table; t; t = t->next) {
150      (void) fprintf (f, "%s %sConst char %s[];\n",
151		      externrefstr, conststr ? conststr : fileprotstr, t->name);
152	for (te = t->tableent; te; te = te->next) {
153	    (void) fprintf (f,
154		"#ifndef %s%s\n#define %s%s ((String)&%s[%lu])\n#endif\n",
155		prefixstr, te->left, prefixstr, te->left, t->name,
156		(unsigned long) te->offset);
157	}
158    }
159
160    (void) fprintf (f, "#endif /* %s */\n", featurestr);
161}
162
163static void SPARCABIWriteHeader (FILE *f, File *phile)
164{
165    Table* t;
166    TableEnt* te;
167
168    for (t = phile->table; t; t = t->next) {
169	for (te = t->tableent; te; te = te->next) {
170	    (void) fprintf (f, "#define %s%s \"%s\"\n",
171			    prefixstr, te->left, te->right);
172	}
173    }
174}
175
176static void FunctionWriteHeader (FILE *f, File *phile)
177{
178    Table* t;
179    TableEnt* te;
180
181    WriteHeaderProlog (f, phile);
182
183    (void) fprintf (f, "%s %sConst char* %s();\n",
184		    externrefstr, conststr ? conststr : fileprotstr,
185		    phile->table->name);
186
187    for (t = phile->table; t; t = t->next) {
188	for (te = t->tableent; te; te = te->next) {
189	    (void) fprintf (f,
190		"#ifndef %s%s\n#define %s%s (%s(%lu))\n#endif\n",
191		prefixstr, te->left, prefixstr, te->left, phile->table->name,
192		(unsigned long) te->offset);
193	}
194    }
195
196    (void) fprintf (f, "#endif /* %s */\n", featurestr);
197}
198
199static void ArrayperWriteHeader (FILE *f, File *phile)
200{
201    Table* t;
202    TableEnt* te;
203
204    WriteHeaderProlog (f, phile);
205
206    for (t = phile->table; t; t = t->next) {
207        for (te = t->tableent; te; te = te->next) {
208	    (void) fprintf (f,
209			    "#ifndef %s%s\n%s %sConst char %s%s[];\n#endif\n",
210			    prefixstr, te->left,
211			    externrefstr, conststr ? conststr : fileprotstr,
212			    prefixstr, te->left);
213	}
214    }
215
216    (void) fprintf (f, "#endif /* %s */\n", featurestr);
217}
218
219static void DefaultWriteHeader (FILE *f, File *phile)
220{
221    Table* t;
222    TableEnt* te;
223
224    WriteHeaderProlog (f, phile);
225
226    (void) fprintf (f, "%s %sConst char %s[];\n",
227		    externrefstr, conststr ? conststr : fileprotstr,
228		    phile->table->name);
229
230    for (t = phile->table; t; t = t->next) {
231	for (te = t->tableent; te; te = te->next) {
232	    (void) fprintf (f,
233		"#ifndef %s%s\n#define %s%s ((String)&%s[%lu])\n#endif\n",
234		prefixstr, te->left, prefixstr, te->left, phile->table->name,
235		(unsigned long) te->offset);
236	}
237    }
238
239    (void) fprintf (f, "#endif /* %s */\n", featurestr);
240}
241
242static void CopyTmplProlog (FILE *tmpl, FILE *f)
243{
244    char buf[1024];
245    static const char* magic_string = X_MAGIC_STRING;
246    size_t magic_string_len = strlen (magic_string);
247
248    while (fgets (buf, sizeof buf, tmpl)) {
249	if (strncmp (buf, magic_string, magic_string_len) == 0) {
250	    return;
251	}
252	(void) fputs (buf, f);
253    }
254}
255
256static void CopyTmplEpilog (FILE *tmpl, FILE *f)
257{
258    char buf[1024];
259
260    while (fgets (buf, sizeof buf, tmpl))
261	(void) fputs (buf, f);
262}
263
264static const char* abistring[] = {
265    "Default", "Array per string", "Intel", "Intel BC", "SPARC", "Function" };
266
267static void WriteHeader (char *tagline, File *phile, int abi)
268{
269    FILE* f;
270    char* tmp;
271    static void (*headerproc[])(FILE *f, File *phile) = {
272	DefaultWriteHeader, ArrayperWriteHeader,
273	IntelABIWriteHeader, IntelABIWriteHeader,
274	SPARCABIWriteHeader, FunctionWriteHeader };
275
276    if ((f = fopen (phile->name, "w+")) == NULL) exit (1);
277
278    if (phile->tmpl) CopyTmplProlog (phile->tmpl, f);
279
280    (void) fprintf (f,
281	"%s\n%s\n/* %s ABI version -- Do not edit */\n",
282	"/* $Xorg: makestrs.c,v 1.6 2001/02/09 02:03:17 xorgcvs Exp $ */",
283	"/* This file is automatically generated. */",
284	abistring[abi]);
285
286    if (tagline) (void) fprintf (f, "/* %s */\n\n", tagline);
287
288    /* do the right thing for Motif, i.e. avoid _XmXmStrDefs_h_ */
289    if (strcmp (prefixstr, "Xm") == 0) {
290#ifdef HAVE_ASPRINTF
291	if (asprintf (&fileprotstr, "_%s_", phile->name) == -1)
292	    exit (1);
293#else
294	if ((fileprotstr = malloc (strlen (phile->name) + 3)) == NULL)
295	   exit (1);
296	(void) sprintf (fileprotstr, "_%s_", phile->name);
297#endif
298    } else {
299#ifdef HAVE_ASPRINTF
300	if (asprintf (&fileprotstr, "_%s%s_", prefixstr, phile->name) == -1)
301	    exit (1);
302#else
303	if ((fileprotstr = malloc (strlen (phile->name) + strlen (prefixstr) +  3)) == NULL)
304	   exit (1);
305	(void) sprintf (fileprotstr, "_%s%s_", prefixstr, phile->name);
306#endif
307    }
308
309    for (tmp = fileprotstr; *tmp; tmp++) if (*tmp == '.') *tmp = '_';
310
311    (*headerproc[abi])(f, phile);
312
313    if (phile->tmpl) CopyTmplEpilog (phile->tmpl, f);
314
315    (void) free (fileprotstr);
316    (void) fclose (phile->tmpl);
317    (void) fclose (f);
318}
319
320static void WriteSourceLine (TableEnt *te, int abi, int fudge)
321{
322    char* c;
323
324    for (c = te->right; *c; c++) (void) printf ("'%c',", *c);
325    (void) printf ("%c", '0');
326    if (te->next || fudge) (void) printf ("%c", ',');
327    (void) printf ("%s", "\n");
328}
329
330#define const_string "%s %sConst char %s[] = {\n"
331
332static void IntelABIWriteSource (int abi)
333{
334    File* phile;
335
336    for (phile = file; phile; phile = phile->next) {
337	Table* t;
338	TableEnt* te;
339
340	for (t = phile->table; t; t = t->next) {
341	    (void) printf (const_string, externdefstr,
342			   conststr ? conststr : "", t->name);
343	    for (te = t->tableent; te; te = te->next) {
344		WriteSourceLine (te, abi, 0);
345	    }
346	    (void) printf ("%s\n\n", "};");
347	}
348    }
349}
350
351static void IntelABIBCWriteSource (int abi)
352{
353    File* phile;
354
355    for (phile = file; phile; phile = phile->next) {
356	Table* t;
357	TableEnt* te;
358
359	(void) printf (const_string, externdefstr,
360		       conststr ? conststr : "", phile->table->name);
361
362	for (t = phile->table; t; t = t->next) {
363	    for (te = t->tableent; te; te = te->next) {
364		WriteSourceLine (te, abi, t->next ? 1 : 0);
365	    }
366	}
367	(void) printf ("%s\n\n", "};");
368
369	if (phile->table->next) {
370	    (void) printf (const_string, externdefstr,
371			   conststr ? conststr : "", phile->table->next->name);
372	    for (t = phile->table->next; t; t = t->next) {
373		for (te = t->tableent; te; te = te->next) {
374		    WriteSourceLine (te, abi, 0);
375		}
376	    }
377	    (void) printf ("%s\n\n", "};");
378	}
379    }
380}
381
382static void FunctionWriteSource (int abi)
383{
384    File* phile;
385
386    for (phile = file; phile; phile = phile->next) {
387	Table* t;
388	TableEnt* te;
389
390	(void) printf ("static %sConst char _%s[] = {\n",
391		       conststr ? conststr : "", phile->table->name);
392
393	for (t = phile->table; t; t = t->next) {
394	    for (te = t->tableent; te; te = te->next) {
395		WriteSourceLine (te, abi, t->next ? 1 : 0);
396	    }
397	}
398	(void) printf ("%s\n\n", "};");
399
400	(void) printf ("%sConst char* %s(index)\n    int index;\n{\n    return &_%s[index];\n}\n\n",
401		       conststr ? conststr : "",
402		       phile->table->name, phile->table->name);
403    }
404}
405
406static void ArrayperWriteSource (int abi)
407{
408    File* phile;
409    static int done_atom;
410
411    for (phile = file; phile; phile = phile->next) {
412	Table* t;
413	TableEnt* te;
414
415	for (t = phile->table; t; t = t->next) {
416	    for (te = t->tableent; te; te = te->next) {
417		if (strcmp (te->left, "RAtom") == 0) {
418		    if (done_atom) return;
419		    done_atom = 1;
420		}
421		(void) printf ("%s %sConst char %s%s[] = \"%s\";\n",
422			       externdefstr, conststr ? conststr : "",
423			       prefixstr,
424			       te->left, te->right);
425	    }
426	}
427    }
428}
429
430static void DefaultWriteSource (int abi)
431{
432    File* phile;
433
434    for (phile = file; phile; phile = phile->next) {
435	Table* t;
436	TableEnt* te;
437
438	(void) printf (const_string, externdefstr, conststr ? conststr : "",
439		       phile->table->name);
440
441	for (t = phile->table; t; t = t->next) {
442	    for (te = t->tableent; te; te = te->next) {
443		WriteSourceLine (te, abi, t->next ? 1 : 0);
444	    }
445	}
446	(void) printf ("%s\n\n", "};");
447    }
448}
449
450static void WriteSource(char *tagline, int abi)
451{
452    static void (*sourceproc[])(int) = {
453	DefaultWriteSource, ArrayperWriteSource,
454	IntelABIWriteSource, IntelABIBCWriteSource,
455	DefaultWriteSource, FunctionWriteSource };
456
457    FILE* tmpl;
458
459    if (ctmplstr) {
460	tmpl = ifopen (ctmplstr, "r");
461
462	if (tmpl) CopyTmplProlog (tmpl, stdout);
463	else {
464	    (void) fprintf (stderr, "Expected template %s, not found\n",
465			    ctmplstr);
466	    exit (1);
467	}
468    } else
469	tmpl = NULL;
470
471
472    (void) printf ("%s\n%s\n/* %s ABI version -- Do not edit */\n",
473		   "/* $Xorg: makestrs.c,v 1.6 2001/02/09 02:03:17 xorgcvs Exp $ */",
474		   "/* This file is automatically generated. */",
475		   abistring[abi]);
476
477    if (tagline) (void) printf ("/* %s */\n\n", tagline);
478
479    (*sourceproc[abi])(abi);
480
481    if (tmpl) {
482	CopyTmplEpilog (tmpl, stdout);
483	fclose(tmpl);
484    }
485}
486
487static void DoLine(char *buf)
488{
489#define X_NO_TOKEN 0
490#define X_FILE_TOKEN 1
491#define X_TABLE_TOKEN 2
492#define X_PREFIX_TOKEN 3
493#define X_FEATURE_TOKEN 4
494#define X_EXTERNREF_TOKEN 5
495#define X_EXTERNDEF_TOKEN 6
496#define X_CTMPL_TOKEN 7
497#define X_HTMPL_TOKEN 8
498#define X_CONST_TOKEN 9
499
500    int token;
501    char lbuf[1024];
502    static const char* file_str = "#file";
503    static const char* table_str = "#table";
504    static const char* prefix_str = "#prefix";
505    static const char* feature_str = "#feature";
506    static const char* externref_str = "#externref";
507    static const char* externdef_str = "#externdef";
508    static const char* ctmpl_str = "#ctmpl";
509    static const char* htmpl_str = "#htmpl";
510    static const char* const_str = "#const";
511
512    if (strncmp (buf, file_str, strlen (file_str)) == 0)
513	token = X_FILE_TOKEN;
514    else if (strncmp (buf, table_str, strlen (table_str)) == 0)
515	token = X_TABLE_TOKEN;
516    else if (strncmp (buf, prefix_str, strlen (prefix_str)) == 0)
517	token = X_PREFIX_TOKEN;
518    else if (strncmp (buf, feature_str, strlen (feature_str)) == 0)
519	token = X_FEATURE_TOKEN;
520    else if (strncmp (buf, externref_str, strlen (externref_str)) == 0)
521	token = X_EXTERNREF_TOKEN;
522    else if (strncmp (buf, externdef_str, strlen (externdef_str)) == 0)
523	token = X_EXTERNDEF_TOKEN;
524    else if (strncmp (buf, ctmpl_str, strlen (ctmpl_str)) == 0)
525	token = X_CTMPL_TOKEN;
526    else if (strncmp (buf, htmpl_str, strlen (htmpl_str)) == 0)
527	token = X_HTMPL_TOKEN;
528    else if (strncmp (buf, const_str, strlen (const_str)) == 0)
529	token = X_CONST_TOKEN;
530    else
531        token = X_NO_TOKEN;
532
533    switch (token) {
534    case X_FILE_TOKEN:
535	{
536	    File* phile;
537
538	    if ((phile = (File*) malloc (sizeof(File))) == NULL)
539		exit(1);
540	    if ((phile->name = strdup (buf + strlen (file_str) + 1)) == NULL)
541		exit(1);
542	    phile->table = NULL;
543	    phile->tablecurrent = NULL;
544	    phile->tabletail = &phile->table;
545	    phile->next = NULL;
546	    phile->tmpl = NULL;
547
548	    *filetail = phile;
549	    filetail = &phile->next;
550	    filecurrent = phile;
551	}
552	break;
553    case X_TABLE_TOKEN:
554	{
555	    Table* table;
556	    if ((table = (Table*) malloc (sizeof(Table))) == NULL)
557		exit(1);
558	    if ((table->name = strdup (buf + strlen (table_str) + 1)) == NULL)
559		exit(1);
560	    if (solaris_abi_names) {
561		if (strcmp(table->name, "XtStringsR6") == 0) {
562		    strcpy(table->name, "XtR6Strings");
563		} else if (strcmp(table->name, "XtShellStringsR6") == 0) {
564		    strcpy(table->name, "XtR6ShellStrings");
565		}
566	    }
567	    table->tableent = NULL;
568	    table->tableentcurrent = NULL;
569	    table->tableenttail = &table->tableent;
570	    table->next = NULL;
571	    table->offset = 0;
572
573	    *filecurrent->tabletail = table;
574	    filecurrent->tabletail = &table->next;
575	    filecurrent->tablecurrent = table;
576	}
577	break;
578    case X_PREFIX_TOKEN:
579	if ((prefixstr = strdup (buf + strlen (prefix_str) + 1)) == NULL)
580	    exit(1);
581	break;
582    case X_FEATURE_TOKEN:
583	if ((featurestr = strdup (buf + strlen (feature_str) + 1)) == NULL)
584	    exit(1);
585	break;
586    case X_EXTERNREF_TOKEN:
587	if ((externrefstr = strdup (buf + strlen (externref_str) + 1)) == NULL)
588	    exit(1);
589	break;
590    case X_EXTERNDEF_TOKEN:
591	if ((externdefstr = strdup (buf + strlen (externdef_str) + 1)) == NULL)
592	    exit(1);
593	break;
594    case X_CTMPL_TOKEN:
595	if ((ctmplstr = strdup (buf + strlen (ctmpl_str) + 1)) == NULL)
596	    exit(1);
597	break;
598    case X_HTMPL_TOKEN:
599	if ((filecurrent->tmpl = ifopen (buf + strlen (htmpl_str) + 1, "r")) == NULL) {
600	    (void) fprintf (stderr,
601			    "Expected template %s, not found\n", htmpl_str);
602	    exit (1);
603	}
604	break;
605    case X_CONST_TOKEN:
606	if ((conststr = strdup (buf + strlen (const_str) + 1)) == NULL)
607	    exit(1);
608	break;
609    default:
610	{
611	    char* right;
612	    TableEnt* tableent;
613	    size_t llen;
614	    size_t rlen;
615	    size_t len;
616
617	    if ((right = strchr(buf, ' ')))
618		*right++ = 0;
619	    else
620		right = buf + 1;
621	    if (buf[0] == 'H') {
622		snprintf (lbuf, sizeof(lbuf), "%s%s", prefixstr, right);
623		right = lbuf;
624	    }
625
626	    llen = len = strlen(buf) + 1;
627	    rlen = strlen(right) + 1;
628	    if (right != buf + 1) len += rlen;
629	    tableent = (TableEnt*)calloc(sizeof(TableEnt) + len, 1);
630	    if (tableent == NULL)
631		exit(1);
632	    tableent->left = (char *)(tableent + 1);
633	    strcpy(tableent->left, buf);
634	    if (llen != len) {
635		tableent->right = tableent->left + llen;
636		strcpy(tableent->right, right);
637	    } else {
638		tableent->right = tableent->left + 1;
639	    }
640	    tableent->next = NULL;
641
642	    *filecurrent->tablecurrent->tableenttail = tableent;
643	    filecurrent->tablecurrent->tableenttail = &tableent->next;
644	    filecurrent->tablecurrent->tableentcurrent = tableent;
645	}
646	break;
647    }
648}
649
650static void IntelABIIndexEntries (File *myfile)
651{
652    Table* t;
653    TableEnt* te;
654
655    for (t = myfile->table; t; t = t->next) {
656	for (te = t->tableent; te; te = te->next) {
657	    te->offset = t->offset;
658	    t->offset += strlen (te->right);
659	    t->offset++;
660	}
661    }
662}
663
664static void DefaultIndexEntries (File *myfile)
665{
666    Table* t;
667    TableEnt* te;
668    size_t offset = 0;
669
670    for (t = myfile->table; t; t = t->next) {
671	for (te = t->tableent; te; te = te->next) {
672	    te->offset = offset;
673	    offset += strlen (te->right);
674	    offset++;
675	}
676    }
677}
678
679static void IndexEntries (File *myfile, int abi)
680{
681    switch (abi) {
682    case X_SPARC_ABI:
683	break;
684    case X_INTEL_ABI:
685    case X_INTEL_ABI_BC:
686	IntelABIIndexEntries (myfile);
687	break;
688    default:
689	DefaultIndexEntries (myfile);
690	break;
691    }
692}
693
694static char* DoComment (char *line)
695{
696    char* tag;
697    char* eol;
698    char* ret;
699    size_t len;
700
701    /* assume that the first line with two '$' in it is the RCS tag line */
702    if ((tag = strchr (line, '$')) == NULL) return NULL;
703    if ((eol = strchr (tag + 1, '$')) == NULL) return NULL;
704    len = (size_t)(eol - tag);
705    if ((ret = malloc (len)) == NULL)
706	exit (1);
707    (void) strncpy (ret, tag + 1, len - 1);
708    ret[len - 2] = 0;
709    return ret;
710}
711
712int main(int argc, char *argv[])
713{
714    size_t len;
715    char* tagline = NULL;
716    File* phile;
717    FILE *f;
718    char buf[1024];
719    int abi =
720#ifndef ARRAYPERSTR
721	X_DEFAULT_ABI;
722#else
723	X_ARRAYPER_ABI;
724#endif
725
726    f = stdin;
727    if (argc > 1) {
728	int i;
729	for (i = 1; i < argc; i++) {
730	    if (strcmp (argv[i], "-f") == 0) {
731		if (++i < argc)
732		    f = fopen (argv[i], "r");
733		else
734		    return 1;
735	    }
736	    if (strcmp (argv[i], "-i") == 0) {
737		if (++i < argc) {
738		    includedir = argv[i];
739		} else {
740		    if (f != 0 && f != stdin) fclose(f);
741		    return 1;
742		}
743	    }
744	    if (strcmp (argv[i], "-sparcabi") == 0)
745		abi = X_SPARC_ABI;
746	    if (strcmp (argv[i], "-intelabi") == 0)
747		abi = X_INTEL_ABI;
748	    if (strcmp (argv[i], "-functionabi") == 0)
749		abi = X_FUNCTION_ABI;
750	    if (strcmp (argv[i], "-earlyR6bc") == 0 && abi == X_INTEL_ABI)
751		abi = X_INTEL_ABI_BC;
752	    if (strcmp (argv[i], "-arrayperabi") == 0)
753		abi = X_ARRAYPER_ABI;
754#ifdef ARRAYPERSTR
755	    if (strcmp (argv[i], "-defaultabi") == 0)
756		abi = X_DEFAULT_ABI;
757#endif
758	    if (strcmp (argv[i], "-solarisabinames") == 0)
759		solaris_abi_names = TRUE;
760	}
761    }
762
763    if (f == NULL) return 1;
764    while (fgets(buf, sizeof buf, f)) {
765	if (!buf[0] || buf[0] == '\n')
766	    continue;
767	if (buf[0] == '!') {
768	    if (tagline) continue;
769	    tagline = DoComment (buf);
770	    continue;
771	}
772	if (buf[(len = strlen (buf) - 1)] == '\n') buf[len] = '\0';
773	DoLine(buf);
774    }
775    for (phile = file; phile; phile = phile->next) {
776	if (abi != X_ARRAYPER_ABI) IndexEntries (phile, abi);
777	WriteHeader (tagline, phile, abi);
778    }
779    WriteSource(tagline, abi);
780    return 0;
781}
782
783