1/* fini.c
2   Copyright (C) 1995 Free Software Foundation, Inc.
3   Contributed by James Craig Burley.
4
5This file is part of GNU Fortran.
6
7GNU Fortran is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Fortran is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Fortran; see the file COPYING.  If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-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
30typedef struct _name_ *name;
31
32struct _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
46struct _name_root_
47  {
48    name first;
49    name last;
50  };
51
52struct _name_alpha_
53  {
54    name ign1;
55    name ign2;
56    name first;
57    name last;
58  };
59
60static FILE *in;
61static FILE *out;
62static char prefix[32];
63static char postfix[32];
64static char storage[32];
65static const char *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
230void testname (bool nested, int indent, name first, name last);
231void testnames (bool nested, int indent, int len, name first, name last);
232
233int
234main (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  for (i = 0; ((size_t) i) < ARRAY_SIZE (names); ++i)
260    {				/* Initialize length/name ordered list roots. */
261      names[i].first = (name) &names[i];
262      names[i].last = (name) &names[i];
263    }
264  names_alpha.first = (name) &names_alpha;	/* Initialize name order. */
265  names_alpha.last = (name) &names_alpha;
266
267  if (argc != 4)
268    {
269      fprintf (stderr, "Command form: fini input output-code output-include\n");
270      exit (1);
271    }
272
273  input_name = argv[1];
274  output_name = argv[2];
275  include_name = argv[3];
276
277  in = fopen (input_name, "r");
278  if (in == NULL)
279    {
280      fprintf (stderr, "Cannot open \"%s\"\n", input_name);
281      exit (1);
282    }
283  out = fopen (output_name, "w");
284  if (out == NULL)
285    {
286      fclose (in);
287      fprintf (stderr, "Cannot open \"%s\"\n", output_name);
288      exit (1);
289    }
290  incl = fopen (include_name, "w");
291  if (incl == NULL)
292    {
293      fclose (in);
294      fprintf (stderr, "Cannot open \"%s\"\n", include_name);
295      exit (1);
296    }
297
298  /* Get past the initial block-style comment (man, this parsing code is just
299     _so_ lame, but I'm too lazy to improve it).  */
300
301  for (;;)
302    {
303      cc = getc (in);
304      if (cc == '{')
305	{
306	  while (((cc = getc (in)) != '}') && (cc != EOF))
307	    ;
308	}
309      else if (cc != EOF)
310	{
311	  while (((cc = getc (in)) != EOF) && (! ISALNUM (cc)))
312	    ;
313	  ungetc (cc, in);
314	  break;
315	}
316      else
317	{
318	  assert ("EOF too soon!" == NULL);
319	  exit (1);
320	}
321    }
322
323  fscanf (in, "%s %s %s %s %s %d %d", prefix, postfix, storage, type, routine,
324	  &do_name, &do_names);
325
326  if (storage[0] == '\0')
327    storage[1] = '\0';
328  else
329    /* Assume string is quoted somehow, replace ending quote with space. */
330    {
331      if (storage[2] == '\0')
332	storage[1] = '\0';
333      else
334	storage[strlen (storage) - 1] = ' ';
335    }
336
337  if (postfix[0] == '\0')
338    postfix[1] = '\0';
339  else				/* Assume string is quoted somehow, strip off
340				   ending quote. */
341    postfix[strlen (postfix) - 1] = '\0';
342
343  for (i = 1; storage[i] != '\0'; ++i)
344    storage[i - 1] = storage[i];
345  storage[i - 1] = '\0';
346
347  for (i = 1; postfix[i] != '\0'; ++i)
348    postfix[i - 1] = postfix[i];
349  postfix[i - 1] = '\0';
350
351  fixlengths = strlen (prefix) + strlen (postfix);
352
353  while (TRUE)
354    {
355      count = fscanf (in, "%s %s", buf, kwname);
356      if (count == EOF)
357	break;
358      len = strlen (buf);
359      if (len == 0)
360	continue;		/* Skip empty lines. */
361      if (buf[0] == ';')
362	continue;		/* Skip commented-out lines. */
363      for (i = strlen (buf) - 1; i > 0; --i)
364	cc = buf[i];
365
366      /* Make new name object to store name and its keyword. */
367
368      newname = (name) malloc (sizeof (*newname));
369      newname->namelen = strlen (buf);
370      newname->kwlen = strlen (kwname);
371      total_length = newname->kwlen + fixlengths;
372      if (total_length >= 32)	/* Else resulting keyword name too long. */
373	{
374	  fprintf (stderr, "%s: %s%s%s is 31+%d chars long\n", input_name,
375		   prefix, kwname, postfix, total_length - 31);
376	  do_exit = TRUE;
377	}
378      strcpy (newname->kwname, kwname);
379      for (i = 0; i < newname->namelen; ++i)
380	{
381	  cc = buf[i];
382	  if (ISALPHA (cc))
383	    {
384	      newname->name_uc[i] = toupper (cc);
385	      newname->name_lc[i] = tolower (cc);
386	      newname->name_ic[i] = cc;
387	    }
388	  else
389	    newname->name_uc[i] = newname->name_lc[i] = newname->name_ic[i]
390	      = cc;
391	}
392      newname->name_uc[i] = newname->name_lc[i] = newname->name_ic[i] = '\0';
393
394      /* Warn user if names aren't alphabetically ordered. */
395
396      if ((last_buf[0] != '\0')
397	  && (strcmp (last_buf, newname->name_uc) >= 0))
398	{
399	  fprintf (stderr, "%s: \"%s\" precedes \"%s\"\n", input_name,
400		   last_buf, newname->name_uc);
401	  do_exit = TRUE;
402	}
403      strcpy (last_buf, newname->name_uc);
404
405      /* Append name to end of alpha-sorted list (assumes names entered in
406	 alpha order wrt name, not kwname, even though kwname is output from
407	 this list). */
408
409      n = names_alpha.last;
410      newname->next_alpha = n->next_alpha;
411      newname->previous_alpha = n;
412      n->next_alpha->previous_alpha = newname;
413      n->next_alpha = newname;
414
415      /* Insert name in appropriate length/name ordered list. */
416
417      n = (name) &names[len];
418      while ((n->next != (name) &names[len])
419	     && (strcmp (buf, n->next->name_uc) > 0))
420	n = n->next;
421      if (strcmp (buf, n->next->name_uc) == 0)
422	{
423	  fprintf (stderr, "%s: extraneous \"%s\"\n", input_name, buf);
424	  do_exit = TRUE;
425	}
426      newname->next = n->next;
427      newname->previous = n;
428      n->next->previous = newname;
429      n->next = newname;
430    }
431
432#if 0
433  for (len = 0; len < ARRAY_SIZE (name); ++len)
434    {
435      if (names[len].first == (name) &names[len])
436	continue;
437      printf ("Length %d:\n", len);
438      for (n = names[len].first; n != (name) &names[len]; n = n->next)
439	printf ("    %s %s %s\n", n->name_uc, n->name_lc, n->name_ic);
440    }
441#endif
442
443  if (do_exit)
444    exit (1);
445
446  /* First output the #include file. */
447
448  for (n = names_alpha.first; n != (name) &names_alpha; n = n->next_alpha)
449    {
450      fprintf (incl, "#define %sl%s%s %d\n", prefix, n->kwname, postfix,
451	       n->namelen);
452    }
453
454  fprintf (incl,
455	   "\
456\n\
457enum %s_\n\
458{\n\
459%sNone%s,\n\
460",
461	   type, prefix, postfix);
462
463  for (n = names_alpha.first; n != (name) &names_alpha; n = n->next_alpha)
464    {
465      fprintf (incl,
466	       "\
467%s%s%s,\n\
468",
469	       prefix, n->kwname, postfix);
470    }
471
472  fprintf (incl,
473	   "\
474%s%s\n\
475};\n\
476typedef enum %s_ %s;\n\
477",
478	   prefix, postfix, type, type);
479
480  /* Now output the C program. */
481
482  fprintf (out,
483	   "\
484%s%s\n\
485%s (ffelexToken t)\n\
486%c\n\
487  char *p;\n\
488  int c;\n\
489\n\
490  p = ffelex_token_text (t);\n\
491\n\
492",
493	   storage, type, routine, '{');
494
495  if (do_name)
496    {
497      if (do_names)
498	fprintf (out,
499		 "\
500  if (ffelex_token_type (t) == FFELEX_typeNAME)\n\
501    {\n\
502      switch (ffelex_token_length (t))\n\
503\t{\n\
504"
505	  );
506      else
507	fprintf (out,
508		 "\
509  assert (ffelex_token_type (t) == FFELEX_typeNAME);\n\
510\n\
511  switch (ffelex_token_length (t))\n\
512    {\n\
513"
514	  );
515
516/* Now output the length as a case, followed by the binary search within that length.  */
517
518      for (len = 0; ((size_t) len) < ARRAY_SIZE (names); ++len)
519	{
520	  if (names[len].first != (name) &names[len])
521	    {
522	      if (do_names)
523		fprintf (out,
524			 "\
525\tcase %d:\n\
526",
527			 len);
528	      else
529		fprintf (out,
530			 "\
531    case %d:\n\
532",
533			 len);
534	      testname (FALSE, do_names ? 10 : 6, names[len].first, names[len].last);
535	      if (do_names)
536		fprintf (out,
537			 "\
538\t  break;\n\
539"
540		  );
541	      else
542		fprintf (out,
543			 "\
544      break;\n\
545"
546		  );
547	    }
548	}
549
550      if (do_names)
551	fprintf (out,
552		 "\
553\t}\n\
554      return %sNone%s;\n\
555    }\n\
556\n\
557",
558		 prefix, postfix);
559      else
560	fprintf (out,
561		 "\
562    }\n\
563\n\
564  return %sNone%s;\n\
565}\n\
566",
567		 prefix, postfix);
568    }
569
570  if (do_names)
571    {
572      fputs ("\
573  assert (ffelex_token_type (t) == FFELEX_typeNAMES);\n\
574\n\
575  switch (ffelex_token_length (t))\n\
576    {\n\
577    default:\n\
578",
579	     out);
580
581      /* Find greatest non-empty length list. */
582
583      for (len = ARRAY_SIZE (names) - 1;
584	   names[len].first == (name) &names[len];
585	   --len)
586	;
587
588/* Now output the length as a case, followed by the binary search within that length. */
589
590      if (len > 0)
591	{
592	  for (; len != 0; --len)
593	    {
594	      fprintf (out,
595		       "\
596    case %d:\n\
597",
598		       len);
599	      if (names[len].first != (name) &names[len])
600		testnames (FALSE, 6, len, names[len].first, names[len].last);
601	    }
602	  if (names[1].first == (name) &names[1])
603	    fprintf (out,
604		     "\
605      ;\n\
606"
607	      );		/* Need empty statement after an empty case
608				   1:  */
609	}
610
611      fprintf (out,
612	       "\
613    }\n\
614\n\
615  return %sNone%s;\n\
616}\n\
617",
618	       prefix, postfix);
619    }
620
621  if (out != stdout)
622    fclose (out);
623  if (incl != stdout)
624    fclose (incl);
625  if (in != stdin)
626    fclose (in);
627  exit (0);
628}
629
630void
631testname (bool nested, int indent, name first, name last)
632{
633  name n;
634  name nhalf;
635  int num;
636  int numhalf;
637
638  assert (!nested || indent >= 2);
639  assert (((size_t) indent) + 4 < ARRAY_SIZE (xspaces));
640
641  num = 0;
642  numhalf = 0;
643  for (n = first, nhalf = first; n != last->next; n = n->next)
644    {
645      if ((++num & 1) == 0)
646	{
647	  nhalf = nhalf->next;
648	  ++numhalf;
649	}
650    }
651
652  if (nested)
653    fprintf (out,
654	     "\
655%s{\n\
656",
657	     xspaces[indent - 2]);
658
659  fprintf (out,
660	   "\
661%sif ((c = ffesrc_strcmp_2c (ffe_case_match (), p, \"%s\", \"%s\", \"%s\")) == 0)\n\
662%sreturn %s%s%s;\n\
663",
664	   xspaces[indent], nhalf->name_uc, nhalf->name_lc, nhalf->name_ic,
665	   xspaces[indent + 2], prefix, nhalf->kwname, postfix);
666
667  if (num != 1)
668    {
669      fprintf (out,
670	       "\
671%selse if (c < 0)\n\
672",
673	       xspaces[indent]);
674
675      if (numhalf == 0)
676	fprintf (out,
677		 "\
678%s;\n\
679",
680		 xspaces[indent + 2]);
681      else
682	testname (TRUE, indent + 4, first, nhalf->previous);
683
684      if (num - numhalf > 1)
685	{
686	  fprintf (out,
687		   "\
688%selse\n\
689",
690		   xspaces[indent]);
691
692	  testname (TRUE, indent + 4, nhalf->next, last);
693	}
694    }
695
696  if (nested)
697    fprintf (out,
698	     "\
699%s}\n\
700",
701	     xspaces[indent - 2]);
702}
703
704void
705testnames (bool nested, int indent, int len, name first, name last)
706{
707  name n;
708  name nhalf;
709  int num;
710  int numhalf;
711
712  assert (!nested || indent >= 2);
713  assert (((size_t) indent) + 4 < ARRAY_SIZE (xspaces));
714
715  num = 0;
716  numhalf = 0;
717  for (n = first, nhalf = first; n != last->next; n = n->next)
718    {
719      if ((++num & 1) == 0)
720	{
721	  nhalf = nhalf->next;
722	  ++numhalf;
723	}
724    }
725
726  if (nested)
727    fprintf (out,
728	     "\
729%s{\n\
730",
731	     xspaces[indent - 2]);
732
733  fprintf (out,
734	   "\
735%sif ((c = ffesrc_strncmp_2c (ffe_case_match (), p, \"%s\", \"%s\", \"%s\", %d)) == 0)\n\
736%sreturn %s%s%s;\n\
737",
738	   xspaces[indent], nhalf->name_uc, nhalf->name_lc, nhalf->name_ic,
739	   len, xspaces[indent + 2], prefix, nhalf->kwname, postfix);
740
741  if (num != 1)
742    {
743      fprintf (out,
744	       "\
745%selse if (c < 0)\n\
746",
747	       xspaces[indent]);
748
749      if (numhalf == 0)
750	fprintf (out,
751		 "\
752%s;\n\
753",
754		 xspaces[indent + 2]);
755      else
756	testnames (TRUE, indent + 4, len, first, nhalf->previous);
757
758      if (num - numhalf > 1)
759	{
760	  fprintf (out,
761		   "\
762%selse\n\
763",
764		   xspaces[indent]);
765
766	  testnames (TRUE, indent + 4, len, nhalf->next, last);
767	}
768    }
769
770  if (nested)
771    fprintf (out,
772	     "\
773%s}\n\
774",
775	     xspaces[indent - 2]);
776}
777