mirror of https://github.com/lianthony/NT4.0
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.
589 lines
12 KiB
589 lines
12 KiB
/**********************************************************************
|
|
|
|
fnterr.c -- Error Support Routines.
|
|
|
|
(c) Copyright 1992 Microsoft Corp.
|
|
All rights reserved.
|
|
|
|
This source file provides support for debugging routines in fnt.c
|
|
(and macjob.c to a much lesser extent). This module keys on the
|
|
#define FSCFG_FNTERR which is defined in fsconfig.h
|
|
|
|
7/28/92 dj First cut.
|
|
8/12/94 deanb included fnterr.h for mac
|
|
12/07/94 deanb changed %x to %hx or %lx; %d to %hd
|
|
|
|
**********************************************************************/
|
|
|
|
#include "fsconfig.h"
|
|
#include "fnterr.h"
|
|
|
|
#ifdef FSCFG_FNTERR
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
/* FILE * fopen(); */
|
|
int abs (int);
|
|
/*
|
|
int strlen (char*);
|
|
int strcmp (char*, char*);
|
|
int strcpy (char*, char*);
|
|
int strncpy( char*, char *, int);
|
|
*/
|
|
|
|
#define ERR_MAX_IFS 8
|
|
#define ERR_MAX_CODE 16
|
|
#define ERR_MAX_FNAME 80
|
|
#define ERR_MAX_MSG 512
|
|
|
|
static int errOpc;
|
|
static int errBreak;
|
|
static int errIfOk = 1;
|
|
static unsigned short errSize = 0;
|
|
static unsigned short errCode = 0;
|
|
static int errIfNdx = 0;
|
|
static long errInstCount;
|
|
static int errIfs[ERR_MAX_IFS];
|
|
static char errOpName[ERR_MAX_CODE];
|
|
static char errFname[ERR_MAX_FNAME];
|
|
static char * errOpcs[] =
|
|
{
|
|
"SVTCA_0",
|
|
"SVTCA_1",
|
|
"SPVTCA",
|
|
"SPVTCA",
|
|
"SFVTCA",
|
|
"SFVTCA",
|
|
"SPVTL",
|
|
"SPVTL",
|
|
"SFVTL",
|
|
"SFVTL",
|
|
"WPV",
|
|
"WFV",
|
|
"RPV",
|
|
"RFV",
|
|
"SFVTPV",
|
|
"ISECT",
|
|
"SetLocalGraphicState",
|
|
"SetLocalGraphicState",
|
|
"SetLocalGraphicState",
|
|
"SetElementPtr",
|
|
"SetElementPtr",
|
|
"SetElementPtr",
|
|
"SetElementPtr",
|
|
"SetLocalGraphicState",
|
|
"SetRoundState",
|
|
"SetRoundState",
|
|
"LMD",
|
|
"ELSE",
|
|
"JMPR",
|
|
"LWTCI",
|
|
"LSWCI",
|
|
"LSW",
|
|
"DUP",
|
|
"SetLocalGraphicState",
|
|
"CLEAR",
|
|
"SWAP",
|
|
"DEPTH",
|
|
"CINDEX",
|
|
"MINDEX",
|
|
"ALIGNPTS",
|
|
"RAW",
|
|
"UTP",
|
|
"LOOPCALL",
|
|
"CALL",
|
|
"FDEF",
|
|
"IllegalInstruction",
|
|
"MDAP",
|
|
"MDAP",
|
|
"IUP",
|
|
"IUP",
|
|
"SHP",
|
|
"SHP",
|
|
"SHC",
|
|
"SHC",
|
|
"SHE",
|
|
"SHE",
|
|
"SHPIX",
|
|
"IP",
|
|
"MSIRP",
|
|
"MSIRP",
|
|
"ALIGNRP",
|
|
"SetRoundState",
|
|
"MIAP",
|
|
"MIAP",
|
|
"NPUSHB",
|
|
"NPUSHW",
|
|
"WS",
|
|
"RS",
|
|
"WCVT",
|
|
"RCVT",
|
|
"RC",
|
|
"RC",
|
|
"WC",
|
|
"MD",
|
|
"MD",
|
|
"MPPEM",
|
|
"MPS",
|
|
"FLIPON",
|
|
"FLIPOFF",
|
|
"DEBUG",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"UnaryOperand",
|
|
"UnaryOperand",
|
|
"IF",
|
|
"EIF",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"UnaryOperand",
|
|
"DELTAP1",
|
|
"SDB",
|
|
"SDS",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"UnaryOperand",
|
|
"UnaryOperand",
|
|
"UnaryOperand",
|
|
"UnaryOperand",
|
|
"ROUND",
|
|
"ROUND",
|
|
"ROUND",
|
|
"ROUND",
|
|
"NROUND",
|
|
"NROUND",
|
|
"NROUND",
|
|
"NROUND",
|
|
"WCVTFOD",
|
|
"DELTAP2",
|
|
"DELTAP3",
|
|
"DELTAC1",
|
|
"DELTAC2",
|
|
"DELTAC3",
|
|
"SROUND",
|
|
"S45ROUND",
|
|
"JROT",
|
|
"JROF",
|
|
"SetRoundState",
|
|
"IllegalInstruction",
|
|
"SetRoundState",
|
|
"SetRoundState",
|
|
"SANGW",
|
|
"AA",
|
|
"FLIPPT",
|
|
"FLIPRGON",
|
|
"FLIPRGOFF",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"SCANCTRL",
|
|
"SDPVTL",
|
|
"SDPVTL",
|
|
"GETINFO",
|
|
"IDEF",
|
|
"ROTATE",
|
|
"BinaryOperand",
|
|
"BinaryOperand",
|
|
"SCANTYPE",
|
|
"INSTCTRL",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"IDefPatch",
|
|
"PUSHB",
|
|
"PUSHB",
|
|
"PUSHB",
|
|
"PUSHB",
|
|
"PUSHB",
|
|
"PUSHB",
|
|
"PUSHB",
|
|
"PUSHB",
|
|
"PUSHW",
|
|
"PUSHW",
|
|
"PUSHW",
|
|
"PUSHW",
|
|
"PUSHW",
|
|
"PUSHW",
|
|
"PUSHW",
|
|
"PUSHW",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MDRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP",
|
|
"MIRP"
|
|
};
|
|
|
|
/*
|
|
errOutput() - writes an error to standard out and to a log file. the
|
|
log file is always opened and closes in order to avoid file corruption
|
|
by an application gone wild.
|
|
*/
|
|
static void errOutput( char * );
|
|
static void errOutput( char * msg )
|
|
{
|
|
static int firsttime = 1;
|
|
FILE * fp;
|
|
|
|
printf("%s", msg);
|
|
fp = fopen ("compfont.err", (firsttime ? "w" : "a"));
|
|
if (fp)
|
|
{
|
|
fprintf (fp, "%s", msg);
|
|
fclose (fp);
|
|
}
|
|
firsttime = 0;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
errPrint() - used to generate a useful (?) error message based on the
|
|
error 'flag' and the parameters ('v1..v4').
|
|
*/
|
|
static void errPrint (int, long, long, long, long);
|
|
static void errPrint (int flag, long v1, long v2, long v3, long v4)
|
|
{
|
|
char msg[ERR_MAX_MSG];
|
|
char * opcodeName;
|
|
char c;
|
|
int i;
|
|
|
|
/*
|
|
build the context line. it indicates the file being processed, the point
|
|
size, the character code (or glyph index), as well as the releative inst
|
|
number of this instruction for this code.
|
|
*/
|
|
i = sprintf (msg, "\n*** ERROR*** ");
|
|
i += sprintf (msg+i, "\"%s\", ", errFname);
|
|
i += sprintf (msg+i, "%hd Point, ", errSize);
|
|
i += sprintf (msg+i, "Code %hd (0x%hX), ", errCode, errCode);
|
|
i += sprintf (msg+i, "Inst: #%ld\n", errInstCount);
|
|
|
|
/*
|
|
build the error line. it indicates the name of the instruction followed
|
|
by the actual error information. note: finding the actual opcode name
|
|
for some the instructions is sorta kludgy. names like "SetLocalGraphicState",
|
|
and "BinaryOperand" are not actual instructions. In these cases, look to
|
|
the second character of the name - if it is lower case, then we need to
|
|
work a little harder, so look to 'errOpName' (which should be set by this
|
|
point) it should contain the correct instruction name.
|
|
*/
|
|
c = *(errOpcs[errOpc]+1);
|
|
opcodeName =(islower(c) && strlen(errOpName)) ? errOpName : errOpcs[errOpc];
|
|
i += sprintf (msg+i, "(%s) ", opcodeName);
|
|
errOpName[0] = '\0';
|
|
|
|
/*
|
|
output what you have so far and then process the error
|
|
*/
|
|
errOutput (msg);
|
|
switch (flag)
|
|
{
|
|
case ERR_RANGE:
|
|
sprintf (msg, "Value out of range: value = %ld, range = %ld .. %ld\n",
|
|
v1, v2, v3);
|
|
break;
|
|
case ERR_ASSERTION:
|
|
sprintf (msg, "Assertion check failed\n");
|
|
break;
|
|
case ERR_CVT:
|
|
sprintf (msg, "CVT out of range: CVT = %ld, range = %ld .. %ld\n",
|
|
v1, v2, v3);
|
|
break;
|
|
case ERR_FDEF:
|
|
sprintf (msg, "FDEF out of range: FDEF = %ld, range = %ld .. %ld\n",
|
|
v1, v2, v3);
|
|
break;
|
|
case ERR_ELEMENT:
|
|
sprintf (msg, "Element %ld exceeds max elements (%ld)\n", v1, v2, v3);
|
|
break;
|
|
case ERR_CONTOUR:
|
|
i = sprintf (msg, "CONTOUR out of range: ");
|
|
sprintf (msg+i, "CONTOUR = %ld, range = %ld .. %ld\n", v1, v2, v3);
|
|
break;
|
|
case ERR_POINT:
|
|
i = sprintf (msg, "POINT out of range: ");
|
|
sprintf (msg+i, "POINT = %ld, range = %ld .. %ld\n", v1, v2, v3);
|
|
break;
|
|
case ERR_INDEX:
|
|
i = sprintf (msg, "POINT 0x%lX is neither element[0] ", v1);
|
|
sprintf( msg+i, "(0x%lX) nor element[1] (0x%lX)\n", v2, v3);
|
|
break;
|
|
case ERR_STORAGE:
|
|
i = sprintf (msg, "Storage index out of range: ");
|
|
sprintf (msg+i, "Index = %ld, range = %ld .. %ld\n", v1, v2, v3);
|
|
break;
|
|
case ERR_STACK:
|
|
i = sprintf (msg, "Stack pointer out of range: ");
|
|
sprintf (msg+i, "Pointer = %ld, range = %ld .. %ld\n", v1, v2, v3);
|
|
break;
|
|
case ERR_VECTOR:
|
|
sprintf (msg, "Illegal (x.y) vector: (%ld.%ld)\n", v1, v2);
|
|
break;
|
|
case ERR_LARGER:
|
|
sprintf (msg, "Value too small: %ld is not larger than %ld\n", v2, v1);
|
|
break;
|
|
case ERR_INT8:
|
|
sprintf (msg, "Value too large: 0x%lX exceeds 1 byte capacity\n", v1);
|
|
break;
|
|
case ERR_INT16:
|
|
sprintf (msg, "Value too large: 0x%lX exceeds 2 byte capacity\n", v1);
|
|
break;
|
|
case ERR_SCANMODE:
|
|
sprintf (msg, "Invalid scan mode: %ld\n", v1);
|
|
break;
|
|
case ERR_SELECTOR:
|
|
sprintf (msg, "Invalid scan value: %ld\n", v1);
|
|
break;
|
|
case ERR_STATE:
|
|
i = sprintf (msg, "Boundry limit error: xmin = ");
|
|
sprintf (msg+1, "%ld, xmax = %ld, ymin = %ld, ymax = %ld\n",
|
|
v1, v2, v3, v4);
|
|
break;
|
|
case ERR_GETSINGLEWIDTHNIL:
|
|
sprintf (msg, "Sanity: Single width is nil\n");
|
|
break;
|
|
case ERR_GETCVTENTRYNIL:
|
|
sprintf (msg, "Sanity: CVT Entry is nil\n");
|
|
break;
|
|
case ERR_INVOPC:
|
|
sprintf (msg, "Invalid opcode: %ld\n", v1);
|
|
break;
|
|
case ERR_UNBALANCEDIF:
|
|
sprintf (msg, "Unbalanced: missing %s instruction\n",
|
|
( v1 > 0 ) ? "EIF" : "IF" );
|
|
break;
|
|
default:
|
|
sprintf (msg, "Unknown Error:\n");
|
|
break;
|
|
}
|
|
|
|
/*
|
|
output the rest and return
|
|
*/
|
|
errOutput (msg);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
fnterr_Context() - called before any other fnterr routine. it records
|
|
the job name, character size and character code / glyph index.
|
|
*/
|
|
void fnterr_Context (int sw, char * str, unsigned short sz, unsigned short cd)
|
|
{
|
|
/*
|
|
record a piece of the context
|
|
*/
|
|
switch (sw)
|
|
{
|
|
case ERR_CONTEXT_FILE:
|
|
strncpy ( errFname, str, ERR_MAX_FNAME);
|
|
errFname[ERR_MAX_FNAME-1] = '\0';
|
|
break;
|
|
case ERR_CONTEXT_SIZE:
|
|
errSize = sz;
|
|
break;
|
|
case ERR_CONTEXT_CODE:
|
|
errCode = cd;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
reset errOpName to be NULL before we start any real processing
|
|
*/
|
|
errOpName[0] = '\0';
|
|
return;
|
|
}
|
|
|
|
/*
|
|
fnterr_Start() - called before the main execute loop of fnt_Execute() and
|
|
fnt_TraceExecute(). it resets the instruction count to zero, and errBreak
|
|
to 0 (ie: don't break out of execution loop). set up IF/EIF counter for
|
|
this level.
|
|
*/
|
|
void fnterr_Start (void)
|
|
{
|
|
errInstCount = 0L;
|
|
errBreak = 0;
|
|
|
|
if (errIfOk && (++errIfNdx < ERR_MAX_IFS ))
|
|
errIfs[errIfNdx] = 0;
|
|
else
|
|
errIfOk = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
fnterr_Record() - called inside the main execute loop of fnt_Execute()
|
|
and fnt_TraceExecute(). it increments the instruction count, and resets
|
|
the opcode number. IFs or EIFs are accounted for. (note: other IFs and
|
|
EIFs will be accounted for by calls to ERR_IF() in fnt.c)
|
|
*/
|
|
void fnterr_Record (int opc)
|
|
{
|
|
errInstCount++;
|
|
errOpc = opc;
|
|
|
|
if (!strcmp ("IF", errOpcs[errOpc]))
|
|
fnterr_If (1);
|
|
else if (!strcmp ("EIF", errOpcs[errOpc]))
|
|
fnterr_If (-1);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
fnterr_Report() - called inside the main execute loop of fnt_Execute()
|
|
and fnt_TraceExecute(). it calls errPrint() (with the passed parameters)
|
|
to note the error, and sets errBreak so that the execution loop will end.
|
|
*/
|
|
void fnterr_Report (int flag, long v1, long v2, long v3, long v4)
|
|
{
|
|
errPrint (flag, v1, v2, v3, v4);
|
|
errBreak = 1;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
fnterr_Break() - returns the value of errBreak. if a non-zero valid is
|
|
returned (re: fnterr_Report()), the main execute loop of fnt_Execute()
|
|
or fnt_TraceExecute() will terminate.
|
|
*/
|
|
int fnterr_Break (void)
|
|
{
|
|
return (errBreak);
|
|
}
|
|
|
|
/*
|
|
fnterr_Opc() - called by combinate fnt calls to indicate the actual
|
|
opcode errGet() can use. this is a kludgy way to get around the non
|
|
real opcode name in the errOpcs[] table.
|
|
*/
|
|
void fnterr_Opc (char *opc)
|
|
{
|
|
strcpy (errOpName, opc);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
fnterr_End() - called after the main execute loop of fnt_Execute() and
|
|
fnt_TraceExecute(). it checks for balanced IF/EIF pairs.
|
|
*/
|
|
void fnterr_End (void)
|
|
{
|
|
if (errIfOk)
|
|
{
|
|
if (errIfs[errIfNdx])
|
|
errPrint (ERR_UNBALANCEDIF, (long)errIfs[errIfNdx], 0L, 0L, 0L);
|
|
if (--errIfNdx < 0)
|
|
errIfOk = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
fnterr_If() - records IF/EIF activity inside of fnt_IF(), fnt_ELSE() and
|
|
fnt_EIF() (re: fnt.c).
|
|
*/
|
|
void fnterr_If (int val)
|
|
{
|
|
if (errIfOk)
|
|
errIfs[errIfNdx] += val;
|
|
return;
|
|
}
|
|
|
|
#endif
|