Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1179 lines
34 KiB

/****************************************************************************/
/* */
/* RC.C - */
/* */
/* Windows 2.0 Resource Compiler - Main Module */
/* */
/* */
/****************************************************************************/
#include "rc.h"
#include <setjmp.h>
#include <ddeml.h>
#define READ_MAX (MAXSTR+80)
#define MAX_CMD 256
#define cDefineMax 100
CHAR resname[_MAX_PATH];
PCHAR szRCPP[MAX_CMD];
/************************************************************************/
/* Define Global Variables */
/************************************************************************/
SHORT ResCount; /* number of resources */
PTYPEINFO pTypInfo;
SHORT nFontsRead;
FONTDIR *pFontList;
FONTDIR *pFontLast;
TOKEN token;
int errorCount;
WCHAR tokenbuf[ MAXSTR + 1 ];
UCHAR exename[ _MAX_PATH ], fullname[ _MAX_PATH ];
UCHAR curFile[ _MAX_PATH ];
HANDLE hHeap = NULL;
PDLGHDR pLocDlg;
UINT mnEndFlagLoc; /* patch location for end of a menu. */
/* we set the high order bit there */
/* BOOL fLeaveFontDir; */
BOOL fVerbose; /* verbose mode (-v) */
BOOL fAFXSymbols;
BOOL fMacRsrcs;
BOOL fAppendNull;
long lOffIndex;
WORD idBase;
BOOL fPreprocessOnly;
CHAR szBuf[_MAX_PATH * 2];
CHAR szPreProcessName[_MAX_PATH];
/* File global variables */
CHAR inname[_MAX_PATH];
PCHAR szTempFileName;
PCHAR szTempFileName2;
PFILE fhBin;
PFILE fhInput;
/* array for include path stuff, initially empty */
PCHAR pchInclude;
/* Substitute font name */
int nBogusFontNames;
WCHAR *pszBogusFontNames[16];
WCHAR szSubstituteFontName[MAXTOKSTR];
static jmp_buf jb;
extern ULONG lCPPTotalLinenumber;
/* Function prototypes for local functions */
HANDLE RCInit(void);
BOOL RC_PreProcess (PCHAR);
VOID CleanUpFiles(void);
/*---------------------------------------------------------------------------*/
/* */
/* rc_main() - */
/* */
/*---------------------------------------------------------------------------*/
int _CRTAPI1
rc_main(
int argc,
char**argv
)
{
PCHAR r;
PCHAR x;
PCHAR s1, s2, s3;
int n;
PCHAR pchIncludeT;
ULONG cchIncludeMax;
int fInclude = TRUE; /* by default, search INCLUDE */
int fIncludeCurrentFirst = TRUE; /* by default, add current dir to start of includes */
int cDefine = 0;
int cUnDefine = 0;
PCHAR pszDefine[cDefineMax];
PCHAR pszUnDefine[cDefineMax];
CHAR szDrive[_MAX_DRIVE];
CHAR szDir[_MAX_DIR];
CHAR szFName[_MAX_FNAME];
CHAR szExt[_MAX_EXT];
CHAR szFullPath[_MAX_PATH];
CHAR szIncPath[_MAX_PATH];
CHAR buf[10];
CHAR *szRC;
PCHAR *ppargv;
int rcpp_argc;
/* Set up for this run of RC */
if (_setjmp(jb)) {
return Nerrors;
}
hHeap = RCInit();
if (hHeap == NULL) {
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1120), 0x01000000);
quit(Msg_Text);
}
pchInclude = pchIncludeT = MyAlloc(_MAX_PATH*2);
cchIncludeMax = _MAX_PATH*2;
szRC = argv[0];
/* process the command line switches */
while ((argc > 1) && (IsSwitchChar(*argv[1]))) {
switch (toupper(argv[1][1])) {
case '?':
case 'H':
/* print out help, and quit */
SendError("\n");
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(10001),
VER_PRODUCTVERSION_STR, VER_PRODUCTBUILD);
SendError(Msg_Text);
SendError(GET_MSG(20001));
SendError("\n");
return 0; /* can just return - nothing to cleanup, yet. */
case 'B':
if (toupper(argv[1][2]) == 'R') { /* base resource id */
unsigned long id;
if (isdigit(argv[1][3]))
argv[1] += 3;
else if (argv[1][3] == ':')
argv[1] += 4;
else {
argc--;
argv++;
if (argc <= 1)
goto BadId;
}
if (*(argv[1]) == 0)
goto BadId;
id = atoi(argv[1]);
if (id < 1 || id > 32767)
quit(GET_MSG(1210));
idBase = (WORD)id;
break;
BadId:
quit(GET_MSG(1209));
}
break;
case 'C':
/* Check for the existence of CodePage Number */
if (argv[1][2])
argv[1] += 2;
else {
argc--;
argv++;
}
/* Now argv point to first digit of CodePage */
if (!argv[1])
quit(GET_MSG(1204));
uiCodePage = atoi(argv[1]);
if (uiCodePage == 0)
quit(GET_MSG(1205));
/* Check if uiCodePage exist in registry. */
if (!IsValidCodePage (uiCodePage))
quit(GET_MSG(1206));
break;
case 'D':
/* if not attached to switch, skip to next */
if (argv[1][2])
argv[1] += 2;
else {
argc--;
argv++;
}
/* remember pointer to string */
pszDefine[cDefine++] = argv[1];
if (cDefine > cDefineMax) {
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1105), argv[1]);
quit(Msg_Text);
}
break;
case 'F':
switch (toupper(argv[1][2])) {
case 'O':
if (argv[1][3])
argv[1] += 3;
else {
argc--;
argv++;
}
if (argc > 1)
strcpy(resname, argv[1]);
else
quit(GET_MSG(1101));
break;
default:
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1103), argv[1]);
quit(Msg_Text);
}
break;
case 'I':
/* add string to directories to search */
/* note: format is <path>\0<path>\0\0 */
/* if not attached to switch, skip to next */
if (argv[1][2])
argv[1] += 2;
else {
argc--;
argv++;
}
if (!argv[1])
quit(GET_MSG(1201));
if ((strlen(argv[1]) + 1 + strlen(pchInclude)) >= cchIncludeMax) {
cchIncludeMax = strlen(pchInclude) + strlen(argv[1]) + _MAX_PATH*2;
pchIncludeT = MyAlloc(cchIncludeMax);
strcpy(pchIncludeT, pchInclude);
MyFree(pchInclude);
pchInclude = pchIncludeT;
pchIncludeT = pchInclude + strlen(pchIncludeT) + 1;
}
/* if not first switch, write over terminator with semicolon */
if (pchInclude != pchIncludeT)
pchIncludeT[-1] = ';';
/* copy the path */
while ((*pchIncludeT++ = *argv[1]++) != 0)
;
break;
case 'L':
/* if not attached to switch, skip to next */
if (argv[1][2])
argv[1] += 2;
else {
argc--;
argv++;
}
if (!argv[1])
quit(GET_MSG(1202));
if (sscanf( argv[1], "%x", &language ) != 1)
quit(GET_MSG(1203));
while (*argv[1]++ != 0)
;
break;
case 'M':
fMacRsrcs = TRUE;
goto MaybeMore;
case 'N':
fAppendNull = TRUE;
goto MaybeMore;
case 'P':
fPreprocessOnly = TRUE;
break;
case 'R':
goto MaybeMore;
case 'S':
// find out from BRAD what -S does
fAFXSymbols = TRUE;
break;
case 'U':
/* if not attached to switch, skip to next */
if (argv[1][2])
argv[1] += 2;
else {
argc--;
argv++;
}
/* remember pointer to string */
pszUnDefine[cUnDefine++] = argv[1];
if (cUnDefine > cDefineMax) {
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1104), argv[1]);
quit(Msg_Text);
}
break;
case 'V':
fVerbose = TRUE; // AFX doesn't set this
goto MaybeMore;
case 'X':
/* remember not to add INCLUDE path */
fInclude = FALSE;
// VC seems to feel the current dir s/b added first no matter what...
// If -X! is specified, don't do that.
if (argv[1][2] == '!') {
fIncludeCurrentFirst = FALSE;
argv[1]++;
}
MaybeMore: /* check to see if multiple switches, like -xrv */
if (argv[1][2]) {
argv[1][1] = '-';
argv[1]++;
continue;
}
break;
case 'Z':
/* if not attached to switch, skip to next */
if (argv[1][2])
argv[1] += 2;
else {
argc--;
argv++;
}
if (!argv[1])
quit(GET_MSG(1211));
s3 = strchr(argv[1], '/');
if (s3 == NULL)
quit(GET_MSG(1212));
*s3 = '\0';
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, s3+1, -1, szSubstituteFontName, MAXTOKSTR);
s1 = argv[1];
do {
s2 = strchr(s1, ',');
if (s2 != NULL)
*s2 = '\0';
if (strlen(s1)) {
if (nBogusFontNames >= 16)
quit(GET_MSG(1213));
pszBogusFontNames[nBogusFontNames] = MyAlloc((strlen(s1)+1) * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, s1, -1, pszBogusFontNames[nBogusFontNames], MAXTOKSTR);
nBogusFontNames += 1;
}
if (s2 != NULL)
*s2++ = ',';
}
while (s1 = s2);
*s3 = '/';
while (*argv[1]++ != 0)
;
break;
default:
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1106), argv[1]);
quit(Msg_Text);
}
/* get next argument or switch */
argc--;
argv++;
}
/* make sure we have at least one file name to work with */
if (argc != 2 || *argv[1] == '\0')
quit(GET_MSG(1107));
if (fVerbose) {
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(10001),
VER_PRODUCTVERSION_STR, VER_PRODUCTBUILD);
printf(Msg_Text);
printf("%s\n", GET_MSG(10002));
}
// Support Multi Code Page
// If user did NOT indicate code in command line, we have to set Default
// for NLS Conversion
if (uiCodePage == 0) {
CHAR *pchCodePageString;
/* At first, search ENVIRONMENT VALUE */
if ((pchCodePageString = getenv("RCCODEPAGE")) != NULL) {
uiCodePage = atoi(pchCodePageString);
if (uiCodePage == 0 || !IsValidCodePage(uiCodePage))
quit(GET_MSG(1207));
}
else
{
/* We use System ANSI Code page (ACP) */
uiCodePage = GetACP();
}
}
uiDefaultCodePage = uiCodePage;
if (fVerbose)
printf("Using codepage %d as default\n", uiDefaultCodePage);
/* If we have no extension, assumer .rc */
/* If .res extension, make sure we have -fo set, or error */
/* Otherwise, just assume file is .rc and output .res (or resname) */
//
// We have to be careful upper casing this, because the codepage
// of the filename might be in something other than current codepage.
//
MultiByteToWideChar(uiCodePage, MB_PRECOMPOSED, argv[1], -1, tokenbuf, MAXSTR+1);
if (CharUpperBuff(tokenbuf, wcslen(tokenbuf)) == 0)
_wcsupr(tokenbuf);
WideCharToMultiByte(uiCodePage, 0, tokenbuf, -1, argv[1], strlen(argv[1]), NULL, NULL);
_splitpath(argv[1], szDrive, szDir, szFName, szExt);
if (!(*szDir || *szDrive)) {
strcpy(szIncPath, ".;");
} else {
strcpy(szIncPath, szDrive);
strcat(szIncPath, szDir);
strcat(szIncPath, ";.;");
}
if ((strlen(szIncPath) + 1 + strlen(pchInclude)) >= cchIncludeMax) {
cchIncludeMax = strlen(pchInclude) + strlen(szIncPath) + _MAX_PATH*2;
pchIncludeT = MyAlloc(cchIncludeMax);
strcpy(pchIncludeT, pchInclude);
MyFree(pchInclude);
pchInclude = pchIncludeT;
pchIncludeT = pchInclude + strlen(pchIncludeT) + 1;
}
pchIncludeT = MyAlloc(cchIncludeMax);
if (fIncludeCurrentFirst) {
strcpy(pchIncludeT, szIncPath);
strcat(pchIncludeT, pchInclude);
} else {
strcpy(pchIncludeT, pchInclude);
strcat(pchIncludeT, ";");
strcat(pchIncludeT, szIncPath);
}
MyFree(pchInclude);
pchInclude = pchIncludeT;
pchIncludeT = pchInclude + strlen(pchIncludeT) + 1;
if (!szExt[0]) {
strcpy(szExt, ".RC");
}
else if (strcmp (szExt, ".RES") == 0) {
quit (GET_MSG(1208));
}
_makepath(inname, szDrive, szDir, szFName, szExt);
if (fPreprocessOnly) {
_makepath(szPreProcessName, NULL, NULL, szFName, ".rcpp");
}
/* Create the name of the .RES file */
if (resname[0] == 0) {
// if building a Mac resource file, we use .rsc to match mrc's output
_makepath(resname, szDrive, szDir, szFName, fMacRsrcs ? ".RSC" : ".RES");
}
/* create the temporary file names */
szTempFileName = MyAlloc(_MAX_PATH);
_fullpath(szFullPath, resname, _MAX_PATH);
_splitpath(szFullPath, szDrive, szDir, NULL, NULL);
_makepath(szTempFileName, szDrive, szDir, "RCXXXXXX", "");
_mktemp (szTempFileName);
szTempFileName2 = MyAlloc(_MAX_PATH);
_makepath(szTempFileName2, szDrive, szDir, "RDXXXXXX", "");
_mktemp (szTempFileName2);
ppargv = szRCPP;
*ppargv++ = "RCPP";
rcpp_argc = 1;
/* Open the .RES file (deleting any old versions which exist). */
if ((fhBin = fopen(resname, "w+b")) == NULL) {
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1109), resname);
quit(Msg_Text);
}
else {
if (fMacRsrcs)
MySeek(fhBin, MACDATAOFFSET, 0);
if (fVerbose) {
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(10102), resname);
printf(Msg_Text);
}
/* Set up for RCPP. This constructs the command line for it. */
*ppargv = _strdup("-CP");
rcpp_argc++ ; ppargv++;
_itoa(uiCodePage, buf, 10);
*ppargv = buf;
rcpp_argc++ ; ppargv++;
*ppargv = _strdup("-f");
rcpp_argc++ ; ppargv++;
*ppargv = _strdup(szTempFileName);
rcpp_argc++ ; ppargv++;
*ppargv = _strdup("-g");
rcpp_argc++ ; ppargv++;
if (fPreprocessOnly) {
*ppargv = _strdup(szPreProcessName);
} else {
*ppargv = _strdup(szTempFileName2);
}
rcpp_argc++ ; ppargv++;
*ppargv = _strdup("-DRC_INVOKED");
rcpp_argc++ ; ppargv++;
if (fAFXSymbols) {
*ppargv = _strdup("-DAPSTUDIO_INVOKED");
rcpp_argc++ ; ppargv++;
}
if (fMacRsrcs) {
*ppargv = _strdup("-D_MAC");
rcpp_argc++ ; ppargv++;
}
*ppargv = _strdup("-D_WIN32"); /* to be compatible with C9/VC++ */
rcpp_argc++ ; ppargv++;
*ppargv = _strdup("-pc\\:/");
rcpp_argc++ ; ppargv++;
*ppargv = _strdup("-E");
rcpp_argc++ ; ppargv++;
/* Parse the INCLUDE environment variable */
if (fInclude) {
*ppargv = _strdup("-I.");
rcpp_argc++ ; ppargv++;
/* add seperator if any -I switches */
if (pchInclude != pchIncludeT)
pchIncludeT[-1] = ';';
/* read 'em */
x = getenv("INCLUDE");
if (x == (PCHAR)NULL)
*pchIncludeT = '\000';
else {
if (strlen(pchInclude) + strlen(x) + 1 >= cchIncludeMax) {
cchIncludeMax = strlen(pchInclude) + strlen(x) + _MAX_PATH*2;
pchIncludeT = MyAlloc(cchIncludeMax);
strcpy(pchIncludeT, pchInclude);
MyFree(pchInclude);
pchInclude = pchIncludeT;
}
strcat(pchInclude, x);
pchIncludeT = pchInclude + strlen(pchInclude);
}
}
/* now put includes on the RCPP command line */
for (x = pchInclude ; *x ; ) {
r = x;
while (*x && *x != ';')
x = CharNextA(x);
/* mark if semicolon */
if (*x)
*x-- = 0;
if (*r != '\0' && /* empty include path? */
*r != '%' /* check for un-expanded stuff */
// && strchr(r, ' ') == NULL /* check for whitespace */
) {
/* add switch */
*ppargv = _strdup("-I");
rcpp_argc++ ; ppargv++;
*ppargv = _strdup(r);
rcpp_argc++ ; ppargv++;
}
/* was semicolon, need to fix for searchenv() */
if (*x) {
*++x = ';';
x++;
}
}
/* include defines */
for (n = 0; n < cDefine; n++) {
*ppargv = _strdup("-D");
rcpp_argc++ ; ppargv++;
*ppargv = pszDefine[n];
rcpp_argc++ ; ppargv++;
}
/* include undefine */
for (n = 0; n < cUnDefine; n++) {
*ppargv = _strdup("-U");
rcpp_argc++ ; ppargv++;
*ppargv = pszUnDefine[n];
rcpp_argc++ ; ppargv++;
}
if (rcpp_argc > MAX_CMD) {
quit(GET_MSG(1102));
}
if (fVerbose) {
/* echo the preprocessor command */
printf("RC:");
for (n = 0 ; n < rcpp_argc ; n++) {
wsprintfA(Msg_Text, " %s", szRCPP[n]);
printf(Msg_Text);
}
printf("\n");
}
/* Add .rc with rcincludes into szTempFileName */
if (!RC_PreProcess(inname))
quit(Msg_Text);
/* Run the Preprocessor. */
if (RCPP(rcpp_argc, szRCPP, NULL) != 0)
quit(GET_MSG(1116));
}
if (fPreprocessOnly) {
sprintf(szBuf, "Preprocessed File Created in: %s\n", szPreProcessName);
quit(szBuf);
}
if (fVerbose)
printf("\n%s", inname);
if ((fhInput = fopen(szTempFileName2, "rb")) == NULL_FILE)
quit(GET_MSG(2180));
if (!InitSymbolInfo())
quit(GET_MSG(22103));
LexInit (fhInput);
uiCodePage = uiDefaultCodePage;
ReadRF(); /* create .RES from .RC */
if (!TermSymbolInfo(fhBin))
quit(GET_MSG(22204));
if (!fMacRsrcs)
MyAlign(fhBin); // Pad end of file so that we can concatenate files
CleanUpFiles();
HeapDestroy(hHeap);
return Nerrors; // return success, not quitting.
}
/* RCInit
* Initializes this run of RC.
*/
HANDLE RCInit(void)
{
Nerrors = 0;
uiCodePage = 0;
nFontsRead = 0;
szTempFileName = NULL;
szTempFileName2 = NULL;
lOffIndex = 0;
idBase = 128;
pTypInfo = NULL;
fVerbose = FALSE;
fMacRsrcs = FALSE;
// Clear the filenames
exename[0] = 0;
resname[0] = 0;
/* create growable local heap of 16MB minimum size */
return HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
}
/*---------------------------------------------------------------------------*/
/* */
/* skipblanks() - */
/* */
/*---------------------------------------------------------------------------*/
PWCHAR skipblanks(PWCHAR pstr, int fTerminate)
{
/* search forward for first non-white character and save its address */
while (*pstr && iswspace(*pstr))
pstr++;
if (fTerminate) {
PWCHAR retval = pstr;
/* search forward for first white character and zero to extract word */
while (*pstr && !iswspace(*pstr))
pstr++;
*pstr = 0;
return retval;
}
else
return pstr;
}
/*---------------------------------------------------------------------------*/
/* */
/* RC_PreProcess() - */
/* */
/*---------------------------------------------------------------------------*/
BOOL RC_PreProcess(PCHAR szname)
{
PFILE fhout; /* fhout: is temp file with rcincluded stuff */
PFILE fhin;
CHAR nm[_MAX_PATH*2];
PCHAR pch;
PWCHAR pwch;
PWCHAR pfilename;
WCHAR readszbuf[READ_MAX];
WCHAR szT[ MAXSTR ];
UINT iLine = 0;
int fBlanks = TRUE;
INT fFileType;
/* Open the .RC source file. */
MultiByteToWideChar(uiCodePage, MB_PRECOMPOSED, szname, -1, Filename, MED_BUFFER+1);
fhin = fopen(szname, "rb");
if (!fhin) {
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1110), szname);
return(FALSE);
}
/* Open the temporary output file. */
fhout = fopen(szTempFileName, "w+b");
if (!fhout) {
strcpy(Msg_Text, GET_MSG(2180));
return(FALSE);
}
/* output the current filename for RCPP messages */
for (pch=nm ; *szname ; szname = CharNextA(szname)) {
*pch++ = *szname;
if (IsDBCSLeadByteEx(uiCodePage, *szname))
*pch++ = *(szname + 1);
/* Hack to fix bug #8786: makes '\' to "\\" */
else if (*szname == '\\')
*pch++ = '\\';
}
*pch++ = '\000';
/* Output the current filename for RCPP messages */
wcscpy(szT, L"#line 1\"");
// hack - strlen("#line 1\"") is 8.
MultiByteToWideChar(uiCodePage, MB_PRECOMPOSED, nm, -1, szT+8, MAXSTR+1-8);
wcscat(szT, L"\"\r\n");
MyWrite(fhout, szT, wcslen(szT) * sizeof(WCHAR));
/* Determine if the input file is Unicode */
fFileType = DetermineFileType (fhin);
/* Process each line of the input file. */
while (fgetl(readszbuf, READ_MAX, fFileType == DFT_FILE_IS_16_BIT, fhin)) {
/* keep track of the number of lines read */
Linenumber = iLine++;
if ((iLine & RC_PREPROCESS_UPDATE) == 0)
UpdateStatus(1, iLine);
/* Skip the Byte Order Mark and the leading bytes. */
pwch = readszbuf;
while (*pwch && (iswspace(*pwch) || *pwch == 0xFEFF))
pwch++;
/* if the line is a rcinclude line... */
if (strpre(L"rcinclude", pwch)) {
/* Get the name of the rcincluded file. */
pfilename = skipblanks(pwch + 9, TRUE);
MyWrite(fhout, L"#include \"", 10 * sizeof(WCHAR));
MyWrite(fhout, pfilename, wcslen(pfilename) * sizeof(WCHAR));
MyWrite(fhout, L"\"\r\n", 3 * sizeof(WCHAR));
}
else if (strpre(L"#pragma", pwch)) {
WCHAR cSave;
pfilename = skipblanks(pwch + 7, FALSE);
if (strpre(L"code_page", pfilename)) {
pfilename = skipblanks(pfilename + 9, FALSE);
if (*pfilename == L'(') {
ULONG cp = 0;
pfilename = skipblanks(pfilename + 1, FALSE);
// BUGBUG really should allow hex/octal, but ...
if (iswdigit(*pfilename)) {
while (iswdigit(*pfilename)) {
cp = cp * 10 + (*pfilename++ - L'0');
}
pfilename = skipblanks(pfilename, FALSE);
}
else if (strpre(L"default", pfilename)) {
cp = uiDefaultCodePage;
pfilename = skipblanks(pfilename + 7, FALSE);
}
if (cp == 0) {
wsprintfA(Msg_Text, "%s%ws", GET_MSG(4212), pfilename);
error(4212);
}
else if (*pfilename != L')') {
strcpy (Msg_Text, GET_MSG (4211));
error(4211);
}
else if (cp == CP_WINUNICODE) {
strcpy (Msg_Text, GET_MSG (4213));
warning(4213);
}
else if (!IsValidCodePage(cp)) {
strcpy (Msg_Text, GET_MSG (4214));
warning(4214);
}
else {
uiCodePage = cp;
/* Copy the #pragma line to the temp file. */
MyWrite(fhout, pwch, wcslen(pwch) * sizeof(WCHAR));
MyWrite(fhout, L"\r\n", 2 * sizeof(WCHAR));
}
}
else {
strcpy (Msg_Text, GET_MSG (4210));
error(4210);
}
}
}
else if (!*pwch)
fBlanks = TRUE;
else {
if (fBlanks) {
swprintf(szT, L"#line %d\r\n", iLine);
MyWrite(fhout, szT, wcslen(szT) * sizeof(WCHAR));
fBlanks = FALSE;
}
/* Copy the .RC line to the temp file. */
MyWrite(fhout, pwch, wcslen(pwch) * sizeof(WCHAR));
MyWrite(fhout, L"\r\n", 2 * sizeof(WCHAR));
}
}
lCPPTotalLinenumber = iLine;
Linenumber = 0;
uiCodePage = uiDefaultCodePage;
fclose(fhout);
fclose(fhin);
return(TRUE);
}
/*---------------------------------------------------------------------------*/
/* */
/* quit() */
/* */
/*---------------------------------------------------------------------------*/
VOID quit(PSTR str)
{
/* print out the error message */
if (str) {
SendError("\n");
SendError(str);
SendError("\n");
}
CleanUpFiles();
/* delete output file */
if (resname)
remove(resname);
HeapDestroy(hHeap);
Nerrors++;
longjmp(jb, Nerrors);
}
BOOL WINAPI Handler(DWORD fdwCtrlType)
{
if (fdwCtrlType == CTRL_C_EVENT) {
SendError("\n");
SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(20101));
SendError(Msg_Text);
CleanUpFiles();
HeapDestroy(hHeap);
/* delete output file */
if (resname)
remove(resname);
return(FALSE);
}
return(FALSE);
}
VOID CleanUpFiles(void)
{
TermSymbolInfo(NULL_FILE);
/* Close ALL files. */
if (fhBin != NULL)
fclose(fhBin);
if (fhInput != NULL)
fclose(fhInput);
if (fhCode != NULL)
fclose(fhCode);
p0_terminate();
/* clean up after font directory temp file */
if (nFontsRead)
remove("rc$x.fdr");
/* delete the temporary files */
if (szTempFileName)
remove(szTempFileName);
if (szTempFileName2)
remove(szTempFileName2);
if (Nerrors > 0)
remove(resname);
}
#if 0
/***
*splitpath.c - break down path name into components
*
* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
*
*Purpose:
* To provide support for accessing the individual components of an
* arbitrary path name
*
*Revision History:
* 06-14-87 DFW initial implementation
* 09-23-87 JCR Removed 'const' from declarations (fixed cl warnings)
* 12-11-87 JCR Added "_LOAD_DS" to declaration
* 11-20-89 GJF Fixed indents, copyright. Added const attribute to
* type of path.
* 03-15-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
* <cruntime.h>.
* 07-25-90 SBM Removed redundant include (stdio.h), replaced local
* MIN macro with standard min macro
* 10-04-90 GJF New-style function declarator.
* 01-22-91 GJF ANSI naming.
* 11-20-92 KRS Port _MBCS support from 16-bit tree.
* 05-12-93 KRS Add fix for MBCS max path handling.
*
*******************************************************************************/
/***
*_splitpath() - split a path name into its individual components
*
*Purpose:
* to split a path name into its individual components
*
*Entry:
* path - pointer to path name to be parsed
* drive - pointer to buffer for drive component, if any
* dir - pointer to buffer for subdirectory component, if any
* fname - pointer to buffer for file base name component, if any
* ext - pointer to buffer for file name extension component, if any
*
*Exit:
* drive - pointer to drive string. Includes ':' if a drive was given.
* dir - pointer to subdirectory string. Includes leading and trailing
* '/' or '\', if any.
* fname - pointer to file base name
* ext - pointer to file extension, if any. Includes leading '.'.
*
*Exceptions:
*
*******************************************************************************/
void _CRTAPI1 _splitpath (
register const char *path,
char *drive,
char *dir,
char *fname,
char *ext
)
{
register char *p;
char *last_slash = NULL, *dot = NULL;
unsigned len;
/* we assume that the path argument has the following form, where any
* or all of the components may be missing.
*
* <drive><dir><fname><ext>
*
* and each of the components has the following expected form(s)
*
* drive:
* 0 to _MAX_DRIVE-1 characters, the last of which, if any, is a
* ':'
* dir:
* 0 to _MAX_DIR-1 characters in the form of an absolute path
* (leading '/' or '\') or relative path, the last of which, if
* any, must be a '/' or '\'. E.g -
* absolute path:
* \top\next\last\ ; or
* /top/next/last/
* relative path:
* top\next\last\ ; or
* top/next/last/
* Mixed use of '/' and '\' within a path is also tolerated
* fname:
* 0 to _MAX_FNAME-1 characters not including the '.' character
* ext:
* 0 to _MAX_EXT-1 characters where, if any, the first must be a
* '.'
*
*/
/* extract drive letter and :, if any */
if (*(path + _MAX_DRIVE - 2) == ':') {
if (drive) {
strncpy(drive, path, _MAX_DRIVE - 1);
*(drive + _MAX_DRIVE-1) = '\0';
}
path += _MAX_DRIVE - 1;
}
else if (drive) {
*drive = '\0';
}
/* extract path string, if any. Path now points to the first character
* of the path, if any, or the filename or extension, if no path was
* specified. Scan ahead for the last occurence, if any, of a '/' or
* '\' path separator character. If none is found, there is no path.
* We will also note the last '.' character found, if any, to aid in
* handling the extension.
*/
for (last_slash = NULL, p = (char *)path; *p; p++) {
if (IsDBCSLeadByteEx(uiCodePage, *p))
p++;
else {
if (*p == '/' || *p == '\\')
/* point to one beyond for later copy */
last_slash = p + 1;
else if (*p == '.')
dot = p;
}
}
if (last_slash) {
/* found a path - copy up through last_slash or max. characters
* allowed, whichever is smaller
*/
if (dir) {
len = __min((last_slash - path), (_MAX_DIR - 1));
strncpy(dir, path, len);
*(dir + len) = '\0';
}
path = last_slash;
}
else if (dir) {
/* no path found */
*dir = '\0';
}
/* extract file name and extension, if any. Path now points to the
* first character of the file name, if any, or the extension if no
* file name was given. Dot points to the '.' beginning the extension,
* if any.
*/
if (dot && (dot >= path)) {
/* found the marker for an extension - copy the file name up to
* the '.'.
*/
if (fname) {
len = __min((dot - path), (_MAX_FNAME - 1));
strncpy(fname, path, len);
*(fname + len) = '\0';
}
/* now we can get the extension - remember that p still points
* to the terminating nul character of path.
*/
if (ext) {
len = __min((p - dot), (_MAX_EXT - 1));
strncpy(ext, dot, len);
*(ext + len) = '\0';
}
}
else {
/* found no extension, give empty extension and copy rest of
* string into fname.
*/
if (fname) {
len = __min((p - path), (_MAX_FNAME - 1));
strncpy(fname, path, len);
*(fname + len) = '\0';
}
if (ext) {
*ext = '\0';
}
}
}
#endif