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