windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/infload1.c

371 lines
11 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#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);
}