diff --git a/compiler/libpc300/sc.h b/compiler/libpc300/sc.h index 14637515..2c303f6e 100755 --- a/compiler/libpc300/sc.h +++ b/compiler/libpc300/sc.h @@ -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); diff --git a/compiler/libpc300/sc1.c b/compiler/libpc300/sc1.c index f8d40611..66697354 100755 --- a/compiler/libpc300/sc1.c +++ b/compiler/libpc300/sc1.c @@ -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...] [options]\n\n"); pc_printf("Options:\n"); - pc_printf(" -A alignment in bytes of the data segment and the stack\n"); - pc_printf(" -a output assembler code\n"); + pc_printf(" -A 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 codepage name or number; e.g. 1252 for Windows Latin-1\n"); + pc_printf(" -c 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 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 set name of error file (quiet compile)\n"); #if defined __WIN32__ || defined _WIN32 || defined _Windows - pc_printf(" -H window handle to send a notification message on finish\n"); + pc_printf(" -H window handle to send a notification message on finish\n"); #endif - pc_printf(" -i path for include files\n"); - pc_printf(" -l create list file (preprocess only)\n"); - pc_printf(" -o set base name of (P-code) output file\n"); - pc_printf(" -p set name of \"prefix\" file\n"); + pc_printf(" -i path for include files\n"); + pc_printf(" -l create list file (preprocess only)\n"); + pc_printf(" -o set base name of (P-code) output file\n"); + pc_printf(" -p 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 stack/heap size in cells (default=%d)\n",(int)sc_stksize); - pc_printf(" -s skip lines from the input file\n"); - pc_printf(" -sui[+/-] show stack usage info\n"); - pc_printf(" -t TAB indent size (in character positions, default=%d)\n",sc_tabsize); - pc_printf(" -v verbosity level; 0=quiet, 1=normal, 2=verbose (default=%d)\n",verbosity); - pc_printf(" -w disable a specific warning by its number\n"); - pc_printf(" -E treat warnings as errors\n"); - pc_printf(" -X 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 stack/heap size in cells (default=%d)\n",(int)sc_stksize); + pc_printf(" -s skip lines from the input file\n"); + pc_printf(" -sui[+/-] show stack usage info\n"); + pc_printf(" -t TAB indent size (in character positions, default=%d)\n",sc_tabsize); + pc_printf(" -v verbosity level; 0=quiet, 1=normal, 2=verbose (default=%d)\n",verbosity); + pc_printf(" -w[+/-] disable a specific warning by its number\n"); + pc_printf(" -E treat warnings as errors\n"); + pc_printf(" -X 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)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 */ diff --git a/compiler/libpc300/sc2.c b/compiler/libpc300/sc2.c index 038d8e21..5c95d055 100755 --- a/compiler/libpc300/sc2.c +++ b/compiler/libpc300/sc2.c @@ -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' '; i++,lptr++) + name[i]=*lptr; + name[i] = '\0'; + parsesingleoption(name); } else { error(207); /* unknown #pragma */ } /* if */ diff --git a/compiler/libpc300/sc3.c b/compiler/libpc300/sc3.c index f54bdb85..395a0dd7 100644 --- a/compiler/libpc300/sc3.c +++ b/compiler/libpc300/sc3.c @@ -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; iarrayidx; /* 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; iname); /* 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 */ diff --git a/compiler/libpc300/sc4.c b/compiler/libpc300/sc4.c index 7cdb4feb..57feca20 100755 --- a/compiler/libpc300/sc4.c +++ b/compiler/libpc300/sc4.c @@ -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"); diff --git a/compiler/libpc300/sc5-in.scp b/compiler/libpc300/sc5-in.scp index 20258750..61baf70d 100644 --- a/compiler/libpc300/sc5-in.scp +++ b/compiler/libpc300/sc5-in.scp @@ -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" }; diff --git a/compiler/libpc300/sc5.c b/compiler/libpc300/sc5.c index 50519fa6..23651973 100755 --- a/compiler/libpc300/sc5.c +++ b/compiler/libpc300/sc5.c @@ -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