|
|
/****************************************************************************/ /* */ /* RCTP.C - */ /* */ /* Windows 3.0 Resource Compiler - Resource Parser */ /* */ /* */ /****************************************************************************/
#include "rc.h"
extern KEY keyList[]; extern SKEY skeyList[]; extern BOOL CheckStr(PWCHAR pStr);
WORD wEndPOPUP[] = { 1, BEGIN }; WORD wEndMENUITEM[] = { 3, TKPOPUP, TKMENUITEM, END }; WORD wEndMENU[] = { 0 };
BYTE bParmsPOPUP[] = { 5, PT_TEXT, PTO_DWORD, PTO_DWORD, PTO_DWORD, PTO_DWORD }; BYTE bParmsMENUITEM[]= { 4, PT_TEXT, PTO_DWORD, PTO_DWORD, PTO_DWORD }; BYTE bParmsMENU[] = { 1, PTO_DWORD };
PARCEL parcels[]= { { wEndPOPUP, bParmsPOPUP }, // PAR_POPUP
{ wEndMENUITEM, bParmsMENUITEM }, // PAR_MENUITEM
{ wEndMENU, bParmsMENU } // PAR_MENU
};
typedef enum { ERR_MOREARGS = 2235, ERR_NEEDARG, ERR_NEEDNUM, ERR_NEEDSTR, ERR_NEEDBEGIN, ERR_NEEDEND, ERR_NEEDPAREN, ERR_BADEXP, ERR_BADSTREXP, ERR_NOSEP, ERR_BADSUBMENU, ERR_NOEMPTYMENU } ERRCODE;
BOOL EndParcel( WORD *pwEnd ) { WORD i;
if (!*pwEnd) return(TRUE);
for (i = *pwEnd; i > 0; i--) if (token.type == pwEnd[i]) return(TRUE);
return(FALSE); }
#define PARM_SET 0x0001
#define PARM_LAST 0x0002
BOOL MyGetExpression(DWORD *pdwExp, BOOL fRecursed);
BOOL GetOp( DWORD *pdwExp, WORD opcode ) { DWORD dwOp2 = 0; BOOL fNest = FALSE;
switch (token.type) { case LPAREN: GetToken(TOKEN_NOEXPRESSION); if (!MyGetExpression(&dwOp2, TRUE)) return(FALSE); fNest = TRUE; break;
case TKMINUS: // -flag (unary minus)
GetToken(TOKEN_NOEXPRESSION); dwOp2 = -token.longval; break;
case TKPLUS: GetToken(TOKEN_NOEXPRESSION); case NUMLIT: dwOp2 = token.longval; break;
case TKNOT: // (x | NOT flag) == (x & ~flag)
opcode = AND; case TILDE: // ~flag
GetToken(TOKEN_NOEXPRESSION); dwOp2 = ~token.longval; break;
default: return(FALSE); }
if (!fNest) { if (token.type != NUMLIT) ParseError2(ERR_NEEDNUM, tokenbuf);
GetToken(TOKEN_NOEXPRESSION); }
switch (opcode) { case TKPLUS: *pdwExp += dwOp2; break;
case TKMINUS: *pdwExp -= dwOp2; break;
case OR: *pdwExp |= dwOp2; break;
case AND: *pdwExp &= dwOp2; break; }
return(TRUE); }
BOOL GetFullExpression( void *pval, WORD wFlags ) { BOOL fRes; DWORD dwExp = 0;
if (!(wFlags & GFE_ZEROINIT)) dwExp = (wFlags & GFE_SHORT) ? (DWORD) *((WORD *) pval) : *((DWORD UNALIGNED *) pval);
fRes = MyGetExpression(&dwExp, FALSE);
if (wFlags & GFE_SHORT) *((WORD *) pval) = (WORD) dwExp; else *((DWORD UNALIGNED *) pval) = dwExp;
return(fRes); }
BOOL MyGetExpression( DWORD *pdwExp, BOOL fRecursed ) { WORD opcode;
if (!GetOp(pdwExp, OR)) return(FALSE);
while (TRUE) { // break out as appropriate
if (token.type == NUMLIT) { if (token.longval < 0) { *pdwExp += token.longval; GetToken(TOKEN_NOEXPRESSION); continue; } //
// This is a hack to fix the problem of a space after a minus sign.
// - for example 10 - 5
// - if this is a problem, please speak to Jeff Bogden
//
if (token.longval == 0 && tokenbuf[0] == L'-' && tokenbuf[1] == L'\0') token.type = TKMINUS; }
switch (token.type) { case TKPLUS: case TKMINUS: case OR: case AND: case TKNOT: opcode = token.type; GetToken(TOKEN_NOEXPRESSION);
if (!GetOp(pdwExp, opcode)) ParseError2(ERR_NEEDNUM, tokenbuf); break;
case RPAREN: if (fRecursed) { GetToken(TOKEN_NOEXPRESSION); return(TRUE); } else { goto parenMismatch; }
default: if (fRecursed) parenMismatch: ParseError2(ERR_NEEDPAREN, tokenbuf); return(TRUE); } } }
WORD MyGetNum( WORD *pwEnd, BOOL fDouble, DWORD *pdwExp ) { WORD wRes; DWORD dwExp = 0;
wRes = MyGetExpression(&dwExp, FALSE) ? PARM_SET : 0;
if (EndParcel(pwEnd)) wRes |= PARM_LAST; else if (!(token.type == COMMA)) ParseError2(ERR_BADEXP, tokenbuf);
if (fDouble) *pdwExp = dwExp; else *((WORD *) pdwExp) = (WORD) dwExp;
return(wRes); }
WORD GetText( PWORD pwEnd, PWCHAR szDst ) { BOOL fEnd; BOOL fPlus = FALSE; WORD wRes = 0;
while (!(fEnd = EndParcel(pwEnd)) && (token.type != COMMA)) { if (CheckStr(szDst)) { szDst += wcslen(szDst);
if (fPlus) fPlus = FALSE; else if (wRes) goto ErrBadStr;
wRes = PARM_SET; } else if ((token.type == TKPLUS) && !fPlus && wRes) { fPlus = TRUE; } else { ErrBadStr: ParseError2(ERR_BADSTREXP, tokenbuf); }
GetToken(TOKEN_NOEXPRESSION); }
if (fPlus) ParseError2(ERR_NEEDSTR, tokenbuf);
if (fEnd) wRes |= PARM_LAST;
return(wRes); }
void __cdecl GetParcel( PARCELTYPE parType, ... ) { PARCEL par = parcels[parType]; WORD wParm; WORD wRes; va_list ap; void *pParm; BOOL fOptional; BOOL fWriteSymbol = FALSE;
va_start(ap, parType);
for (wParm = 1; wParm <= *par.pwParms; wParm++) { pParm = va_arg(ap, void *); fOptional = par.pwParms[wParm] & PT_OPTIONAL; switch (par.pwParms[wParm] & ~PT_OPTIONAL) { case PT_TEXT: wRes = GetText(par.pwEnd, (PWCHAR) pParm); fWriteSymbol = TRUE; break;
case PT_WORD: wRes = MyGetNum(par.pwEnd, FALSE, (DWORD *) pParm); break;
case PT_DWORD: wRes = MyGetNum(par.pwEnd, TRUE, (DWORD *) pParm); break; }
if (!(wRes & PARM_SET) && !fOptional) goto ErrMissingParm;
if (wRes & PARM_LAST) { while (wParm < *par.pwParms) { if (!(par.pwParms[++wParm] & PT_OPTIONAL)) ErrMissingParm: ParseError2(ERR_NEEDARG, tokenbuf); } goto Exit; }
GetToken(TOKEN_NOEXPRESSION);
WriteSymbolUse(&token.sym); }
if (!EndParcel(par.pwEnd)) ParseError2(ERR_MOREARGS, tokenbuf);
Exit: va_end(ap); }
/*---------------------------------------------------------------------------*/ /* */ /* DoMenuItem() - */ /* */ /*---------------------------------------------------------------------------*/
WORD DoMenuItem( int fPopup ) { MENU mn;
mn.wResInfo = fPopup ? MFR_POPUP : 0; mn.dwType = 0; mn.dwState = 0; mn.dwID = 0; mn.dwHelpID = 0; mn.szText[0] = 0;
GetToken(TOKEN_NOEXPRESSION); //TRUE);
if ((token.type == NUMLIT) && (token.val == MFT_SEPARATOR)) { if (fPopup) ParseError2(ERR_NOSEP, tokenbuf);
mn.dwType = MFT_SEPARATOR; mn.dwState = 0; mn.dwID = 0; GetToken(TOKEN_NOEXPRESSION); //TRUE);
if (!EndParcel(parcels[PAR_MENUITEM].pwEnd)) ParseError2(ERR_MOREARGS, tokenbuf); } else if (fPopup) { GetParcel(PAR_POPUP, mn.szText, &mn.dwID, &mn.dwType, &mn.dwState, &mn.dwHelpID); } else { GetParcel(PAR_MENUITEM, mn.szText, &mn.dwID, &mn.dwType, &mn.dwState); }
// set it up in the buffer (?)
return(SetUpMenu(&mn)); }
/*---------------------------------------------------------------------------*/ /* */ /* ParseMenu() - */ /* */ /*---------------------------------------------------------------------------*/
int ParseMenu( int fRecursing, PRESINFO pRes /* TRUE iff popup */ ) { int bItemRead = FALSE; WORD wEndFlagLoc = 0; DWORD dwHelpID = 0;
if (!fRecursing) { // Write Help ID to header
GetParcel(PAR_MENU, &dwHelpID); WriteLong(dwHelpID); PreBeginParse(pRes, 2121); } else { /* make sure its really a menu */ if (token.type != BEGIN) ParseError1(2121); //"BEGIN expected in menu"
GetToken(TRUE); // vs. TOKEN_NOEXPRESSION ??
}
/* get the individual menu items */ while (token.type != END) { switch (token.type) { case TKMENUITEM: bItemRead = TRUE; wEndFlagLoc = DoMenuItem(FALSE); break;
case TKPOPUP: bItemRead = TRUE; wEndFlagLoc = DoMenuItem(TRUE); ParseMenu(TRUE, pRes); break;
default: ParseError2(ERR_BADSUBMENU, tokenbuf); break; } }
/* did we die on an END? */ if (token.type != END) ParseError2(ERR_NEEDEND, tokenbuf);
/* make sure we have a menu item */ if (!bItemRead) ParseError2(ERR_NOEMPTYMENU, tokenbuf);
/* Get next token if this was NOT the last END*/ if (fRecursing) GetToken(TOKEN_NOEXPRESSION);
/* mark the last item in the menu */ FixMenuPatch(wEndFlagLoc);
return (TRUE); }
|