/******************************************************************************
* Module : Parse --- Search for a particular line.
*
* Author : John W. M. Stevens
******************************************************************************/
#include "compiler.h"
#include "unpost.h"
#include "regexp.h"
#include "uudec.h"
#include "modflnm.h"
#include "ident.h"
#include "parse.h"
#include "config.h"
#include "utils.h"
/* These are the elements we have to parse out of either the header or
* the body of the message BEFORE we find the first UUencoded line.
*/
typedef enum {
ID_STRING,
SEGMENT_NO,
NO_SEGMENTS
} PARSE_ELS;
/*
* Regular expression source strings.
*
* To configure the program for different systems, these are the
* strings to change.
*/
static PART_RE Parts1[] =
{
{ "^Subject:(.*)[[({]Part[_ \t]*([0-9]+)[^0-9]+([0-9]+)[)\\]}](.*)",
1, 2, 3, 4, IGN_CASE, NULL
},
{ "^Subject:(.*)Part[_ \t]*[[({]([0-9]+)[^0-9]+([0-9]+)[)\\]}](.*)",
1, 2, 3, 4, IGN_CASE, NULL
},
{ "^Subject:(.*)Part[_ \t]+([0-9]+)[^0-9]+([0-9]+)(.*)",
1, 2, 3, 4, IGN_CASE, NULL
},
{ "^Subject:(.*)[([{][ \t]*([0-9]+)[^0-9]+([0-9]+)[ \t]*[)\\]}](.*)",
1, 2, 3, 4, IGN_CASE, NULL
},
{ "^Subject:(.*)([0-9]+)([/|]|[ \t]+of[ \t]+)([0-9]+)(.*)",
1, 2, 4, 5, IGN_CASE, NULL
},
{ "^Subject:(.*)",
1, 0, 0, 0, IGN_CASE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
static PART_RE Parts3[] =
{
{ "^X-File-Name:[ \t]+(.*)",
1, 0, 0, 0, CASE_SENSITIVE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
static PART_RE Parts4[] =
{
{ "^X-Part:[ \t]+([0-9]+)",
0, 1, 0, 0, CASE_SENSITIVE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
static PART_RE Parts5[] =
{
{ "^X-Part-Total:[ \t]+([0-9]+)",
0, 0, 1, 0, CASE_SENSITIVE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
static PART_RE Parts6[] =
{
{ "^Uusplit-part:[ \t]+([0-9]+)",
0, 1, 0, 0, CASE_SENSITIVE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
static PART_RE Parts7[] =
{
{ "^Uusplit-parts:[ \t]+([0-9]+)",
0, 0, 1, 0, CASE_SENSITIVE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
static PART_RE Parts8[] =
{
{ "^section ([0-9]+) of uuencode [0-9]+\\.[0-9]+ of file ([^ \t]+)[ \t]+by R.E.M.",
2, 1, 0, 0, CASE_SENSITIVE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
/*
static PART_RE Parts9[] =
{
{ "^([^ \t]+)[ \t]+section[ \t]+([0-9]+)/([0-9]+)[ \t]+UUXFER ver ",
1, 2, 3, 0, CASE_SENSITIVE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
*/
static PART_RE Parts10[] =
{
{ "^POST V.* ([^ \t]+).*\\(Part ([0-9]+)/([0-9]+)\\)",
1, 2, 3, 0, CASE_SENSITIVE, NULL
},
{ NULL,
0, 0, 0, 0, IGN_CASE, NULL
}
};
static IDENT Hdr1[] =
{
{ "^Subject:", Parts1, NULL },
{ "^X-File-Name:", Parts3, NULL },
{ "^X-Part:", Parts4, NULL },
{ "^X-Part-Total:", Parts5, NULL },
{ "^Uusplit-part:", Parts6, NULL },
{ "^Uusplit-parts:", Parts7, NULL },
{ NULL, NULL, NULL }
};
static IDENT Body1[] =
{
{ "^Subject:", Parts1, NULL },
{ "^section [0-9]+ of uuencode [0-9]+\\.[0-9]+ of file [^ \t]+ by R.E.M.",
Parts8, NULL },
{ "^POST V", Parts10, NULL },
/* { "^[^ \t]+[ \t]+section[ \t]+[0-9]+/[0-9]+[ \t]+UUXFER ver ",
Parts9, NULL },
*/
{ NULL, NULL, NULL }
};
/*=============================================================================
|| SEGMENT begin line regular expressions are defined below.
||
|| These can be set by command line switch.
=============================================================================*/
static SEGMENT RnSegs[] =
{
{ "^(Article[:]?|X-NEWS:) ", Hdr1, Body1, NULL },
{ NULL, NULL, NULL, NULL }
};
static SEGMENT NnSegs[] =
{
{ "^From[:]? ", Hdr1, Body1, NULL },
{ NULL, NULL, NULL, NULL }
};
static SEGMENT EmailSegs[] =
{
{ "^From ", Hdr1, Body1, NULL },
{ NULL, NULL, NULL, NULL }
};
static SEGMENT GroupsSegs[] =
{
{ "^Newsgroups: ", Hdr1, Body1, NULL },
{ NULL, NULL, NULL, NULL }
};
static SEGMENT *Segments = RnSegs;
static REG_EXP_NODE *Begin = NULL;
static REG_EXP_NODE *End = NULL;
static REG_EXP_NODE *CrcRE = NULL;
static char *BeginStr = "^begin[ \t]+([0-7]+)[ \t]+([^ \t]+)";
static char *EndStr = "^end[ \t]*$";
static char *CrcStr = "^POST Crc: 0x([0-9a-fA-F]+)";
/*-----------------------------------------------------------------------------
| Routine : GetBinFlNm() --- Get the binary file name.
|
| Inputs : InFlPtr - Pointer to source file.
| Outputs : FlName - Pointer to file name buffer.
-----------------------------------------------------------------------------*/
int GetBinFlNm(FILE *InFlPtr,
char **RetStrs,
char *FlName)
{
auto long LnOfs;
auto int RetVal;
auto char *tp;
auto char *sp;
auto int OutLen;
auto char Exten[5];
auto char BeginName[FL_NM_SZ];
/* Externals used by this function. */
extern BYTE OutBfr[];
extern char SegLine[];
extern char InBfr[];
extern char UULine[];
extern FILE *ErrFile;
extern int MsDosFileNms;
/* Extract the file name. */
for (tp = BeginName, sp = RetStrs[2];
*sp && *sp != '\n' && *sp != ' ' && *sp != '\t';
)
*tp++ = *sp++;
*tp = '\0';
/* Munge file name? */
RetVal = 0;
if ( MsDosFileNms )
{
/* Get the current file offset. */
LnOfs = ftell( InFlPtr );
/* Get next line and identify file type. */
*Exten = '\0';
if (ReadLine(InFlPtr, InBfr, BFR_SIZE) == EOF)
{
fprintf(ErrFile,
"%s %d : Warning - Unexpected end of file in segment:\n",
__FILE__,
__LINE__);
fprintf(ErrFile,
"\tSegment: '%s'\n",
SegLine);
RetVal = 2;
}
else if (DecUULine(InBfr, &OutLen, OutBfr) == NOT_UU_LINE)
{
fprintf(ErrFile,
"%s %d : Warning - No UU line after begin.\n",
__FILE__,
__LINE__);
fprintf(ErrFile,
"\tSegment: '%s'\n",
SegLine);
RetVal = 2;
}
else
{
/* Attempt to ID the file. */
IdUUFile(OutBfr, OutLen, Exten);
/* Modify the file name to be MS-DOS compatible. */
ModifyFlNm(BeginName, Exten, FlName);
}
/* Position file pointer to start of line. */
if (fseek(InFlPtr, LnOfs, SEEK_SET) != 0)
{
fprintf(ErrFile,
"%s %d : Error - %s\n",
__FILE__,
__LINE__,
strerror( errno ));
exit( 1 );
}
}
else
strcpy(FlName, BeginName);
#if defined(UNPOST_DEBUG)
printf("\tBinary File Name: '%s'\n", FlName);
#endif
return( RetVal );
}
/*-----------------------------------------------------------------------------
| Routine : MatchEnd() --- Match a uuencode end line.
|
| Inputs : Line - The line to attempt to match against.
-----------------------------------------------------------------------------*/
int MatchEnd(char *Line)
{
auto char **RetStrs;
/* Attempt to match the line. */
return( ReMatch(Line, CASE_SENSITIVE, End, &RetStrs) );
}
/*-----------------------------------------------------------------------------
| Routine : MatchBegin() --- Match a uuencode begin line.
|
| Inputs : Line - The line to attempt to match against.
| Outputs : RetStrs - Returned sub-strings.
-----------------------------------------------------------------------------*/
int MatchBegin(char *Line,
char ***RetStrs)
{
/* Attempt to match the line. */
return( ReMatch(Line, CASE_SENSITIVE, Begin, RetStrs) );
}
/*-----------------------------------------------------------------------------
| Routine : MatchSegment() --- Match a SEGMENT begin line.
|
| Inputs : Line - The line to attempt to match against.
| Outputs : Hdr - Pointer to header ID line RE's.
| Body - Pointer to body ID line RE's.
-----------------------------------------------------------------------------*/
int MatchSegment(char *Line,
IDENT **Hdr,
IDENT **Body)
{
register int i;
auto char **RetStrs;
/* Attempt to match the line. */
for (i = 0; Segments[i].ReExprStr; i++)
{
/* Attempt to match one of the segment begin lines. */
if (ReMatch(Line,
CASE_SENSITIVE,
Segments[i].ReExpr,
&RetStrs) != 0)
{
*Hdr = Segments[i].Header;
*Body = Segments[i].Body;
return( 1 );
}
}
/* Return not matched. */
Hdr = NULL;
Body = NULL;
return( 0 );
}
/*-----------------------------------------------------------------------------
| Routine : GetBinID() --- Get binary ID string.
|
| Inputs : SubStr - Pointer to possible ID sub-string.
| Outputs : IDStr - Pointer to ID string buffer.
-----------------------------------------------------------------------------*/
static
void GetBinID(char *SubStr,
char *IDStr)
{
auto int ExtSep;
auto char *DestPtr;
auto char *tp;
extern int MsDosFileNms;
/* Filter string. */
FlNmFilter( SubStr );
/* Attempt to guess at a file name. */
for (tp = SubStr; *tp; )
{
/* Skip white space. */
while (*tp == ' ' || *tp == '\t')
tp++;
/* Get word. */
for (DestPtr = IDStr, ExtSep = 0;
*tp && *tp != ' ' && *tp != '\t';
tp++)
{
/* Check to see if this is and extension separator
* character, and if so, count how many.
*/
if (*tp == EXT_SEP_CHAR)
ExtSep++;
/* Copy character. */
*DestPtr++ = *tp;
}
*DestPtr = '\0';
/* Does this look like a file name? */
if ( ExtSep )
{
#if defined(UNPOST_DEBUG)
printf("\tBinary ID: '%s'\n", IDStr);
#endif
return;
}
}
/* OK, we didn't find anything that looks like it could possibly
* be a file name, so munge all the pieces together.
*/
for (tp = SubStr, DestPtr = IDStr; *tp; )
{
/* Skip white space. */
if (*tp == ' ' || *tp == '\t')
tp++;
else
*DestPtr++ = *tp++;
}
*DestPtr = '\0';
#if defined(UNPOST_DEBUG)
printf("\tBinary ID: '%s'\n", IDStr);
#endif
}
/*-----------------------------------------------------------------------------
| Routine : ParseIDLine() --- Extract the ID string, part number and
| total number of parts from the ID line.
|
| Inputs : IDLine - Pointer to ID line.
| PartREs - Array of part number parsing RE's.
| Outputs : Elements - Aqquisition flags for the three items to
| parse out, ID string, Segment number and
| total number of segments.
| SegInfo - Pointer to segment information buffer.
-----------------------------------------------------------------------------*/
static
void ParseIDLine(char *IDLine,
PART_RE *PartREs,
int *Elements,
SEG_INFO *SegInfo)
{
register int i;
auto char **RetStrs;
auto PART_RE *PartRec;
auto char IDBfr[FL_NM_SZ];
/* Externals used in this function. */
extern FILE *ErrFile;
/* Seach for a matching part number parsing regular expression. */
for (PartRec = NULL, i = 0;
PartREs[i].ReExpStr;
i++)
{
/* Does this RE match the ID line? */
if (ReMatch(IDLine,
PartREs[i].Case,
PartREs[i].ReExpr,
&RetStrs) != 0)
{
#if defined(UNPOST_DEBUG)
printf("\tExtract RE: /%s/\n", PartREs[i].ReExpStr);
#endif
PartRec = PartREs + i;
break;
}
}
/* If no match found, return. */
if (PartRec == NULL)
return;
/* Get what elements we do not yet have. */
for (i = ID_STRING; i <= NO_SEGMENTS; i++)
{
/* Get this element, if it is available. */
switch ( i )
{
case 0: /* Get ID string. */
/* Check for no ID string. */
if (PartRec->IDStr == 0)
break;
/* Extract ID string from sub string. */
GetBinID(RetStrs[ PartRec->IDStr ], IDBfr);
/* Check to see if there was an ID string or not. */
if (*IDBfr == '\0')
{
/* Is there an alternate regular expression for
* extracting the binary ID string?
*/
if (PartRec->AltIDStr > 0)
{
/* OK, try other side. */
GetBinID(RetStrs[ PartRec->AltIDStr ], IDBfr);
if (*IDBfr == '\0')
break;
}
else
break;
}
/* Duplicate the ID string. */
if (SegInfo->IDString != NULL)
free( SegInfo->IDString );
SegInfo->IDString = StrDup( IDBfr );
Elements[i] = 1;
break;
case 1: /* Get the segment number. */
/* Check for no segment number. */
if (PartRec->SegNo == 0)
break;
/* Get the segment number. */
if ((SegInfo->SegNo = atoi( RetStrs[ PartRec->SegNo ] )) < 0)
break;
Elements[i] = 1;
break;
case 2: /* Get total number of segments. */
/* Check for no total number of segments. */
if (PartRec->NoSegs == 0)
break;
/* Get the total number of segments. */
if ((SegInfo->NoSegs = atoi( RetStrs[ PartRec->NoSegs ] )) <= 0)
break;
Elements[i] = 1;
break;
}
}
}
/*-----------------------------------------------------------------------------
| Routine : IdSearch() --- Search for an ID line.
|
| Inputs : InFlPtr - Input file pointer.
| IdPtr - Pointer to ID RE hierarchy for this SEGMENT.
| Outputs : Elements - Check list for data elements.
| IDLine - Contains ID line.
| UULnType - Type of UU encoded line found.
| RetStrs - Returned sub strings from RE match.
| SegInfo - Pointer to segment information buffer.
|
| Returns : Returns one of:
-----------------------------------------------------------------------------*/
static
long IdSearch(FILE *InFlPtr,
IDENT *IdPtr,
int *Elements,
char *IDLine,
CHK_UU_ENC *UULnType,
char ***RetStrs,
SEG_INFO *SegInfo)
{
register int i;
auto long LnOfs;
auto int EncLen;
auto IDENT *Hdr;
auto IDENT *Body;
extern FILE *ErrFile;
/* Search forwards through the file for the first ID line. */
for ( ; ; )
{
/* Get the current file offset. */
LnOfs = ftell( InFlPtr );
/* Get a line from the file. */
if (ReadLine(InFlPtr, IDLine, BFR_SIZE) == EOF)
{
LnOfs = PRS_NO_UU_LN;
break;
}
/* Is this a SEGMENT begin line? */
if ( MatchSegment(IDLine, &Hdr, &Body) )
{
/* Position file pointer to start of line. */
if (fseek(InFlPtr, LnOfs, SEEK_SET) != 0)
{
fprintf(ErrFile,
"%s %d : Error - %s\n",
__FILE__,
__LINE__,
strerror( errno ));
exit( 1 );
}
/* Return that no UU encoded line was found. */
LnOfs = PRS_NO_UU_LN;
break;
}
/* Is this a UUencoded line? */
*UULnType = ChkUULine(IDLine, RetStrs, &EncLen);
if (*UULnType == IS_UU_LINE ||
*UULnType == UU_BEGIN ||
*UULnType == UU_END)
{
/* Did we miss getting a piece of data we would like to
* have?
*/
if (Elements[SEGMENT_NO] == 0 && Elements[NO_SEGMENTS])
{
/* Error message. */
fprintf(ErrFile,
"%s %d : Error - Got number of segments but not ",
__FILE__,
__LINE__);
fprintf(ErrFile,
"segment number.\n");
/* Check for totally idiotic mess. */
if (SegInfo->NoSegs == 1)
{
/* Attempt assumption. */
fprintf(ErrFile,
"\tNumber of Segments: %d\n",
SegInfo->NoSegs);
fprintf(ErrFile,
"\tAssuming Part 1 of 1\n");
SegInfo->SegNo = SegInfo->NoSegs = 1;
}
else
LnOfs = PRS_NO_SEG_NUM;
}
else if (Elements[SEGMENT_NO] && Elements[NO_SEGMENTS] == 0)
{
/* Error message. */
fprintf(ErrFile,
"%s %d : Error - Got segment number but not number ",
__FILE__,
__LINE__);
fprintf(ErrFile,
"of segments.\n");
/* Check segment number. */
if (SegInfo->SegNo == 1)
{
/* Attempt assumption. */
fprintf(ErrFile,
"Segment Number: %d\n\tAssuming Part 1 of 1\n",
SegInfo->SegNo);
SegInfo->SegNo = SegInfo->NoSegs = 1;
}
else
LnOfs = PRS_NO_NUM_SEGS;
}
else if (Elements[SEGMENT_NO] == 0 && Elements[NO_SEGMENTS] == 0)
SegInfo->SegNo = SegInfo->NoSegs = 1;
break;
}
/* Is this an ID line? */
for (i = 0; IdPtr[i].ReExprStr; i++)
{
/* Does this line match? */
if (ReMatch(IDLine,
CASE_SENSITIVE,
IdPtr[i].ReExpr,
RetStrs) != 0)
{
#if defined(UNPOST_DEBUG)
printf("\n\tID Line: '%s'\n", IDLine);
printf("\tBody RE: /%s/\n", IdPtr[i].ReExprStr);
#endif
/* Attempt to parse out one or more elements. */
ParseIDLine(IDLine, IdPtr[i].IdParts, Elements, SegInfo);
break;
}
}
/* Is this a POST CRC line? */
if (ReMatch(IDLine,
IGN_CASE,
CrcRE,
RetStrs) != 0)
{
/* Convert the string to an unsigned long. */
SegInfo->PostCRC = (CRC_TYPE) HexToUL( (*RetStrs)[1] );
SegInfo->ChkCRC = 1;
}
}
/* Return status. */
return( LnOfs );
}
/*-----------------------------------------------------------------------------
| Routine : Header() --- Search for legal header ID lines.
|
| Inputs : InFlPtr - Input file pointer.
| IdPtr - Pointer to ID RE hierarchy for this SEGMENT.
| Outputs : Elements - Checklist for needed pieces of information.
| IDLine - Contains ID line.
| SegInfo - Pointer to segment information buffer.
|
| Returns : Returns one of:
| PRS_NO_UU_LN - For no uuencoded line found in segment.
| 1L - OK.
-----------------------------------------------------------------------------*/
static
long Header(FILE *InFlPtr,
IDENT *IdPtr,
int *Elements,
char *IDLine,
SEG_INFO *SegInfo)
{
register int i;
auto char **RetStrs;
auto char *tp;
extern FILE *ErrFile;
/* Search forwards through the file for the first ID line. */
for ( ; ; )
{
/* Is this an ID line? */
for (i = 0; IdPtr[i].ReExprStr; i++)
{
/* Does this line match? */
if (ReMatch(IDLine,
CASE_SENSITIVE,
IdPtr[i].ReExpr,
&RetStrs) != 0)
{
#if defined(UNPOST_DEBUG)
printf("\n\tID Line: '%s'\n", IDLine);
printf("\tHeader RE: /%s/\n", IdPtr[i].ReExprStr);
#endif
/* Attempt to parse out one or more elements. */
ParseIDLine(IDLine, IdPtr[i].IdParts, Elements, SegInfo);
break;
}
}
/* Get a line from the file. */
if (ReadLine(InFlPtr, IDLine, BFR_SIZE) == EOF)
return( PRS_NO_UU_LN );
/* Check for a blank line, which is the header delimiter. */
for (tp = IDLine; *tp == ' ' || *tp == '\t'; tp++)
;
if (*tp == '\0' || *tp == '\n')
break;
}
/* Return that no errors occured. */
return( 1L );
}
/*-----------------------------------------------------------------------------
| Routine : Parse() --- Parse out a SEGMENT and ID line.
|
| Inputs : InFlPtr - Input file pointer.
| Outputs : SegLine - Contains the segment line.
| IDLine - Contains ID line.
| UULine - Contains the first UU encoded line.
| SegInfo - Pointer to segment information buffer.
|
| Returns : Returns one of:
| PRS_NO_SEGMENT - End of file found.
| PRS_NO_UU_LN - No uuencoded line found in article.
| PRS_NO_ID_STR - No ID string found at all.
| PRS_NO_BEGIN - No uuencode begin line found in first
| segment.
-----------------------------------------------------------------------------*/
long Parse(FILE *InFlPtr,
char *SegLine,
char *IDLine,
SEG_INFO *SegInfo)
{
register int i;
auto long LnOfs;
auto char **RetStrs;
auto IDENT *Hdr;
auto IDENT *Body;
auto CHK_UU_ENC UULnType;
auto int Elements[NO_SEGMENTS + 1];
auto char FlName[FL_NM_SZ];
/* Externals used by this function. */
extern FILE *ErrFile;
extern int MsDosFileNms;
/* Initialize the elements array to show that we have none of the
* elements.
*/
for (i = ID_STRING; i <= NO_SEGMENTS; i++)
Elements[i] = 0;
/* Search forwards through the file for the first SEGMENT
* begin line.
*/
for ( ; ; )
{
/* Get the current file offset. */
LnOfs = ftell( InFlPtr );
/* Get a line from the file. */
if (ReadLine(InFlPtr, SegLine, BFR_SIZE) == EOF)
return( PRS_NO_SEGMENT );
/* Is this a SEGMENT begin line? */
if ( MatchSegment(SegLine, &Hdr, &Body) )
{
#if defined(UNPOST_DEBUG)
printf("Segment Begin: '%s'\n", SegLine);
#endif
strcpy(IDLine, SegLine);
break;
}
}
/* Initialize new segment. */
SegInfo->SegOfs = LnOfs;
/* Process header block. */
LnOfs = Header(InFlPtr,
Hdr,
Elements,
IDLine,
SegInfo);
if (LnOfs < 0L)
return( LnOfs );
/* Process body to end of segment or first UU line. */
LnOfs = IdSearch(InFlPtr,
Body,
Elements,
IDLine,
&UULnType,
&RetStrs,
SegInfo);
if (LnOfs < 0L)
return( LnOfs );
/* Is this the begin line? */
SegInfo->UUOfs = LnOfs;
if (UULnType != UU_BEGIN)
{
/* If this is segment number 1 and we did not find a begin line,
* that is BIG trouble, so report an error.
*/
if (SegInfo->SegNo == 1)
{
fprintf(ErrFile,
"%s %d : Error - No begin line in first segment:\n",
__FILE__,
__LINE__);
fprintf(ErrFile,
"\tSegment: '%s'\n",
SegLine);
return( PRS_NO_BEGIN );
}
return( 0L );
}
/* Get file name from begin line. */
GetBinFlNm(InFlPtr, RetStrs, FlName);
#if defined(UNPOST_DEBUG)
printf("\tFile Name: '%s'\n", FlName);
#endif
/* Return no errors occurred. */
if ( *FlName )
SegInfo->FlName = StrDup( FlName );
return( 0L );
}
/*-----------------------------------------------------------------------------
| Routine : FreeCfg() --- Free a configuration that was created by
| reading a configuration file.
-----------------------------------------------------------------------------*/
static
void FreeCfg(void)
{
register int i;
register int j;
register int k;
/* If the default configuration is in place, do nothing, else
* free the old configuration.
*/
if (Segments != NnSegs && Segments != RnSegs &&
Segments != GroupsSegs && Segments != EmailSegs)
{
/* Free all ID prefix lists in SEGMENT list. */
for (i = 0; Segments[i].ReExprStr; i++)
{
/* Free all ID part lists in ID prefix list. */
for (j = 0;
Segments[i].Header[j].ReExprStr;
j++)
{
/* Free all part extraction RE's, etc. */
for (k = 0;
Segments[i].Header[j].IdParts[k].ReExpStr;
k++)
{
free( Segments[i].Header[j].IdParts[k].ReExpStr );
FreeReExpr( Segments[i].Header[j].IdParts[k].ReExpr );
}
/* Free list memory and regular expression. */
free( Segments[i].Header[j].IdParts );
free( Segments[i].Header[j].ReExprStr );
(void) FreeReExpr( Segments[i].Header[j].ReExpr );
}
free( Segments[i].Header );
/* Free all ID part lists in ID prefix list. */
for (j = 0;
Segments[i].Body[j].ReExprStr;
j++)
{
/* Free all part extraction RE's, etc. */
for (k = 0;
Segments[i].Body[j].IdParts[k].ReExpStr;
k++)
{
free( Segments[i].Body[j].IdParts[k].ReExpStr );
FreeReExpr( Segments[i].Body[j].IdParts[k].ReExpr );
}
/* Free list memory and regular expression. */
free( Segments[i].Body[j].IdParts );
free( Segments[i].Body[j].ReExprStr );
(void) FreeReExpr( Segments[i].Body[j].ReExpr );
}
free( Segments[i].Body );
/* Free the regular expression graph for the segment. */
free( Segments[i].ReExprStr );
(void) FreeReExpr( Segments[i].ReExpr );
}
/* Free SEGMENT list. */
free( Segments );
}
}
/*-----------------------------------------------------------------------------
| Routine : SetSegBegin() --- Set the segment begin line regular
| expression.
|
| Inputs : SegType - Either 'e', 'g', 'n', 'm', 'r'.
-----------------------------------------------------------------------------*/
void SetSegBegin(char *SegType)
{
register int i;
/* Free any previously allocated configurations (configurations
* read in from a config file only.
*/
FreeCfg();
/* Determine which type, based on input string. */
switch ( tolower( *SegType ) )
{
case 'e':
Segments = EmailSegs;
break;
case 'g':
Segments = GroupsSegs;
break;
case 'n':
Segments = NnSegs;
break;
case 'r':
default:
Segments = RnSegs;
break;
}
/* Compile SEGMENT begin RE's. */
for (i = 0; Segments[i].ReExprStr; i++)
if (Segments[i].ReExpr == NULL)
Segments[i].ReExpr = ReCompile( Segments[i].ReExprStr );
}
/*-----------------------------------------------------------------------------
| Routine : CompCfg() --- Compile a configuration.
-----------------------------------------------------------------------------*/
static
void CompCfg(void)
{
register int i;
register int j;
register int k;
auto PART_RE *PartPtr;
auto IDENT *IdPtr;
auto SEGMENT *SegPtr;
/* Compile the regular expressions. */
for (i = 0; Segments[i].ReExprStr; i++)
{
/* Compile the unique SEGMENT line prefix. */
SegPtr = Segments + i;
if (SegPtr->ReExpr == NULL)
SegPtr->ReExpr = ReCompile( SegPtr->ReExprStr );
/* Compile all Header ID line information. */
for (j = 0; SegPtr->Header[j].ReExprStr; j++)
{
/* Compile the unique ID line prefix. */
IdPtr = SegPtr->Header + j;
IdPtr->ReExpr = ReCompile( IdPtr->ReExprStr );
/* Compile the part number parsing RE's. */
for (k = 0; IdPtr->IdParts[k].ReExpStr; k++)
{
PartPtr = IdPtr->IdParts + k;
PartPtr->ReExpr = ReCompile( PartPtr->ReExpStr );
}
}
/* Compile all Body ID line information. */
for (j = 0; SegPtr->Body[j].ReExprStr; j++)
{
/* Compile the unique Body ID line prefix. */
IdPtr = SegPtr->Body + j;
IdPtr->ReExpr = ReCompile( IdPtr->ReExprStr );
/* Compile the part number parsing RE's. */
for (k = 0; IdPtr->IdParts[k].ReExpStr; k++)
{
PartPtr = IdPtr->IdParts + k;
PartPtr->ReExpr = ReCompile( PartPtr->ReExpStr );
}
}
}
}
/*-----------------------------------------------------------------------------
| Routine : LoadCfg() --- Load a configuration file.
|
| Inputs : CfgFlNm - Configuration file name.
-----------------------------------------------------------------------------*/
void LoadCfg(char *CfgFlNm)
{
extern FILE *ErrFile;
/* Check for reading a configuration file. */
if (CfgFlNm == NULL || *CfgFlNm == '\0')
{
fprintf(ErrFile,
"%s %d : Error - Missing configuraiton file name.\n",
__FILE__,
__LINE__);
return;
}
/* Free any previously allocated configuration trees. */
FreeCfg();
/* Parse configuration file. */
Segments = ReadConfig( CfgFlNm );
/* Compile the configuration. */
CompCfg();
}
/*-----------------------------------------------------------------------------
| Routine : ParseInit() --- Compile regular expressions here that will
| not change during run time, and compile the default
| configuration.
-----------------------------------------------------------------------------*/
void ParseInit(void)
{
/* Compile the RN default configuration. */
CompCfg();
/* Compile the UU encoding RE's. */
Begin = ReCompile( BeginStr );
End = ReCompile( EndStr );
CrcRE = ReCompile( CrcStr );
}
syntax highlighted by Code2HTML, v. 0.9.1