|
|
#include "precomp.h"
#pragma hdrstop
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
infload1.c
Abstract:
Routines to load an INF file and proprocess it, eliminating comments and line continuations, and collapsing adjacent WS and NLs.
The result is a series of NUL-terminated lines, with no blank lines or lines with only comments or whitespace, etc.
Author:
Ted Miller (tedm) 9-Spetember-1991
--*/
/*
The purpose of the preprocessing step is to create a series of significant lines, with comments stripped out.
The file is read from disk into a single large buffer. A destination buffer is allocated to hold the preprocessed file. This buffer is initially the size of the file image but will be reallocated when proprocessing is completed.
The input image is considered to be a sequence of LF or CR/LF separated lines. One line in the input file is equivalent to one line in the output unless the lines are logically joined with line continuation characters.
- A line continuation character is a non-quoted + which has no non-space, non-tab, or non-comment text after it on the line. Line continuation is accomplished by eliminating all characters from the + through adjacent spaces, tabs, comments, and EOLs.
- Two consecutive double quote characters inside a quoted string are replaced by a single double quote.
- Semantic double quuote chars (ie, those that begin and end strings) are replaced by DQUOTE. Double quotes that are actually part of the string (see first rule) are emitted as actual double quote chars. This is so that later steps can tell the difference between two adjacent quoted strings and a string containing a quoted double quote.
- All strings of consecutive spaces and tabs are replaced by a single space. A single space is in turn eliminated if it occurs immediately adjacent to a comma.
- All comments are eliminated. A comment is an unquoted semi-colon and consists of the rest of the line (to EOL).
- CR/LF or LF are replaced by NUL. The EOL does not result in any implied actions being carried out -- ie, a terminating double quote being supplied if none exists in the input.
- Adjacent NULs are never stored in the output. There will be at most a single consecutive NUL character in the output. Also, a space following a NUL is eliminated, as is a space preceeding a NUL.
No syntax errors are reported from this step. */
PUCHAR CurrentOut; // points to next cell in output image
BOOL InsideQuotes; // self-explanatory flag
#define IsWS(x) (((x) == ' ') || ((x) == '\t'))
#define SkipWS(x) Preprocess_SkipChars(x," \t")
#define SkipWSEOL(x) Preprocess_SkipChars(x," \t\r\n");
#define SkipComment(x) Preprocess_SkipChars(x,"");
#define CtN 0 // Normal char; NOTE: same as ZERO!
#define CtS 1 // Space
#define CtE 2 // EOL
#define CtC 3 // Comma
#define CtF 4 // EOF
static BYTE charTypeTable [256] = { // 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
// 0 1 2 3 4 5 6 7 8 9 11 12 13 13 14 15
/////////////////////////////////////////////////////////////////////////////////////////
/* 00 */ CtE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CtF, 0, 0, 0, 0, 0, /* 20 */ CtS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CtC, 0, 0, 0, /* 30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/*
In: pointer to a char list of chars to skip Out: pointer to first char not in the skip list
Also: skips comments. */
VOID Preprocess_SkipChars( LPBYTE *StartingLoc, LPSTR CharList ) { UCHAR c; PUCHAR p = *StartingLoc; PUCHAR pch; BOOL InList;
while(1) {
c = *p;
InList = FALSE; for(pch=CharList; *pch; pch++) { if(*pch == c) { InList = TRUE; break; } }
if(!InList) {
/*
We don't need to bother with seeing if we're in quotes because this routine is never called when we are. */
if(c == ';') {
while(*(++p) != NL) { ; } // at loop exit, p points to NL
} else { // not in skip list and not a comment
*StartingLoc = p; return; }
} else { // c is in the list, so skip it
p++; } } }
/*
Create a preprocessed in-memory version of an inf file as follows:
The result is a series of NUL-terminated lines, with no blank lines or lines with only comments or whitespace, etc. */
GRC PreprocessINFFile( LPSTR FileName, LPBYTE *ResultBuffer, UINT *ResultBufferSize ) { HANDLE FileHandle; LONG FileSize; LPBYTE FileBuffer; // the input
LPBYTE INFBuffer; // the output
LPBYTE p,q; // current char in file image
UCHAR c; register int iEmit ; int iEmit2 ; static UCHAR PreviousChar = EOL; static PUCHAR PreviousPos;
if((FileHandle = (HANDLE)LongToHandle(_lopen(FileName,OF_READ))) == (HANDLE)(-1)) { return(grcBadINF); }
FileSize = _llseek(HandleToUlong(FileHandle),0,2); // move to end of file
_llseek(HandleToUlong(FileHandle),0,0); // move back to start of file
if((FileBuffer = SAlloc(FileSize+2)) == NULL) { _lclose(HandleToUlong(FileHandle)); return(grcOutOfMemory); }
if(_lread(HandleToUlong(FileHandle),FileBuffer,(UINT)FileSize) == -1) { _lclose(HandleToUlong(FileHandle)); SFree(FileBuffer); return(grcBadINF); }
_lclose(HandleToUlong(FileHandle)); FileBuffer[FileSize] = NL; // in case last line is incomplete
FileBuffer[FileSize+1] = 0; // to terminate the image
if((INFBuffer = SAlloc(FileSize)) == NULL) { SFree(FileBuffer); return(grcOutOfMemory); }
p = FileBuffer; CurrentOut = INFBuffer;
InsideQuotes = FALSE;
iEmit = -1 ; iEmit2 = -1 ;
while(c = *p) { if(c == CR) {
p++; continue;
} else if(c == NL) {
iEmit = 0 ; p++;
} else if(c == '"') {
if(InsideQuotes && (*(p+1) == '"')) { // we've got a quoted quote
iEmit = '"' ; p++; // skip first quote
} else { InsideQuotes = !InsideQuotes; iEmit = DQUOTE ; } p++;
} else if(InsideQuotes) {
// just spit out the character
iEmit = c ; p++;
} else if (c == '+') { // line continuation
p++; // skip the +
q = p;
SkipWS(&p);
if((*p == CR) || (*p == NL)) { // line continuation
SkipWSEOL(&p);
} else { // ordinary character
iEmit = '+' ; // p already advanced (above)
if(p != q) { // preserve ws between + and
iEmit2 = ' ' ; // char that follows
} }
} else if(IsWS(c)) {
iEmit = ' ' ; SkipWS(&p);
} else if(c == ';') {
SkipComment(&p);
} else {
iEmit = c ; // plain old character
p++; }
/*
Store a character in the output stream.
Control-z's are eliminated. Consecutive NL's after the first are eliminated. WS immediately following a NL is eliminated. NL immediately following a WS is stored over the WS, eliminating it. WS immediately before and after a comma is eliminated. */
if ( iEmit >= 0 ) { switch ( charTypeTable[iEmit] ) { case CtN: // Normal stuff
break ;
case CtS: // Space
if( PreviousChar == EOL ||(!InsideQuotes && (PreviousChar == ','))) { // don't store WS after NL's or ,'s
iEmit = -1 ; } break ;
case CtE: // EOL
if(PreviousChar == EOL) { iEmit = -1 ; // don't store adjacent NL's
} else if(PreviousChar == ' ') { // WS/NL ==> collapse to NL
CurrentOut = PreviousPos; // back up over the space first
} InsideQuotes = FALSE; // reset quotes status
break ;
case CtC: // Comma
if ( !InsideQuotes && (PreviousChar == ' ')) { CurrentOut = PreviousPos; } break ;
case CtF: // 0x1a or Ctrl-Z
iEmit= -1 ; break ; }
if ( iEmit >= 0 ) { PreviousChar = (UCHAR)iEmit ; PreviousPos = CurrentOut; *CurrentOut++ = (UCHAR)iEmit;
if ( iEmit2 >= 0 ) { PreviousChar = (UCHAR)iEmit2 ; PreviousPos = CurrentOut; *CurrentOut++ = (UCHAR)iEmit2 ; iEmit2 = -1 ; } iEmit = -1 ; } } }
SFree(FileBuffer);
*ResultBufferSize = (UINT)(CurrentOut - INFBuffer) ;
*ResultBuffer = SRealloc(INFBuffer,*ResultBufferSize); Assert(*ResultBuffer); // it was shrinking!
return(grcOkay); }
|