mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2025-01-12 23:08:03 +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
|
#endif
|
||||||
#define TAGMASK (~PUBLICTAG)
|
#define TAGMASK (~PUBLICTAG)
|
||||||
|
|
||||||
|
typedef enum s_warnmode {
|
||||||
|
warnDISABLE,
|
||||||
|
warnENABLE,
|
||||||
|
warnTOGGLE
|
||||||
|
} warnmode;
|
||||||
|
|
||||||
/* interface functions */
|
/* interface functions */
|
||||||
#if defined __cplusplus
|
#if defined __cplusplus
|
||||||
@ -451,7 +456,9 @@ typedef enum s_optmark {
|
|||||||
int pc_compile(int argc, char **argv);
|
int pc_compile(int argc, char **argv);
|
||||||
int pc_addconstant(char *name,cell value,int tag);
|
int pc_addconstant(char *name,cell value,int tag);
|
||||||
int pc_addtag(char *name);
|
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)
|
* 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 */
|
/* function prototypes in SC5.C */
|
||||||
SC_FUNC int error(int number,...) INVISIBLE;
|
SC_FUNC int error(int number,...) INVISIBLE;
|
||||||
SC_FUNC void errorset(int code, int line);
|
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 */
|
/* function prototypes in SC6.C */
|
||||||
SC_FUNC int assemble(FILE *fout,FILE *fin);
|
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) */
|
error(100,incfname); /* cannot read from ... (fatal error) */
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
warnstack_init();
|
||||||
preprocess(); /* fetch first line */
|
preprocess(); /* fetch first line */
|
||||||
parse(); /* process all input */
|
parse(); /* process all input */
|
||||||
sc_parsenum++;
|
sc_parsenum++;
|
||||||
|
warnstack_cleanup();
|
||||||
} while (sc_reparse);
|
} while (sc_reparse);
|
||||||
|
|
||||||
/* second (or third) pass */
|
/* second (or third) pass */
|
||||||
@ -723,8 +725,10 @@ int pc_compile(int argc, char *argv[])
|
|||||||
else
|
else
|
||||||
plungequalifiedfile(incfname); /* parse implicit include file (again) */
|
plungequalifiedfile(incfname); /* parse implicit include file (again) */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
warnstack_init();
|
||||||
preprocess(); /* fetch first line */
|
preprocess(); /* fetch first line */
|
||||||
parse(); /* process all input */
|
parse(); /* process all input */
|
||||||
|
warnstack_cleanup();
|
||||||
/* inpf is already closed when readline() attempts to pop of a file */
|
/* inpf is already closed when readline() attempts to pop of a file */
|
||||||
writetrailer(); /* write remaining stuff */
|
writetrailer(); /* write remaining stuff */
|
||||||
|
|
||||||
@ -1129,8 +1133,10 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam
|
|||||||
} /* switch */
|
} /* switch */
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
strncpy(ename,option_value(ptr),_MAX_PATH); /* set name of error file */
|
if (ename) {
|
||||||
ename[_MAX_PATH-1]='\0';
|
strncpy(ename,option_value(ptr),_MAX_PATH); /* set name of error file */
|
||||||
|
ename[_MAX_PATH-1]='\0';
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
sc_warnings_are_errors = 1;
|
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 */
|
sc_listing=TRUE; /* skip second pass & code generation */
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
strncpy(oname,option_value(ptr),_MAX_PATH); /* set name of (binary) output file */
|
if(oname) {
|
||||||
oname[_MAX_PATH-1]='\0';
|
strncpy(oname,option_value(ptr),_MAX_PATH); /* set name of (binary) output file */
|
||||||
|
oname[_MAX_PATH-1]='\0';
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
strncpy(pname,option_value(ptr),_MAX_PATH); /* set name of implicit include file */
|
if(pname) {
|
||||||
pname[_MAX_PATH-1]='\0';
|
strncpy(pname,option_value(ptr),_MAX_PATH); /* set name of implicit include file */
|
||||||
|
pname[_MAX_PATH-1]='\0';
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#if !defined SC_LIGHT
|
#if !defined SC_LIGHT
|
||||||
case 'r':
|
case 'r':
|
||||||
|
if (!rname)
|
||||||
|
break;
|
||||||
strncpy(rname,option_value(ptr),_MAX_PATH); /* set name of report file */
|
strncpy(rname,option_value(ptr),_MAX_PATH); /* set name of report file */
|
||||||
rname[_MAX_PATH-1]='\0';
|
rname[_MAX_PATH-1]='\0';
|
||||||
sc_makereport=TRUE;
|
sc_makereport=TRUE;
|
||||||
@ -1222,11 +1234,11 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam
|
|||||||
case 'w':
|
case 'w':
|
||||||
i=(int)strtol(option_value(ptr),(char **)&ptr,10);
|
i=(int)strtol(option_value(ptr),(char **)&ptr,10);
|
||||||
if (*ptr=='-')
|
if (*ptr=='-')
|
||||||
pc_enablewarning(i,0);
|
pc_enablewarning(i,warnDISABLE);
|
||||||
else if (*ptr=='+')
|
else if (*ptr=='+')
|
||||||
pc_enablewarning(i,1);
|
pc_enablewarning(i,warnENABLE);
|
||||||
else if (*ptr=='\0')
|
else if (*ptr=='\0') /* Note: returned by strtol especially */
|
||||||
pc_enablewarning(i,2);
|
pc_enablewarning(i,warnTOGGLE);
|
||||||
break;
|
break;
|
||||||
case 'X':
|
case 'X':
|
||||||
i=atoi(option_value(ptr));
|
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 */
|
str[i]='\0'; /* str holds symbol name */
|
||||||
i=atoi(ptr+1);
|
i=atoi(ptr+1);
|
||||||
add_constant(str,i,sGLOBAL,0);
|
add_constant(str,i,sGLOBAL,0);
|
||||||
} else {
|
} else if (oname) {
|
||||||
strncpy(str,argv[arg],sizeof(str)-5); /* -5 because default extension is 4 characters */
|
strncpy(str,argv[arg],sizeof(str)-5); /* -5 because default extension is 4 characters */
|
||||||
str[sizeof(str)-5]='\0';
|
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);
|
insert_sourcefile(str);
|
||||||
/* The output name is the first input name with a different extension,
|
/* The output name is the first input name with a different extension,
|
||||||
* but it is stored in a different directory
|
* 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 */
|
} /* 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
|
#if !defined SC_LIGHT
|
||||||
static void parserespf(char *filename,char *oname,char *ename,char *pname,
|
static void parserespf(char *filename,char *oname,char *ename,char *pname,
|
||||||
char *rname,char *codepage)
|
char *rname,char *codepage)
|
||||||
@ -1462,44 +1486,44 @@ static void about(void)
|
|||||||
setcaption();
|
setcaption();
|
||||||
pc_printf("Usage: pawncc <filename> [filename...] [options]\n\n");
|
pc_printf("Usage: pawncc <filename> [filename...] [options]\n\n");
|
||||||
pc_printf("Options:\n");
|
pc_printf("Options:\n");
|
||||||
pc_printf(" -A<num> alignment in bytes of the data segment and the stack\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 output assembler code\n");
|
||||||
#if AMX_COMPACTMARGIN > 2
|
#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
|
#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
|
#if defined dos_setdrive
|
||||||
pc_printf(" -Dpath active directory path\n");
|
pc_printf(" -Dpath active directory path\n");
|
||||||
#endif
|
#endif
|
||||||
pc_printf(" -d0 no symbolic information, no run-time checks\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(" -d1 [default] run-time checks, no symbolic information\n");
|
||||||
pc_printf(" -d2 full debug information and dynamic checking\n");
|
pc_printf(" -d2 full debug information and dynamic checking\n");
|
||||||
pc_printf(" -d3 full debug information, dynamic checking, no optimization\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(" -e<name> set name of error file (quiet compile)\n");
|
||||||
#if defined __WIN32__ || defined _WIN32 || defined _Windows
|
#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
|
#endif
|
||||||
pc_printf(" -i<name> path for include files\n");
|
pc_printf(" -i<name> path for include files\n");
|
||||||
pc_printf(" -l create list file (preprocess only)\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(" -o<name> set base name of (P-code) output file\n");
|
||||||
pc_printf(" -p<name> set name of \"prefix\" file\n");
|
pc_printf(" -p<name> set name of \"prefix\" file\n");
|
||||||
#if !defined SC_LIGHT
|
#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
|
#endif
|
||||||
pc_printf(" -S<num> stack/heap size in cells (default=%d)\n",(int)sc_stksize);
|
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(" -s<num> skip lines from the input file\n");
|
||||||
pc_printf(" -sui[+/-] show stack usage info\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(" -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(" -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(" -w<num>[+/-] disable a specific warning by its number\n");
|
||||||
pc_printf(" -E treat warnings as errors\n");
|
pc_printf(" -E treat warnings as errors\n");
|
||||||
pc_printf(" -X<num> abstract machine size limit in bytes\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(" -^ 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 a semicolon to end each statement (default=%c)\n", sc_needsemicolon ? '+' : '-');
|
||||||
pc_printf(" -([+/-] require parantheses for function invocation (default=%c)\n", optproccall ? '-' : '+');
|
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=val define constant \"sym\" with value \"val\"\n");
|
||||||
pc_printf(" sym= define constant \"sym\" with value 0\n");
|
pc_printf(" sym= define constant \"sym\" with value 0\n");
|
||||||
#if defined __WIN32__ || defined _WIN32 || defined _Windows || defined __MSDOS__
|
#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("\nOptions may start with a dash or a slash; the options \"-d0\" and \"/d0\" are\n");
|
||||||
pc_printf("equivalent.\n");
|
pc_printf("equivalent.\n");
|
||||||
@ -1549,7 +1573,7 @@ static void setconstants(void)
|
|||||||
#endif
|
#endif
|
||||||
add_constant("charbits",sCHARBITS,sGLOBAL,0);
|
add_constant("charbits",sCHARBITS,sGLOBAL,0);
|
||||||
add_constant("charmin",0,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("ucharmax",(1 << (sizeof(cell)-1)*8)-1,sGLOBAL,0);
|
||||||
|
|
||||||
add_constant("__Pawn",VERSION_INT,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;
|
int numdim;
|
||||||
short filenum;
|
short filenum;
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
constvalue *enumroot;
|
constvalue *enumroot=NULL;
|
||||||
#if !defined NDEBUG
|
#if !defined NDEBUG
|
||||||
cell glbdecl=0;
|
cell glbdecl=0;
|
||||||
#endif
|
#endif
|
||||||
@ -2066,7 +2090,7 @@ static int declloc(int fstatic)
|
|||||||
int idxtag[sDIMEN_MAX];
|
int idxtag[sDIMEN_MAX];
|
||||||
char name[sNAMEMAX+1];
|
char name[sNAMEMAX+1];
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
constvalue *enumroot;
|
constvalue *enumroot=NULL;
|
||||||
cell val,size;
|
cell val,size;
|
||||||
char *str;
|
char *str;
|
||||||
value lval = {0};
|
value lval = {0};
|
||||||
@ -2736,7 +2760,7 @@ static void decl_enum(int vclass)
|
|||||||
/* go through all constants */
|
/* go through all constants */
|
||||||
value=0; /* default starting value */
|
value=0; /* default starting value */
|
||||||
do {
|
do {
|
||||||
int idxtag,fieldtag;
|
int idxtag,fieldtag=0;
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
if (matchtoken('}')) { /* quick exit if '}' follows ',' */
|
if (matchtoken('}')) { /* quick exit if '}' follows ',' */
|
||||||
lexpush();
|
lexpush();
|
||||||
@ -2812,7 +2836,7 @@ static int getstates(const char *funcname)
|
|||||||
fsa=-1;
|
fsa=-1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!(islabel=matchtoken(tLABEL)) && !needtoken(tSYMBOL))
|
if ((islabel=matchtoken(tLABEL))==0 && !needtoken(tSYMBOL))
|
||||||
break;
|
break;
|
||||||
tokeninfo(&val,&str);
|
tokeninfo(&val,&str);
|
||||||
assert(strlen(str)<sizeof fsaname);
|
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(sSETFILE,sym->fnumber);
|
||||||
errorset(sSETLINE,sym->lnumber);
|
errorset(sSETLINE,sym->lnumber);
|
||||||
error(204,sym->name); /* value assigned to symbol is never used */
|
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) {
|
} else if ((sym->usage & (uWRITTEN | uPUBLIC | uCONST))==0 && sym->ident==iREFARRAY) {
|
||||||
errorset(sSETFILE,sym->fnumber);
|
errorset(sSETFILE,sym->fnumber);
|
||||||
errorset(sSETLINE,sym->lnumber);
|
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 */
|
/* constant doesn't exist yet, an entry must be created */
|
||||||
sym=addsym(name,val,iCONSTEXPR,vclass,tag,uDEFINE);
|
sym=addsym(name,val,iCONSTEXPR,vclass,tag,uDEFINE);
|
||||||
assert(sym!=NULL); /* fatal error 103 must be given on error */
|
assert(sym!=NULL); /* fatal error 103 must be given on error */
|
||||||
|
if (vclass == sLOCAL)
|
||||||
|
sym->compound = nestlevel;
|
||||||
if (sc_status == statIDLE)
|
if (sc_status == statIDLE)
|
||||||
sym->usage |= uPREDEF;
|
sym->usage |= uPREDEF;
|
||||||
return sym;
|
return sym;
|
||||||
@ -5124,13 +5150,13 @@ static void dofor(void)
|
|||||||
assert(stgidx==0);
|
assert(stgidx==0);
|
||||||
index=stgidx;
|
index=stgidx;
|
||||||
stgmark(sSTARTREORDER);
|
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 */
|
setlabel(skiplab); /* jump to this point after 1st expression */
|
||||||
if (matchtoken(';')==0) {
|
if (matchtoken(';')==0) {
|
||||||
test(wq[wqEXIT],FALSE,FALSE); /* expression 2 (jump to wq[wqEXIT] if false) */
|
test(wq[wqEXIT],FALSE,FALSE); /* expression 2 (jump to wq[wqEXIT] if false) */
|
||||||
needtoken(';');
|
needtoken(';');
|
||||||
} /* if */
|
} /* 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) {
|
if (matchtoken(')')==0) {
|
||||||
doexpr(TRUE,TRUE,TRUE,TRUE,NULL,NULL,FALSE); /* expression 3 */
|
doexpr(TRUE,TRUE,TRUE,TRUE,NULL,NULL,FALSE); /* expression 3 */
|
||||||
needtoken(')');
|
needtoken(')');
|
||||||
@ -5649,7 +5675,7 @@ static void dostate(void)
|
|||||||
|
|
||||||
fsa=0;
|
fsa=0;
|
||||||
|
|
||||||
if (!(islabel=matchtoken(tLABEL)) && !needtoken(tSYMBOL)) {
|
if ((islabel=matchtoken(tLABEL))==0 && !needtoken(tSYMBOL)) {
|
||||||
delete_autolisttable();
|
delete_autolisttable();
|
||||||
return;
|
return;
|
||||||
} /* if */
|
} /* if */
|
||||||
|
@ -846,6 +846,8 @@ enum {
|
|||||||
* Global variables: iflevel, ifstack (altered)
|
* Global variables: iflevel, ifstack (altered)
|
||||||
* lptr (altered)
|
* lptr (altered)
|
||||||
*/
|
*/
|
||||||
|
void parsesingleoption(char *argv);
|
||||||
|
|
||||||
static int command(void)
|
static int command(void)
|
||||||
{
|
{
|
||||||
int tok,ret;
|
int tok,ret;
|
||||||
@ -1051,10 +1053,11 @@ static int command(void)
|
|||||||
!strcmp(str, "explib") ||
|
!strcmp(str, "explib") ||
|
||||||
!strcmp(str, "expclass") ||
|
!strcmp(str, "expclass") ||
|
||||||
!strcmp(str, "defclasslib") ) {
|
!strcmp(str, "defclasslib") ) {
|
||||||
char name[sNAMEMAX+1],sname[sNAMEMAX+1];
|
char name[sNAMEMAX+1] = { 0 }, sname[sNAMEMAX + 1];
|
||||||
const char *prefix = "";
|
const char *prefix = ""; /* it's empty on library only */
|
||||||
sname[0] = '\0';
|
sname[0] = '\0';
|
||||||
sname[1] = '\0';
|
sname[1] = '\0';
|
||||||
|
|
||||||
if (!strcmp(str, "reqlib"))
|
if (!strcmp(str, "reqlib"))
|
||||||
prefix = "?rl_";
|
prefix = "?rl_";
|
||||||
else if (!strcmp(str, "reqclass"))
|
else if (!strcmp(str, "reqclass"))
|
||||||
@ -1097,7 +1100,7 @@ static int command(void)
|
|||||||
pc_addlibtable=FALSE;
|
pc_addlibtable=FALSE;
|
||||||
} else {
|
} else {
|
||||||
/* add the name if it does not yet exist in the table */
|
/* 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)
|
if (strlen(name) + strlen(prefix) + strlen(sname) <= sNAMEMAX)
|
||||||
{
|
{
|
||||||
strcpy(newname, prefix);
|
strcpy(newname, prefix);
|
||||||
@ -1190,8 +1193,42 @@ static int command(void)
|
|||||||
if (comma)
|
if (comma)
|
||||||
lptr++;
|
lptr++;
|
||||||
} while (comma);
|
} while (comma);
|
||||||
} else if (strcmp(str, "showstackusageinfo")==0) {
|
} else if (strcmp(str,"showstackusageinfo")==0) {
|
||||||
sc_stkusageinfo=TRUE;
|
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 {
|
} else {
|
||||||
error(207); /* unknown #pragma */
|
error(207); /* unknown #pragma */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
@ -603,6 +603,10 @@ static void plnge2(void (*oper)(void),
|
|||||||
} /* if */
|
} /* if */
|
||||||
/* ??? ^^^ should do same kind of error checking with functions */
|
/* ??? ^^^ 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
|
/* check whether an "operator" function is defined for the tag names
|
||||||
* (a constant expression cannot be optimized in that case)
|
* (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;
|
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)
|
static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
|
||||||
{
|
{
|
||||||
if (oper==ob_or)
|
if (oper==ob_or)
|
||||||
@ -662,9 +688,9 @@ static cell calc(cell left,void (*oper)(),cell right,char *boolresult)
|
|||||||
else if (oper==os_mult)
|
else if (oper==os_mult)
|
||||||
return (left * right);
|
return (left * right);
|
||||||
else if (oper==os_div)
|
else if (oper==os_div)
|
||||||
return (left - truemodulus(left,right)) / right;
|
return flooreddiv(left,right,FALSE);
|
||||||
else if (oper==os_mod)
|
else if (oper==os_mod)
|
||||||
return truemodulus(left,right);
|
return flooreddiv(left,right,TRUE);
|
||||||
else
|
else
|
||||||
error(29); /* invalid expression, assumed 0 (this should never occur) */
|
error(29); /* invalid expression, assumed 0 (this should never occur) */
|
||||||
return 0;
|
return 0;
|
||||||
@ -749,7 +775,7 @@ static int hier14(value *lval1)
|
|||||||
* negative value would do).
|
* negative value would do).
|
||||||
*/
|
*/
|
||||||
for (i=0; i<sDIMEN_MAX; i++)
|
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 */
|
org_arrayidx=lval1->arrayidx; /* save current pointer, to reset later */
|
||||||
if (lval1->arrayidx==NULL)
|
if (lval1->arrayidx==NULL)
|
||||||
lval1->arrayidx=arrayidx1;
|
lval1->arrayidx=arrayidx1;
|
||||||
@ -850,22 +876,23 @@ static int hier14(value *lval1)
|
|||||||
{
|
{
|
||||||
int same=TRUE;
|
int same=TRUE;
|
||||||
assert(lval2.arrayidx==arrayidx2);
|
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]);
|
same=same && (lval3.arrayidx[i]==lval2.arrayidx[i]);
|
||||||
|
}
|
||||||
if (same)
|
if (same)
|
||||||
error(226,lval3.sym->name); /* self-assignment */
|
error(226,lval3.sym->name); /* self-assignment */
|
||||||
} /* if */
|
} /* if */
|
||||||
} else {
|
} else {
|
||||||
if (oper){
|
if (oper) {
|
||||||
rvalue(lval1);
|
rvalue(lval1);
|
||||||
plnge2(oper,hier14,lval1,&lval2);
|
plnge2(oper,hier14,lval1,&lval2);
|
||||||
} else {
|
} else {
|
||||||
/* if direct fetch and simple assignment: no "push"
|
/* if direct fetch and simple assignment: no "push"
|
||||||
* and "pop" needed -> call hier14() directly, */
|
* and "pop" needed -> call hier14() directly, */
|
||||||
if (hier14(&lval2))
|
if (hier14(&lval2))
|
||||||
rvalue(&lval2); /* instead of plnge2(). */
|
rvalue(&lval2); /* instead of plnge2(). */
|
||||||
else if (lval2.ident==iVARIABLE)
|
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);
|
checkfunction(&lval2);
|
||||||
/* check whether lval2 and lval3 (old lval1) refer to the same variable */
|
/* check whether lval2 and lval3 (old lval1) refer to the same variable */
|
||||||
if (lval2.ident==iVARIABLE && lval3.ident==lval2.ident && lval3.sym==lval2.sym) {
|
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);
|
int lvalue=plnge1(hier12,lval);
|
||||||
if (matchtoken('?')) {
|
if (matchtoken('?')) {
|
||||||
int locheap=decl_heap; /* save current heap delta */
|
int locheap=decl_heap; /* save current heap delta */
|
||||||
long heap1,heap2; /* max. heap delta either branch */
|
long heap1=0,heap2=0; /* max. heap delta either branch */
|
||||||
valuepair *heaplist_node;
|
valuepair *heaplist_node=NULL;
|
||||||
int flab1=getlabel();
|
int flab1=getlabel();
|
||||||
int flab2=getlabel();
|
int flab2=getlabel();
|
||||||
value lval2 = {0};
|
value lval2 = {0};
|
||||||
@ -1209,6 +1236,8 @@ static int hier2(value *lval)
|
|||||||
rvalue(lval);
|
rvalue(lval);
|
||||||
invert(); /* bitwise NOT */
|
invert(); /* bitwise NOT */
|
||||||
lval->constval=~lval->constval;
|
lval->constval=~lval->constval;
|
||||||
|
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
|
||||||
|
lval->ident=iEXPRESSION;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
case '!': /* ! (logical negate) */
|
case '!': /* ! (logical negate) */
|
||||||
if (hier2(lval))
|
if (hier2(lval))
|
||||||
@ -1220,6 +1249,8 @@ static int hier2(value *lval)
|
|||||||
lneg(); /* 0 -> 1, !0 -> 0 */
|
lneg(); /* 0 -> 1, !0 -> 0 */
|
||||||
lval->constval=!lval->constval;
|
lval->constval=!lval->constval;
|
||||||
lval->tag=pc_addtag("bool");
|
lval->tag=pc_addtag("bool");
|
||||||
|
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
|
||||||
|
lval->ident=iEXPRESSION;
|
||||||
} /* if */
|
} /* if */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
case '-': /* unary - (two's complement) */
|
case '-': /* unary - (two's complement) */
|
||||||
@ -1248,6 +1279,8 @@ static int hier2(value *lval)
|
|||||||
} else {
|
} else {
|
||||||
neg(); /* arithmic negation */
|
neg(); /* arithmic negation */
|
||||||
lval->constval=-lval->constval;
|
lval->constval=-lval->constval;
|
||||||
|
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
|
||||||
|
lval->ident=iEXPRESSION;
|
||||||
} /* if */
|
} /* if */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
case tLABEL: /* tagname override */
|
case tLABEL: /* tagname override */
|
||||||
|
@ -1224,6 +1224,10 @@ SC_FUNC void inc(value *lval)
|
|||||||
symbol *sym;
|
symbol *sym;
|
||||||
|
|
||||||
sym=lval->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) {
|
if (lval->ident==iARRAYCELL) {
|
||||||
/* indirect increment, address already in PRI */
|
/* indirect increment, address already in PRI */
|
||||||
stgwrite("\tinc.i\n");
|
stgwrite("\tinc.i\n");
|
||||||
@ -1282,6 +1286,10 @@ SC_FUNC void dec(value *lval)
|
|||||||
symbol *sym;
|
symbol *sym;
|
||||||
|
|
||||||
sym=lval->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) {
|
if (lval->ident==iARRAYCELL) {
|
||||||
/* indirect decrement, address already in PRI */
|
/* indirect decrement, address already in PRI */
|
||||||
stgwrite("\tdec.i\n");
|
stgwrite("\tdec.i\n");
|
||||||
|
@ -107,7 +107,8 @@ static char *errmsg[] = {
|
|||||||
/*085*/ "no states are defined for function \"%s\"\n",
|
/*085*/ "no states are defined for function \"%s\"\n",
|
||||||
/*086*/ "unknown automaton \"%s\"\n",
|
/*086*/ "unknown automaton \"%s\"\n",
|
||||||
/*087*/ "unknown state \"%s\" for 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[] = {
|
static char *fatalmsg[] = {
|
||||||
@ -168,4 +169,5 @@ static char *warnmsg[] = {
|
|||||||
/*232*/ "output file is written, but with compact encoding disabled\n",
|
/*232*/ "output file is written, but with compact encoding disabled\n",
|
||||||
/*233*/ "symbol \"%s\" is marked as deprecated: %s\n",
|
/*233*/ "symbol \"%s\" is marked as deprecated: %s\n",
|
||||||
/*234*/ "recursive function \"%s\"\n",
|
/*234*/ "recursive function \"%s\"\n",
|
||||||
|
/*235*/ "detected %s with no corresponding %s\n"
|
||||||
};
|
};
|
||||||
|
@ -48,7 +48,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NUM_WARNINGS (sizeof warnmsg / sizeof warnmsg[0])
|
#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 errflag;
|
||||||
static int errfile;
|
static int errfile;
|
||||||
@ -90,7 +93,7 @@ static short lastfile;
|
|||||||
if (number>=200) {
|
if (number>=200) {
|
||||||
int index=(number-200)/8;
|
int index=(number-200)/8;
|
||||||
int mask=1 << ((number-200)%8);
|
int mask=1 << ((number-200)%8);
|
||||||
if ((warndisable[index] & mask)!=0)
|
if ((warnstack.disable[index] & mask)!=0)
|
||||||
return 0;
|
return 0;
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
@ -214,32 +217,77 @@ SC_FUNC void errorset(int code,int line)
|
|||||||
* o 1 for enable
|
* o 1 for enable
|
||||||
* o 2 for toggle
|
* o 2 for toggle
|
||||||
*/
|
*/
|
||||||
int pc_enablewarning(int number,int enable)
|
int pc_enablewarning(int number,warnmode enable)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
unsigned char mask;
|
unsigned char mask;
|
||||||
|
|
||||||
if (number<200)
|
if (number<200)
|
||||||
return FALSE; /* errors and fatal errors cannot be disabled */
|
return FALSE; /* errors and fatal errors cannot be disabled */
|
||||||
number -= 200;
|
number-=200;
|
||||||
if (number>=NUM_WARNINGS)
|
if (number>=NUM_WARNINGS)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
index=number/8;
|
index=number/8;
|
||||||
mask=(unsigned char)(1 << (number%8));
|
mask=(unsigned char)(1 << (number%8));
|
||||||
switch (enable) {
|
switch (enable) {
|
||||||
case 0:
|
case warnDISABLE:
|
||||||
warndisable[index] |= mask;
|
warnstack.disable[index] |= mask;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case warnENABLE:
|
||||||
warndisable[index] &= (unsigned char)~mask;
|
warnstack.disable[index] &= (unsigned char)~mask;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case warnTOGGLE:
|
||||||
warndisable[index] ^= mask;
|
warnstack.disable[index] ^= mask;
|
||||||
break;
|
break;
|
||||||
} /* switch */
|
} /* switch */
|
||||||
|
|
||||||
return TRUE;
|
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
|
#undef SCPACK_TABLE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user