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