windows-nt/Source/XPSP1/NT/sdktools/rcdll/rcutil.c
2020-09-26 16:20:57 +08:00

503 lines
13 KiB
C

/****************************************************************************/
/* */
/* rcutil.C - */
/* */
/* Windows 3.0 Resource Compiler - Utility Functions */
/* */
/* */
/****************************************************************************/
#include "rc.h"
/*---------------------------------------------------------------------------*/
/* */
/* MyAlloc() - */
/* */
/*---------------------------------------------------------------------------*/
// HACK Alert. Allocate an extra longlong and return past it (to allow for PREVCH()
// to store a byte before the allocation block and to maintain 8 byte alignment).
VOID *
MyAlloc(
UINT nbytes
)
{
PVOID s;
if ((s = HeapAlloc(hHeap, HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, nbytes+8)) != NULL) {
return(((PCHAR)s)+8);
} else {
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1120), nbytes);
quit(Msg_Text);
}
return NULL;
}
/*---------------------------------------------------------------------------*/
/* */
/* MyFree() - */
/* */
/*---------------------------------------------------------------------------*/
VOID *
MyFree(
VOID *p
)
{
if (p) {
HeapFree(hHeap, HEAP_NO_SERIALIZE, ((PCHAR)p)-8);
}
return(NULL);
}
/*---------------------------------------------------------------------------*/
/* */
/* MyMakeStr() - */
/* */
/*---------------------------------------------------------------------------*/
WCHAR *
MyMakeStr(
WCHAR *s
)
{
WCHAR * s1;
if (s) {
s1 = (WCHAR *) MyAlloc((wcslen(s) + 1) * sizeof(WCHAR)); /* allocate buffer */
wcscpy(s1, s); /* copy string */
} else {
s1 = s;
}
return(s1);
}
/*---------------------------------------------------------------------------*/
/* */
/* MyRead() - */
/* */
/*---------------------------------------------------------------------------*/
UINT
MyRead(
FILE *fh,
VOID *p,
UINT n
)
{
UINT n1;
n1 = fread(p, 1, (size_t)n, fh);
if (ferror (fh)) {
quit(GET_MSG(1121));
return 0;
} else {
return(n1);
}
}
/*---------------------------------------------------------------------------*/
/* */
/* MyWrite() - */
/* */
/*---------------------------------------------------------------------------*/
UINT
MyWrite(
FILE *fh,
VOID *p,
UINT n
)
{
UINT n1;
if ((n1 = fwrite(p, 1, n, fh)) != n) {
quit("RC : fatal error RW1022: I/O error writing file.");
return (0);
} else {
return(n1);
}
}
/*---------------------------------------------------------------------------*/
/* */
/* MyAlign() - */
/* */
/*---------------------------------------------------------------------------*/
UINT
MyAlign(
PFILE fh
)
{
DWORD t0 = 0;
DWORD ib;
/* align file to dword */
ib = MySeek(fh, 0L, SEEK_CUR);
if (ib % 4) {
ib = 4 - ib % 4;
MyWrite(fh, (PVOID)&t0, (UINT)ib);
return(ib);
}
return(0);
}
/*---------------------------------------------------------------------------*/
/* */
/* MySeek() - */
/* */
/*---------------------------------------------------------------------------*/
LONG
MySeek(
FILE *fh,
LONG pos,
int cmd
)
{
if (fseek(fh, pos, cmd))
quit("RC : fatal error RW1023: I/O error seeking in file");
if ((pos = ftell (fh)) == -1L)
quit("RC : fatal error RW1023: I/O error seeking in file");
return(pos);
}
/*---------------------------------------------------------------------------*/
/* */
/* MyCopy() - */
/* */
/*---------------------------------------------------------------------------*/
int
MyCopy(
FILE *srcfh,
PFILE dstfh,
ULONG nbytes
)
{
PCHAR buffer = (PCHAR) MyAlloc(BUFSIZE);
UINT n;
while (nbytes) {
if (nbytes <= BUFSIZE)
n = (UINT)nbytes;
else
n = BUFSIZE;
nbytes -= n;
MyRead(srcfh, buffer, n);
MyWrite( dstfh, buffer, n);
}
MyFree(buffer);
return(n);
}
/*---------------------------------------------------------------------------*/
/* */
/* MyCopyAll() - */
/* */
/*---------------------------------------------------------------------------*/
int
MyCopyAll(
FILE *srcfh,
PFILE dstfh
)
{
PCHAR buffer = (PCHAR) MyAlloc(BUFSIZE);
UINT n;
while ((n = fread(buffer, 1, BUFSIZE, srcfh)) != 0)
MyWrite(dstfh, buffer, n);
MyFree(buffer);
return TRUE;
}
/*---------------------------------------------------------------------------*/
/* */
/* strpre() - */
/* */
/*---------------------------------------------------------------------------*/
/* strpre: return -1 if pch1 is a prefix of pch2, 0 otherwise.
* compare is case insensitive.
*/
int
strpre(
PWCHAR pch1,
PWCHAR pch2
)
{
while (*pch1) {
if (!*pch2)
return 0;
else if (towupper(*pch1) == towupper(*pch2))
pch1++, pch2++;
else
return 0;
}
return - 1;
}
/*---------------------------------------------------------------------------*/
/* */
/* iswhite() - */
/* */
/*---------------------------------------------------------------------------*/
int
iswhite (
WCHAR c
)
{
/* returns true for whitespace and linebreak characters */
switch (c) {
case L' ':
case L'\t':
case L'\r':
case L'\n':
case EOF:
return(-1);
break;
default:
return(0);
break;
}
}
/*---------------------------------------------------------------------------*/
/* */
/* IsSwitchChar() - */
/* */
/*---------------------------------------------------------------------------*/
BOOL
IsSwitchChar(
CHAR c
)
{
/* true for switch characters */
return (c == '/' || c == '-');
}
/*---------------------------------------------------------------------------*/
/* */
/* searchenv() - */
/* */
/*---------------------------------------------------------------------------*/
/* the _searchenv() function in the C5.0 RTL doesn't work. In particular,
* it fails to check for \ characters and can end up returning paths like
* D:\\FILE.EXT. szActual is assumed to be at least MAX_PATH and will
* always get walked all over
*/
VOID
searchenv(
PCHAR szFile,
PCHAR szVar,
PCHAR szActual
)
{
PCHAR pchVar;
PCHAR pch;
int ich;
PFILE fhTemp;
if (!strcmp(szVar, "INCLUDE"))
pchVar = pchInclude;
else
pchVar = getenv(szVar);
if (!pchVar)
return;
/* we don't do absolute paths */
if (szFile[0] == '\\' || szFile[0] == '/' || szFile[1] == ':') {
for (ich = 0; szActual[ich] = szFile[ich]; ich++)
;
return;
}
do {
/* copy the next environment string... */
for (ich = 0; (szActual[ich] = pchVar[ich]) != '\000'; ich++)
if (pchVar[ich] == ';')
break;
szActual[ich] = '\000';
pchVar += ich;
if (*pchVar)
pchVar++;
/* HARD LOOP -- find end of path string */
for (pch = szActual; *pch; pch++)
;
/* check first! this is what _searchenv() messed up! */
if (pch[-1] != '\\' && pch[-1] != '/')
*pch++ = '\\';
/* HARD LOOP -- we already know szFile does start with a drive or abs. dir */
for (ich = 0; pch[ich] = szFile[ich]; ich++)
;
/* is the file here? szActual already contains name */
if ((fhTemp = fopen(szActual, "rb")) != NULL) {
fclose (fhTemp);
return;
}
} while (szActual[0] && *pchVar);
/* if we reach here, we know szActual is empty */
return;
}
/*---------------------------------------------------------------------------*/
/* */
/* ExtractFileName(szFullName, szFileName) - */
/* */
/* This routine is used to extract just the file name from a string */
/* that may or may not contain a full or partial path name. */
/* */
/*---------------------------------------------------------------------------*/
VOID
ExtractFileName(
PWCHAR szFullName,
PWCHAR szFileName
)
{
int iLen;
PWCHAR pCh;
iLen = wcslen(szFullName);
/* Goto the last character of the full name; */
pCh = (PWCHAR)(szFullName + iLen);
pCh--;
/* Look for '/', '\\' or ':' character */
while (iLen--) {
if ((*pCh == L'\\') || (*pCh == L'/') || (*pCh == L':'))
break;
pCh--;
}
wcscpy(szFileName, ++pCh);
}
DWORD
wcsatoi(
WCHAR *s
)
{
DWORD t = 0;
while (*s) {
t = 10 * t + (DWORD)((CHAR)*s - '0');
s++;
}
return t;
}
WCHAR *
wcsitow(
LONG v,
WCHAR *s,
DWORD r
)
{
DWORD cb = 0;
DWORD t;
DWORD tt = v;
while (tt) {
t = tt % r;
cb++;
tt /= r;
}
s += cb;
*s-- = 0;
while (v) {
t = v % r;
*s-- = (WCHAR)((CHAR)t + '0');
v /= r;
}
return ++s;
}
// ----------------------------------------------------------------------------
//
// PreBeginParse
//
// ----------------------------------------------------------------------------
VOID
PreBeginParse(
PRESINFO pRes,
int id
)
{
while (token.type != BEGIN) {
switch (token.type) {
case TKLANGUAGE:
pRes->language = GetLanguage();
break;
case TKVERSION:
GetToken(FALSE);
if (token.type != NUMLIT)
ParseError1(2139);
pRes->version = token.longval;
break;
case TKCHARACTERISTICS:
GetToken(FALSE);
if (token.type != NUMLIT)
ParseError1(2140);
pRes->characteristics = token.longval;
break;
default:
ParseError1(id);
break;
}
GetToken(FALSE);
}
if (token.type != BEGIN)
ParseError1(id);
GetToken(TRUE);
}