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