mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-25 06:15:37 +03:00
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:
parent
7cb045c688
commit
c0844ccfaf
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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"
|
||||
};
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user