home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume36 / unpost / part02 / lex.c next >
Encoding:
C/C++ Source or Header  |  1993-04-18  |  16.1 KB  |  592 lines

  1. /******************************************************************************
  2. * Module    :   Lexical Analyzer --- Process the input text file into tokens
  3. *               that the configuration file parser can understand.
  4. *
  5. * Routines  :   Lex()   - Return the next token from the file.
  6. *               OpenPrg - Open the back up program script file.
  7. *
  8. * Author    :   John W. M. Stevens
  9. ******************************************************************************/
  10.  
  11. #include    "compiler.h"
  12.  
  13. #include    "lex.h"
  14.  
  15. /* Type definitions for this file.  */
  16. typedef struct  key_st  {
  17.     char    c;
  18.     TKNS    val;
  19.     struct  key_st  *branch;
  20. } KEY;
  21.  
  22. /* Constants local to this file.    */
  23. #define     NOT_FND     -2
  24.  
  25. /* Object Data. */
  26. static  char    word[80];   /* Last string analyzed.                        */
  27. static  int     LnNo = 0;   /* The current line number reading the script.  */
  28. static  FILE    *PrgFl;     /* Pointer to the ASCII file that contains the
  29.                             *   backup program script.
  30.                             */
  31.  
  32. /* Trie data structure containing all the keywords and punctuation marks for
  33. *   the backup language.
  34. */
  35. static
  36. KEY T8[2] = {
  37.     {   ' ',                  2,    NULL                    },
  38.     {   'e',        T_ALTERNATE,    NULL                    }
  39. };
  40.  
  41. static
  42. KEY T7[2] = {
  43.     {   ' ',                  2,    NULL                    },
  44.     {   't',                  0,    T8                      }
  45. };
  46.  
  47. static
  48. KEY T6[2] = {
  49.     {   ' ',                  2,    NULL                    },
  50.     {   'a',                  0,    T7                      }
  51. };
  52.  
  53. static
  54. KEY T5[2] = {
  55.     {   ' ',                  2,    NULL                    },
  56.     {   'n',                  0,    T6                      }
  57. };
  58.  
  59. static
  60. KEY T4[2] = {
  61.     {   ' ',                  2,    NULL                    },
  62.      {   'r',                  0,    T5                      }
  63. };
  64.  
  65. static
  66. KEY T3[2] = {
  67.     {   ' ',                  2,    NULL                    },
  68.     {   'e',                  0,    T4                      }
  69. };
  70.  
  71. static
  72. KEY T2[2] = {
  73.     {   ' ',                  2,    NULL                    },
  74.     {   't',                  0,    T3                      }
  75. };
  76.  
  77. static
  78. KEY T1[2] = {
  79.     {   ' ',                  2,    NULL                    },
  80.     {   'l',                  0,    T2                      }
  81. };
  82.  
  83. static
  84. KEY Tb[2] = {
  85.     {   ' ',                  2,    NULL                    },
  86.     {   'y',             T_BODY,    NULL                    }
  87. };
  88.  
  89. static
  90. KEY Ta[2] = {
  91.     {   ' ',                  2,    NULL                    },
  92.     {   'd',                  0,    Tb                      }
  93. };
  94.  
  95. static
  96. KEY T9[2] = {
  97.     {   ' ',                  2,    NULL                    },
  98.     {   'o',                  0,    Ta                      }
  99. };
  100.  
  101. static
  102. KEY Te[2] = {
  103.     {   ' ',                  2,    NULL                    },
  104.     {   'e',             T_CASE,    NULL                    }
  105. };
  106.  
  107. static
  108. KEY Td[2] = {
  109.     {   ' ',                  2,    NULL                    },
  110.     {   's',                  0,    Te                      }
  111. };
  112.  
  113. static
  114. KEY Tc[2] = {
  115.     {   ' ',                  2,    NULL                    },
  116.     {   'a',                  0,    Td                      }
  117. };
  118.  
  119. static
  120. KEY T13[2] = {
  121.     {   ' ',                  2,    NULL                    },
  122.     {   'r',           T_HEADER,    NULL                    }
  123. };
  124.  
  125. static
  126. KEY T12[2] = {
  127.     {   ' ',                  2,    NULL                    },
  128.      {   'e',                  0,    T13                     }
  129. };
  130.  
  131. static
  132. KEY T11[2] = {
  133.     {   ' ',                  2,    NULL                    },
  134.     {   'd',                  0,    T12                     }
  135. };
  136.  
  137. static
  138. KEY T10[2] = {
  139.     {   ' ',                  2,    NULL                    },
  140.     {   'a',                  0,    T11                     }
  141. };
  142.  
  143. static
  144. KEY Tf[2] = {
  145.     {   ' ',                  2,    NULL                    },
  146.     {   'e',                  0,    T10                     }
  147. };
  148.  
  149. static
  150. KEY T18[2] = {
  151.     {   ' ',                  2,    NULL                    },
  152.     {   'e',           T_IGNORE,    NULL                    }
  153. };
  154.  
  155. static
  156. KEY T17[2] = {
  157.     {   ' ',                  2,    NULL                    },
  158.     {   'r',                  0,    T18                     }
  159. };
  160.  
  161. static
  162. KEY T16[2] = {
  163.     {   ' ',                  2,    NULL                    },
  164.     {   'o',                  0,    T17                     }
  165. };
  166.  
  167. static
  168. KEY T15[2] = {
  169.     {   ' ',                  2,    NULL                    },
  170.     {   'n',                  0,    T16                     }
  171. };
  172.  
  173. static
  174. KEY T14[3] = {
  175.     {   ' ',                  3,    NULL                    },
  176.     {   'd',               T_ID,    NULL                    },
  177.     {   'g',                  0,    T15                     }
  178. };
  179.  
  180. static
  181. KEY T1d[2] = {
  182.     {   ' ',                  2,    NULL                    },
  183.     {   'r',           T_NUMBER,    NULL                    }
  184. };
  185.  
  186. static
  187. KEY T1c[2] = {
  188.     {   ' ',                  2,    NULL                    },
  189.     {   'e',                  0,    T1d                     }
  190. };
  191.  
  192. static
  193. KEY T1b[2] = {
  194.      {   ' ',                  2,    NULL                    },
  195.     {   'b',                  0,    T1c                     }
  196. };
  197.  
  198. static
  199. KEY T1a[2] = {
  200.     {   ' ',                  2,    NULL                    },
  201.     {   'm',                  0,    T1b                     }
  202. };
  203.  
  204. static
  205. KEY T19[2] = {
  206.     {   ' ',                  2,    NULL                    },
  207.     {   'u',                  0,    T1a                     }
  208. };
  209.  
  210. static
  211. KEY T20[2] = {
  212.     {   ' ',                  2,    NULL                    },
  213.     {   't',             T_PART,    NULL                    }
  214. };
  215.  
  216. static
  217. KEY T1f[2] = {
  218.     {   ' ',                  2,    NULL                    },
  219.     {   'r',                  0,    T20                     }
  220. };
  221.  
  222. static
  223. KEY T1e[2] = {
  224.     {   ' ',                  2,    NULL                    },
  225.     {   'a',                  0,    T1f                     }
  226. };
  227.  
  228. static
  229. KEY T27[2] = {
  230.     {   ' ',                  2,    NULL                    },
  231.     {   's',         T_SEGMENTS,    NULL                    }
  232. };
  233.  
  234. static
  235. KEY T26[2] = {
  236.     {   ' ',                  2,    NULL                    },
  237.     {   't',          T_SEGMENT,    T27                     }
  238. };
  239.  
  240. static
  241. KEY T25[2] = {
  242.     {   ' ',                  2,    NULL                    },
  243.     {   'n',                  0,    T26                     }
  244. };
  245.  
  246. static
  247. KEY T24[2] = {
  248.     {   ' ',                  2,    NULL                    },
  249.     {   'e',                  0,    T25                     }
  250. };
  251.  
  252. static
  253. KEY T23[2] = {
  254.     {   ' ',                  2,    NULL                    },
  255.     {   'm',                  0,    T24                     }
  256. };
  257.  
  258. static
  259. KEY T2d[2] = {
  260.      {   ' ',                  2,    NULL                    },
  261.     {   'e',        T_SENSITIVE,    NULL                    }
  262. };
  263.  
  264. static
  265. KEY T2c[2] = {
  266.     {   ' ',                  2,    NULL                    },
  267.     {   'v',                  0,    T2d                     }
  268. };
  269.  
  270. static
  271. KEY T2b[2] = {
  272.     {   ' ',                  2,    NULL                    },
  273.     {   'i',                  0,    T2c                     }
  274. };
  275.  
  276. static
  277. KEY T2a[2] = {
  278.     {   ' ',                  2,    NULL                    },
  279.     {   't',                  0,    T2b                     }
  280. };
  281.  
  282. static
  283. KEY T29[2] = {
  284.     {   ' ',                  2,    NULL                    },
  285.     {   'i',                  0,    T2a                     }
  286. };
  287.  
  288. static
  289. KEY T28[2] = {
  290.     {   ' ',                  2,    NULL                    },
  291.     {   's',                  0,    T29                     }
  292. };
  293.  
  294. static
  295. KEY T22[3] = {
  296.     {   ' ',                  3,    NULL                    },
  297.     {   'g',                  0,    T23                     },
  298.     {   'n',                  0,    T28                     }
  299. };
  300.  
  301. static
  302. KEY T31[2] = {
  303.     {   ' ',                  2,    NULL                    },
  304.     {   'g',           T_STRING,    NULL                    }
  305. };
  306.  
  307. static
  308. KEY T30[2] = {
  309.     {   ' ',                  2,    NULL                    },
  310.     {   'n',                  0,    T31                     }
  311. };
  312.  
  313. static
  314. KEY T2f[2] = {
  315.     {   ' ',                  2,    NULL                    },
  316.     {   'i',                  0,    T30                     }
  317. };
  318.  
  319. static
  320. KEY T2e[2] = {
  321.     {   ' ',                  2,    NULL                    },
  322.     {   'r',                  0,    T2f                     }
  323. };
  324.  
  325. static
  326. KEY  T21[3] = {
  327.     {   ' ',                  3,    NULL                    },
  328.     {   'e',                  0,    T22                     },
  329.     {   't',                  0,    T2e                     }
  330. };
  331.  
  332. static
  333. KEY T35[2] = {
  334.     {   ' ',                  2,    NULL                    },
  335.     {   'l',            T_TOTAL,    NULL                    }
  336. };
  337.  
  338. static
  339. KEY T34[2] = {
  340.     {   ' ',                  2,    NULL                    },
  341.     {   'a',                  0,    T35                     }
  342. };
  343.  
  344. static
  345. KEY T33[2] = {
  346.     {   ' ',                  2,    NULL                    },
  347.     {   't',                  0,    T34                     }
  348. };
  349.  
  350. static
  351. KEY T32[2] = {
  352.     {   ' ',                  2,    NULL                    },
  353.     {   'o',                  0,    T33                     }
  354. };
  355.  
  356. static
  357. KEY T0[12] = {
  358.     {   ' ',                 12,    NULL                    },
  359.     {   'a',                  0,    T1                      },
  360.     {   'b',                  0,    T9                      },
  361.     {   'c',                  0,    Tc                      },
  362.     {   'h',                  0,    Tf                      },
  363.     {   'i',                  0,    T14                     },
  364.     {   'n',                  0,    T19                     },
  365.     {   'p',                  0,    T1e                     },
  366.     {   's',                  0,    T21                     },
  367.     {   't',                  0,    T32                     },
  368.     {   '{',          T_L_BRACE,    NULL                    },
  369.     {   '}',          T_R_BRACE,    NULL                    }
  370. };
  371.  
  372. /*-----------------------------------------------------------------------------
  373. | Routine   :   TrieSrch() --- Search the trie for a token.
  374. |
  375. | Inputs    :   Keys    - The trie level pointer.
  376. |               ch      - The current character to search for.
  377. |               WordPtr - The pointer to the current byte of the word buffer.
  378. | Outputs   :   The token number or TKN_NOT_FND for not found.
  379. -----------------------------------------------------------------------------*/
  380.  
  381. static
  382. int     TrieSrch(KEY    *Keys,
  383.                  int    ch,
  384.                  char   *WordPtr)
  385. {
  386.     register    int     mid;        /* Mid point of array piece.            */
  387.     register    TKNS    ret;        /* Return value of comparison.          */
  388.  
  389.     auto        int     lo;         /* Limits of current array piece.       */
  390.     auto        int     hi;
  391.  
  392.      /* Make sure that input is lower case.  */
  393.     ch = tolower( ch );
  394.  
  395.     /* Search for a token.  */
  396.     hi = Keys[0].val - 1;
  397.     lo = 1;
  398.     do
  399.     {
  400.         /* Find mid point of current array piece.   */
  401.         mid = (lo + hi) >> 1;
  402.  
  403.         /* Do character comparison. */
  404.         ret = ch - Keys[mid].c;
  405.  
  406.         /* Fix the array limits.    */
  407.         if (ret <= 0)
  408.             hi = mid - 1;
  409.         if (ret >= 0)
  410.             lo = mid + 1;
  411.  
  412.     }  while (hi >= lo);
  413.  
  414.     /*  If the character matches one of the entries in this level and this
  415.     *   entry has a child, recurse.  If a match is found but the matching
  416.     *   entry has no child, return the token value associated with the
  417.     *   match.  If the return value from the recursive call indicates that
  418.     *   no match was found at a lower level, return the token value
  419.     *   associated with the match at this level of the trie.
  420.     */
  421.     if (ret == 0)
  422.     {
  423.         /* Save the current character.  */
  424.         *WordPtr++ = ch;
  425.  
  426.         /* Is this the last character in the string?    */
  427.         if ( Keys[mid].branch )
  428.         {
  429.             /* Get the next character.  */
  430.             if ((ch = fgetc( PrgFl )) == EOF)
  431.                 return( EOF );
  432.  
  433.             /* Search next level.   */
  434.             if ((ret = TrieSrch(Keys[mid].branch, ch, WordPtr)) == T_NOT_FND)
  435.             {
  436.                 ungetc(ch, PrgFl);
  437.                 return( Keys[mid].val );
  438.             }
  439.             return( ret );
  440.         }
  441.         else
  442.         {
  443.             *WordPtr = '\0';
  444.             return( Keys[mid].val );
  445.         }
  446.     }
  447.  
  448.     /* Return not found.    */
  449.     *WordPtr = '\0';
  450.     return( T_NOT_FND );
  451. }
  452.  
  453. /*-----------------------------------------------------------------------------
  454. | Routine   :   Lex() --- Get the next key word from the input file.
  455. |
  456. | Outputs   :   sym - The symbolic data read from the file.
  457. |
  458. | Return :   Returns the token read or EOF.
  459. -----------------------------------------------------------------------------*/
  460.  
  461. int     Lex(TOKEN   *sym)
  462. {
  463.     register    int     tkn;
  464.     auto        int     ch;
  465.     extern      FILE    *ErrFile;
  466.  
  467.     /* Strip comments and white space.  If the character read is a '#',
  468.     *   every thing to the end of the line is a comment.
  469.     */
  470.     ch = fgetc( PrgFl );
  471.     while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#')
  472.     {
  473.         /* Process the special characters '#' and '\n'.     */
  474.         if (ch == '\n')
  475.             LnNo++;
  476.         else if (ch == '#')
  477.         {
  478.             while (fgetc( PrgFl ) != '\n')
  479.                 ;
  480.             LnNo++;
  481.         }
  482.  
  483.         /* Get the next character.  */
  484.         ch = fgetc( PrgFl );
  485.     }
  486.  
  487.     /* Get strings, etc.    */
  488.     if (ch == '"')
  489.     {
  490.         auto    char    *bf;
  491.  
  492.         /* Get contents of string.  */
  493.         bf = sym->str;
  494.         while ((ch = fgetc( PrgFl )) != '"' && ch != EOF)
  495.             *bf++ = ch;
  496.         *bf = '\0';
  497.  
  498.         /* Return string token. */
  499.         return( T_DBL_QUOTE );
  500.     }
  501.     else if (ch >= '0' && ch <= '9')
  502.     {
  503.         /* Get the number.  */
  504.         sym->no = 0;
  505.         do
  506.         {
  507.             sym->no = sym->no * 10 + (ch - '0');
  508.         }  while ((ch = fgetc( PrgFl )) >= '0' && ch <= '9');
  509.  
  510.         /* Return the unused character. */
  511.         ungetc(ch, PrgFl);
  512.         return( T_INT_NO );
  513.     }
  514.     else if (ch == EOF)
  515.         return( EOF );
  516.  
  517.     /* Call the trie search routine to return the next token, EOF
  518.     *   or NOT_FND.  If not found, print an error and quit.
  519.     */
  520.     if ((tkn = TrieSrch(T0, ch, word)) == T_NOT_FND || tkn == 0)
  521.     {
  522.         fprintf(ErrFile,
  523.                 "%s %d : Error - cannot identify string '%s' ",
  524.                  __FILE__,
  525.                 __LINE__,
  526.                 word);
  527.         fprintf(ErrFile,
  528.                 "in line %d\n",
  529.                 LnNo + 1);
  530.         exit( 1 );
  531.     }
  532.  
  533.     /* Return the token found.  */
  534.     return( tkn );
  535. }
  536.  
  537. /*-----------------------------------------------------------------------------
  538. | Routine   :   OpenCfg() --- Open the ASCII text file that contains the
  539. |               configuration data.
  540. -----------------------------------------------------------------------------*/
  541.  
  542. void    OpenCfg(char    *FileNm)
  543. {
  544.     extern  FILE    *ErrFile;
  545.  
  546.     /* Open the program script file.    */
  547.     if ((PrgFl = fopen(FileNm, TXT_READ)) == NULL)
  548.     {
  549.         fprintf(ErrFile,
  550.                 "%s %d : Error - %s\n",
  551.                 __FILE__,
  552.                 __LINE__,
  553.                 sys_errlist[errno]);
  554.         fprintf(ErrFile,
  555.                 "\tFile Name: '%s'\n",
  556.                 FileNm);
  557.         exit( 1 );
  558.     }
  559. }
  560.  
  561. /*-----------------------------------------------------------------------------
  562. | Routine   :   CloseCfg() --- Close the ASCII text file that contains the
  563. |               configuration data.
  564. -----------------------------------------------------------------------------*/
  565.  
  566. void    CloseCfg(void)
  567. {
  568.     fclose( PrgFl );
  569. }
  570.  
  571. /*-----------------------------------------------------------------------------
  572. | Routine   :   ParseErr() --- Report a parse error.
  573. |
  574. | Inputs    :   ErrStr  - The error string.
  575. -----------------------------------------------------------------------------*/
  576.  
  577. void    ParseErr(char   *ErrStr)
  578. {
  579.     extern  FILE    *ErrFile;
  580.  
  581.     fprintf(ErrFile,
  582.             "%s %d : Error - %s\n",
  583.             __FILE__,
  584.             __LINE__,
  585.             ErrStr);
  586.     fprintf(ErrFile,
  587.             "\tLine %d, word '%s'\n",
  588.             LnNo + 1,
  589.             word);
  590.      exit( 1 );
  591. }
  592.