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

  1. /******************************************************************************
  2. * Module    :   Parse Configuration File --- Build the regular expression
  3. *               hierarchy tree by reading data from a configuration file.
  4. *
  5. * Notes     :   Configuration file grammar:
  6. *
  7. *   CONFIG_FILE ::= SEGMENT <EOF>
  8. *                   | SEGMENT CONFIG_FILE
  9. *
  10. *   SEGMENT     ::= 'segment' STRING '{' ID_LINES '}'
  11. *
  12. *   ID_LINES    ::= 'header' '{' PREFIXES '}'
  13. *                   'body' '{' PREFIXES '}'
  14. *
  15. *   PREFIXES    ::= PREFIX
  16. *                   | PREFIX PREFIXES
  17. *
  18. *   PREFIX      ::= STRING '{' ID_PARTS '}'
  19. *
  20. *   ID_PARTS    ::= ID_PART_RE
  21. *                   | ID_PART_RE ID_PARTS
  22. *
  23. *   ID_PART_RE  :=  STRING '{'
  24. *                   'id' NUMBER
  25. *                   'segment' 'number' NUMBER
  26. *                   'segments' NUMBER
  27. *                   'alternate' 'id' NUMBER
  28. *                   'case' CASE_TYPE
  29. *                   '}'
  30. *
  31. *   CASE_TYPE   ::= 'sensitive'
  32. *                   | 'ignore'
  33. *
  34. *   STRING      ::= '"' [ -~]* '"'
  35. *
  36. *   NUMBER      ::= [0-9]+
  37. *
  38. * Author    :   John W. M. Stevens
  39. ******************************************************************************/
  40.  
  41. #include    "compiler.h"
  42.  
  43. #include    "unpost.h"
  44. #include    "lex.h"
  45. #include    "list.h"
  46. #include    "parse.h"
  47. #include    "regexp.h"
  48. #include    "config.h"
  49. #include    "utils.h"
  50.  
  51. typedef enum    {
  52.     ID_SUB_EXPR,
  53.     SEG_NO_SUB_EXPR,
  54.     NO_SEGS_SUB_EXPR,
  55.     ALT_ID_SUB_EXPR,
  56.     CASE_SENSITIVITY
  57. } ID_PARTS_IDX;
  58.  
  59. static  char    ReStr[512];
  60.  
  61. /*-----------------------------------------------------------------------------
  62. | Routine   :   ParseParts() --- Parse the ID line part number blocks.
  63. |
  64. | Returns   :   A pointer to the root of the ID part regular expression tree.
  65. -----------------------------------------------------------------------------*/
  66.  
  67. static
  68. PART_RE *ParseParts(void)
  69. {
  70.     register    int     i;
  71.     auto        TOKEN   sym;
  72.     auto        int     tkn;
  73.     auto        int     Elements[5];
  74.     auto        char    *tp;
  75.     auto        PART_RE NewPart;
  76.     auto        LIST    *PartList;
  77.  
  78.     /*  Create ID list. */
  79.     PartList = CrtList( sizeof( PART_RE ) );
  80.  
  81.     /*  Get list of part extraction regular expressions.    */
  82.     while ((tkn = Lex( &sym )) == T_DBL_QUOTE)
  83.     {
  84.         /*  Initialize new part re structure.   */
  85.         NewPart.IDStr    = 0;
  86.         NewPart.SegNo    = 0;
  87.         NewPart.NoSegs   = 0;
  88.         NewPart.AltIDStr = 0;
  89.         NewPart.Case     = IGN_CASE;
  90.  
  91.         /*  Get IDENT line part regular expression string.  */
  92.         for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
  93.         {
  94.             /*  Copy string from token structure to buffer. */
  95.             strcpy(tp, sym.str);
  96.  
  97.             /*  Get next token. */
  98.             if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
  99.                 break;
  100.         }
  101.  
  102.         /*  Create ID prefix regular expression string. */
  103.         NewPart.ReExpStr = StrDup( ReStr );
  104.  
  105.         /*  Check for opening curly brace.  */
  106.         if (tkn != T_L_BRACE)
  107.         {
  108.             ParseErr("expecting '{' to open ID part block.");
  109.             exit( 1 );
  110.         }
  111.  
  112.         /*  Process components in ANY order.    */
  113.         for (i = ID_SUB_EXPR; i <= CASE_SENSITIVITY; i++)
  114.             Elements[i] = 0;
  115.  
  116.         for (i = ID_SUB_EXPR; i <= CASE_SENSITIVITY; i++)
  117.         {
  118.             /*  Get a token.    */
  119.             if ((tkn = Lex( &sym )) == T_R_BRACE)
  120.                 break;
  121.  
  122.             /*  Select parse action based on token. */
  123.             switch ( tkn )
  124.             {
  125.             case T_ID:
  126.                 /*  Check for duplication.  */
  127.                 if (Elements[ID_SUB_EXPR] != 0)
  128.                 {
  129.                     ParseErr("duplicate sub-expression numbers.");
  130.                     exit( 1 );
  131.                 }
  132.  
  133.                 /*  Get the sub-expression number for the ID sub-string.    */
  134.                 if ((tkn = Lex( &sym )) != T_INT_NO)
  135.                 {
  136.                     ParseErr("missing sub-expression number.");
  137.                     exit( 1 );
  138.                 }
  139.                 NewPart.IDStr = sym.no;
  140.                 Elements[ID_SUB_EXPR] = 1;
  141.                 break;
  142.             case T_SEGMENT:
  143.                 /*  Check for duplication.  */
  144.                 if (Elements[SEG_NO_SUB_EXPR] != 0)
  145.                 {
  146.                     ParseErr("duplicate sub-expression numbers.");
  147.                     exit( 1 );
  148.                 }
  149.  
  150.                 /*  Get next token. */
  151.                 if ((tkn = Lex( &sym )) != T_NUMBER)
  152.                 {
  153.                     ParseErr("missing 'number' after 'segment'.");
  154.                     exit( 1 );
  155.                 }
  156.  
  157.                 /*  Get sub-expression number for the segment number
  158.                 *   sub-string.
  159.                 */
  160.                 if ((tkn = Lex( &sym )) != T_INT_NO)
  161.                 {
  162.                     ParseErr("missing sub-expression number.");
  163.                     exit( 1 );
  164.                 }
  165.                 NewPart.SegNo = sym.no;
  166.                 Elements[SEG_NO_SUB_EXPR] = 1;
  167.                 break;
  168.             case T_SEGMENTS:
  169.                 /*  Check for duplication.  */
  170.                 if (Elements[NO_SEGS_SUB_EXPR] != 0)
  171.                 {
  172.                     ParseErr("duplicate sub-expression numbers.");
  173.                     exit( 1 );
  174.                 }
  175.  
  176.                 /*  Get number of segments sub-expression number.   */
  177.                 if ((tkn = Lex( &sym )) != T_INT_NO)
  178.                 {
  179.                     ParseErr("missing sub-expression number.");
  180.                     exit( 1 );
  181.                 }
  182.                 NewPart.NoSegs = sym.no;
  183.                 Elements[NO_SEGS_SUB_EXPR] = 1;
  184.                 break;
  185.             case T_ALTERNATE:
  186.                 /*  Check for duplication.  */
  187.                 if (Elements[ALT_ID_SUB_EXPR] != 0)
  188.                 {
  189.                     ParseErr("duplicate sub-expression numbers.");
  190.                     exit( 1 );
  191.                 }
  192.  
  193.                 /*  Get next token. */
  194.                 if ((tkn = Lex( &sym )) != T_ID)
  195.                 {
  196.                     ParseErr("missing 'id' after 'alternate'.");
  197.                     exit( 1 );
  198.                  }
  199.  
  200.                 /*  Get alternate ID string sub-expression number.  */
  201.                 if ((tkn = Lex( &sym )) != T_INT_NO)
  202.                 {
  203.                     ParseErr("missing sub-expression number.");
  204.                     exit( 1 );
  205.                 }
  206.                 NewPart.AltIDStr = sym.no;
  207.                 Elements[ALT_ID_SUB_EXPR] = 1;
  208.                 break;
  209.             case T_CASE:
  210.                 /*  Check for duplication.  */
  211.                 if (Elements[CASE_SENSITIVITY] != 0)
  212.                 {
  213.                     ParseErr("duplicate sub-expression numbers.");
  214.                     exit( 1 );
  215.                 }
  216.  
  217.                 /*  Get case sensitivity type.  */
  218.                 if ((tkn = Lex( &sym )) == T_SENSITIVE)
  219.                     NewPart.Case = CASE_SENSITIVE;
  220.                 else if (tkn == T_IGNORE)
  221.                     NewPart.Case = IGN_CASE;
  222.                 else
  223.                 {
  224.                     ParseErr("expected case sensitivity type after 'case'.");
  225.                     exit( 1 );
  226.                 }
  227.                 Elements[CASE_SENSITIVITY] = 1;
  228.                 break;
  229.             default:
  230.                 ParseErr( "Unexpected token in ID part block" );
  231.                 break;
  232.             }
  233.         }
  234.  
  235.         /*  Compile string and save pointer to expression tree in
  236.         *   structure, then save structure in segment list.
  237.         */
  238.         NewPart.ReExpr = ReCompile( NewPart.ReExpStr );
  239.         PartList = AppList(PartList, &NewPart);
  240.  
  241.         /*  Get closing token.  */
  242.         if (tkn != T_R_BRACE)
  243.         {
  244.             /*  Get and discard the right brace.    */
  245.             if ((tkn = Lex( &sym )) != T_R_BRACE)
  246.             {
  247.                 ParseErr("expecting '}' to close ID part block.");
  248.                 exit( 1 );
  249.             }
  250.         }
  251.     }
  252.  
  253.     /*  Check closing token.    */
  254.     if (tkn != T_R_BRACE)
  255.     {
  256.         ParseErr("expecting '}' to close ID prefix block.");
  257.         exit( 1 );
  258.     }
  259.  
  260.     /*  Append a null record.   */
  261.     memset(&NewPart, 0, sizeof( PART_RE ));
  262.     PartList = AppList(PartList, &NewPart);
  263.  
  264.      /*  Return pointer to list. */
  265.     MemCopy(PartList,
  266.             PartList->List,
  267.             sizeof( PART_RE ) * PartList->NoElems);
  268.  
  269.     /*  Return pointer to list. */
  270.     return( (PART_RE *) PartList );
  271. }
  272.  
  273. /*-----------------------------------------------------------------------------
  274. | Routine   :   ParseIDs() --- Parse the ID blocks.
  275. |
  276. | Returns   :   A pointer to the root of the ID regular expression tree.
  277. -----------------------------------------------------------------------------*/
  278.  
  279. static
  280. IDENT   *ParseIDs(void)
  281. {
  282.     auto        TOKEN       sym;
  283.     auto        int         tkn;
  284.     auto        char        *tp;
  285.     auto        IDENT       NewID;
  286.     auto        LIST        *PreFixList;
  287.  
  288.     /*  Create ID list. */
  289.     PreFixList = CrtList( sizeof( IDENT ) );
  290.  
  291.     /*  Get regular expression source string.   */
  292.     while ((tkn = Lex( &sym )) == T_DBL_QUOTE)
  293.     {
  294.         /*  Get IDENT line regular expression string.   */
  295.         for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
  296.         {
  297.             /*  Copy string from token structure to buffer. */
  298.             strcpy(tp, sym.str);
  299.  
  300.             /*  Get next token. */
  301.             if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
  302.                 break;
  303.         }
  304.  
  305.         /*  Check for opening curly brace.  */
  306.         if (tkn != T_L_BRACE)
  307.         {
  308.             ParseErr("expecting '{' after ID prefix regular expression.");
  309.             exit( 1 );
  310.         }
  311.  
  312.         /*  Create ID prefix regular expression string. */
  313.         NewID.ReExprStr = StrDup( ReStr );
  314.  
  315.         /*  Parse header regular expression configuration block.    */
  316.         NewID.IdParts = ParseParts();
  317.  
  318.         /*  Compile string and save pointer to expression tree in
  319.         *   structure, then save structure in segment list.
  320.         */
  321.         NewID.ReExpr = ReCompile( NewID.ReExprStr );
  322.         PreFixList = AppList(PreFixList, &NewID);
  323.     }
  324.  
  325.     /*  Check closing token.    */
  326.     if (tkn != T_R_BRACE)
  327.     {
  328.         ParseErr("expecting '}' to close ID block.");
  329.         exit( 1 );
  330.      }
  331.  
  332.     /*  Append a null record.   */
  333.     memset(&NewID, 0, sizeof( IDENT ));
  334.     PreFixList = AppList(PreFixList, &NewID);
  335.  
  336.     /*  Return pointer to list. */
  337.     MemCopy(PreFixList,
  338.             PreFixList->List,
  339.             sizeof( IDENT ) * PreFixList->NoElems);
  340.  
  341.     /*  Return pointer to list. */
  342.     return( (IDENT *) PreFixList );
  343. }
  344.  
  345. /*-----------------------------------------------------------------------------
  346. | Routine   :   ReadConfig() --- Read the configuration file.
  347. |
  348. | Inputs    :   CfgFlNm - Name of configuration file name.
  349. |
  350. | Returns   :   A pointer to the root of the SEGMENT regular expression tree.
  351. -----------------------------------------------------------------------------*/
  352.  
  353. SEGMENT *ReadConfig(char    *CfgFlNm)
  354. {
  355.     auto        TOKEN       sym;
  356.     auto        int         tkn;
  357.     auto        char        *tp;
  358.     auto        SEGMENT     NewSeg;
  359.     auto        LIST        *SegList;
  360.  
  361.     /*  Open the configuration file.    */
  362.     OpenCfg( CfgFlNm );
  363.  
  364.     /*  Get token.  */
  365.     if ((tkn = Lex( &sym )) != T_SEGMENT)
  366.     {
  367.         ParseErr("expecting SEGMENT token.");
  368.         exit( 1 );
  369.     }
  370.  
  371.     /*  Create segment list.    */
  372.     SegList = CrtList( sizeof( SEGMENT ) );
  373.  
  374.     /*  Process multiple SEGMENT begin line blocks. */
  375.     while (tkn == T_SEGMENT)
  376.     {
  377.         /*  Get regular expression source string.   */
  378.         if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
  379.         {
  380.             ParseErr("expecting regular expression source string.");
  381.             exit( 1 );
  382.         }
  383.  
  384.         /*  Get SEGMENT begin line regular expression string.   */
  385.         for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
  386.         {
  387.             /*  Copy string from token structure to buffer. */
  388.             strcpy(tp, sym.str);
  389.  
  390.             /*  Get next token. */
  391.             if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
  392.                 break;
  393.         }
  394.  
  395.         /*  Check for opening curly brace.  */
  396.          if (tkn != T_L_BRACE)
  397.         {
  398.             ParseErr("expecting '{' to open SEGMENT block.");
  399.             exit( 1 );
  400.         }
  401.  
  402.         /*  Create SEGMENT regular expression string.   */
  403.         NewSeg.ReExprStr = StrDup( ReStr );
  404.  
  405.         /*  Get header block prefix.    */
  406.         if ((tkn = Lex( &sym )) != T_HEADER)
  407.         {
  408.             ParseErr("expecting 'header' in SEGMENT block.");
  409.             exit( 1 );
  410.         }
  411.  
  412.         /*  Get open curly brace.   */
  413.         if ((tkn = Lex( &sym )) != T_L_BRACE)
  414.         {
  415.             ParseErr("expecting '{' to open HEADER block.");
  416.             exit( 1 );
  417.         }
  418.  
  419.         /*  Get header block.   */
  420.         NewSeg.Header = ParseIDs();
  421.  
  422.         /*  Get body block prefix.  */
  423.         if ((tkn = Lex( &sym )) != T_BODY)
  424.         {
  425.             ParseErr("expecting 'body' in SEGMENT block.");
  426.             exit( 1 );
  427.         }
  428.  
  429.         /*  Get open curly brace.   */
  430.         if ((tkn = Lex( &sym )) != T_L_BRACE)
  431.         {
  432.             ParseErr("expecting '{' to open BODY block.");
  433.             exit( 1 );
  434.         }
  435.  
  436.         /*  Parse body ID block.    */
  437.         NewSeg.Body = ParseIDs();
  438.  
  439.         /*  Compile string and save pointer to expression tree in
  440.         *   structure, then save structure in SEGMENT begin line list.
  441.         */
  442.         NewSeg.ReExpr = ReCompile( NewSeg.ReExprStr );
  443.         SegList = AppList(SegList, &NewSeg);
  444.  
  445.         /*  Get closing token.  */
  446.         if ((tkn = Lex( &sym )) != T_R_BRACE)
  447.         {
  448.             ParseErr("expecting '}' to close SEGMENT block.");
  449.             exit( 1 );
  450.         }
  451.  
  452.         /*  Get next token. */
  453.         if ((tkn = Lex( &sym )) == EOF)
  454.             break;
  455.     }
  456.  
  457.     /*  Append a null record.   */
  458.     memset(&NewSeg, 0, sizeof( SEGMENT ));
  459.     SegList = AppList(SegList, &NewSeg);
  460.  
  461.     /*  Return pointer to list. */
  462.     MemCopy(SegList,
  463.             SegList->List,
  464.             sizeof( SEGMENT ) * SegList->NoElems);
  465.  
  466.     /*  Close the configuration file and return a pointer to the new
  467.     *   configuration tree.
  468.     */
  469.     CloseCfg();
  470.     return( (SEGMENT *) SegList );
  471. }
  472.