home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * Module : Parse Configuration File --- Build the regular expression
- * hierarchy tree by reading data from a configuration file.
- *
- * Notes : Configuration file grammar:
- *
- * CONFIG_FILE ::= SEGMENT <EOF>
- * | SEGMENT CONFIG_FILE
- *
- * SEGMENT ::= 'segment' STRING '{' ID_LINES '}'
- *
- * ID_LINES ::= 'header' '{' PREFIXES '}'
- * 'body' '{' PREFIXES '}'
- *
- * PREFIXES ::= PREFIX
- * | PREFIX PREFIXES
- *
- * PREFIX ::= STRING '{' ID_PARTS '}'
- *
- * ID_PARTS ::= ID_PART_RE
- * | ID_PART_RE ID_PARTS
- *
- * ID_PART_RE := STRING '{'
- * 'id' NUMBER
- * 'segment' 'number' NUMBER
- * 'segments' NUMBER
- * 'alternate' 'id' NUMBER
- * 'case' CASE_TYPE
- * '}'
- *
- * CASE_TYPE ::= 'sensitive'
- * | 'ignore'
- *
- * STRING ::= '"' [ -~]* '"'
- *
- * NUMBER ::= [0-9]+
- *
- * Author : John W. M. Stevens
- ******************************************************************************/
-
- #include "compiler.h"
-
- #include "unpost.h"
- #include "lex.h"
- #include "list.h"
- #include "parse.h"
- #include "regexp.h"
- #include "config.h"
- #include "utils.h"
-
- typedef enum {
- ID_SUB_EXPR,
- SEG_NO_SUB_EXPR,
- NO_SEGS_SUB_EXPR,
- ALT_ID_SUB_EXPR,
- CASE_SENSITIVITY
- } ID_PARTS_IDX;
-
- static char ReStr[512];
-
- /*-----------------------------------------------------------------------------
- | Routine : ParseParts() --- Parse the ID line part number blocks.
- |
- | Returns : A pointer to the root of the ID part regular expression tree.
- -----------------------------------------------------------------------------*/
-
- static
- PART_RE *ParseParts(void)
- {
- register int i;
- auto TOKEN sym;
- auto int tkn;
- auto int Elements[5];
- auto char *tp;
- auto PART_RE NewPart;
- auto LIST *PartList;
-
- /* Create ID list. */
- PartList = CrtList( sizeof( PART_RE ) );
-
- /* Get list of part extraction regular expressions. */
- while ((tkn = Lex( &sym )) == T_DBL_QUOTE)
- {
- /* Initialize new part re structure. */
- NewPart.IDStr = 0;
- NewPart.SegNo = 0;
- NewPart.NoSegs = 0;
- NewPart.AltIDStr = 0;
- NewPart.Case = IGN_CASE;
-
- /* Get IDENT line part regular expression string. */
- for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
- {
- /* Copy string from token structure to buffer. */
- strcpy(tp, sym.str);
-
- /* Get next token. */
- if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
- break;
- }
-
- /* Create ID prefix regular expression string. */
- NewPart.ReExpStr = StrDup( ReStr );
-
- /* Check for opening curly brace. */
- if (tkn != T_L_BRACE)
- {
- ParseErr("expecting '{' to open ID part block.");
- exit( 1 );
- }
-
- /* Process components in ANY order. */
- for (i = ID_SUB_EXPR; i <= CASE_SENSITIVITY; i++)
- Elements[i] = 0;
-
- for (i = ID_SUB_EXPR; i <= CASE_SENSITIVITY; i++)
- {
- /* Get a token. */
- if ((tkn = Lex( &sym )) == T_R_BRACE)
- break;
-
- /* Select parse action based on token. */
- switch ( tkn )
- {
- case T_ID:
- /* Check for duplication. */
- if (Elements[ID_SUB_EXPR] != 0)
- {
- ParseErr("duplicate sub-expression numbers.");
- exit( 1 );
- }
-
- /* Get the sub-expression number for the ID sub-string. */
- if ((tkn = Lex( &sym )) != T_INT_NO)
- {
- ParseErr("missing sub-expression number.");
- exit( 1 );
- }
- NewPart.IDStr = sym.no;
- Elements[ID_SUB_EXPR] = 1;
- break;
- case T_SEGMENT:
- /* Check for duplication. */
- if (Elements[SEG_NO_SUB_EXPR] != 0)
- {
- ParseErr("duplicate sub-expression numbers.");
- exit( 1 );
- }
-
- /* Get next token. */
- if ((tkn = Lex( &sym )) != T_NUMBER)
- {
- ParseErr("missing 'number' after 'segment'.");
- exit( 1 );
- }
-
- /* Get sub-expression number for the segment number
- * sub-string.
- */
- if ((tkn = Lex( &sym )) != T_INT_NO)
- {
- ParseErr("missing sub-expression number.");
- exit( 1 );
- }
- NewPart.SegNo = sym.no;
- Elements[SEG_NO_SUB_EXPR] = 1;
- break;
- case T_SEGMENTS:
- /* Check for duplication. */
- if (Elements[NO_SEGS_SUB_EXPR] != 0)
- {
- ParseErr("duplicate sub-expression numbers.");
- exit( 1 );
- }
-
- /* Get number of segments sub-expression number. */
- if ((tkn = Lex( &sym )) != T_INT_NO)
- {
- ParseErr("missing sub-expression number.");
- exit( 1 );
- }
- NewPart.NoSegs = sym.no;
- Elements[NO_SEGS_SUB_EXPR] = 1;
- break;
- case T_ALTERNATE:
- /* Check for duplication. */
- if (Elements[ALT_ID_SUB_EXPR] != 0)
- {
- ParseErr("duplicate sub-expression numbers.");
- exit( 1 );
- }
-
- /* Get next token. */
- if ((tkn = Lex( &sym )) != T_ID)
- {
- ParseErr("missing 'id' after 'alternate'.");
- exit( 1 );
- }
-
- /* Get alternate ID string sub-expression number. */
- if ((tkn = Lex( &sym )) != T_INT_NO)
- {
- ParseErr("missing sub-expression number.");
- exit( 1 );
- }
- NewPart.AltIDStr = sym.no;
- Elements[ALT_ID_SUB_EXPR] = 1;
- break;
- case T_CASE:
- /* Check for duplication. */
- if (Elements[CASE_SENSITIVITY] != 0)
- {
- ParseErr("duplicate sub-expression numbers.");
- exit( 1 );
- }
-
- /* Get case sensitivity type. */
- if ((tkn = Lex( &sym )) == T_SENSITIVE)
- NewPart.Case = CASE_SENSITIVE;
- else if (tkn == T_IGNORE)
- NewPart.Case = IGN_CASE;
- else
- {
- ParseErr("expected case sensitivity type after 'case'.");
- exit( 1 );
- }
- Elements[CASE_SENSITIVITY] = 1;
- break;
- default:
- ParseErr( "Unexpected token in ID part block" );
- break;
- }
- }
-
- /* Compile string and save pointer to expression tree in
- * structure, then save structure in segment list.
- */
- NewPart.ReExpr = ReCompile( NewPart.ReExpStr );
- PartList = AppList(PartList, &NewPart);
-
- /* Get closing token. */
- if (tkn != T_R_BRACE)
- {
- /* Get and discard the right brace. */
- if ((tkn = Lex( &sym )) != T_R_BRACE)
- {
- ParseErr("expecting '}' to close ID part block.");
- exit( 1 );
- }
- }
- }
-
- /* Check closing token. */
- if (tkn != T_R_BRACE)
- {
- ParseErr("expecting '}' to close ID prefix block.");
- exit( 1 );
- }
-
- /* Append a null record. */
- memset(&NewPart, 0, sizeof( PART_RE ));
- PartList = AppList(PartList, &NewPart);
-
- /* Return pointer to list. */
- MemCopy(PartList,
- PartList->List,
- sizeof( PART_RE ) * PartList->NoElems);
-
- /* Return pointer to list. */
- return( (PART_RE *) PartList );
- }
-
- /*-----------------------------------------------------------------------------
- | Routine : ParseIDs() --- Parse the ID blocks.
- |
- | Returns : A pointer to the root of the ID regular expression tree.
- -----------------------------------------------------------------------------*/
-
- static
- IDENT *ParseIDs(void)
- {
- auto TOKEN sym;
- auto int tkn;
- auto char *tp;
- auto IDENT NewID;
- auto LIST *PreFixList;
-
- /* Create ID list. */
- PreFixList = CrtList( sizeof( IDENT ) );
-
- /* Get regular expression source string. */
- while ((tkn = Lex( &sym )) == T_DBL_QUOTE)
- {
- /* Get IDENT line regular expression string. */
- for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
- {
- /* Copy string from token structure to buffer. */
- strcpy(tp, sym.str);
-
- /* Get next token. */
- if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
- break;
- }
-
- /* Check for opening curly brace. */
- if (tkn != T_L_BRACE)
- {
- ParseErr("expecting '{' after ID prefix regular expression.");
- exit( 1 );
- }
-
- /* Create ID prefix regular expression string. */
- NewID.ReExprStr = StrDup( ReStr );
-
- /* Parse header regular expression configuration block. */
- NewID.IdParts = ParseParts();
-
- /* Compile string and save pointer to expression tree in
- * structure, then save structure in segment list.
- */
- NewID.ReExpr = ReCompile( NewID.ReExprStr );
- PreFixList = AppList(PreFixList, &NewID);
- }
-
- /* Check closing token. */
- if (tkn != T_R_BRACE)
- {
- ParseErr("expecting '}' to close ID block.");
- exit( 1 );
- }
-
- /* Append a null record. */
- memset(&NewID, 0, sizeof( IDENT ));
- PreFixList = AppList(PreFixList, &NewID);
-
- /* Return pointer to list. */
- MemCopy(PreFixList,
- PreFixList->List,
- sizeof( IDENT ) * PreFixList->NoElems);
-
- /* Return pointer to list. */
- return( (IDENT *) PreFixList );
- }
-
- /*-----------------------------------------------------------------------------
- | Routine : ReadConfig() --- Read the configuration file.
- |
- | Inputs : CfgFlNm - Name of configuration file name.
- |
- | Returns : A pointer to the root of the SEGMENT regular expression tree.
- -----------------------------------------------------------------------------*/
-
- SEGMENT *ReadConfig(char *CfgFlNm)
- {
- auto TOKEN sym;
- auto int tkn;
- auto char *tp;
- auto SEGMENT NewSeg;
- auto LIST *SegList;
-
- /* Open the configuration file. */
- OpenCfg( CfgFlNm );
-
- /* Get token. */
- if ((tkn = Lex( &sym )) != T_SEGMENT)
- {
- ParseErr("expecting SEGMENT token.");
- exit( 1 );
- }
-
- /* Create segment list. */
- SegList = CrtList( sizeof( SEGMENT ) );
-
- /* Process multiple SEGMENT begin line blocks. */
- while (tkn == T_SEGMENT)
- {
- /* Get regular expression source string. */
- if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
- {
- ParseErr("expecting regular expression source string.");
- exit( 1 );
- }
-
- /* Get SEGMENT begin line regular expression string. */
- for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
- {
- /* Copy string from token structure to buffer. */
- strcpy(tp, sym.str);
-
- /* Get next token. */
- if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
- break;
- }
-
- /* Check for opening curly brace. */
- if (tkn != T_L_BRACE)
- {
- ParseErr("expecting '{' to open SEGMENT block.");
- exit( 1 );
- }
-
- /* Create SEGMENT regular expression string. */
- NewSeg.ReExprStr = StrDup( ReStr );
-
- /* Get header block prefix. */
- if ((tkn = Lex( &sym )) != T_HEADER)
- {
- ParseErr("expecting 'header' in SEGMENT block.");
- exit( 1 );
- }
-
- /* Get open curly brace. */
- if ((tkn = Lex( &sym )) != T_L_BRACE)
- {
- ParseErr("expecting '{' to open HEADER block.");
- exit( 1 );
- }
-
- /* Get header block. */
- NewSeg.Header = ParseIDs();
-
- /* Get body block prefix. */
- if ((tkn = Lex( &sym )) != T_BODY)
- {
- ParseErr("expecting 'body' in SEGMENT block.");
- exit( 1 );
- }
-
- /* Get open curly brace. */
- if ((tkn = Lex( &sym )) != T_L_BRACE)
- {
- ParseErr("expecting '{' to open BODY block.");
- exit( 1 );
- }
-
- /* Parse body ID block. */
- NewSeg.Body = ParseIDs();
-
- /* Compile string and save pointer to expression tree in
- * structure, then save structure in SEGMENT begin line list.
- */
- NewSeg.ReExpr = ReCompile( NewSeg.ReExprStr );
- SegList = AppList(SegList, &NewSeg);
-
- /* Get closing token. */
- if ((tkn = Lex( &sym )) != T_R_BRACE)
- {
- ParseErr("expecting '}' to close SEGMENT block.");
- exit( 1 );
- }
-
- /* Get next token. */
- if ((tkn = Lex( &sym )) == EOF)
- break;
- }
-
- /* Append a null record. */
- memset(&NewSeg, 0, sizeof( SEGMENT ));
- SegList = AppList(SegList, &NewSeg);
-
- /* Return pointer to list. */
- MemCopy(SegList,
- SegList->List,
- sizeof( SEGMENT ) * SegList->NoElems);
-
- /* Close the configuration file and return a pointer to the new
- * configuration tree.
- */
- CloseCfg();
- return( (SEGMENT *) SegList );
- }
-