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