2020-09-30 17:12:29 +02:00

438 lines
11 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*** ERROR.C -- error handling functions *************************************
*
* Copyright (c) 1988-1990, Microsoft Corporation. All rights reserved.
*
* Revision History:
* 01-Feb-1994 HV Move messages to external file.
* 29-Oct-1993 HV Change the version scheme.
* 15-Oct-1993 HV Use tchar.h instead of mbstring.h directly, change STR*() to _ftcs*()
* 18-May-1993 HV Change reference to messageTable[] to __MSGTAB. The new
* (and more standard) mkmsg.exe output __MSGTAB instead
* of messageTable. See message.h
* 10-May-1993 HV Add include file mbstring.h
* Change the str* functions to STR*
* 08-Jun-1992 SS add IDE feedback support
* 08-Jun-1992 SS Port to DOSX32
* 23-Feb-1990 SB Version No correctly displayed
* 31-Jan-1990 SB Debug version changes
* 05-Jan-1990 SB Rev no in std format; #ifdef LEADING_ZERO for old code
* 07-Dec-1989 SB Changed CopyRight Years to 1988-90; Add #ifdef DEBUG_HEAP
* 06-Nov-1989 SB Error messages now show NMAKE and not argv0
* 04-Sep-1989 SB heapdump() has two extra parameters
* 18-Aug-1989 SB For -z nothing done by makeMessage; Fix later
* 05-Jul-1989 SB localize rest of the messages in makeError()
* 14-Jun-1989 SB modified to localize all messages and auto update version no
* 05-Jun-1989 SB modified heapdump(), has a previous member in the list too
* 14-Apr-1989 SB modified heapdump() for better error messages when DEBUG
* 05-Apr-1989 SB made functions NEAR; all funcs to one code segment
* modified heapdump() to give better heap violations
* 22-Mar-1989 SB del call to unlinkTmpFiles() ;add call to delScriptFiles().
* 17-Mar-1989 SB heapdump() has an additional check built-in
* 10-Mar-1989 SB Changed makeMessage() for -z to get echo CMD's into PWB.SHL
* 16-Feb-1989 SB changed makeError() and makeMessage() to handle -help
* 09-Jan-1989 SB changes in makeError() to handle -help correctly
* 05-Dec-1988 SB Added CDECL for makeError(), makeMessage(); Pascal calling
* #ifdef'd heapdump prototype
* 20-Oct-1988 SB Changed some eoln comments to be in the same column
* 12-Oct-1988 SB Made GetFarMsg() to be Model independent & efficient
* 17-Aug-1988 RB Clean up.
* 24-Jun-1988 rj Added doError flag to unlinkTmpFiles call.
*
******************************************************************************/
#include "nmake.h"
#include "nmmsg.h"
#include "proto.h"
#include "globals.h"
#include "grammar.h"
#pragma hdrstop
#include "version.h"
#define FATAL 1 /* error levels for */
#define ERROR 2 /* systems lanuguages*/
#define RESERVED 3 /* products */
#define WARNING 4
#define CopyRightYrs "1988-93"
#define NmakeStr "NMAKE"
/* Hacked to work upto build no 9 */
#ifdef FINAL_RELEASE
#define paste(a, b, c) #a "." #b
#else // !FINAL_RELEASE
#define paste(a, b, c) #a "." #b "." #c
#endif // FINAL_RELEASE
#define VERSION(major, minor, buildno) paste(major, minor, buildno)
extern char * startupDir;
LOCAL char * NEAR getFarMsg(unsigned);
void CDECL NEAR
makeError (
unsigned lineNumber,
unsigned msg,
...)
{
unsigned exitCode = 2, /* general program err */
level;
va_list args; /* More arguments */
va_start (args, msg); /* Point 'args' at first extra arg */
if (ON(gFlags,F1_CRYPTIC_OUTPUT)
&& (msg / 1000) == WARNING)
return;
displayBanner();
if (lineNumber)
fprintf(stderr,"%s(%d) : ",fName,lineNumber);
else fprintf(stderr,"%s : ",NmakeStr);
switch (level = msg / 1000) {
case FATAL: makeMessage(FATAL_ERROR_MESSAGE);
if (msg == OUT_OF_MEMORY) exitCode = 4;
break;
case ERROR: makeMessage(ERROR_MESSAGE);
break;
case WARNING: makeMessage(WARNING_MESSAGE);
break;
default: break;
}
fprintf(stderr," U%04d: ",msg); /* U for utilities */
vfprintf(stderr,getFarMsg(msg),args);
putc('\n',stderr);
fflush(stderr);
#ifdef DEBUG_ERRORS
if (msg == 1010) heapdump(__FILE__, __LINE__);
#endif
if (level == FATAL) {
#ifdef DOS
//change directory to startup directory; ignore error code ... we
//cannot handle it
chdir(startupDir);
#endif
fprintf(stderr,"Stop.\n");
delScriptFiles();
#ifdef NMK_DEBUG
fprintf(stderr, "Exiting with an error ...\n");
#endif
#if !defined(NDEBUG) && !defined(NT_BUILD)
printStats();
#endif
exit(exitCode);
}
}
void CDECL NEAR
makeMessage(
unsigned msg,
...)
{
va_list args;
FILE *stream = stdout;
va_start (args, msg);
if (msg != USER_MESSAGE && ON(gFlags,F1_CRYPTIC_OUTPUT))
return;
displayBanner();
if (msg >= FATAL_ERROR_MESSAGE && msg <= COPYRIGHT_MESSAGE_2)
stream = stderr;
if (msg == COPYRIGHT_MESSAGE_1)
putc('\n',stream);
vfprintf(stream,getFarMsg(msg),args);
if ((msg < COMMANDS_MESSAGE || msg > STOP_MESSAGE) && msg != MESG_LAST)
putc('\n',stream);
fflush(stream);
}
#define MAX_IDE_STRING 132
void CDECL NEAR
makeIdeMessage(unsigned uIdeCode, unsigned uMsg,...)
{
#if 0 //We don't use this anymore
static BOOL fIdeFeedback = FALSE;
char buffer[MAX_IDE_STRING];
char * pszWrite = buffer;
if (!uIdeCode) { // first call
char _FAR * pszIdeFlags;
if ((pszIdeFlags = getenv ("_MSC_IDE_FLAGS")) &&
#ifdef FLAT
_ftcsstr (pszIdeFlags, "-FEEDBACK"))
#else
_fstrstr (pszIdeFlags, (char far *) "-FEEDBACK"))
#endif
fIdeFeedback = TRUE;
}
if (!fIdeFeedback)
return;
*pszWrite++ = '@';
*pszWrite++ = 'I';
switch (uIdeCode) {
case 0:
*pszWrite++ = '0';
break;
case 1:
*pszWrite++ = '1';
break;
case 2:
*pszWrite++ = '2';
break;
case 3:
*pszWrite++ = '3';
break;
default:
return;
}
if (uIdeCode) {
va_list args;
va_start (args, uMsg);
_vsnprintf(pszWrite, (size_t) MAX_IDE_STRING - 4, getFarMsg(uMsg), args);
buffer[MAX_IDE_STRING - 1] = '\0';
pszWrite = buffer + _ftcslen (buffer);
}
if (uMsg != COPYRIGHT_MESSAGE_2)
*pszWrite++ = '\n';
*pszWrite = '\0';
_write(_fileno(stderr), buffer, (unsigned) (pszWrite-buffer));
#endif
}
/*** getFarMsg - get message from far segment
*
* Purpose:
* Gets an error message from the far message segment by either returning
* a pointer to the message (C and L model) or copying to a static near
* buffer and returning a pointer to the buffer (other models).
*
* Input:
* n = error message #, defined as a symbolic constant
*
* Output:
* Returns a pointer to the message buffer. In Compact and Large Models
* it returns a far pointer and in others it returns a near pointer.
*
* Notes:
* Previously the routine always copied to a static near buffer. Now the
* action has been changed to returning a far pointer in case of Compact
* and Large models and it copies to near buffer otherwise, returning
* a pointer to the buffer. [sundeep]
*
*
*/
LOCAL char * NEAR
getFarMsg(n)
unsigned n;
{
char _FAR *p;
#ifndef FLAT
#if !(defined(M_I86CM) || defined(M_I86LM)) /* if not C or L model */
char *q;
static char buf[80];
register int i;
i = sizeof(buf);
#endif
#endif
p = get_err(n);
#if !defined (FLAT) && !(defined(M_I86CM) || defined(M_I86LM)) /* if not C or L model */
if (p == 0L)
*buf = '\0';
else /* copy to near buffer */
for (q = buf; q < buf + i && (*q++ = *p++);)
;
if (q == buf + i)
q[-1] = '\0';
return(buf);
#else /* if compact or large model */
return(p);
#endif
}
/*** displayBanner - display SignOn Banner *************************************
*
* Scope:
* Global
*
* Purpose:
* Displays SignOn Banner (Version & Copyright Message)
*
* Input:
*
* Output:
*
* Errors/Warnings:
*
* Assumes:
* If rup is 0 then build version is to be suppressed
*
* Modifies Globals:
* bannerDisplayed -- Set to TRUE
*
* Uses Globals:
*
* Notes:
* 1> Display Banner to stderr for compatibility with Microsoft C Compiler.
* 2> rmj, rmm, rup are set by SLM as #define's in VERSION.H
* 3> szCopyrightYrs is a macro set in this file
*
*******************************************************************************/
void NEAR
displayBanner()
{
#ifdef LEADING_ZEROES
char szRevisionNo[5]; /* For '.nnn\0' */
char szMinorVersion[3]; /* For 'nn\0' */
#endif
if (bannerDisplayed)
return;
bannerDisplayed = TRUE;
#ifdef LEADING_ZEROES
szMinorVersion[0] = '0';
szMinorVersion[1] = '0';
itoa(rmm, szMinorVersion + (rmm < 10 ? 1 : 0), 10);
szRevisionNo[0] = rup ? '.' : '\0'; /* if 0 Revision is not shown */
szRevisionNo[1] = '0';
szRevisionNo[2] = '0';
itoa(rup, szRevisionNo + (rup < 10 ? 3 : (rup < 100 ? 2 : 1)), 10);
makeMessage(COPYRIGHT_MESSAGE_1, rmj, szMinorVersion, szRevisionNo);
#endif
makeIdeMessage(1, COPYRIGHT_MESSAGE_1, VERSION(rmj, rmm, rup));
makeIdeMessage(2, COPYRIGHT_MESSAGE_2, CopyRightYrs);
makeMessage(COPYRIGHT_MESSAGE_1, VERSION(rmj, rmm, rup));
makeMessage(COPYRIGHT_MESSAGE_2, CopyRightYrs);
fflush(stderr);
}
#ifdef HEAP
void NEAR
heapdump(file, line)
char *file;
int line;
{
struct _heapinfo h, prev;
int status;
BOOL fDetails = FALSE;
#ifdef TEST_RECURSION
fDetails = TRUE;
#endif
h._pentry = NULL;
prev = h;
printf("heapdump at %s(%d): ", file, line);
if (fDetails) putchar('\n');
while((status = _heapwalk(&h)) == _HEAPOK) {
if (fDebug || fDetails)
printf("%6s block at %p of size %4.4X\n",
(h._useflag == _USEDENTRY) ? "USED" : "FREE",
h._pentry,
h._size);
if (!h._size)
if (h._useflag == _USEDENTRY)
printf("**** Error, Block of size 0 in use at %p ***\n",
h._pentry);
else if (fDebug)
printf("** Plausible error, free block of size 0 at %p **\n",
h._pentry);
prev = h;
}
switch (status) {
case _HEAPEMPTY: printf("OK - empty heap\n\n"); break;
case _HEAPEND: printf("OK - end of heap\n\n"); break;
case _HEAPBADBEGIN: printf("ERROR - bad pointer to heap at %p\n\n",
h._pentry); break;
case _HEAPBADNODE: printf("ERROR - bad node in heap at %p\n\n",
h._pentry); break;
}
fflush(stdout);
}
#endif
/*** usage - prints the usage message ***************************************
*
* Scope:
* Extern
*
* Purpose:
* Prints a usage message
*
* Input: none
* Output: to screen
*
* Assumes:
* The usage messages are in order between MESG_FIRST and MESG_LAST in the
* messages file.
*
* Notes:
*
*******************************************************************************/
void CDECL NEAR
usage (void)
{
unsigned mesg;
BOOL fOut = FALSE;
char buf1[80];
char buf2[80];
for (mesg = MESG_FIRST; mesg < MESG_A; ++mesg)
makeMessage(mesg, "NMAKE");
for (mesg = MESG_A; mesg < MESG_LAST; mesg++)
{
#if defined(FLAT) || !defined(DOS)
if (mesg == MESG_M)
mesg++;
#endif
#if !defined(SELF_RECURSE)
if (mesg == MESG_V)
mesg++;
#endif
if (mesg == MESG_LAST)
break;
if (!fOut)
_ftcscpy (buf1, getFarMsg(mesg));
else
{
_ftcscpy (buf2, getFarMsg(mesg));
makeMessage (MESG_OPTIONS, buf1, buf2);
}
fOut = (BOOL) !fOut;
}
if (fOut)
makeMessage (MESG_OPTIONS, buf1, "");
makeMessage (MESG_LAST);
}