xref: /openbsd/gnu/usr.bin/gcc/gcc/f/fini.c (revision c87b03e5)
1 /* fini.c
2    Copyright (C) 1995 Free Software Foundation, Inc.
3    Contributed by James Craig Burley.
4 
5 This file is part of GNU Fortran.
6 
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11 
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21 
22 #define USE_HCONFIG
23 
24 #include "proj.h"
25 #include "malloc.h"
26 
27 #undef MAXNAMELEN
28 #define MAXNAMELEN 100
29 
30 typedef struct _name_ *name;
31 
32 struct _name_
33   {
34     name next;
35     name previous;
36     name next_alpha;
37     name previous_alpha;
38     int namelen;
39     int kwlen;
40     char kwname[MAXNAMELEN];
41     char name_uc[MAXNAMELEN];
42     char name_lc[MAXNAMELEN];
43     char name_ic[MAXNAMELEN];
44   };
45 
46 struct _name_root_
47   {
48     name first;
49     name last;
50   };
51 
52 struct _name_alpha_
53   {
54     name ign1;
55     name ign2;
56     name first;
57     name last;
58   };
59 
60 static FILE *in;
61 static FILE *out;
62 static char prefix[32];
63 static char postfix[32];
64 static char storage[32];
65 static const char *const xspaces[]
66 =
67 {
68   "",				/* 0 */
69   " ",				/* 1 */
70   "  ",				/* 2 */
71   "   ",			/* 3 */
72   "    ",			/* 4 */
73   "     ",			/* 5 */
74   "      ",			/* 6 */
75   "       ",			/* 7 */
76   "\t",				/* 8 */
77   "\t ",			/* 9 */
78   "\t  ",			/* 10 */
79   "\t   ",			/* 11 */
80   "\t    ",			/* 12 */
81   "\t     ",			/* 13 */
82   "\t      ",			/* 14 */
83   "\t       ",			/* 15 */
84   "\t\t",			/* 16 */
85   "\t\t ",			/* 17 */
86   "\t\t  ",			/* 18 */
87   "\t\t   ",			/* 19 */
88   "\t\t    ",			/* 20 */
89   "\t\t     ",			/* 21 */
90   "\t\t      ",			/* 22 */
91   "\t\t       ",		/* 23 */
92   "\t\t\t",			/* 24 */
93   "\t\t\t ",			/* 25 */
94   "\t\t\t  ",			/* 26 */
95   "\t\t\t   ",			/* 27 */
96   "\t\t\t    ",			/* 28 */
97   "\t\t\t     ",		/* 29 */
98   "\t\t\t      ",		/* 30 */
99   "\t\t\t       ",		/* 31 */
100   "\t\t\t\t",			/* 32 */
101   "\t\t\t\t ",			/* 33 */
102   "\t\t\t\t  ",			/* 34 */
103   "\t\t\t\t   ",		/* 35 */
104   "\t\t\t\t    ",		/* 36 */
105   "\t\t\t\t     ",		/* 37 */
106   "\t\t\t\t      ",		/* 38 */
107   "\t\t\t\t       ",		/* 39 */
108   "\t\t\t\t\t",			/* 40 */
109   "\t\t\t\t\t ",		/* 41 */
110   "\t\t\t\t\t  ",		/* 42 */
111   "\t\t\t\t\t   ",		/* 43 */
112   "\t\t\t\t\t    ",		/* 44 */
113   "\t\t\t\t\t     ",		/* 45 */
114   "\t\t\t\t\t      ",		/* 46 */
115   "\t\t\t\t\t       ",		/* 47 */
116   "\t\t\t\t\t\t",		/* 48 */
117   "\t\t\t\t\t\t ",		/* 49 */
118   "\t\t\t\t\t\t  ",		/* 50 */
119   "\t\t\t\t\t\t   ",		/* 51 */
120   "\t\t\t\t\t\t    ",		/* 52 */
121   "\t\t\t\t\t\t     ",		/* 53 */
122   "\t\t\t\t\t\t      ",		/* 54 */
123   "\t\t\t\t\t\t       ",	/* 55 */
124   "\t\t\t\t\t\t\t",		/* 56 */
125   "\t\t\t\t\t\t\t ",		/* 57 */
126   "\t\t\t\t\t\t\t  ",		/* 58 */
127   "\t\t\t\t\t\t\t   ",		/* 59 */
128   "\t\t\t\t\t\t\t    ",		/* 60 */
129   "\t\t\t\t\t\t\t     ",	/* 61 */
130   "\t\t\t\t\t\t\t      ",	/* 62 */
131   "\t\t\t\t\t\t\t       ",	/* 63 */
132   "\t\t\t\t\t\t\t\t",		/* 64 */
133   "\t\t\t\t\t\t\t\t ",		/* 65 */
134   "\t\t\t\t\t\t\t\t  ",		/* 66 */
135   "\t\t\t\t\t\t\t\t   ",	/* 67 */
136   "\t\t\t\t\t\t\t\t    ",	/* 68 */
137   "\t\t\t\t\t\t\t\t     ",	/* 69 */
138   "\t\t\t\t\t\t\t\t      ",	/* 70 */
139   "\t\t\t\t\t\t\t\t       ",	/* 71 */
140   "\t\t\t\t\t\t\t\t\t",		/* 72 */
141   "\t\t\t\t\t\t\t\t\t ",	/* 73 */
142   "\t\t\t\t\t\t\t\t\t  ",	/* 74 */
143   "\t\t\t\t\t\t\t\t\t   ",	/* 75 */
144   "\t\t\t\t\t\t\t\t\t    ",	/* 76 */
145   "\t\t\t\t\t\t\t\t\t     ",	/* 77 */
146   "\t\t\t\t\t\t\t\t\t      ",	/* 78 */
147   "\t\t\t\t\t\t\t\t\t       ",	/* 79 */
148   "\t\t\t\t\t\t\t\t\t\t",	/* 80 */
149   "\t\t\t\t\t\t\t\t\t\t ",	/* 81 */
150   "\t\t\t\t\t\t\t\t\t\t  ",	/* 82 */
151   "\t\t\t\t\t\t\t\t\t\t   ",	/* 83 */
152   "\t\t\t\t\t\t\t\t\t\t    ",	/* 84 */
153   "\t\t\t\t\t\t\t\t\t\t     ",	/* 85 */
154   "\t\t\t\t\t\t\t\t\t\t      ",	/* 86 */
155   "\t\t\t\t\t\t\t\t\t\t       ",/* 87 */
156   "\t\t\t\t\t\t\t\t\t\t\t",	/* 88 */
157   "\t\t\t\t\t\t\t\t\t\t\t ",	/* 89 */
158   "\t\t\t\t\t\t\t\t\t\t\t  ",	/* 90 */
159   "\t\t\t\t\t\t\t\t\t\t\t   ",	/* 91 */
160   "\t\t\t\t\t\t\t\t\t\t\t    ",	/* 92 */
161   "\t\t\t\t\t\t\t\t\t\t\t     ",/* 93 */
162   "\t\t\t\t\t\t\t\t\t\t\t      ",	/* 94 */
163   "\t\t\t\t\t\t\t\t\t\t\t       ",	/* 95 */
164   "\t\t\t\t\t\t\t\t\t\t\t\t",	/* 96 */
165   "\t\t\t\t\t\t\t\t\t\t\t\t ",	/* 97 */
166   "\t\t\t\t\t\t\t\t\t\t\t\t  ",	/* 98 */
167   "\t\t\t\t\t\t\t\t\t\t\t\t   ",/* 99 */
168   "\t\t\t\t\t\t\t\t\t\t\t\t    ",	/* 100 */
169   "\t\t\t\t\t\t\t\t\t\t\t\t     ",	/* 101 */
170   "\t\t\t\t\t\t\t\t\t\t\t\t      ",	/* 102 */
171   "\t\t\t\t\t\t\t\t\t\t\t\t       ",	/* 103 */
172   "\t\t\t\t\t\t\t\t\t\t\t\t\t",	/* 104 */
173   "\t\t\t\t\t\t\t\t\t\t\t\t\t ",/* 105 */
174   "\t\t\t\t\t\t\t\t\t\t\t\t\t  ",	/* 106 */
175   "\t\t\t\t\t\t\t\t\t\t\t\t\t   ",	/* 107 */
176   "\t\t\t\t\t\t\t\t\t\t\t\t\t    ",	/* 108 */
177   "\t\t\t\t\t\t\t\t\t\t\t\t\t     ",	/* 109 */
178   "\t\t\t\t\t\t\t\t\t\t\t\t\t      ",	/* 110 */
179   "\t\t\t\t\t\t\t\t\t\t\t\t\t       ",	/* 111 */
180   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t",	/* 112 */
181   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t ",	/* 113 */
182   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ",	/* 114 */
183   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ",	/* 115 */
184   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t    ",	/* 116 */
185   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t     ",	/* 117 */
186   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t      ",	/* 118 */
187   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t       ",	/* 119 */
188   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t",	/* 120 */
189   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ",	/* 121 */
190   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ",	/* 122 */
191   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ",	/* 123 */
192   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t    ",	/* 124 */
193   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     ",	/* 125 */
194   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t      ",	/* 126 */
195   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       ",	/* 127 */
196   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t",	/* 128 */
197   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ",	/* 129 */
198   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ",	/* 130 */
199   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ",	/* 131 */
200   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t    ",	/* 132 */
201   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     ",	/* 133 */
202   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t      ",	/* 134 */
203   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       ",	/* 135 */
204   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t",	/* 136 */
205   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ",	/* 137 */
206   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ",	/* 138 */
207   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ",	/* 139 */
208   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t    ",	/* 140 */
209   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     ",	/* 141 */
210   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t      ",	/* 142 */
211   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       ",	/* 143 */
212   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t",	/* 144 */
213   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ",	/* 145 */
214   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ",	/* 146 */
215   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ",	/* 147 */
216   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t    ",	/* 148 */
217   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     ",	/* 149 */
218   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t      ",	/* 150 */
219   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       ",	/* 151 */
220   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t",	/* 152 */
221   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ",	/* 153 */
222   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  ",	/* 154 */
223   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ",	/* 155 */
224   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t    ",	/* 156 */
225   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     ",	/* 157 */
226   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t      ",	/* 158 */
227   "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       ",	/* 159 */
228 };
229 
230 void testname (bool nested, int indent, name first, name last);
231 void testnames (bool nested, int indent, int len, name first, name last);
232 
233 int
main(int argc,char ** argv)234 main (int argc, char **argv)
235 {
236   char buf[MAXNAMELEN];
237   char last_buf[MAXNAMELEN];
238   char kwname[MAXNAMELEN];
239   char routine[32];
240   char type[32];
241   int i;
242   int count;
243   int len;
244   struct _name_root_ names[200];
245   struct _name_alpha_ names_alpha;
246   name n;
247   name newname;
248   char *input_name;
249   char *output_name;
250   char *include_name;
251   FILE *incl;
252   int fixlengths;
253   int total_length;
254   int do_name;			/* TRUE if token may be NAME. */
255   int do_names;			/* TRUE if token may be NAMES. */
256   int cc;
257   bool do_exit = FALSE;
258 
259   last_buf[0] = '\0';
260 
261   for (i = 0; ((size_t) i) < ARRAY_SIZE (names); ++i)
262     {				/* Initialize length/name ordered list roots. */
263       names[i].first = (name) &names[i];
264       names[i].last = (name) &names[i];
265     }
266   names_alpha.first = (name) &names_alpha;	/* Initialize name order. */
267   names_alpha.last = (name) &names_alpha;
268 
269   if (argc != 4)
270     {
271       fprintf (stderr, "Command form: fini input output-code output-include\n");
272       return (1);
273     }
274 
275   input_name = argv[1];
276   output_name = argv[2];
277   include_name = argv[3];
278 
279   in = fopen (input_name, "r");
280   if (in == NULL)
281     {
282       fprintf (stderr, "Cannot open \"%s\"\n", input_name);
283       return (1);
284     }
285   out = fopen (output_name, "w");
286   if (out == NULL)
287     {
288       fclose (in);
289       fprintf (stderr, "Cannot open \"%s\"\n", output_name);
290       return (1);
291     }
292   incl = fopen (include_name, "w");
293   if (incl == NULL)
294     {
295       fclose (in);
296       fprintf (stderr, "Cannot open \"%s\"\n", include_name);
297       return (1);
298     }
299 
300   /* Get past the initial block-style comment (man, this parsing code is just
301      _so_ lame, but I'm too lazy to improve it).  */
302 
303   for (;;)
304     {
305       cc = getc (in);
306       if (cc == '{')
307 	{
308 	  while (((cc = getc (in)) != '}') && (cc != EOF))
309 	    ;
310 	}
311       else if (cc != EOF)
312 	{
313 	  while (((cc = getc (in)) != EOF) && (! ISALNUM (cc)))
314 	    ;
315 	  ungetc (cc, in);
316 	  break;
317 	}
318       else
319 	{
320 	  assert ("EOF too soon!" == NULL);
321 	  return (1);
322 	}
323     }
324 
325   fscanf (in, "%s %s %s %s %s %d %d", prefix, postfix, storage, type, routine,
326 	  &do_name, &do_names);
327 
328   if (storage[0] == '\0')
329     storage[1] = '\0';
330   else
331     /* Assume string is quoted somehow, replace ending quote with space. */
332     {
333       if (storage[2] == '\0')
334 	storage[1] = '\0';
335       else
336 	storage[strlen (storage) - 1] = ' ';
337     }
338 
339   if (postfix[0] == '\0')
340     postfix[1] = '\0';
341   else				/* Assume string is quoted somehow, strip off
342 				   ending quote. */
343     postfix[strlen (postfix) - 1] = '\0';
344 
345   for (i = 1; storage[i] != '\0'; ++i)
346     storage[i - 1] = storage[i];
347   storage[i - 1] = '\0';
348 
349   for (i = 1; postfix[i] != '\0'; ++i)
350     postfix[i - 1] = postfix[i];
351   postfix[i - 1] = '\0';
352 
353   fixlengths = strlen (prefix) + strlen (postfix);
354 
355   while (TRUE)
356     {
357       count = fscanf (in, "%s %s", buf, kwname);
358       if (count == EOF)
359 	break;
360       len = strlen (buf);
361       if (len == 0)
362 	continue;		/* Skip empty lines. */
363       if (buf[0] == ';')
364 	continue;		/* Skip commented-out lines. */
365       for (i = strlen (buf) - 1; i > 0; --i)
366 	cc = buf[i];
367 
368       /* Make new name object to store name and its keyword. */
369 
370       newname = (name) xmalloc (sizeof (*newname));
371       newname->namelen = strlen (buf);
372       newname->kwlen = strlen (kwname);
373       total_length = newname->kwlen + fixlengths;
374       if (total_length >= 32)	/* Else resulting keyword name too long. */
375 	{
376 	  fprintf (stderr, "%s: %s%s%s is 31+%d chars long\n", input_name,
377 		   prefix, kwname, postfix, total_length - 31);
378 	  do_exit = TRUE;
379 	}
380       strcpy (newname->kwname, kwname);
381       for (i = 0; i < newname->namelen; ++i)
382 	{
383 	  cc = buf[i];
384 	  newname->name_uc[i] = TOUPPER (cc);
385 	  newname->name_lc[i] = TOLOWER (cc);
386 	  newname->name_ic[i] = cc;
387 	}
388       newname->name_uc[i] = newname->name_lc[i] = newname->name_ic[i] = '\0';
389 
390       /* Warn user if names aren't alphabetically ordered. */
391 
392       if ((last_buf[0] != '\0')
393 	  && (strcmp (last_buf, newname->name_uc) >= 0))
394 	{
395 	  fprintf (stderr, "%s: \"%s\" precedes \"%s\"\n", input_name,
396 		   last_buf, newname->name_uc);
397 	  do_exit = TRUE;
398 	}
399       strcpy (last_buf, newname->name_uc);
400 
401       /* Append name to end of alpha-sorted list (assumes names entered in
402 	 alpha order wrt name, not kwname, even though kwname is output from
403 	 this list). */
404 
405       n = names_alpha.last;
406       newname->next_alpha = n->next_alpha;
407       newname->previous_alpha = n;
408       n->next_alpha->previous_alpha = newname;
409       n->next_alpha = newname;
410 
411       /* Insert name in appropriate length/name ordered list. */
412 
413       n = (name) &names[len];
414       while ((n->next != (name) &names[len])
415 	     && (strcmp (buf, n->next->name_uc) > 0))
416 	n = n->next;
417       if (strcmp (buf, n->next->name_uc) == 0)
418 	{
419 	  fprintf (stderr, "%s: extraneous \"%s\"\n", input_name, buf);
420 	  do_exit = TRUE;
421 	}
422       newname->next = n->next;
423       newname->previous = n;
424       n->next->previous = newname;
425       n->next = newname;
426     }
427 
428 #if 0
429   for (len = 0; len < ARRAY_SIZE (name); ++len)
430     {
431       if (names[len].first == (name) &names[len])
432 	continue;
433       printf ("Length %d:\n", len);
434       for (n = names[len].first; n != (name) &names[len]; n = n->next)
435 	printf ("    %s %s %s\n", n->name_uc, n->name_lc, n->name_ic);
436     }
437 #endif
438 
439   if (do_exit)
440     return (1);
441 
442   /* First output the #include file. */
443 
444   for (n = names_alpha.first; n != (name) &names_alpha; n = n->next_alpha)
445     {
446       fprintf (incl, "#define %sl%s%s %d\n", prefix, n->kwname, postfix,
447 	       n->namelen);
448     }
449 
450   fprintf (incl,
451 	   "\
452 \n\
453 enum %s_\n\
454 {\n\
455 %sNone%s,\n\
456 ",
457 	   type, prefix, postfix);
458 
459   for (n = names_alpha.first; n != (name) &names_alpha; n = n->next_alpha)
460     {
461       fprintf (incl,
462 	       "\
463 %s%s%s,\n\
464 ",
465 	       prefix, n->kwname, postfix);
466     }
467 
468   fprintf (incl,
469 	   "\
470 %s%s\n\
471 };\n\
472 typedef enum %s_ %s;\n\
473 ",
474 	   prefix, postfix, type, type);
475 
476   /* Now output the C program. */
477 
478   fprintf (out,
479 	   "\
480 %s%s\n\
481 %s (ffelexToken t)\n\
482 %c\n\
483   char *p;\n\
484   int c;\n\
485 \n\
486   p = ffelex_token_text (t);\n\
487 \n\
488 ",
489 	   storage, type, routine, '{');
490 
491   if (do_name)
492     {
493       if (do_names)
494 	fprintf (out,
495 		 "\
496   if (ffelex_token_type (t) == FFELEX_typeNAME)\n\
497     {\n\
498       switch (ffelex_token_length (t))\n\
499 \t{\n\
500 "
501 	  );
502       else
503 	fprintf (out,
504 		 "\
505   assert (ffelex_token_type (t) == FFELEX_typeNAME);\n\
506 \n\
507   switch (ffelex_token_length (t))\n\
508     {\n\
509 "
510 	  );
511 
512 /* Now output the length as a case, followed by the binary search within that length.  */
513 
514       for (len = 0; ((size_t) len) < ARRAY_SIZE (names); ++len)
515 	{
516 	  if (names[len].first != (name) &names[len])
517 	    {
518 	      if (do_names)
519 		fprintf (out,
520 			 "\
521 \tcase %d:\n\
522 ",
523 			 len);
524 	      else
525 		fprintf (out,
526 			 "\
527     case %d:\n\
528 ",
529 			 len);
530 	      testname (FALSE, do_names ? 10 : 6, names[len].first, names[len].last);
531 	      if (do_names)
532 		fprintf (out,
533 			 "\
534 \t  break;\n\
535 "
536 		  );
537 	      else
538 		fprintf (out,
539 			 "\
540       break;\n\
541 "
542 		  );
543 	    }
544 	}
545 
546       if (do_names)
547 	fprintf (out,
548 		 "\
549 \t}\n\
550       return %sNone%s;\n\
551     }\n\
552 \n\
553 ",
554 		 prefix, postfix);
555       else
556 	fprintf (out,
557 		 "\
558     }\n\
559 \n\
560   return %sNone%s;\n\
561 }\n\
562 ",
563 		 prefix, postfix);
564     }
565 
566   if (do_names)
567     {
568       fputs ("\
569   assert (ffelex_token_type (t) == FFELEX_typeNAMES);\n\
570 \n\
571   switch (ffelex_token_length (t))\n\
572     {\n\
573     default:\n\
574 ",
575 	     out);
576 
577       /* Find greatest non-empty length list. */
578 
579       for (len = ARRAY_SIZE (names) - 1;
580 	   names[len].first == (name) &names[len];
581 	   --len)
582 	;
583 
584 /* Now output the length as a case, followed by the binary search within that length. */
585 
586       if (len > 0)
587 	{
588 	  for (; len != 0; --len)
589 	    {
590 	      fprintf (out,
591 		       "\
592     case %d:\n\
593 ",
594 		       len);
595 	      if (names[len].first != (name) &names[len])
596 		testnames (FALSE, 6, len, names[len].first, names[len].last);
597 	    }
598 	  if (names[1].first == (name) &names[1])
599 	    fprintf (out,
600 		     "\
601       ;\n\
602 "
603 	      );		/* Need empty statement after an empty case
604 				   1:  */
605 	}
606 
607       fprintf (out,
608 	       "\
609     }\n\
610 \n\
611   return %sNone%s;\n\
612 }\n\
613 ",
614 	       prefix, postfix);
615     }
616 
617   if (out != stdout)
618     fclose (out);
619   if (incl != stdout)
620     fclose (incl);
621   if (in != stdin)
622     fclose (in);
623   return (0);
624 }
625 
626 void
testname(bool nested,int indent,name first,name last)627 testname (bool nested, int indent, name first, name last)
628 {
629   name n;
630   name nhalf;
631   int num;
632   int numhalf;
633 
634   assert (!nested || indent >= 2);
635   assert (((size_t) indent) + 4 < ARRAY_SIZE (xspaces));
636 
637   num = 0;
638   numhalf = 0;
639   for (n = first, nhalf = first; n != last->next; n = n->next)
640     {
641       if ((++num & 1) == 0)
642 	{
643 	  nhalf = nhalf->next;
644 	  ++numhalf;
645 	}
646     }
647 
648   if (nested)
649     fprintf (out,
650 	     "\
651 %s{\n\
652 ",
653 	     xspaces[indent - 2]);
654 
655   fprintf (out,
656 	   "\
657 %sif ((c = ffesrc_strcmp_2c (ffe_case_match (), p, \"%s\", \"%s\", \"%s\")) == 0)\n\
658 %sreturn %s%s%s;\n\
659 ",
660 	   xspaces[indent], nhalf->name_uc, nhalf->name_lc, nhalf->name_ic,
661 	   xspaces[indent + 2], prefix, nhalf->kwname, postfix);
662 
663   if (num != 1)
664     {
665       fprintf (out,
666 	       "\
667 %selse if (c < 0)\n\
668 ",
669 	       xspaces[indent]);
670 
671       if (numhalf == 0)
672 	fprintf (out,
673 		 "\
674 %s;\n\
675 ",
676 		 xspaces[indent + 2]);
677       else
678 	testname (TRUE, indent + 4, first, nhalf->previous);
679 
680       if (num - numhalf > 1)
681 	{
682 	  fprintf (out,
683 		   "\
684 %selse\n\
685 ",
686 		   xspaces[indent]);
687 
688 	  testname (TRUE, indent + 4, nhalf->next, last);
689 	}
690     }
691 
692   if (nested)
693     fprintf (out,
694 	     "\
695 %s}\n\
696 ",
697 	     xspaces[indent - 2]);
698 }
699 
700 void
testnames(bool nested,int indent,int len,name first,name last)701 testnames (bool nested, int indent, int len, name first, name last)
702 {
703   name n;
704   name nhalf;
705   int num;
706   int numhalf;
707 
708   assert (!nested || indent >= 2);
709   assert (((size_t) indent) + 4 < ARRAY_SIZE (xspaces));
710 
711   num = 0;
712   numhalf = 0;
713   for (n = first, nhalf = first; n != last->next; n = n->next)
714     {
715       if ((++num & 1) == 0)
716 	{
717 	  nhalf = nhalf->next;
718 	  ++numhalf;
719 	}
720     }
721 
722   if (nested)
723     fprintf (out,
724 	     "\
725 %s{\n\
726 ",
727 	     xspaces[indent - 2]);
728 
729   fprintf (out,
730 	   "\
731 %sif ((c = ffesrc_strncmp_2c (ffe_case_match (), p, \"%s\", \"%s\", \"%s\", %d)) == 0)\n\
732 %sreturn %s%s%s;\n\
733 ",
734 	   xspaces[indent], nhalf->name_uc, nhalf->name_lc, nhalf->name_ic,
735 	   len, xspaces[indent + 2], prefix, nhalf->kwname, postfix);
736 
737   if (num != 1)
738     {
739       fprintf (out,
740 	       "\
741 %selse if (c < 0)\n\
742 ",
743 	       xspaces[indent]);
744 
745       if (numhalf == 0)
746 	fprintf (out,
747 		 "\
748 %s;\n\
749 ",
750 		 xspaces[indent + 2]);
751       else
752 	testnames (TRUE, indent + 4, len, first, nhalf->previous);
753 
754       if (num - numhalf > 1)
755 	{
756 	  fprintf (out,
757 		   "\
758 %selse\n\
759 ",
760 		   xspaces[indent]);
761 
762 	  testnames (TRUE, indent + 4, len, nhalf->next, last);
763 	}
764     }
765 
766   if (nested)
767     fprintf (out,
768 	     "\
769 %s}\n\
770 ",
771 	     xspaces[indent - 2]);
772 }
773