OSDN Git Service

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