home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / g77-0.5.15-src.tgz / tar.out / fsf / g77 / f / fini.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  19KB  |  774 lines

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