818 lines
20 KiB
C
818 lines
20 KiB
C
/*** scanasl.c - ASL scanner
|
|
*
|
|
* Copyright (c) 1996,1997 Microsoft Corporation
|
|
* Author: Michael Tsang (MikeTs)
|
|
* Created: 09/05/96
|
|
*
|
|
* This module provides the token scanning functions for the ASL language.
|
|
*
|
|
* MODIFICATION HISTORY
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
/*** Local function prototypes
|
|
*/
|
|
|
|
int LOCAL ScanSym(int c, PTOKEN ptoken);
|
|
int LOCAL ScanSpace(int c, PTOKEN ptoken);
|
|
int LOCAL ScanID(int c, PTOKEN ptoken);
|
|
int LOCAL ScanNum(int c, PTOKEN ptoken);
|
|
int LOCAL ScanString(int c, PTOKEN ptoken);
|
|
int LOCAL ScanChar(int c, PTOKEN ptoken);
|
|
int LOCAL ProcessInLineComment(PTOKEN ptoken);
|
|
int LOCAL ProcessComment(PTOKEN ptoken);
|
|
int LOCAL LookupSym(PTOKEN ptoken, int iTable);
|
|
LONG LOCAL LookupID(PTOKEN ptoken);
|
|
int LOCAL GetEscapedChar(PLINE pline);
|
|
BOOL EXPORT StrToQWord(PSZ psz, DWORD dwBase, QWORD *pqw);
|
|
|
|
/*** Local data
|
|
*/
|
|
|
|
PFNTOKEN apfnToken[] =
|
|
{
|
|
ScanSym,
|
|
ScanSpace,
|
|
ScanID,
|
|
ScanNum,
|
|
ScanString,
|
|
ScanChar,
|
|
(PFNTOKEN)NULL
|
|
};
|
|
|
|
#ifdef TUNE
|
|
WORD awcTokenType[] =
|
|
{
|
|
0, //TOKTYPE_SYMBOL
|
|
0, //TOKTYPE_SPACE
|
|
0, //TOKTYPE_ID
|
|
0, //TOKTYPE_NUM
|
|
0, //TOKTYPE_STRING
|
|
0 //TOKTYPE_CHAR
|
|
};
|
|
#endif
|
|
|
|
//
|
|
// The string positions of the symbol characters in SymCharTable
|
|
// is used as an index into the SymTokTable. Therefore, if anything
|
|
// is changed in either SymCharTable or SymTokTable, the other
|
|
// table has to be changed correspondingly.
|
|
//
|
|
typedef struct symtok_s
|
|
{
|
|
char chSym;
|
|
int iSymType;
|
|
int iLink;
|
|
} SYMTOK;
|
|
//
|
|
// Note that the symbol position in the following array must be the same
|
|
// position as in the SymCharTable array.
|
|
//
|
|
SYMTOK SymTokTable[] =
|
|
{
|
|
'{', SYM_LBRACE, 0, //0
|
|
'}', SYM_RBRACE, 0, //1
|
|
'(', SYM_LPARAN, 0, //2
|
|
')', SYM_RPARAN, 0, //3
|
|
',', SYM_COMMA, 0, //4
|
|
'/', SYM_SLASH, 7, //5
|
|
'*', SYM_ASTERISK, 9, //6
|
|
'/', SYM_INLINECOMMENT, 8, //7
|
|
'*', SYM_OPENCOMMENT, 0, //8
|
|
'/', SYM_CLOSECOMMENT, 0, //9
|
|
};
|
|
|
|
#define SYMTOK_TABLE_SIZE (sizeof(SymTokTable)/sizeof(SYMTOK))
|
|
|
|
/***EP OpenScan - scanner initialization
|
|
*
|
|
* ENTRY
|
|
* pfileSrc -> source file
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns the pointer to the allocated token structure;
|
|
* EXIT-FAILURE
|
|
* returns NULL
|
|
*/
|
|
|
|
PTOKEN EXPORT OpenScan(FILE *pfileSrc)
|
|
{
|
|
PTOKEN ptoken;
|
|
|
|
ENTER((4, "OpenScan(pfileSrc=%p)\n", pfileSrc));
|
|
|
|
#ifdef TUNE
|
|
ptoken = OpenToken(pfileSrc, apfnToken, awcTokenType);
|
|
#else
|
|
ptoken = OpenToken(pfileSrc, apfnToken);
|
|
#endif
|
|
|
|
EXIT((4, "OpenScan=%p\n", ptoken));
|
|
return ptoken;
|
|
} //OpenScan
|
|
|
|
/***EP CloseScan - scanner cleanup
|
|
*
|
|
* ENTRY
|
|
* ptoken->token structure
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID EXPORT CloseScan(PTOKEN ptoken)
|
|
{
|
|
ENTER((4, "CloseScan(ptoken=%p)\n", ptoken));
|
|
|
|
CloseToken(ptoken);
|
|
|
|
EXIT((4, "CloseScan!\n"));
|
|
} //CloseScan
|
|
|
|
/***LP ScanSym - scan symbols token
|
|
*
|
|
* ENTRY
|
|
* c - first character of the token
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TOKERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns TOKERR_NO_MATCH - not a symbol token
|
|
*/
|
|
|
|
int LOCAL ScanSym(int c, PTOKEN ptoken)
|
|
{
|
|
int rc = TOKERR_NO_MATCH;
|
|
char *pch;
|
|
|
|
ENTER((4, "ScanSym(c=%c,ptoken=%p)\n", c, ptoken));
|
|
|
|
if ((pch = strchr(SymCharTable, c)) != NULL)
|
|
{
|
|
int i, j;
|
|
|
|
i = (int)(pch - SymCharTable);
|
|
if (i != (j = LookupSym(ptoken, i)))
|
|
{
|
|
i = j;
|
|
ptoken->szToken[ptoken->wTokenLen++] = SymTokTable[i].chSym;
|
|
}
|
|
|
|
ptoken->iTokenType = TOKTYPE_SYMBOL;
|
|
ptoken->llTokenValue = SymTokTable[i].iSymType;
|
|
ptoken->szToken[ptoken->wTokenLen] = '\0';
|
|
|
|
if (ptoken->llTokenValue == SYM_INLINECOMMENT)
|
|
rc = ProcessInLineComment(ptoken);
|
|
else if (ptoken->llTokenValue == SYM_OPENCOMMENT)
|
|
rc = ProcessComment(ptoken);
|
|
else
|
|
rc = TOKERR_NONE;
|
|
}
|
|
|
|
EXIT((4, "ScanSym=%d (SymType=%I64d,Symbol=%s)\n",
|
|
rc, ptoken->llTokenValue, ptoken->szToken));
|
|
return rc;
|
|
} //ScanSym
|
|
|
|
/***LP ScanSpace - scans and skips all white spaces
|
|
*
|
|
* ENTRY
|
|
* c - first character of the token
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TOKERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns TOKTYPE_NO_MATCH - not a space token
|
|
*/
|
|
|
|
int LOCAL ScanSpace(int c, PTOKEN ptoken)
|
|
{
|
|
int rc = TOKERR_NO_MATCH;
|
|
|
|
ENTER((4, "ScanSpace(c=%c,ptoken=%p)\n", c, ptoken));
|
|
|
|
if (isspace(c))
|
|
{
|
|
rc = TOKERR_NONE;
|
|
while (((c = LineGetC(ptoken->pline)) != EOF) && isspace(c))
|
|
;
|
|
|
|
LineUnGetC(c, ptoken->pline);
|
|
|
|
if (ptoken->wfToken & TOKF_NOIGNORESPACE)
|
|
{
|
|
strcpy(ptoken->szToken, " ");
|
|
ptoken->wTokenLen = 1;
|
|
ptoken->iTokenType = TOKTYPE_SPACE;
|
|
}
|
|
else
|
|
ptoken->iTokenType = TOKTYPE_NULL;
|
|
}
|
|
|
|
EXIT((4, "ScanSpace=%d\n", rc));
|
|
return rc;
|
|
} //ScanSpace
|
|
|
|
/***LP ScanID - scan ID token
|
|
*
|
|
* ENTRY
|
|
* c - first character of the token
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TOKERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns TOKTYPE_NO_MATCH - not an ID token
|
|
* TOKERR_TOKEN_TOO_LONG - ID too long
|
|
*/
|
|
|
|
int LOCAL ScanID(int c, PTOKEN ptoken)
|
|
{
|
|
int rc = TOKERR_NO_MATCH;
|
|
|
|
ENTER((4, "ScanID(c=%c,ptoken=%p)\n", c, ptoken));
|
|
|
|
if (isalpha(c) || (c == '_') ||
|
|
(c == CH_ROOT_PREFIX) || (c == CH_PARENT_PREFIX))
|
|
{
|
|
BOOL fParentPrefix = (c == CH_PARENT_PREFIX);
|
|
|
|
rc = TOKERR_NONE;
|
|
ptoken->iTokenType = TOKTYPE_ID;
|
|
while (((c = LineGetC(ptoken->pline)) != EOF) &&
|
|
(fParentPrefix && (c == CH_PARENT_PREFIX) ||
|
|
isalnum(c) || (c == '_') || (c == CH_NAMESEG_SEP)))
|
|
{
|
|
fParentPrefix = (c == CH_PARENT_PREFIX);
|
|
if (rc == TOKERR_TOKEN_TOO_LONG)
|
|
continue;
|
|
else if (ptoken->wTokenLen < MAX_TOKEN_LEN)
|
|
ptoken->szToken[ptoken->wTokenLen++] = (char)c;
|
|
else
|
|
{
|
|
ptoken->wErrLine = ptoken->pline->wLineNum;
|
|
ptoken->wErrPos = ptoken->pline->wLinePos;
|
|
rc = TOKERR_TOKEN_TOO_LONG;
|
|
}
|
|
}
|
|
|
|
ptoken->szToken[ptoken->wTokenLen] = '\0';
|
|
LineUnGetC(c, ptoken->pline);
|
|
if (rc == TOKERR_NONE)
|
|
{
|
|
ptoken->llTokenValue = LookupID(ptoken);
|
|
}
|
|
}
|
|
|
|
EXIT((4, "ScanID=%d (IDType=%I64d,ID=%s)\n",
|
|
rc, ptoken->llTokenValue, ptoken->szToken));
|
|
return rc;
|
|
} //ScanID
|
|
|
|
/***LP ScanNum - scan number token
|
|
*
|
|
* ENTRY
|
|
* c - first character of the token
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TOKERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns TOKTYPE_NO_MATCH - not a number token
|
|
* TOKERR_TOKEN_TOO_LONG - number too long
|
|
*/
|
|
|
|
int LOCAL ScanNum(int c, PTOKEN ptoken)
|
|
{
|
|
int rc = TOKERR_NO_MATCH;
|
|
|
|
ENTER((4, "ScanNum(c=%c,ptoken=%p)\n", c, ptoken));
|
|
|
|
if (isdigit(c))
|
|
{
|
|
BOOL fHex = FALSE;
|
|
|
|
rc = TOKERR_NONE;
|
|
ptoken->iTokenType = TOKTYPE_NUMBER;
|
|
if ((c == '0') && ((c = LineGetC(ptoken->pline)) != EOF))
|
|
{
|
|
if (c != 'x')
|
|
LineUnGetC(c, ptoken->pline);
|
|
else
|
|
{
|
|
ptoken->szToken[ptoken->wTokenLen++] = (char)c;
|
|
fHex = TRUE;
|
|
}
|
|
}
|
|
|
|
while (((c = LineGetC(ptoken->pline)) != EOF) &&
|
|
((!fHex && isdigit(c)) || fHex && isxdigit(c)))
|
|
{
|
|
if (rc == TOKERR_TOKEN_TOO_LONG)
|
|
continue;
|
|
else if (ptoken->wTokenLen < MAX_TOKEN_LEN)
|
|
ptoken->szToken[ptoken->wTokenLen++] = (char)c;
|
|
else
|
|
{
|
|
ptoken->wErrLine = ptoken->pline->wLineNum;
|
|
ptoken->wErrPos = ptoken->pline->wLinePos;
|
|
rc = TOKERR_TOKEN_TOO_LONG;
|
|
}
|
|
}
|
|
|
|
ptoken->szToken[ptoken->wTokenLen] = '\0';
|
|
LineUnGetC(c, ptoken->pline);
|
|
|
|
if (rc == TOKERR_NONE)
|
|
{
|
|
if (!StrToQWord(ptoken->szToken, 0, (QWORD *)&ptoken->llTokenValue))
|
|
{
|
|
ptoken->wErrLine = ptoken->pline->wLineNum;
|
|
ptoken->wErrPos = ptoken->pline->wLinePos;
|
|
rc = TOKERR_TOKEN_TOO_LONG;
|
|
}
|
|
}
|
|
}
|
|
|
|
EXIT((4, "ScanNum=%d (Num=%I64d,Token=%s)\n",
|
|
rc, ptoken->llTokenValue, ptoken->szToken));
|
|
return rc;
|
|
} //ScanNum
|
|
|
|
/***LP ScanString - scan string token
|
|
*
|
|
* ENTRY
|
|
* c - first character of the token
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TOKERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns TOKTYPE_NO_MATCH - not a string token
|
|
* TOKERR_TOKEN_TOO_LONG - string too long
|
|
* TOKERR_UNCLOSED_STRING - EOF before string close
|
|
*/
|
|
|
|
int LOCAL ScanString(int c, PTOKEN ptoken)
|
|
{
|
|
int rc = TOKERR_NO_MATCH;
|
|
|
|
ENTER((4, "ScanString(c=%c,ptoken=%p)\n", c, ptoken));
|
|
|
|
if (c == '"')
|
|
{
|
|
rc = TOKERR_NONE;
|
|
ptoken->iTokenType = TOKTYPE_STRING;
|
|
ptoken->wTokenLen--;
|
|
while (((c = LineGetC(ptoken->pline)) != EOF) && (c != '"'))
|
|
{
|
|
if (rc == TOKERR_TOKEN_TOO_LONG)
|
|
continue;
|
|
else if (ptoken->wTokenLen >= MAX_TOKEN_LEN)
|
|
{
|
|
ptoken->wErrLine = ptoken->pline->wLineNum;
|
|
ptoken->wErrPos = ptoken->pline->wLinePos;
|
|
rc = TOKERR_TOKEN_TOO_LONG;
|
|
}
|
|
else
|
|
{
|
|
if (c == '\\')
|
|
c = GetEscapedChar(ptoken->pline);
|
|
ptoken->szToken[ptoken->wTokenLen++] = (char)c;
|
|
}
|
|
}
|
|
|
|
ptoken->szToken[ptoken->wTokenLen] = '\0';
|
|
if (c == EOF)
|
|
{
|
|
ptoken->wErrLine = ptoken->pline->wLineNum;
|
|
if ((ptoken->wErrPos = ptoken->pline->wLinePos) != 0)
|
|
ptoken->wErrPos--;
|
|
rc = TOKERR_UNCLOSED_STRING;
|
|
}
|
|
}
|
|
|
|
EXIT((4, "ScanString=%d (string=%s)\n", rc, ptoken->szToken));
|
|
return rc;
|
|
} //ScanString
|
|
|
|
/***LP ScanChar - scan character token
|
|
*
|
|
* ENTRY
|
|
* c - first character of the token
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TOKERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns TOKERR_NO_MATCH - not a character token
|
|
* TOKERR_TOKEN_TOO_LONG - token too long
|
|
* TOKERR_UNCLOSED_CHAR - cannot find character close
|
|
*/
|
|
|
|
int LOCAL ScanChar(int c, PTOKEN ptoken)
|
|
{
|
|
int rc = TOKERR_NO_MATCH;
|
|
|
|
ENTER((4, "ScanChar(c=%c,ptoken=%p)\n", c, ptoken));
|
|
|
|
if (c == '\'')
|
|
{
|
|
rc = TOKERR_NONE;
|
|
ptoken->iTokenType = TOKTYPE_CHAR;
|
|
ptoken->wTokenLen--;
|
|
if (((c = LineGetC(ptoken->pline)) == EOF) ||
|
|
(c == '\\') && ((c = GetEscapedChar(ptoken->pline)) == EOF))
|
|
{
|
|
rc = TOKERR_UNCLOSED_CHAR;
|
|
}
|
|
else
|
|
{
|
|
ptoken->szToken[ptoken->wTokenLen++] = (char)c;
|
|
ptoken->szToken[ptoken->wTokenLen] = '\0';
|
|
ptoken->llTokenValue = c;
|
|
if ((c = LineGetC(ptoken->pline)) == EOF)
|
|
rc = TOKERR_UNCLOSED_CHAR;
|
|
else if (c != '\'')
|
|
rc = TOKERR_TOKEN_TOO_LONG;
|
|
}
|
|
|
|
if (rc != TOKERR_NONE)
|
|
{
|
|
ptoken->wErrLine = ptoken->pline->wLineNum;
|
|
if ((ptoken->wErrPos = ptoken->pline->wLinePos) != 0)
|
|
ptoken->wErrPos--;
|
|
|
|
if (rc == TOKERR_TOKEN_TOO_LONG)
|
|
{
|
|
while (((c = LineGetC(ptoken->pline)) != EOF) && (c != '\''))
|
|
;
|
|
|
|
if (c == EOF)
|
|
rc = TOKERR_UNCLOSED_CHAR;
|
|
}
|
|
}
|
|
}
|
|
|
|
EXIT((4, "ScanChar=%d (Value=%I64d,Char=%s)\n",
|
|
rc, ptoken->llTokenValue, ptoken->szToken));
|
|
return rc;
|
|
} //ScanChar
|
|
|
|
/***LP ProcessInLineComment - handle inline comment
|
|
*
|
|
* ENTRY
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT
|
|
* always returns TOKERR_NONE
|
|
*/
|
|
|
|
int LOCAL ProcessInLineComment(PTOKEN ptoken)
|
|
{
|
|
ENTER((4, "ProcessInLineComment(ptoken=%p,Token=%s,Comment=%s)\n",
|
|
ptoken, ptoken->szToken,
|
|
&ptoken->pline->szLineBuff[ptoken->pline->wLinePos]));
|
|
|
|
LineFlush(ptoken->pline);
|
|
ptoken->iTokenType = TOKTYPE_NULL;
|
|
|
|
EXIT((4, "ProcessInLineComment=%d\n", TOKERR_NONE));
|
|
return TOKERR_NONE;
|
|
} //ProcessInLineComment
|
|
|
|
/***LP ProcessComment - handle comment
|
|
*
|
|
* ENTRY
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT
|
|
* always returns TOKERR_NONE
|
|
*/
|
|
|
|
int LOCAL ProcessComment(PTOKEN ptoken)
|
|
{
|
|
int rc = TOKERR_UNCLOSED_COMMENT;
|
|
int c;
|
|
char *pch;
|
|
|
|
ENTER((4, "ProcessComment(ptoken=%p,Token=%s,Comment=%s)\n",
|
|
ptoken, ptoken->szToken,
|
|
&ptoken->pline->szLineBuff[ptoken->pline->wLinePos]));
|
|
|
|
while ((c = LineGetC(ptoken->pline)) != EOF)
|
|
{
|
|
if ((pch = strchr(SymCharTable, c)) != NULL)
|
|
{
|
|
int i;
|
|
|
|
i = LookupSym(ptoken, (int)(pch - SymCharTable));
|
|
if (SymTokTable[i].iSymType == SYM_CLOSECOMMENT)
|
|
{
|
|
ptoken->iTokenType = TOKTYPE_NULL;
|
|
rc = TOKERR_NONE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rc != TOKERR_NONE)
|
|
{
|
|
ptoken->wErrLine = ptoken->pline->wLineNum;
|
|
if ((ptoken->wErrPos = ptoken->pline->wLinePos) != 0)
|
|
ptoken->wErrPos--;
|
|
}
|
|
|
|
EXIT((4, "ProcessComment=%d\n", rc));
|
|
return rc;
|
|
} //ProcessComment
|
|
|
|
/***LP LookupSym - match for 2-char. symbols
|
|
*
|
|
* ENTRY
|
|
* ptoken -> token structure
|
|
* iTable = SymCharTable index
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns a different index than iTable;
|
|
* EXIT-FAILURE
|
|
* returns iTable;
|
|
*/
|
|
|
|
int LOCAL LookupSym(PTOKEN ptoken, int iTable)
|
|
{
|
|
int i = iTable;
|
|
int c;
|
|
|
|
ENTER((4, "LookupSym(ptoken=%p,iTable=%d)\n", ptoken, iTable));
|
|
|
|
if ((SymTokTable[iTable].iLink != 0) &&
|
|
((c = LineGetC(ptoken->pline)) != EOF))
|
|
{
|
|
i = SymTokTable[iTable].iLink;
|
|
while ((c != SymTokTable[i].chSym) && (SymTokTable[i].iLink != 0))
|
|
i = SymTokTable[i].iLink;
|
|
|
|
if (c != SymTokTable[i].chSym)
|
|
{
|
|
LineUnGetC(c, ptoken->pline);
|
|
i = iTable;
|
|
}
|
|
}
|
|
|
|
EXIT((4, "LookupSym=%d\n", i));
|
|
return i;
|
|
} //LookupSym
|
|
|
|
/***LP LookupID - lookup the token in our reserved ID list
|
|
*
|
|
* ENTRY
|
|
* ptoken -> token structure
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns index of TermTable
|
|
* EXIT-FAILURE
|
|
* returns ID_USER
|
|
*/
|
|
|
|
LONG LOCAL LookupID(PTOKEN ptoken)
|
|
{
|
|
LONG lID = ID_USER;
|
|
LONG i;
|
|
|
|
ENTER((4, "LookupID(ptoken=%p)\n", ptoken));
|
|
|
|
for (i = 0; TermTable[i].pszID != NULL; ++i)
|
|
{
|
|
if (_stricmp(TermTable[i].pszID, ptoken->szToken) == 0)
|
|
{
|
|
lID = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
EXIT((4, "LookupID=%ld\n", lID));
|
|
return lID;
|
|
} //LookupID
|
|
|
|
/***LP GetEscapedChar - read and translate escape character
|
|
*
|
|
* ENTRY
|
|
* pline -> line structure
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns the escape character
|
|
* EXIT-FAILURE
|
|
* returns EOF - eof encountered
|
|
*/
|
|
|
|
int LOCAL GetEscapedChar(PLINE pline)
|
|
{
|
|
int c;
|
|
#define ESCAPE_BUFF_SIZE 5
|
|
char achEscapedBuff[ESCAPE_BUFF_SIZE];
|
|
int i;
|
|
|
|
ENTER((4, "GetEscapedChar(pline=%p)\n", pline));
|
|
|
|
if ((c = LineGetC(pline)) != EOF)
|
|
{
|
|
switch(c)
|
|
{
|
|
case '0':
|
|
achEscapedBuff[0] = (char)c;
|
|
for (i = 1; i < 4; i++) //maximum 3 digits
|
|
{
|
|
if (((c = LineGetC(pline)) != EOF) &&
|
|
(c >= '0') && (c <= '7'))
|
|
{
|
|
achEscapedBuff[i] = (char)c;
|
|
}
|
|
else
|
|
{
|
|
LineUnGetC(c, pline);
|
|
break;
|
|
}
|
|
}
|
|
achEscapedBuff[i] = '\0';
|
|
c = (int)strtoul(achEscapedBuff, NULL, 8);
|
|
break;
|
|
|
|
case 'a':
|
|
c = '\a'; //alert (bell)
|
|
break;
|
|
|
|
case 'b':
|
|
c = '\b'; //backspace
|
|
break;
|
|
|
|
case 'f':
|
|
c = '\f'; //form feed
|
|
break;
|
|
|
|
case 'n':
|
|
c = '\n'; //newline
|
|
break;
|
|
|
|
case 'r':
|
|
c = '\r'; //carriage return
|
|
break;
|
|
|
|
case 't':
|
|
c = '\t'; //horizontal tab
|
|
break;
|
|
|
|
case 'v':
|
|
c = '\v'; //vertical tab
|
|
break;
|
|
|
|
case 'x':
|
|
for (i = 0; i < 2; i++) //maximum 2 digits
|
|
{
|
|
if (((c = LineGetC(pline)) != EOF) && isxdigit(c))
|
|
achEscapedBuff[i] = (char)c;
|
|
else
|
|
{
|
|
LineUnGetC(c, pline);
|
|
break;
|
|
}
|
|
}
|
|
achEscapedBuff[i] = '\0';
|
|
c = (int)strtoul(achEscapedBuff, NULL, 16);
|
|
}
|
|
}
|
|
|
|
EXIT((4, "GetEscapedChar=%x\n", c));
|
|
return c;
|
|
} //GetEscapedChar
|
|
|
|
/***EP PrintScanErr - print scan error
|
|
*
|
|
* ENTRY
|
|
* ptoken -> token structure
|
|
* rcErr - error code
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID EXPORT PrintScanErr(PTOKEN ptoken, int rcErr)
|
|
{
|
|
WORD i;
|
|
|
|
ENTER((4, "PrintScanErr(ptoken=%p,Err=%d)\n", ptoken, rcErr));
|
|
|
|
ASSERT(ptoken->wTokenLine == ptoken->wErrLine);
|
|
|
|
ErrPrintf("%5u: %s\n ",
|
|
ptoken->wTokenLine, ptoken->pline->szLineBuff);
|
|
|
|
for (i = 0; i < ptoken->wErrPos; ++i)
|
|
{
|
|
if (ptoken->pline->szLineBuff[i] == '\t')
|
|
{
|
|
ErrPrintf("\t");
|
|
}
|
|
else
|
|
{
|
|
ErrPrintf(" ");
|
|
}
|
|
}
|
|
|
|
ErrPrintf("^***\n");
|
|
|
|
switch (rcErr)
|
|
{
|
|
case TOKERR_TOKEN_TOO_LONG:
|
|
ErrPrintf("ScanErr: Token too long\n");
|
|
break;
|
|
|
|
case TOKERR_UNCLOSED_STRING:
|
|
ErrPrintf("ScanErr: Unclosed string\n");
|
|
break;
|
|
|
|
case TOKERR_UNCLOSED_CHAR:
|
|
ErrPrintf("ScanErr: Unclosed character quote\n");
|
|
break;
|
|
|
|
default:
|
|
ErrPrintf("ScanErr: Syntax error\n");
|
|
break;
|
|
}
|
|
|
|
EXIT((4, "PrintScanErr!\n"));
|
|
} //PrintScanErr
|
|
|
|
/***EP StrToQWord - convert the number in a string to a QWord
|
|
*
|
|
* ENTRY
|
|
* psz -> string
|
|
* dwBase - the base of the number (if 0, auto-detect base)
|
|
* pqw -> to hold the resulting QWord
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TRUE
|
|
* EXIT-FAILURE
|
|
* returns FALSE
|
|
*/
|
|
|
|
BOOL EXPORT StrToQWord(PSZ psz, DWORD dwBase, QWORD *pqw)
|
|
{
|
|
BOOL rc = TRUE;
|
|
ULONG m;
|
|
|
|
ENTER((4, "StrToQWord(Str=%s,Base=%x,pqw=%p)\n", psz, dwBase, pqw));
|
|
|
|
*pqw = 0;
|
|
if (dwBase == 0)
|
|
{
|
|
if (psz[0] == '0')
|
|
{
|
|
if ((psz[1] == 'x') || (psz[1] == 'X'))
|
|
{
|
|
dwBase = 16;
|
|
psz += 2;
|
|
}
|
|
else
|
|
{
|
|
dwBase = 8;
|
|
psz++;
|
|
}
|
|
}
|
|
else
|
|
dwBase = 10;
|
|
}
|
|
|
|
while (*psz != '\0')
|
|
{
|
|
if ((*psz >= '0') && (*psz <= '9'))
|
|
m = *psz - '0';
|
|
else if ((*psz >= 'A') && (*psz <= 'Z'))
|
|
m = *psz - 'A' + 10;
|
|
else if ((*psz >= 'a') && (*psz <= 'z'))
|
|
m = *psz - 'a' + 10;
|
|
else
|
|
{
|
|
rc = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (m < dwBase)
|
|
{
|
|
*pqw = (*pqw * dwBase) + m;
|
|
psz++;
|
|
}
|
|
else
|
|
{
|
|
rc = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
EXIT((4, "StrToQWord=%x (QWord=0x%I64x)\n", rc, *pqw));
|
|
return rc;
|
|
} //StrToQWord
|