705 lines
16 KiB
C
705 lines
16 KiB
C
#include "precomp.h"
|
|
#pragma hdrstop
|
|
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
inf_rt2.c
|
|
|
|
Abstract:
|
|
|
|
INF file runtime field interpreter.
|
|
|
|
A given string is interpreted as a tokenized field and an output
|
|
buffer containing the result is constructed.
|
|
|
|
Author:
|
|
|
|
Ted Miller (tedm) 10-Spetember-1991
|
|
|
|
--*/
|
|
|
|
|
|
/* Input stuff */
|
|
|
|
LPBYTE Interpret_Inputp;
|
|
|
|
#define GETTOKEN() (*Interpret_Inputp++)
|
|
#define PEEKTOKEN() (*Interpret_Inputp)
|
|
#define UNGETTOKEN(t) (*(--Interpret_Inputp) = t)
|
|
#define VERIFY_SIZE(s) \
|
|
if ( SpaceLeftInFieldBuffer < (s) ) { \
|
|
GrowBuffer(s); \
|
|
}
|
|
|
|
|
|
/* end input stuff */
|
|
|
|
/* Output stuff */
|
|
|
|
#define MAX_FIELD_LENGTH 4096
|
|
|
|
PUCHAR InterpretedFieldBuffer;
|
|
UINT SpaceLeftInFieldBuffer;
|
|
UINT BufferSize;
|
|
PUCHAR Interpret_OutputLoc;
|
|
|
|
/* end output stuff */
|
|
|
|
SZ Interpret_GetField(VOID);
|
|
|
|
BOOL DoVariable(VOID);
|
|
BOOL DoListFromSectionNthItem(VOID);
|
|
BOOL DoFieldAddressor(VOID);
|
|
BOOL DoAppendItemToList(VOID);
|
|
BOOL DoNthItemFromList(VOID);
|
|
BOOL DoLocateItemInList(VOID);
|
|
BOOL DoList(VOID);
|
|
BOOL DoString(BYTE StringToken);
|
|
|
|
/* Run time error field */
|
|
GRC grcRTLastError = grcOkay;
|
|
|
|
VOID GrowBuffer(UINT Size);
|
|
SZ
|
|
APIENTRY
|
|
InterpretField(
|
|
SZ Field
|
|
)
|
|
{
|
|
SZ ReturnString,
|
|
InputSave = Interpret_Inputp;
|
|
|
|
Interpret_Inputp = Field;
|
|
|
|
ReturnString = Interpret_GetField();
|
|
|
|
Interpret_Inputp = InputSave;
|
|
return(ReturnString);
|
|
}
|
|
|
|
|
|
|
|
SZ
|
|
Interpret_GetField(
|
|
VOID
|
|
)
|
|
{
|
|
LPSTR OldOutputBuffer = InterpretedFieldBuffer;
|
|
LPSTR OldInterpretLoc = Interpret_OutputLoc;
|
|
UINT OldSpaceLeft = SpaceLeftInFieldBuffer;
|
|
LPSTR ReturnString = NULL;
|
|
BYTE Token;
|
|
|
|
if((InterpretedFieldBuffer
|
|
= SAlloc(SpaceLeftInFieldBuffer = MAX_FIELD_LENGTH))
|
|
== NULL)
|
|
{
|
|
grcRTLastError = grcOutOfMemory;
|
|
return(NULL);
|
|
}
|
|
BufferSize = MAX_FIELD_LENGTH;
|
|
Interpret_OutputLoc = InterpretedFieldBuffer;
|
|
|
|
VERIFY_SIZE(1);
|
|
SpaceLeftInFieldBuffer--; // leave space for terminating NUL
|
|
|
|
while((Token = GETTOKEN())
|
|
&& (Token != TOKEN_COMMA)
|
|
&& (Token != TOKEN_SPACE)
|
|
&& (Token != TOKEN_RIGHT_PAREN)
|
|
&& (Token != TOKEN_LIST_END))
|
|
{
|
|
if(IS_STRING_TOKEN(Token)) {
|
|
if(!DoString(Token)) {
|
|
SFree(InterpretedFieldBuffer);
|
|
goto Cleanup;
|
|
}
|
|
} else {
|
|
switch(Token) {
|
|
|
|
case TOKEN_VARIABLE:
|
|
|
|
if(!DoVariable()) {
|
|
SFree(InterpretedFieldBuffer);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_LIST_FROM_SECTION_NTH_ITEM:
|
|
|
|
if(!DoListFromSectionNthItem()) {
|
|
SFree(InterpretedFieldBuffer);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_FIELD_ADDRESSOR:
|
|
|
|
if(!DoFieldAddressor()) {
|
|
SFree(InterpretedFieldBuffer);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_APPEND_ITEM_TO_LIST:
|
|
|
|
if(!DoAppendItemToList()) {
|
|
SFree(InterpretedFieldBuffer);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_NTH_ITEM_FROM_LIST:
|
|
|
|
if(!DoNthItemFromList()) {
|
|
SFree(InterpretedFieldBuffer);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_LOCATE_ITEM_IN_LIST:
|
|
|
|
if(!DoLocateItemInList()) {
|
|
SFree(InterpretedFieldBuffer);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_LIST_START:
|
|
|
|
if(!DoList()) {
|
|
SFree(InterpretedFieldBuffer);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
#if DBG
|
|
{
|
|
char str[100];
|
|
wsprintf(str,"Bogus token: %u",Token);
|
|
MessBoxSzSz("Interpret_GetField",str);
|
|
}
|
|
#endif
|
|
break;
|
|
} // switch
|
|
} // if-else
|
|
} // while
|
|
|
|
/*
|
|
The following is because we want the routines DoOperator()
|
|
and DoList() (below) to have access to their terminators.
|
|
*/
|
|
|
|
if((Token == TOKEN_RIGHT_PAREN) || (Token == TOKEN_LIST_END)) {
|
|
UNGETTOKEN(Token);
|
|
}
|
|
|
|
Assert((LONG)SpaceLeftInFieldBuffer >= 0); // space provided for above
|
|
*Interpret_OutputLoc = NUL;
|
|
|
|
ReturnString = SRealloc(InterpretedFieldBuffer,
|
|
BufferSize - SpaceLeftInFieldBuffer
|
|
);
|
|
|
|
Assert(ReturnString); // buffer was shrinking;
|
|
|
|
Cleanup:
|
|
Interpret_OutputLoc = OldInterpretLoc;
|
|
InterpretedFieldBuffer = OldOutputBuffer;
|
|
SpaceLeftInFieldBuffer = OldSpaceLeft;
|
|
return(ReturnString);
|
|
}
|
|
|
|
|
|
/*
|
|
This routine gets the fields of an operator into an rgsz.
|
|
*/
|
|
|
|
RGSZ
|
|
DoOperator(
|
|
UINT FieldCount
|
|
)
|
|
{
|
|
UINT x;
|
|
RGSZ rgsz;
|
|
|
|
Assert(FieldCount);
|
|
|
|
if((rgsz = (RGSZ)SAlloc((FieldCount+1)*sizeof(SZ))) == NULL) {
|
|
grcRTLastError = grcOutOfMemory;
|
|
return(NULL);
|
|
}
|
|
|
|
rgsz[FieldCount] = NULL;
|
|
|
|
for(x=0; x<FieldCount-1; x++) {
|
|
|
|
if((rgsz[x] = Interpret_GetField()) == NULL) {
|
|
FFreeRgsz(rgsz);
|
|
return(NULL);
|
|
}
|
|
if(PEEKTOKEN() == TOKEN_RIGHT_PAREN) {
|
|
FFreeRgsz(rgsz);
|
|
grcRTLastError = grcNotOkay;
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
if((rgsz[FieldCount-1] = Interpret_GetField()) == NULL) {
|
|
FFreeRgsz(rgsz);
|
|
return(NULL);
|
|
}
|
|
|
|
Assert(PEEKTOKEN() != NUL);
|
|
|
|
if(GETTOKEN() != TOKEN_RIGHT_PAREN) { // skips )
|
|
FFreeRgsz(rgsz);
|
|
grcRTLastError = grcNotOkay;
|
|
return(NULL);
|
|
}
|
|
return(rgsz);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoVariable(
|
|
VOID
|
|
)
|
|
{
|
|
RGSZ rgsz;
|
|
SZ SymbolValue;
|
|
UINT x,SymbolValueLength;
|
|
BOOL rc = TRUE;
|
|
|
|
if((rgsz = DoOperator(1)) == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
if((SymbolValue = SzFindSymbolValueInSymTab(rgsz[0])) == NULL) {
|
|
SymbolValue = "";
|
|
}
|
|
|
|
SymbolValueLength = lstrlen(SymbolValue);
|
|
|
|
VERIFY_SIZE(SymbolValueLength);
|
|
|
|
if(SpaceLeftInFieldBuffer >= SymbolValueLength) {
|
|
SpaceLeftInFieldBuffer -= SymbolValueLength;
|
|
for(x=0; x<SymbolValueLength; x++) {
|
|
*Interpret_OutputLoc++ = *SymbolValue++;
|
|
}
|
|
} else {
|
|
grcRTLastError = grcNotOkay;
|
|
rc = FALSE;
|
|
}
|
|
|
|
FFreeRgsz(rgsz);
|
|
return(rc);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoListFromSectionNthItem(
|
|
VOID
|
|
)
|
|
{
|
|
RGSZ rgsz,rgszList = NULL;
|
|
UINT LineCount,n,x,LineNo;
|
|
BOOL rc = FALSE;
|
|
SZ List,ListSave;
|
|
|
|
if((rgsz = DoOperator(2)) == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
grcRTLastError = grcNotOkay;
|
|
n = atoi(rgsz[1]);
|
|
|
|
LineCount = CKeysFromInfSection(rgsz[0],TRUE);
|
|
|
|
if((rgszList = (RGSZ)SAlloc((LineCount+1)*sizeof(SZ))) != NULL) {
|
|
|
|
LineNo = FindInfSectionLine(rgsz[0]);
|
|
|
|
for(x=0; x<LineCount; x++) {
|
|
LineNo = FindNextLineFromInf(LineNo);
|
|
Assert(LineNo != -1);
|
|
rgszList[x] = SzGetNthFieldFromInfLine(LineNo,n);
|
|
}
|
|
rgszList[LineCount] = NULL;
|
|
if((List = SzListValueFromRgsz(rgszList)) != NULL) {
|
|
ListSave = List;
|
|
x = lstrlen(List);
|
|
VERIFY_SIZE(x);
|
|
if(SpaceLeftInFieldBuffer >= x) {
|
|
SpaceLeftInFieldBuffer -= x;
|
|
for(n=0; n<x; n++) {
|
|
*Interpret_OutputLoc++ = *List++;
|
|
}
|
|
grcRTLastError = grcOkay;
|
|
rc = TRUE;
|
|
}
|
|
SFree(ListSave);
|
|
} else {
|
|
grcRTLastError = grcOutOfMemory;
|
|
}
|
|
} else {
|
|
grcRTLastError = grcOutOfMemory;
|
|
}
|
|
|
|
if(rgszList != NULL) {
|
|
FFreeRgsz(rgszList);
|
|
}
|
|
FFreeRgsz(rgsz);
|
|
return(rc);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoFieldAddressor(
|
|
VOID
|
|
)
|
|
{
|
|
RGSZ rgsz;
|
|
UINT x,n;
|
|
SZ Result,ResultSave;
|
|
BOOL rc = FALSE;
|
|
|
|
if((rgsz = DoOperator(3)) == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
grcRTLastError = grcNotOkay;
|
|
n = atoi(rgsz[2]);
|
|
|
|
// rgsz[0] has section, rgsz[1] has key
|
|
|
|
if((Result = SzGetNthFieldFromInfSectionKey(rgsz[0],rgsz[1],n)) != NULL) {
|
|
|
|
ResultSave = Result;
|
|
n = lstrlen(Result);
|
|
VERIFY_SIZE(n);
|
|
if(SpaceLeftInFieldBuffer >= n) {
|
|
SpaceLeftInFieldBuffer -= n;
|
|
for(x=0; x<n; x++) {
|
|
*Interpret_OutputLoc++ = *Result++;
|
|
}
|
|
grcRTLastError = grcOkay;
|
|
rc = TRUE;
|
|
}
|
|
SFree(ResultSave);
|
|
}
|
|
FFreeRgsz(rgsz);
|
|
return(rc);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoAppendItemToList(
|
|
VOID
|
|
)
|
|
{
|
|
RGSZ rgsz,rgszList1,rgszList2;
|
|
UINT RgszSize,x,y;
|
|
SZ ListValue,ListTemp;
|
|
|
|
if((rgsz = DoOperator(2)) == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
// rgsz[0] has list, rgsz[1] has item
|
|
|
|
if((rgszList1 = RgszFromSzListValue(rgsz[0])) == NULL) {
|
|
FFreeRgsz(rgsz);
|
|
grcRTLastError = grcOutOfMemory;
|
|
return(FALSE);
|
|
}
|
|
|
|
for (RgszSize = 0; rgszList1[RgszSize] != NULL; RgszSize++) {
|
|
;
|
|
}
|
|
|
|
if ((rgszList2 = (RGSZ)SRealloc(rgszList1, (RgszSize+2)*sizeof(SZ)
|
|
)) == NULL)
|
|
{
|
|
FFreeRgsz(rgszList1);
|
|
FFreeRgsz(rgsz);
|
|
grcRTLastError = grcOutOfMemory;
|
|
return(FALSE);
|
|
}
|
|
|
|
rgszList2[RgszSize] = SzDupl(rgsz[1]);
|
|
rgszList2[RgszSize+1] = NULL;
|
|
|
|
ListValue = SzListValueFromRgsz(rgszList2);
|
|
|
|
FFreeRgsz(rgszList2);
|
|
|
|
if(ListValue == NULL) {
|
|
FFreeRgsz(rgsz);
|
|
grcRTLastError = grcOutOfMemory;
|
|
return(FALSE);
|
|
}
|
|
|
|
x = lstrlen(ListValue);
|
|
VERIFY_SIZE(x);
|
|
if(x > SpaceLeftInFieldBuffer) {
|
|
SFree(ListValue);
|
|
FFreeRgsz(rgsz);
|
|
grcRTLastError = grcNotOkay;
|
|
return(FALSE);
|
|
}
|
|
ListTemp = ListValue;
|
|
for(y=0; y<x; y++) {
|
|
*Interpret_OutputLoc++ = *ListTemp++;
|
|
}
|
|
SpaceLeftInFieldBuffer -= x;
|
|
|
|
SFree(ListValue);
|
|
FFreeRgsz(rgsz);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoNthItemFromList(
|
|
VOID
|
|
)
|
|
{
|
|
RGSZ rgsz,
|
|
rgszList = NULL;
|
|
UINT n,x,y,ListSize;
|
|
PUCHAR Item;
|
|
BOOL rc = FALSE;
|
|
|
|
if((rgsz = DoOperator(2)) == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
grcRTLastError = grcNotOkay;
|
|
n = atoi(rgsz[1]);
|
|
|
|
if((rgszList = RgszFromSzListValue(rgsz[0])) != NULL) {
|
|
|
|
for(ListSize=0; rgszList[ListSize]; ListSize++) {
|
|
;
|
|
} // count list items
|
|
if(!n || (n > ListSize)) {
|
|
Item = "";
|
|
} else {
|
|
Item = rgszList[n-1];
|
|
}
|
|
x = lstrlen(Item);
|
|
VERIFY_SIZE(x);
|
|
if(SpaceLeftInFieldBuffer >= x) {
|
|
SpaceLeftInFieldBuffer -= x;
|
|
for(y=0; y<x; y++) {
|
|
*Interpret_OutputLoc++ = *Item++;
|
|
}
|
|
grcRTLastError = grcOkay;
|
|
rc = TRUE;
|
|
}
|
|
} else {
|
|
grcRTLastError = grcOutOfMemory;
|
|
}
|
|
if(rgszList != NULL) {
|
|
FFreeRgsz(rgszList);
|
|
}
|
|
FFreeRgsz(rgsz);
|
|
return(rc);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoLocateItemInList( // 1-based, 0 if not found
|
|
VOID
|
|
)
|
|
{
|
|
RGSZ rgsz,rgszList;
|
|
UINT Item = 0,
|
|
x,y;
|
|
BOOL rc = FALSE;
|
|
char szItem[25]; // arbitrary length
|
|
char *szItemTemp;
|
|
|
|
if((rgsz = DoOperator(2)) == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
grcRTLastError = grcNotOkay;
|
|
// rgsz[0] has list, rgsz[1] has item to locate
|
|
|
|
if((rgszList = RgszFromSzListValue(rgsz[0])) != NULL) {
|
|
|
|
for(x=0; rgszList[x]; x++) {
|
|
|
|
if(!lstrcmpi(rgsz[1],rgszList[x])) {
|
|
Item = x+1;
|
|
break;
|
|
}
|
|
}
|
|
FFreeRgsz(rgszList);
|
|
|
|
wsprintf(szItem,"%u",Item);
|
|
x = lstrlen(szItem);
|
|
VERIFY_SIZE(x);
|
|
if( x <= SpaceLeftInFieldBuffer) {
|
|
|
|
SpaceLeftInFieldBuffer -= x;
|
|
szItemTemp = szItem;
|
|
for(y=0; y<x; y++) {
|
|
*Interpret_OutputLoc++ = *szItemTemp++;
|
|
}
|
|
rc = TRUE;
|
|
grcRTLastError = grcOkay;
|
|
}
|
|
} else {
|
|
grcRTLastError = grcOutOfMemory;
|
|
}
|
|
FFreeRgsz(rgsz);
|
|
return(rc);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoList(
|
|
VOID
|
|
)
|
|
{
|
|
RGSZ rgsz;
|
|
LPVOID r;
|
|
UINT RgszSize;
|
|
UINT ItemCount;
|
|
UINT ListLength,x;
|
|
SZ List,ListSave;
|
|
BOOL rc;
|
|
|
|
if((rgsz = (RGSZ)SAlloc(10 * sizeof(SZ))) == NULL) {
|
|
grcRTLastError = grcOutOfMemory;
|
|
return(FALSE);
|
|
}
|
|
RgszSize = 10;
|
|
ItemCount = 1; // reserve space for the NULL entry
|
|
|
|
while(PEEKTOKEN() != TOKEN_LIST_END) {
|
|
if(ItemCount == RgszSize) {
|
|
if((r = SRealloc(rgsz,
|
|
(RgszSize + 10) * sizeof(SZ)
|
|
)
|
|
)
|
|
== NULL)
|
|
{
|
|
rgsz[ItemCount-1] = NULL; // for FFreeRgsz
|
|
FFreeRgsz(rgsz);
|
|
grcRTLastError = grcOutOfMemory;
|
|
return(FALSE);
|
|
}
|
|
RgszSize += 10;
|
|
rgsz = r;
|
|
}
|
|
if((rgsz[ItemCount-1] = Interpret_GetField()) == NULL) {
|
|
FFreeRgsz(rgsz);
|
|
return(FALSE);
|
|
}
|
|
ItemCount++;
|
|
}
|
|
|
|
EvalAssert(GETTOKEN() == TOKEN_LIST_END); // skip list end
|
|
|
|
Assert(ItemCount <= RgszSize);
|
|
rgsz[ItemCount-1] = NULL; // space for this reserved above
|
|
|
|
rgsz = (RGSZ)SRealloc(rgsz,ItemCount * sizeof(SZ));
|
|
Assert(rgsz); // it was shrinking
|
|
|
|
List = SzListValueFromRgsz(rgsz);
|
|
FFreeRgsz(rgsz);
|
|
if(List == NULL) {
|
|
grcRTLastError = grcOutOfMemory;
|
|
return(FALSE);
|
|
}
|
|
ListLength = lstrlen(List);
|
|
ListSave = List;
|
|
VERIFY_SIZE(ListLength);
|
|
if(SpaceLeftInFieldBuffer >= ListLength) {
|
|
SpaceLeftInFieldBuffer -= ListLength;
|
|
for(x=0; x<ListLength; x++) {
|
|
*Interpret_OutputLoc++ = *List++;
|
|
}
|
|
rc = TRUE;
|
|
} else {
|
|
grcRTLastError = grcNotOkay;
|
|
rc = FALSE;
|
|
}
|
|
SFree(ListSave);
|
|
return(rc);
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoString(
|
|
BYTE StringToken
|
|
)
|
|
{
|
|
USHORT StringLength;
|
|
UINT x;
|
|
|
|
Assert(IS_STRING_TOKEN(StringToken));
|
|
|
|
if(StringToken < TOKEN_STRING) { // test for short string
|
|
StringLength = (USHORT)StringToken - (USHORT)TOKEN_SHORT_STRING;
|
|
} else if (StringToken == TOKEN_STRING) { // test for regular string
|
|
StringLength = (USHORT)GETTOKEN() + (USHORT)100;
|
|
} else { // long string
|
|
Assert(StringToken == TOKEN_LONG_STRING);
|
|
StringLength = (USHORT)GETTOKEN() << 8;
|
|
StringLength |= (USHORT)GETTOKEN();
|
|
}
|
|
VERIFY_SIZE( StringLength );
|
|
if(SpaceLeftInFieldBuffer >= StringLength) {
|
|
SpaceLeftInFieldBuffer -= StringLength;
|
|
for(x=0; x<StringLength; x++) {
|
|
*Interpret_OutputLoc++ = GETTOKEN();
|
|
}
|
|
} else {
|
|
grcRTLastError = grcNotOkay;
|
|
return(FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
VOID
|
|
GrowBuffer( UINT Size )
|
|
{
|
|
|
|
while ( SpaceLeftInFieldBuffer < Size ) {
|
|
|
|
//
|
|
// Reallocate buffer
|
|
//
|
|
PUCHAR p;
|
|
UINT_PTR Offset = Interpret_OutputLoc - InterpretedFieldBuffer;
|
|
|
|
p = (PUCHAR)SRealloc( InterpretedFieldBuffer,
|
|
BufferSize + MAX_FIELD_LENGTH);
|
|
|
|
if ( p ) {
|
|
|
|
InterpretedFieldBuffer = p;
|
|
Interpret_OutputLoc = InterpretedFieldBuffer + Offset;
|
|
SpaceLeftInFieldBuffer += MAX_FIELD_LENGTH;
|
|
BufferSize += MAX_FIELD_LENGTH;
|
|
|
|
} else {
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|