compiler improvments

New pragmas: option, warning.
New simplified zero division detector.
Fixed const scopes.
Fixed 'assigned to itself' warning on multidimensional array's cell's (invertion operators).
This commit is contained in:
shel 2020-11-26 03:38:06 +04:00
parent 7cb045c688
commit c0844ccfaf
7 changed files with 240 additions and 77 deletions

View File

@ -439,6 +439,11 @@ typedef enum s_optmark {
#endif
#define TAGMASK (~PUBLICTAG)
typedef enum s_warnmode {
warnDISABLE,
warnENABLE,
warnTOGGLE
} warnmode;
/* interface functions */
#if defined __cplusplus
@ -451,7 +456,9 @@ typedef enum s_optmark {
int pc_compile(int argc, char **argv);
int pc_addconstant(char *name,cell value,int tag);
int pc_addtag(char *name);
int pc_enablewarning(int number,int enable);
int pc_enablewarning(int number,warnmode enable);
void pc_pushwarnings(void);
void pc_popwarnings(void);
/*
* Functions called from the compiler (to be implemented by you)
@ -664,6 +671,8 @@ SC_FUNC void outval(cell val,int newline);
/* function prototypes in SC5.C */
SC_FUNC int error(int number,...) INVISIBLE;
SC_FUNC void errorset(int code, int line);
SC_FUNC void warnstack_init(void);
SC_FUNC void warnstack_cleanup(void);
/* function prototypes in SC6.C */
SC_FUNC int assemble(FILE *fout,FILE *fin);

View File

@ -656,9 +656,11 @@ int pc_compile(int argc, char *argv[])
error(100,incfname); /* cannot read from ... (fatal error) */
} /* if */
} /* if */
warnstack_init();
preprocess(); /* fetch first line */
parse(); /* process all input */
sc_parsenum++;
warnstack_cleanup();
} while (sc_reparse);
/* second (or third) pass */
@ -723,8 +725,10 @@ int pc_compile(int argc, char *argv[])
else
plungequalifiedfile(incfname); /* parse implicit include file (again) */
} /* if */
warnstack_init();
preprocess(); /* fetch first line */
parse(); /* process all input */
warnstack_cleanup();
/* inpf is already closed when readline() attempts to pop of a file */
writetrailer(); /* write remaining stuff */
@ -1129,8 +1133,10 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam
} /* switch */
break;
case 'e':
strncpy(ename,option_value(ptr),_MAX_PATH); /* set name of error file */
ename[_MAX_PATH-1]='\0';
if (ename) {
strncpy(ename,option_value(ptr),_MAX_PATH); /* set name of error file */
ename[_MAX_PATH-1]='\0';
}
break;
case 'E':
sc_warnings_are_errors = 1;
@ -1163,15 +1169,21 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam
sc_listing=TRUE; /* skip second pass & code generation */
break;
case 'o':
strncpy(oname,option_value(ptr),_MAX_PATH); /* set name of (binary) output file */
oname[_MAX_PATH-1]='\0';
if(oname) {
strncpy(oname,option_value(ptr),_MAX_PATH); /* set name of (binary) output file */
oname[_MAX_PATH-1]='\0';
}
break;
case 'p':
strncpy(pname,option_value(ptr),_MAX_PATH); /* set name of implicit include file */
pname[_MAX_PATH-1]='\0';
if(pname) {
strncpy(pname,option_value(ptr),_MAX_PATH); /* set name of implicit include file */
pname[_MAX_PATH-1]='\0';
}
break;
#if !defined SC_LIGHT
case 'r':
if (!rname)
break;
strncpy(rname,option_value(ptr),_MAX_PATH); /* set name of report file */
rname[_MAX_PATH-1]='\0';
sc_makereport=TRUE;
@ -1222,11 +1234,11 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam
case 'w':
i=(int)strtol(option_value(ptr),(char **)&ptr,10);
if (*ptr=='-')
pc_enablewarning(i,0);
pc_enablewarning(i,warnDISABLE);
else if (*ptr=='+')
pc_enablewarning(i,1);
else if (*ptr=='\0')
pc_enablewarning(i,2);
pc_enablewarning(i,warnENABLE);
else if (*ptr=='\0') /* Note: returned by strtol especially */
pc_enablewarning(i,warnTOGGLE);
break;
case 'X':
i=atoi(option_value(ptr));
@ -1264,10 +1276,10 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam
str[i]='\0'; /* str holds symbol name */
i=atoi(ptr+1);
add_constant(str,i,sGLOBAL,0);
} else {
} else if (oname) {
strncpy(str,argv[arg],sizeof(str)-5); /* -5 because default extension is 4 characters */
str[sizeof(str)-5]='\0';
set_extension(str,".p",FALSE);
set_extension(str,".sma",FALSE); /* add default extension if it doesn't exist */
insert_sourcefile(str);
/* The output name is the first input name with a different extension,
* but it is stored in a different directory
@ -1296,6 +1308,18 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam
} /* for */
}
void parsesingleoption(char *argv)
{
/* argv[0] is the program, which we don't need here */
char *args[2] = { 0, argv };
char codepage[MAXCODEPAGE + 1] = { 0 };
codepage[0] = '\0';
parseoptions(2, args, NULL, NULL, NULL, NULL, codepage);
/* need explicit support for codepages */
if (codepage[0] && !cp_set(codepage))
error(108); /* codepage mapping file not found */
}
#if !defined SC_LIGHT
static void parserespf(char *filename,char *oname,char *ename,char *pname,
char *rname,char *codepage)
@ -1462,44 +1486,44 @@ static void about(void)
setcaption();
pc_printf("Usage: pawncc <filename> [filename...] [options]\n\n");
pc_printf("Options:\n");
pc_printf(" -A<num> alignment in bytes of the data segment and the stack\n");
pc_printf(" -a output assembler code\n");
pc_printf(" -A<num> alignment in bytes of the data segment and the stack\n");
pc_printf(" -a output assembler code\n");
#if AMX_COMPACTMARGIN > 2
pc_printf(" -C[+/-] compact encoding for output file (default=%c)\n", sc_compress ? '+' : '-');
pc_printf(" -C[+/-] compact encoding for output file (default=%c)\n", sc_compress ? '+' : '-');
#endif
pc_printf(" -c<name> codepage name or number; e.g. 1252 for Windows Latin-1\n");
pc_printf(" -c<name> codepage name or number; e.g. 1252 for Windows Latin-1\n");
#if defined dos_setdrive
pc_printf(" -Dpath active directory path\n");
pc_printf(" -Dpath active directory path\n");
#endif
pc_printf(" -d0 no symbolic information, no run-time checks\n");
pc_printf(" -d1 [default] run-time checks, no symbolic information\n");
pc_printf(" -d2 full debug information and dynamic checking\n");
pc_printf(" -d3 full debug information, dynamic checking, no optimization\n");
pc_printf(" -e<name> set name of error file (quiet compile)\n");
pc_printf(" -d0 no symbolic information, no run-time checks\n");
pc_printf(" -d1 [default] run-time checks, no symbolic information\n");
pc_printf(" -d2 full debug information and dynamic checking\n");
pc_printf(" -d3 full debug information, dynamic checking, no optimization\n");
pc_printf(" -e<name> set name of error file (quiet compile)\n");
#if defined __WIN32__ || defined _WIN32 || defined _Windows
pc_printf(" -H<hwnd> window handle to send a notification message on finish\n");
pc_printf(" -H<hwnd> window handle to send a notification message on finish\n");
#endif
pc_printf(" -i<name> path for include files\n");
pc_printf(" -l create list file (preprocess only)\n");
pc_printf(" -o<name> set base name of (P-code) output file\n");
pc_printf(" -p<name> set name of \"prefix\" file\n");
pc_printf(" -i<name> path for include files\n");
pc_printf(" -l create list file (preprocess only)\n");
pc_printf(" -o<name> set base name of (P-code) output file\n");
pc_printf(" -p<name> set name of \"prefix\" file\n");
#if !defined SC_LIGHT
pc_printf(" -r[name] write cross reference report to console or to specified file\n");
pc_printf(" -r[name] write cross reference report to console or to specified file\n");
#endif
pc_printf(" -S<num> stack/heap size in cells (default=%d)\n",(int)sc_stksize);
pc_printf(" -s<num> skip lines from the input file\n");
pc_printf(" -sui[+/-] show stack usage info\n");
pc_printf(" -t<num> TAB indent size (in character positions, default=%d)\n",sc_tabsize);
pc_printf(" -v<num> verbosity level; 0=quiet, 1=normal, 2=verbose (default=%d)\n",verbosity);
pc_printf(" -w<num> disable a specific warning by its number\n");
pc_printf(" -E treat warnings as errors\n");
pc_printf(" -X<num> abstract machine size limit in bytes\n");
pc_printf(" -\\ use '\\' for escape characters\n");
pc_printf(" -^ use '^' for escape characters\n");
pc_printf(" -;[+/-] require a semicolon to end each statement (default=%c)\n", sc_needsemicolon ? '+' : '-');
pc_printf(" -([+/-] require parantheses for function invocation (default=%c)\n", optproccall ? '-' : '+');
pc_printf(" sym=val define constant \"sym\" with value \"val\"\n");
pc_printf(" sym= define constant \"sym\" with value 0\n");
pc_printf(" -S<num> stack/heap size in cells (default=%d)\n",(int)sc_stksize);
pc_printf(" -s<num> skip lines from the input file\n");
pc_printf(" -sui[+/-] show stack usage info\n");
pc_printf(" -t<num> TAB indent size (in character positions, default=%d)\n",sc_tabsize);
pc_printf(" -v<num> verbosity level; 0=quiet, 1=normal, 2=verbose (default=%d)\n",verbosity);
pc_printf(" -w<num>[+/-] disable a specific warning by its number\n");
pc_printf(" -E treat warnings as errors\n");
pc_printf(" -X<num> abstract machine size limit in bytes\n");
pc_printf(" -\\ use '\\' for escape characters\n");
pc_printf(" -^ use '^' for escape characters\n");
pc_printf(" -;[+/-] require a semicolon to end each statement (default=%c)\n", sc_needsemicolon ? '+' : '-');
pc_printf(" -([+/-] require parantheses for function invocation (default=%c)\n", optproccall ? '-' : '+');
pc_printf(" sym=val define constant \"sym\" with value \"val\"\n");
pc_printf(" sym= define constant \"sym\" with value 0\n");
#if defined __WIN32__ || defined _WIN32 || defined _Windows || defined __MSDOS__
pc_printf("\nOptions may start with a dash or a slash; the options \"-d0\" and \"/d0\" are\n");
pc_printf("equivalent.\n");
@ -1549,7 +1573,7 @@ static void setconstants(void)
#endif
add_constant("charbits",sCHARBITS,sGLOBAL,0);
add_constant("charmin",0,sGLOBAL,0);
add_constant("charmax",~(-1UL << sCHARBITS) - 1,sGLOBAL,0);
add_constant("charmax",~((~(ucell)0) << sCHARBITS) - 1,sGLOBAL,0);
add_constant("ucharmax",(1 << (sizeof(cell)-1)*8)-1,sGLOBAL,0);
add_constant("__Pawn",VERSION_INT,sGLOBAL,0);
@ -1944,7 +1968,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst
int numdim;
short filenum;
symbol *sym;
constvalue *enumroot;
constvalue *enumroot=NULL;
#if !defined NDEBUG
cell glbdecl=0;
#endif
@ -2066,7 +2090,7 @@ static int declloc(int fstatic)
int idxtag[sDIMEN_MAX];
char name[sNAMEMAX+1];
symbol *sym;
constvalue *enumroot;
constvalue *enumroot=NULL;
cell val,size;
char *str;
value lval = {0};
@ -2736,7 +2760,7 @@ static void decl_enum(int vclass)
/* go through all constants */
value=0; /* default starting value */
do {
int idxtag,fieldtag;
int idxtag,fieldtag=0;
symbol *sym;
if (matchtoken('}')) { /* quick exit if '}' follows ',' */
lexpush();
@ -2812,7 +2836,7 @@ static int getstates(const char *funcname)
fsa=-1;
do {
if (!(islabel=matchtoken(tLABEL)) && !needtoken(tSYMBOL))
if ((islabel=matchtoken(tLABEL))==0 && !needtoken(tSYMBOL))
break;
tokeninfo(&val,&str);
assert(strlen(str)<sizeof fsaname);
@ -4458,7 +4482,7 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst)
errorset(sSETFILE,sym->fnumber);
errorset(sSETLINE,sym->lnumber);
error(204,sym->name); /* value assigned to symbol is never used */
#if 0 // ??? not sure whether it is a good idea to force people use "const"
#if 0 // ??? not sure whether it is a good idea to force people use "const" | I guess we should start using this due pawn specification about arrays
} else if ((sym->usage & (uWRITTEN | uPUBLIC | uCONST))==0 && sym->ident==iREFARRAY) {
errorset(sSETFILE,sym->fnumber);
errorset(sSETLINE,sym->lnumber);
@ -4664,6 +4688,8 @@ SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag)
/* constant doesn't exist yet, an entry must be created */
sym=addsym(name,val,iCONSTEXPR,vclass,tag,uDEFINE);
assert(sym!=NULL); /* fatal error 103 must be given on error */
if (vclass == sLOCAL)
sym->compound = nestlevel;
if (sc_status == statIDLE)
sym->usage |= uPREDEF;
return sym;
@ -5124,13 +5150,13 @@ static void dofor(void)
assert(stgidx==0);
index=stgidx;
stgmark(sSTARTREORDER);
stgmark((char)(sEXPRSTART+0)); /* mark start of 2nd expression in stage */
stgmark((unsigned char)(sEXPRSTART+0)); /* mark start of 2nd expression in stage */
setlabel(skiplab); /* jump to this point after 1st expression */
if (matchtoken(';')==0) {
test(wq[wqEXIT],FALSE,FALSE); /* expression 2 (jump to wq[wqEXIT] if false) */
needtoken(';');
} /* if */
stgmark((char)(sEXPRSTART+1)); /* mark start of 3th expression in stage */
stgmark((unsigned char)(sEXPRSTART+1)); /* mark start of 3th expression in stage */
if (matchtoken(')')==0) {
doexpr(TRUE,TRUE,TRUE,TRUE,NULL,NULL,FALSE); /* expression 3 */
needtoken(')');
@ -5649,7 +5675,7 @@ static void dostate(void)
fsa=0;
if (!(islabel=matchtoken(tLABEL)) && !needtoken(tSYMBOL)) {
if ((islabel=matchtoken(tLABEL))==0 && !needtoken(tSYMBOL)) {
delete_autolisttable();
return;
} /* if */

View File

@ -846,6 +846,8 @@ enum {
* Global variables: iflevel, ifstack (altered)
* lptr (altered)
*/
void parsesingleoption(char *argv);
static int command(void)
{
int tok,ret;
@ -1051,10 +1053,11 @@ static int command(void)
!strcmp(str, "explib") ||
!strcmp(str, "expclass") ||
!strcmp(str, "defclasslib") ) {
char name[sNAMEMAX+1],sname[sNAMEMAX+1];
const char *prefix = "";
char name[sNAMEMAX+1] = { 0 }, sname[sNAMEMAX + 1];
const char *prefix = ""; /* it's empty on library only */
sname[0] = '\0';
sname[1] = '\0';
if (!strcmp(str, "reqlib"))
prefix = "?rl_";
else if (!strcmp(str, "reqclass"))
@ -1097,7 +1100,7 @@ static int command(void)
pc_addlibtable=FALSE;
} else {
/* add the name if it does not yet exist in the table */
char newname[sNAMEMAX+1];
char newname[sNAMEMAX+1] = { 0 };
if (strlen(name) + strlen(prefix) + strlen(sname) <= sNAMEMAX)
{
strcpy(newname, prefix);
@ -1190,8 +1193,42 @@ static int command(void)
if (comma)
lptr++;
} while (comma);
} else if (strcmp(str, "showstackusageinfo")==0) {
sc_stkusageinfo=TRUE;
} else if (strcmp(str,"showstackusageinfo")==0) {
sc_stkusageinfo=TRUE;
} else if (strcmp(str,"warning")==0) {
int ok=lex(&val,&str) == tSYMBOL;
if (ok) {
if (strcmp(str,"enable")==0 || strcmp(str,"disable")==0) {
cell val;
enum s_warnmode enable=(str[0]=='e') ? warnENABLE : warnDISABLE;
do {
preproc_expr(&val,NULL);
pc_enablewarning(val,enable);
} while (*lptr != '\0');
}
else if (strcmp(str,"push")==0) {
pc_pushwarnings();
}
else if (strcmp(str,"pop")==0) {
pc_popwarnings();
}
else {
ok=FALSE;
} /* if */
}
if (!ok) {
error(207); /* unknown #pragma */
} /* if */
} else if (strcmp(str,"option")==0) {
char name[sNAMEMAX + 1] = { 0 };
int i;
/* first gather all information, start with the tag name */
while (*lptr <= ' ' && *lptr != '\0')
lptr++;
for (i=0; i<sNAMEMAX && *lptr && *lptr>' '; i++,lptr++)
name[i]=*lptr;
name[i] = '\0';
parsesingleoption(name);
} else {
error(207); /* unknown #pragma */
} /* if */

View File

@ -603,6 +603,10 @@ static void plnge2(void (*oper)(void),
} /* if */
/* ??? ^^^ should do same kind of error checking with functions */
/* If we're handling a division operation, make sure the divisor is not zero. */
if ((oper == os_div || oper == os_mod) && lval2->ident == iCONSTEXPR && lval2->constval == 0)
error(89); /* division by zero */
/* check whether an "operator" function is defined for the tag names
* (a constant expression cannot be optimized in that case)
*/
@ -629,6 +633,28 @@ static cell truemodulus(cell a,cell b)
return (a % b + b) % b;
}
static cell flooreddiv(cell a,cell b,int return_remainder)
{
cell q,r;
if (b==0) {
// error(89); /* division by zero */ /* never called on const values, so, moved to plnge2 */
return 0;
} /* if */
/* first implement truncated division in a portable way */
#define IABS(a) ((a)>=0 ? (a) : (-a))
q=IABS(a)/IABS(b);
if ((cell)(a ^ b)<0)
q=-q; /* swap sign if either "a" or "b" is negative (but not both) */
r=a-q*b; /* calculate the matching remainder */
/* now "fiddle" with the values to get floored division */
if (r!=0 && (cell)(r ^ b)<0) {
q--;
r+=b;
} /* if */
return return_remainder ? r : q;
}
static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
{
if (oper==ob_or)
@ -662,9 +688,9 @@ static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
else if (oper==os_mult)
return (left * right);
else if (oper==os_div)
return (left - truemodulus(left,right)) / right;
return flooreddiv(left,right,FALSE);
else if (oper==os_mod)
return truemodulus(left,right);
return flooreddiv(left,right,TRUE);
else
error(29); /* invalid expression, assumed 0 (this should never occur) */
return 0;
@ -749,7 +775,7 @@ static int hier14(value *lval1)
* negative value would do).
*/
for (i=0; i<sDIMEN_MAX; i++)
arrayidx1[i]=arrayidx2[i]=(cell)(-1UL << (sizeof(cell)*8-1));
arrayidx1[i]=arrayidx2[i]=(cell)((~(ucell)0) << (sizeof(cell)*8-1));
org_arrayidx=lval1->arrayidx; /* save current pointer, to reset later */
if (lval1->arrayidx==NULL)
lval1->arrayidx=arrayidx1;
@ -850,22 +876,23 @@ static int hier14(value *lval1)
{
int same=TRUE;
assert(lval2.arrayidx==arrayidx2);
for (i=0; i<sDIMEN_MAX; i++)
for (i=0; i<sDIMEN_MAX; i++) {
same=same && (lval3.arrayidx[i]==lval2.arrayidx[i]);
}
if (same)
error(226,lval3.sym->name); /* self-assignment */
} /* if */
} else {
if (oper){
if (oper) {
rvalue(lval1);
plnge2(oper,hier14,lval1,&lval2);
} else {
/* if direct fetch and simple assignment: no "push"
* and "pop" needed -> call hier14() directly, */
if (hier14(&lval2))
rvalue(&lval2); /* instead of plnge2(). */
rvalue(&lval2); /* instead of plnge2(). */
else if (lval2.ident==iVARIABLE)
lval2.ident=iEXPRESSION;/* mark as "rvalue" if it is not an "lvalue" */
lval2.ident=iEXPRESSION; /* mark as "rvalue" if it is not an "lvalue" */
checkfunction(&lval2);
/* check whether lval2 and lval3 (old lval1) refer to the same variable */
if (lval2.ident==iVARIABLE && lval3.ident==lval2.ident && lval3.sym==lval2.sym) {
@ -1011,8 +1038,8 @@ static int hier13(value *lval)
int lvalue=plnge1(hier12,lval);
if (matchtoken('?')) {
int locheap=decl_heap; /* save current heap delta */
long heap1,heap2; /* max. heap delta either branch */
valuepair *heaplist_node;
long heap1=0,heap2=0; /* max. heap delta either branch */
valuepair *heaplist_node=NULL;
int flab1=getlabel();
int flab2=getlabel();
value lval2 = {0};
@ -1209,6 +1236,8 @@ static int hier2(value *lval)
rvalue(lval);
invert(); /* bitwise NOT */
lval->constval=~lval->constval;
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
lval->ident=iEXPRESSION;
return FALSE;
case '!': /* ! (logical negate) */
if (hier2(lval))
@ -1220,6 +1249,8 @@ static int hier2(value *lval)
lneg(); /* 0 -> 1, !0 -> 0 */
lval->constval=!lval->constval;
lval->tag=pc_addtag("bool");
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
lval->ident=iEXPRESSION;
} /* if */
return FALSE;
case '-': /* unary - (two's complement) */
@ -1248,6 +1279,8 @@ static int hier2(value *lval)
} else {
neg(); /* arithmic negation */
lval->constval=-lval->constval;
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
lval->ident=iEXPRESSION;
} /* if */
return FALSE;
case tLABEL: /* tagname override */

View File

@ -1224,6 +1224,10 @@ SC_FUNC void inc(value *lval)
symbol *sym;
sym=lval->sym;
#if 0 // useless due forcing const usage is disable in sc1.c
if (sym != NULL)
markusage(sym,uWRITTEN);
#endif
if (lval->ident==iARRAYCELL) {
/* indirect increment, address already in PRI */
stgwrite("\tinc.i\n");
@ -1282,6 +1286,10 @@ SC_FUNC void dec(value *lval)
symbol *sym;
sym=lval->sym;
#if 0 // useless due forcing const usage is disable in sc1.c
if (sym != NULL)
markusage(sym,uWRITTEN);
#endif
if (lval->ident==iARRAYCELL) {
/* indirect decrement, address already in PRI */
stgwrite("\tdec.i\n");

View File

@ -107,7 +107,8 @@ static char *errmsg[] = {
/*085*/ "no states are defined for function \"%s\"\n",
/*086*/ "unknown automaton \"%s\"\n",
/*087*/ "unknown state \"%s\" for automaton \"%s\"\n",
/*088*/ "number of arguments does not match definition\n"
/*088*/ "number of arguments does not match definition\n",
/*089*/ "division by zero\n"
};
static char *fatalmsg[] = {
@ -168,4 +169,5 @@ static char *warnmsg[] = {
/*232*/ "output file is written, but with compact encoding disabled\n",
/*233*/ "symbol \"%s\" is marked as deprecated: %s\n",
/*234*/ "recursive function \"%s\"\n",
/*235*/ "detected %s with no corresponding %s\n"
};

View File

@ -48,7 +48,10 @@
#endif
#define NUM_WARNINGS (sizeof warnmsg / sizeof warnmsg[0])
static unsigned char warndisable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char */
static struct s_warnstack {
unsigned char disable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char */
struct s_warnstack *next;
} warnstack;
static int errflag;
static int errfile;
@ -90,7 +93,7 @@ static short lastfile;
if (number>=200) {
int index=(number-200)/8;
int mask=1 << ((number-200)%8);
if ((warndisable[index] & mask)!=0)
if ((warnstack.disable[index] & mask)!=0)
return 0;
} /* if */
@ -214,32 +217,77 @@ SC_FUNC void errorset(int code,int line)
* o 1 for enable
* o 2 for toggle
*/
int pc_enablewarning(int number,int enable)
int pc_enablewarning(int number,warnmode enable)
{
int index;
unsigned char mask;
if (number<200)
return FALSE; /* errors and fatal errors cannot be disabled */
number -= 200;
number-=200;
if (number>=NUM_WARNINGS)
return FALSE;
index=number/8;
mask=(unsigned char)(1 << (number%8));
switch (enable) {
case 0:
warndisable[index] |= mask;
case warnDISABLE:
warnstack.disable[index] |= mask;
break;
case 1:
warndisable[index] &= (unsigned char)~mask;
case warnENABLE:
warnstack.disable[index] &= (unsigned char)~mask;
break;
case 2:
warndisable[index] ^= mask;
case warnTOGGLE:
warnstack.disable[index] ^= mask;
break;
} /* switch */
return TRUE;
}
/* pc_pushwarnings()
* Saves currently disabled warnings, used to implement #pragma warning push
*/
void pc_pushwarnings(void)
{
void *p;
p=calloc(sizeof(struct s_warnstack),1);
if (p==NULL)
error(103); /* insufficient memory */
memmove(p,&warnstack,sizeof(struct s_warnstack));
warnstack.next=p;
}
/* pc_popwarnings()
* This function is the reverse of pc_pushwarnings()
*/
void pc_popwarnings(void)
{
void *p=warnstack.next;
if (p==NULL) { /* nothing to do */
error(235,"#pragma warning pop","#pragma warning push");
return;
} /* if */
memmove(&warnstack,p,sizeof(struct s_warnstack));
free(p);
}
SC_FUNC void warnstack_init(void)
{
memset(&warnstack,0,sizeof(warnstack));
}
SC_FUNC void warnstack_cleanup(void)
{
struct s_warnstack *cur=warnstack.next,*next;
if (cur!=NULL)
error(1,"#pragma warning pop","-end of file-");
for (;cur!=NULL;cur=next) {
next=cur->next;
free(cur);
} /* for */
warnstack.next=NULL;
}
#undef SCPACK_TABLE