From 5a0fd0fda19ab2449827853dbeddfd6e024fa080 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 7 Jan 2018 20:19:05 +0530 Subject: [PATCH 01/88] fixes inconsistencies with the tagof operator The standalone tagof operator tries to export tall tags which it works with. The tagof operator when used as a default argument checks if the tag is zero before exporting. As the zero tag identifier cannot be exported (even if its `PUBLICTAG` bit is set), it makes sense to use `0` as tag identifier instead of `0 | PUBLICTAG`. This commit changes the standalone tagof operator behaviour so that the zero tag identifier does not get its `PUBLICTAG` bit set. --- source/compiler/sc3.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 3421f46..adc40d9 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -1424,10 +1424,13 @@ static int hier2(value *lval) else if (level==sym->dim.array.level+1 && idxsym!=NULL) tag=idxsym->x.tags.index; } /* if */ - exporttag(tag); + if (tag!=0) { + exporttag(tag); + tag |= PUBLICTAG; + } /* if */ clear_value(lval); lval->ident=iCONSTEXPR; - lval->constval=tag | PUBLICTAG; + lval->constval=tag; ldconst(lval->constval,sPRI); while (paranthese--) needtoken(')'); From 30e1ef93890a494ef54f713e63c0ed013d9fe73a Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Fri, 12 Jan 2018 23:30:04 +0700 Subject: [PATCH 02/88] Memoize the last node in constvalue lists --- source/compiler/sc.h | 4 ++++ source/compiler/sc1.c | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index f60a1ad..b9e16ea 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -113,6 +113,10 @@ typedef struct s_constvalue { * tag for enumeration lists */ } constvalue; +typedef struct s_constvalue_root { + constvalue *next,*last; +} constvalue_root; + /* Symbol table format * * The symbol name read from the input file is stored in "name", the diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index ede7c9a..0192d91 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -4906,8 +4906,8 @@ static void destructsymbols(symbol *root,int level) popreg(sPRI); } -static constvalue *insert_constval(constvalue *prev,constvalue *next,const char *name,cell val, - int index) +static constvalue *insert_constval(constvalue *prev,constvalue *next, + const char *name,cell val,int index) { constvalue *cur; @@ -4927,12 +4927,12 @@ static constvalue *insert_constval(constvalue *prev,constvalue *next,const char SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index) { - constvalue *cur,*prev; + constvalue_root *root=(constvalue_root *)table; + constvalue *newvalue; - /* find the end of the constant table */ - for (prev=table, cur=table->next; cur!=NULL; prev=cur, cur=cur->next) - /* nothing */; - return insert_constval(prev,NULL,name,val,index); + newvalue=insert_constval(((root->last!=NULL) ? root->last : table),NULL,name,val,index); + root->last=newvalue; + return newvalue; } SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index) @@ -4962,12 +4962,15 @@ static constvalue *find_constval_byval(constvalue *table,cell val) #if 0 /* never used */ static int delete_constval(constvalue *table,char *name) { - constvalue *prev = table; - constvalue *cur = prev->next; + constvalue *prev=table; + constvalue *cur=prev->next; + constvalue_root *root=(constvalue_root *)table; while (cur!=NULL) { if (strcmp(name,cur->name)==0) { prev->next=cur->next; + if (root->last==cur) + root->last=prev; free(cur); return TRUE; } /* if */ From 57ef6150ede317fee5a90923488e7847c8a5f3c0 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 7 Jan 2018 10:35:21 +0530 Subject: [PATCH 03/88] warning for meaningless class combinations 1. Adds a generic new warning which is triggered when meaningless combination of class specifiers are used. 2. This commit adds code to trigger a warning for the following two cases: - constant reference - - not meaningful as as references always point to cells in PAWN (unlike C++ where it would help costly copies while guaranteeing to not modify the object) which makes const reference is as good as pass-by-value - constant variable arguments - - for similar reasons as in the previous case --- source/compiler/sc1.c | 4 ++++ source/compiler/sc5.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index b9260f2..13d0483 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -3867,6 +3867,8 @@ static int declargs(symbol *sym,int chkshadow) case '&': if (ident!=iVARIABLE || numtags>0) error(1,"-identifier-","&"); + if (fconst) + error(238, "const reference"); /* meaningless combination of class specifiers */ ident=iREFERENCE; break; case tCONST: @@ -3941,6 +3943,8 @@ static int declargs(symbol *sym,int chkshadow) case tELLIPS: if (ident!=iVARIABLE) error(10); /* illegal function or declaration */ + if (fconst) + error(238, "const variable arguments"); /* meaningless combination of class specifiers */ if (numtags==0) tags[numtags++]=0; /* default tag */ if ((sym->usage & uPROTOTYPED)==0) { diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index ac08c96..43f2e29 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -191,7 +191,8 @@ static char *warnmsg[] = { /*234*/ "function is deprecated (symbol \"%s\") %s\n", /*235*/ "public function lacks forward declaration (symbol \"%s\")\n", /*236*/ "unknown parameter in substitution (incorrect #define pattern)\n", -/*237*/ "user warning: %s\n" +/*237*/ "user warning: %s\n", +/*238*/ "meaningless combination of class specifiers (%s)\n" }; #define NUM_WARNINGS (sizeof warnmsg / sizeof warnmsg[0]) From a8ca60b6b901d5a336c53f14b325c91364ef7931 Mon Sep 17 00:00:00 2001 From: YashasSamaga Date: Sat, 13 Jan 2018 00:39:18 +0530 Subject: [PATCH 04/88] add test for 172 --- source/compiler/tests/CMakeLists.txt | 6 ++++++ .../meaningless_class_specifiers_gh_172.pwn | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) mode change 100644 => 100755 source/compiler/tests/CMakeLists.txt create mode 100755 source/compiler/tests/meaningless_class_specifiers_gh_172.pwn diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt old mode 100644 new mode 100755 index a63fdeb..f8c0628 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -40,6 +40,12 @@ set_tests_properties(unused_symbol_line_gh_252 PROPERTIES PASS_REGULAR_EXPRESSIO .*\\.pwn\\(1\\) : warning 203: symbol is never used: \\\"x\\\" ") +add_compiler_test(meaningless_class_specifiers_gh_172 ${CMAKE_CURRENT_SOURCE_DIR}/meaningless_class_specifiers_gh_172.pwn) +set_tests_properties(meaningless_class_specifiers_gh_172 PROPERTIES PASS_REGULAR_EXPRESSION "\ +.*\\.pwn\\(1\\) : warning 238: meaningless combination of class specifiers \\(const reference\\)\ +.*\\.pwn\\(2\\) : warning 238: meaningless combination of class specifiers \\(const variable arguments\\)\ +") + # Crashers # # These tests simply check that the compiler doesn't crash. diff --git a/source/compiler/tests/meaningless_class_specifiers_gh_172.pwn b/source/compiler/tests/meaningless_class_specifiers_gh_172.pwn new file mode 100755 index 0000000..68bfd02 --- /dev/null +++ b/source/compiler/tests/meaningless_class_specifiers_gh_172.pwn @@ -0,0 +1,20 @@ +f1(const &v) { } +f2(const ...) { } +f3(const v) { + #pragma unused v +} +f4(...) { } +f5(v) { + #pragma unused v +} +f6(&v) { } + +main() { + new a; + f1(a); + f2(a); + f3(a); + f4(a); + f5(a); + f6(a); +} \ No newline at end of file From 87d718f12c883491b19ed69362909c5ee2124f55 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 14 Jan 2018 13:12:55 +0530 Subject: [PATCH 05/88] call destructors on implicit return The destructors for local variables were not being called when the function returns without the user expclitly giving a return statement. This commit adds code to call the destructors for the local variables on an implicit return. --- source/compiler/sc1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index b9260f2..a7380c0 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -3752,6 +3752,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc declared=0; } /* if */ if ((lastst!=tRETURN) && (lastst!=tGOTO)){ + destructsymbols(&loctab, 0); ldconst(0,sPRI); ffret(strcmp(sym->name,uENTRYFUNC)!=0); if ((sym->usage & uRETVALUE)!=0 && (sym->flags & flagNAKED)==0) { From 8fd46af2ecff2c1de6493dc67724fe151715a9b5 Mon Sep 17 00:00:00 2001 From: Yashas Date: Mon, 15 Jan 2018 00:21:37 +0530 Subject: [PATCH 06/88] prevent destructor calls for static locals --- source/compiler/sc1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index a7380c0..d017713 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -4861,7 +4861,7 @@ static void destructsymbols(symbol *root,int level) int savepri=FALSE; symbol *sym=root->next; while (sym!=NULL && sym->compound>=level) { - if (sym->ident==iVARIABLE || sym->ident==iARRAY) { + if ((sym->ident==iVARIABLE || sym->ident==iARRAY) && !(sym->vclass == sSTATIC && sym->fnumber == -1)) { char symbolname[16]; symbol *opsym; cell elements; From 39ec8421303faed6c703c6bf6bf73f41f3ec9c13 Mon Sep 17 00:00:00 2001 From: Yashas Date: Mon, 15 Jan 2018 01:24:10 +0530 Subject: [PATCH 07/88] corrects behaviour of md-array destructor calls Currently, the destructors are triggered for each indirection level of the multi-dimensional array. The PAWN Implementer Guide states that the destructor must be triggered for the actual data only. Apart from the above correction, this commit also fixes a typo which caused wrong sizes to be passed to the destructor. --- source/compiler/sc1.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index d017713..d3bb48e 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -4845,7 +4845,7 @@ static cell calc_array_datasize(symbol *sym, cell *offset) if (offset!=NULL) *offset=length*(*offset+sizeof(cell)); if (sublength>0) - length*=length*sublength; + length*=sublength; else length=0; } else { @@ -4875,6 +4875,15 @@ static void destructsymbols(symbol *root,int level) } /* if */ /* if the variable is an array, get the number of elements */ if (sym->ident==iARRAY) { + /* according to the PAWN Implementer Guide, the destructor + * should be triggered for the data of the array only; hence + * if the array is a part of a larger array, it must be ignored + * as it's parent would(or has already) trigger(ed) the destructor + */ + if (sym->parent != NULL) { + sym=sym->next; + continue; + } elements=calc_array_datasize(sym,&offset); /* "elements" can be zero when the variable is declared like * new mytag: myvar[2][] = { {1, 2}, {3, 4} } From 0ecffcb834a8f1b86fb32c9ec963e44bc0b911e8 Mon Sep 17 00:00:00 2001 From: Yashas Date: Mon, 15 Jan 2018 01:43:25 +0530 Subject: [PATCH 08/88] corrected formatting of code --- source/compiler/sc1.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index d3bb48e..2c3edc0 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -3752,7 +3752,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc declared=0; } /* if */ if ((lastst!=tRETURN) && (lastst!=tGOTO)){ - destructsymbols(&loctab, 0); + destructsymbols(&loctab,0); ldconst(0,sPRI); ffret(strcmp(sym->name,uENTRYFUNC)!=0); if ((sym->usage & uRETVALUE)!=0 && (sym->flags & flagNAKED)==0) { @@ -4861,7 +4861,7 @@ static void destructsymbols(symbol *root,int level) int savepri=FALSE; symbol *sym=root->next; while (sym!=NULL && sym->compound>=level) { - if ((sym->ident==iVARIABLE || sym->ident==iARRAY) && !(sym->vclass == sSTATIC && sym->fnumber == -1)) { + if ((sym->ident==iVARIABLE || sym->ident==iARRAY) && !(sym->vclass==sSTATIC && sym->fnumber==-1)) { char symbolname[16]; symbol *opsym; cell elements; @@ -4880,10 +4880,10 @@ static void destructsymbols(symbol *root,int level) * if the array is a part of a larger array, it must be ignored * as it's parent would(or has already) trigger(ed) the destructor */ - if (sym->parent != NULL) { + if (sym->parent!=NULL) { sym=sym->next; continue; - } + } /* if */ elements=calc_array_datasize(sym,&offset); /* "elements" can be zero when the variable is declared like * new mytag: myvar[2][] = { {1, 2}, {3, 4} } From 1d60153af1637a66811632aca2a324495c1100c2 Mon Sep 17 00:00:00 2001 From: Yashas Date: Thu, 18 Jan 2018 23:58:18 +0530 Subject: [PATCH 09/88] don't do implicit return tasks in naked functions This commits prevents the compiler from calling destructors and adding the return instructions implicitly in naked functions. --- source/compiler/sc1.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index b9260f2..d00337f 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -3743,7 +3743,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc sc_curstates=0; if ((rettype & uRETVALUE)!=0) sym->usage|=uRETVALUE; - if (declared!=0) { + if (declared!=0 && (curfunc->flags & flagNAKED)==0) { /* This happens only in a very special (and useless) case, where a function * has only a single statement in its body (no compound block) and that * statement declares a new variable @@ -3751,10 +3751,10 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc modstk((int)declared*sizeof(cell)); /* remove all local variables */ declared=0; } /* if */ - if ((lastst!=tRETURN) && (lastst!=tGOTO)){ + if ((lastst!=tRETURN) && (lastst!=tGOTO) && (sym->flags & flagNAKED)==0){ ldconst(0,sPRI); ffret(strcmp(sym->name,uENTRYFUNC)!=0); - if ((sym->usage & uRETVALUE)!=0 && (sym->flags & flagNAKED)==0) { + if ((sym->usage & uRETVALUE)!=0) { char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */ funcdisplayname(symname,sym->name); error(209,symname); /* function should return a value */ @@ -5304,9 +5304,11 @@ static void compound(int stmt_sameline,int starttok) } /* if */ } /* while */ if (lastst!=tRETURN) - destructsymbols(&loctab,nestlevel); + if(nestlevel >= 1 || (curfunc->flags & flagNAKED)==0) + destructsymbols(&loctab,nestlevel); if (lastst!=tRETURN && lastst!=tGOTO) - modstk((int)(declared-save_decl)*sizeof(cell)); /* delete local variable space */ + if(nestlevel >= 1 || (curfunc->flags & flagNAKED)==0) + modstk((int)(declared-save_decl)*sizeof(cell)); /* delete local variable space */ testsymbols(&loctab,nestlevel,FALSE,TRUE); /* look for unused block locals */ declared=save_decl; delete_symbols(&loctab,nestlevel,FALSE,TRUE); /* erase local symbols, but From 8c1133b00d2c8d011c5c437cdf7fcc447ff5104c Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Thu, 11 Jan 2018 23:04:08 +0700 Subject: [PATCH 10/88] sc7: Optimize string copying in rebuffer() and stgwrite() --- source/compiler/sc7.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/source/compiler/sc7.c b/source/compiler/sc7.c index 07a25b5..1f897c3 100644 --- a/source/compiler/sc7.c +++ b/source/compiler/sc7.c @@ -1332,14 +1332,12 @@ SC_FUNC void stgmark(char mark) static int rebuffer(char *str) { if (sc_status==statWRITE) { + int st_len=strlen(str); if (pipeidx>=2 && stgpipe[pipeidx-1]=='\0' && stgpipe[pipeidx-2]!='\n') - pipeidx-=1; /* overwrite last '\0' */ - while (*str!='\0') { /* copy to staging buffer */ - CHECK_STGPIPE(pipeidx); - stgpipe[pipeidx++]=*str++; - } /* while */ - CHECK_STGPIPE(pipeidx); - stgpipe[pipeidx++]='\0'; + pipeidx-=1; /* overwrite last '\0' */ + CHECK_STGPIPE(pipeidx+st_len+1); + memcpy(stgpipe+pipeidx,str,st_len+1); /* copy to staging buffer */ + pipeidx+=st_len+1; } /* if */ return TRUE; } @@ -1372,22 +1370,18 @@ static int filewrite(char *str) SC_FUNC void stgwrite(const char *st) { int len; - int st_len; + int st_len=strlen(st); if (staging) { assert(stgidx==0 || stgbuf!=NULL); /* staging buffer must be valid if there is (apparently) something in it */ if (stgidx>=2 && stgbuf[stgidx-1]=='\0' && stgbuf[stgidx-2]!='\n') - stgidx-=1; /* overwrite last '\0' */ - while (*st!='\0') { /* copy to staging buffer */ - CHECK_STGBUFFER(stgidx); - stgbuf[stgidx++]=*st++; - stglen++; - } /* while */ - CHECK_STGBUFFER(stgidx); - stgbuf[stgidx++]='\0'; + stgidx-=1; /* overwrite last '\0' */ + CHECK_STGBUFFER(stgidx+st_len+1); + memcpy(stgbuf+stgidx,st,st_len+1); /* copy to staging buffer */ + stgidx+=st_len+1; + stglen+=st_len; } else { len=(stgbuf!=NULL) ? stglen : 0; - st_len=strlen(st); CHECK_STGBUFFER(len+st_len+1); memcpy(stgbuf+len,st,st_len+1); len=len+st_len; From 42c18c2a10d7067c5ae63f4d31b5a7706e5717d7 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 28 Jan 2018 12:46:03 +0530 Subject: [PATCH 11/88] fixes tagof behaviour on default values Previously, if the tagof operator was used on an argument with default value, the tag identifier recorded would be 0 in case the default value was used. ``` f({Tag1, Tag2}:a = Tag2:123, b = tagof(a)) { } main () { f(); } ``` In the above code, the argument `a` would have the value `123` but `b` would have `0`. This commit patches the bug. The value of `b` will be the tag identifier of the default argument. This commit patches for two cases: default argument is a reference and default argument is a variable. The case of reference arrays is not handled correctly as the tag of the default reference array is not well defined. **Implementation details:** The compiler first processes arguments which are not taking default values (including `tagof` and `sizeof` parameters). The compiler does a second pass on the list of all formal parameters and processes the default values. The compiler then does a final pass on the list of formal parameters and processes `sizeof` and `tagof` parameters. The compiler maintains a list of tags of all the arguments in a `constvalue` list called `taglst` as it processes the arguments. The name field of the members of the tag list is the argument name and the tag field stores the tag identifier of that argument (tag identifier of the actual parameter). In the first pass where the expclit arguments are being processed, the compiler checks the argument's tag and adds the tag along with the formal parameter name (can be thought of as ) to the tag list if the tag identifier is NOT zero. In the second pass where the default values are being handled, the compiler does not modify the tag list (**source of the bug**). After all the arguments other than `sizeof` and `tagof` have been handled othe, the compiler iterates through the list of arguments and takes care of `sizeof` and `tagof` arguments. Here it checks to which formal parameter (say F) the `tagof` parameter (say T) points to. It then checks the tag list for that symbol F, if an entry is found, it uses the tag identifier associated with that argument. If not found, it defaults to 0. Since the tags of default arguments along with it's formal name is not added to the tag list, the third pass won't be aware of any tag associated with the default values and assumes 0. This commit adds code to add the tags of the default values to the tag list so that the compiler is aware of the tag of the default values in the final pass. --- source/compiler/sc3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 3421f46..bf5b66f 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -2343,6 +2343,8 @@ static int nesting=0; check_userop(NULL,arg[argidx].defvalue_tag,arg[argidx].tags[0],2,NULL,&dummytag); assert(dummytag==arg[argidx].tags[0]); } /* if */ + if (arg[argidx].defvalue_tag!=0) + append_constval(&taglst,arg[argidx].name,arg[argidx].defvalue_tag,0); pushreg(sPRI); /* store the function argument on the stack */ markexpr(sPARM,NULL,0); /* mark the end of a sub-expression */ nest_stkusage++; From 4f099e7eb1b196b8360e9d914bc6895fdc0c7dca Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Wed, 31 Jan 2018 04:09:05 +0700 Subject: [PATCH 12/88] emit: Disallow the use of the '-' sign with function names for arguments of type 'any' --- source/compiler/sc1.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index b1ad703..f2a2465 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -5984,6 +5984,8 @@ fetchtok: goto invalid_token; } /* if */ if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { + if (neg!=FALSE) + goto invalid_token_neg; if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)==0 && sym->addr>=0) sym->addr=ntv_funcid++; markusage(sym,uREAD); @@ -6012,9 +6014,10 @@ fetchtok: neg=TRUE; goto fetchtok; } else { - char ival[sNAMEMAX+2]="-"; - strcpy(ival+1,str); - error(1,sc_tokens[tSYMBOL-tFIRST],ival); + char ival[sNAMEMAX+2]; + invalid_token_neg: + sprintf(ival,"-%s",str); + error(1,sc_tokens[teNUMERIC-tFIRST],ival); break; } /* if */ default: From ca01cbdf7d3d32a679b110be674361f95b9f6f91 Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Wed, 31 Jan 2018 06:10:23 +0700 Subject: [PATCH 13/88] emit: Redo instruction output --- source/compiler/sc.h | 12 ++++- source/compiler/sc1.c | 109 ++++++++++++++++++++---------------------- source/compiler/sc4.c | 17 +++++-- 3 files changed, 76 insertions(+), 62 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index 48d43fd..78bdd78 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -475,6 +475,16 @@ typedef enum s_optmark { #define MAX_INSTR_LEN 30 +#define eotNUMBER 0 +#define eotFUNCTION 1 +typedef struct s_emit_outval { + int type; + union { + ucell ucell; + const char *string; + } value; +} emit_outval; + /* interface functions */ #if defined __cplusplus extern "C" { @@ -699,7 +709,7 @@ SC_FUNC void dec(value *lval); SC_FUNC void jmp_ne0(int number); SC_FUNC void jmp_eq0(int number); SC_FUNC void outval(cell val,int newline); -SC_FUNC void outinstr(const char *name,ucell args[],int numargs); +SC_FUNC void outinstr(const char *name, emit_outval params[],int numparams); /* function prototypes in SC5.C */ SC_FUNC int error(int number,...); diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index f2a2465..de2bba3 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -5953,7 +5953,7 @@ static void SC_FASTCALL emit_invalid_token(int expected_token,int found_token) } /* if */ } -static void SC_FASTCALL emit_param_any(ucell *p) +static void SC_FASTCALL emit_param_any(emit_outval *p) { char *str; cell val,cidx; @@ -5962,14 +5962,15 @@ static void SC_FASTCALL emit_param_any(ucell *p) int tok,neg,ident,index; neg=FALSE; + p->type=eotNUMBER; fetchtok: tok=lex(&val,&str); switch (tok) { case tNUMBER: - *p=(neg!=FALSE) ? -val : val; + p->value.ucell=(ucell)((neg!=FALSE) ? -val : val); break; case tRATIONAL: - *p=(neg!=FALSE) ? (val|((cell)1 << (PAWN_CELL_SIZE-1))) : val; + p->value.ucell=(ucell)((neg!=FALSE) ? (val|((cell)1 << (PAWN_CELL_SIZE-1))) : val); break; case tSYMBOL: sym=findloc(str); @@ -5989,10 +5990,12 @@ fetchtok: if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)==0 && sym->addr>=0) sym->addr=ntv_funcid++; markusage(sym,uREAD); + p->type=eotFUNCTION; + p->value.string=str; } else { markusage(sym,uREAD | uWRITTEN); + p->value.ucell=(ucell)((neg!=FALSE) ? -sym->addr : sym->addr); } /* if */ - *p=(neg!=FALSE) ? -sym->addr : sym->addr; break; case '(': if ((emit_flags & efEXPR)==0) @@ -6007,7 +6010,7 @@ fetchtok: if ((emit_flags & efEXPR)==0) stgset(FALSE); needtoken(')'); - *p=(neg!=FALSE) ? -val : val; + p->value.ucell=(ucell)((neg!=FALSE) ? -val : val); break; case '-': if (neg==FALSE) { @@ -6026,17 +6029,18 @@ fetchtok: } /* switch */ } -static void SC_FASTCALL emit_param_data(ucell *p) +static void SC_FASTCALL emit_param_data(emit_outval *p) { cell val; char *str; symbol *sym; int tok; + p->type=eotNUMBER; tok=lex(&val,&str); switch (tok) { case tNUMBER: - *p=val; + p->value.ucell=(ucell)val; break; case tSYMBOL: sym=findloc(str); @@ -6061,7 +6065,7 @@ static void SC_FASTCALL emit_param_data(ucell *p) } /* if */ } /* if */ markusage(sym,uREAD | uWRITTEN); - *p=sym->addr; + p->value.ucell=(ucell)sym->addr; break; default: invalid_token: @@ -6069,17 +6073,18 @@ static void SC_FASTCALL emit_param_data(ucell *p) } /* switch */ } -static void SC_FASTCALL emit_param_local(ucell *p) +static void SC_FASTCALL emit_param_local(emit_outval *p) { cell val; char *str; symbol *sym; int tok; + p->type=eotNUMBER; tok=lex(&val,&str); switch (tok) { case tNUMBER: - *p=val; + p->value.ucell=(ucell)val; break; case tSYMBOL: sym=findloc(str); @@ -6100,7 +6105,7 @@ static void SC_FASTCALL emit_param_local(ucell *p) } /* if */ } /* if */ markusage(sym,uREAD | uWRITTEN); - *p=sym->addr; + p->value.ucell=(ucell)sym->addr; break; default: invalid_token: @@ -6108,7 +6113,7 @@ static void SC_FASTCALL emit_param_local(ucell *p) } /* switch */ } -static void SC_FASTCALL emit_param_index(ucell *p,const cell *valid_values,int numvalues) +static void SC_FASTCALL emit_param_index(emit_outval *p,const cell *valid_values,int numvalues) { cell val; char *str; @@ -6168,14 +6173,15 @@ fetchtok: return; } /* switch */ - *p=val; + p->type=eotNUMBER; + p->value.ucell=(ucell)val; for (i=0; iusage|=uREAD; - *p=*(ucell *)&sym->addr; + p->type=eotNUMBER; + p->value.ucell=(ucell)sym->addr; } -static void SC_FASTCALL emit_param_function(ucell *p,int isnative) +static void SC_FASTCALL emit_param_function(emit_outval *p,int isnative) { cell val; char *str; @@ -6222,9 +6229,11 @@ static void SC_FASTCALL emit_param_function(ucell *p,int isnative) if (isnative!=FALSE) { if ((sym->usage & uREAD)==0 && sym->addr>=0) sym->addr=ntv_funcid++; - *p=sym->addr; + p->type=eotNUMBER; + p->value.ucell=(ucell)sym->addr; } else { - *(char **)p=str; + p->type=eotFUNCTION; + p->value.string=str; } /* if */ markusage(sym,uREAD); } @@ -6241,7 +6250,7 @@ static void SC_FASTCALL emit_parm0(char *name) static void SC_FASTCALL emit_parm1_any(char *name) { - ucell p[1]; + emit_outval p[1]; emit_param_any(&p[0]); outinstr(name,p,(sizeof p / sizeof p[0])); @@ -6249,7 +6258,7 @@ static void SC_FASTCALL emit_parm1_any(char *name) static void SC_FASTCALL emit_parm1_data(char *name) { - ucell p[1]; + emit_outval p[1]; emit_param_data(&p[0]); outinstr(name,p,(sizeof p / sizeof p[0])); @@ -6257,7 +6266,7 @@ static void SC_FASTCALL emit_parm1_data(char *name) static void SC_FASTCALL emit_parm1_local(char *name) { - ucell p[1]; + emit_outval p[1]; emit_param_local(&p[0]); outinstr(name,p,(sizeof p / sizeof p[0])); @@ -6265,7 +6274,7 @@ static void SC_FASTCALL emit_parm1_local(char *name) static void SC_FASTCALL emit_parm1_label(char *name) { - ucell p[1]; + emit_outval p[1]; emit_param_label(&p[0]); outinstr(name,p,(sizeof p / sizeof p[0])); @@ -6273,36 +6282,29 @@ static void SC_FASTCALL emit_parm1_label(char *name) static void SC_FASTCALL emit_do_casetbl(char *name) { - ucell p[2]; + emit_outval p[2]; (void)name; emit_param_any(&p[0]); emit_param_label(&p[1]); stgwrite("\tcasetbl\n"); - stgwrite("\tcase "); - outval(p[0],FALSE); - stgwrite(" "); - outval(p[1],TRUE); - code_idx+=opcodes(1)+opargs(2); + outinstr("case",p,(sizeof p / sizeof p[0])); } static void SC_FASTCALL emit_do_case(char *name) { - ucell p[2]; + emit_outval p[2]; emit_param_any(&p[0]); emit_param_label(&p[1]); - stgwrite("\tcase "); - outval(p[0],FALSE); - stgwrite(" "); - outval(p[1],TRUE); - code_idx+=opargs(2); + outinstr("case",p,(sizeof p / sizeof p[0])); + code_idx-=opcodes(1); } static void SC_FASTCALL emit_do_lodb_strb(char *name) { static const cell valid_values[] = { 1,2,4 }; - ucell p[1]; + emit_outval p[1]; emit_param_index(&p[0],valid_values,(sizeof valid_values / sizeof valid_values[0])); outinstr(name,p,(sizeof p / sizeof p[0])); @@ -6311,7 +6313,7 @@ static void SC_FASTCALL emit_do_lodb_strb(char *name) static void SC_FASTCALL emit_do_lctrl(char *name) { static const cell valid_values[] = { 0,1,2,3,4,5,6,7,8,9 }; - ucell p[1]; + emit_outval p[1]; emit_param_index(&p[0],valid_values,(sizeof valid_values / sizeof valid_values[0])); outinstr(name,p,(sizeof p / sizeof p[0])); @@ -6320,7 +6322,7 @@ static void SC_FASTCALL emit_do_lctrl(char *name) static void SC_FASTCALL emit_do_sctrl(char *name) { static const cell valid_values[] = { 2,4,5,6,8,9 }; - ucell p[1]; + emit_outval p[1]; emit_param_index(&p[0],valid_values,(sizeof valid_values / sizeof valid_values[0])); outinstr(name,p,(sizeof p / sizeof p[0])); @@ -6328,22 +6330,15 @@ static void SC_FASTCALL emit_do_sctrl(char *name) static void SC_FASTCALL emit_do_call(char *name) { - char *funcname=NULL; + emit_outval p[1]; - emit_param_function((ucell *)&funcname,FALSE); - stgwrite("\t"); - stgwrite(name); - if (funcname!=NULL) { - stgwrite(" ."); - stgwrite(funcname); - } /* if */ - stgwrite("\n"); - code_idx+=opcodes(1)+opargs(1); + emit_param_function(&p[0],FALSE); + outinstr(name,p,(sizeof p / sizeof p[0])); } static void SC_FASTCALL emit_do_sysreq_c(char *name) { - ucell p[1]; + emit_outval p[1]; emit_param_function(&p[0],TRUE); @@ -6362,7 +6357,7 @@ static void SC_FASTCALL emit_do_sysreq_c(char *name) static void SC_FASTCALL emit_do_sysreq_n(char *name) { - ucell p[2]; + emit_outval p[2]; emit_param_function(&p[0],TRUE); emit_param_any(&p[1]); @@ -6378,14 +6373,14 @@ static void SC_FASTCALL emit_do_sysreq_n(char *name) } else { outinstr("push.c",&p[1],1); outinstr("sysreq.c",&p[0],1); - p[1]+=sizeof(cell); + p[1].value.ucell+=sizeof(cell); outinstr("stack",&p[1],1); } /* if */ } static void SC_FASTCALL emit_do_const(char *name) { - ucell p[2]; + emit_outval p[2]; emit_param_data(&p[0]); emit_param_any(&p[1]); @@ -6409,7 +6404,7 @@ static void SC_FASTCALL emit_do_const(char *name) static void SC_FASTCALL emit_do_const_s(char *name) { - ucell p[2]; + emit_outval p[2]; emit_param_local(&p[0]); emit_param_any(&p[1]); @@ -6433,7 +6428,7 @@ static void SC_FASTCALL emit_do_const_s(char *name) static void SC_FASTCALL emit_do_load_both(char *name) { - ucell p[2]; + emit_outval p[2]; emit_param_data(&p[0]); emit_param_data(&p[1]); @@ -6453,7 +6448,7 @@ static void SC_FASTCALL emit_do_load_both(char *name) static void SC_FASTCALL emit_do_load_s_both(char *name) { - ucell p[2]; + emit_outval p[2]; emit_param_local(&p[0]); emit_param_local(&p[1]); @@ -6473,7 +6468,7 @@ static void SC_FASTCALL emit_do_load_s_both(char *name) static void SC_FASTCALL emit_do_pushn_c(char *name) { - ucell p[5]; + emit_outval p[5]; int i,numargs; assert(name[0]=='p' && name[1]=='u' && name[2]=='s' @@ -6495,7 +6490,7 @@ static void SC_FASTCALL emit_do_pushn_c(char *name) static void SC_FASTCALL emit_do_pushn(char *name) { - ucell p[5]; + emit_outval p[5]; int i,numargs; assert(name[0]=='p' && name[1]=='u' && name[2]=='s' @@ -6517,7 +6512,7 @@ static void SC_FASTCALL emit_do_pushn(char *name) static void SC_FASTCALL emit_do_pushn_s_adr(char *name) { - ucell p[5]; + emit_outval p[5]; int i,numargs; assert(name[0]=='p' && name[1]=='u' && name[2]=='s' diff --git a/source/compiler/sc4.c b/source/compiler/sc4.c index 2d9e2b8..b335ddb 100644 --- a/source/compiler/sc4.c +++ b/source/compiler/sc4.c @@ -1379,19 +1379,28 @@ SC_FUNC void outval(cell val,int newline) } /* write an instruction with arguments */ -SC_FUNC void outinstr(const char *name,ucell args[],int numargs) +SC_FUNC void outinstr(const char *name, emit_outval params[],int numparams) { int i; stgwrite("\t"); stgwrite(name); - for (i=0; i Date: Wed, 31 Jan 2018 07:07:24 +0700 Subject: [PATCH 14/88] emit: Add new argument type: 'non-negative integer' --- source/compiler/sc.h | 5 ++-- source/compiler/sc1.c | 67 +++++++++++++++++++++++++++++++++++++++---- source/compiler/sc2.c | 2 +- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index 78bdd78..46ff20a 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -403,9 +403,10 @@ typedef struct s_valuepair { #define teLOCAL 341 /* local variable (name or offset) */ #define teFUNCTN 342 /* Pawn function */ #define teNATIVE 343 /* native function */ +#define teNONNEG 344 /* nonnegative integer */ /* for assigment to "lastst" only (see SC1.C) */ -#define tEXPR 344 -#define tENDLESS 345 /* endless loop */ +#define tEXPR 345 +#define tENDLESS 346 /* endless loop */ /* (reversed) evaluation of staging buffer */ #define sSTARTREORDER 0x01 diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index de2bba3..8132c18 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -6181,6 +6181,53 @@ fetchtok: error(50); /* invalid range */ } +static void SC_FASTCALL emit_param_nonneg(emit_outval *p) +{ + cell val; + char *str; + symbol *sym; + int tok,global; + + tok=lex(&val,&str); + switch (tok) { + case tNUMBER: + break; + case tSYMBOL: + global=FALSE; + sym=findloc(str); + if (sym==NULL) { + global=TRUE; + sym=findglb(str,sSTATEVAR); + } /* if */ + if (sym==NULL) { + error(17,str); /* undefined symbol */ + return; + } /* if */ + switch (sym->ident) { + case iCONSTEXPR: + break; + case iLABEL: + tok=tLABEL; + goto invalid_token; + case iFUNCTN: + case iREFFUNC: + tok=((sym->usage & uNATIVE)!=0) ? teNATIVE : teFUNCTN; + goto invalid_token; + default: + tok=(global==FALSE && sym->vclass!=sSTATIC) ? teLOCAL : teDATA; + goto invalid_token; + } /* switch */ + markusage(sym,uREAD); + default: + invalid_token: + emit_invalid_token(teNONNEG,tok); + return; + } /* switch */ + + p->type=eotNUMBER; + p->value.ucell=(ucell)val; +} + static void SC_FASTCALL emit_param_label(emit_outval *p) { cell val; @@ -6280,12 +6327,20 @@ static void SC_FASTCALL emit_parm1_label(char *name) outinstr(name,p,(sizeof p / sizeof p[0])); } +static void SC_FASTCALL emit_parm1_nonneg(char *name) +{ + emit_outval p[1]; + + emit_param_nonneg(&p[0]); + outinstr(name,p,(sizeof p / sizeof p[0])); +} + static void SC_FASTCALL emit_do_casetbl(char *name) { emit_outval p[2]; (void)name; - emit_param_any(&p[0]); + emit_param_nonneg(&p[0]); emit_param_label(&p[1]); stgwrite("\tcasetbl\n"); outinstr("case",p,(sizeof p / sizeof p[0])); @@ -6542,13 +6597,13 @@ static EMIT_OPCODE emit_opcodelist[] = { { 30, "align.alt", emit_parm1_any }, { 29, "align.pri", emit_parm1_any }, { 81, "and", emit_parm0 }, - {121, "bounds", emit_parm1_any }, + {121, "bounds", emit_parm1_nonneg }, {137, "break", emit_parm0 }, { 49, "call", emit_do_call }, { 50, "call.pri", emit_parm0 }, { 0, "case", emit_do_case }, {130, "casetbl", emit_do_casetbl }, - {118, "cmps", emit_parm1_any }, + {118, "cmps", emit_parm1_nonneg }, {156, "const", emit_do_const }, { 12, "const.alt", emit_parm1_any }, { 11, "const.pri", emit_parm1_any }, @@ -6561,10 +6616,10 @@ static EMIT_OPCODE emit_opcodelist[] = { { 95, "eq", emit_parm0 }, {106, "eq.c.alt", emit_parm1_any }, {105, "eq.c.pri", emit_parm1_any }, - {119, "fill", emit_parm1_any }, + {119, "fill", emit_parm1_nonneg }, {100, "geq", emit_parm0 }, { 99, "grtr", emit_parm0 }, - {120, "halt", emit_parm1_any }, + {120, "halt", emit_parm1_nonneg }, { 45, "heap", emit_parm1_any }, { 27, "idxaddr", emit_parm0 }, { 28, "idxaddr.b", emit_parm1_any }, @@ -6608,7 +6663,7 @@ static EMIT_OPCODE emit_opcodelist[] = { { 7, "lref.s.pri", emit_parm1_local }, { 34, "move.alt", emit_parm0 }, { 33, "move.pri", emit_parm0 }, - {117, "movs", emit_parm1_any }, + {117, "movs", emit_parm1_nonneg }, { 85, "neg", emit_parm0 }, { 96, "neq", emit_parm0 }, {134, "nop", emit_parm0 }, diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index 291d086..b32141a 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -2098,7 +2098,7 @@ char *sc_tokens[] = { ";", ";", "-integer value-", "-rational value-", "-identifier-", "-label-", "-string-", "-numeric value-", "-data offset-", "-local variable-", "-function-", - "-native function-" + "-native function-", "-nonnegative integer-" }; SC_FUNC int lex(cell *lexvalue,char **lexsym) From bc76324d03df8ffe7a0f87ab43a3021ff800e7ae Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Wed, 31 Jan 2018 07:46:27 +0700 Subject: [PATCH 15/88] emit: Check if the argument of 'shl.c.pri/alt' and 'shr.c.pri/alt' is in range from 0 to (sizeof(cell)*8-1) --- source/compiler/sc1.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 8132c18..3a773cb 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -6113,7 +6113,7 @@ static void SC_FASTCALL emit_param_local(emit_outval *p) } /* switch */ } -static void SC_FASTCALL emit_param_index(emit_outval *p,const cell *valid_values,int numvalues) +static void SC_FASTCALL emit_param_index(emit_outval *p,int isrange,const cell *valid_values,int numvalues) { cell val; char *str; @@ -6121,7 +6121,7 @@ static void SC_FASTCALL emit_param_index(emit_outval *p,const cell *valid_values int tok,i,global; int neg=FALSE; - assert(numvalues>0); + assert(isrange ? (numvalues==2) : (numvalues>0)); fetchtok: tok=lex(&val,&str); switch (tok) { @@ -6175,9 +6175,14 @@ fetchtok: p->type=eotNUMBER; p->value.ucell=(ucell)val; - for (i=0; i Date: Wed, 31 Jan 2018 19:15:10 +0700 Subject: [PATCH 16/88] emit: Allow the use of labels in arguments of type 'any' --- source/compiler/sc.h | 1 + source/compiler/sc1.c | 11 ++++++----- source/compiler/sc4.c | 3 +++ source/compiler/sc6.c | 8 +++++++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index 46ff20a..e38b147 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -478,6 +478,7 @@ typedef enum s_optmark { #define eotNUMBER 0 #define eotFUNCTION 1 +#define eotLABEL 2 typedef struct s_emit_outval { int type; union { diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 3a773cb..5d7ff97 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -5981,10 +5981,12 @@ fetchtok: break; } /* if */ if (sym->ident==iLABEL) { - tok=tLABEL; - goto invalid_token; - } /* if */ - if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { + if (neg!=FALSE) + goto invalid_token_neg; + sym->usage|=uREAD; + p->type=eotLABEL; + p->value.ucell=(ucell)sym->addr; + } else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { if (neg!=FALSE) goto invalid_token_neg; if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)==0 && sym->addr>=0) @@ -6024,7 +6026,6 @@ fetchtok: break; } /* if */ default: - invalid_token: emit_invalid_token(teNUMERIC,tok); } /* switch */ } diff --git a/source/compiler/sc4.c b/source/compiler/sc4.c index b335ddb..410f7a9 100644 --- a/source/compiler/sc4.c +++ b/source/compiler/sc4.c @@ -1390,6 +1390,9 @@ SC_FUNC void outinstr(const char *name, emit_outval params[],int numparams) stgwrite(" "); switch (params[i].type) { + case eotLABEL: + stgwrite("l."); + /* fallthrough */ case eotNUMBER: stgwrite(itoh(params[i].value.ucell)); break; diff --git a/source/compiler/sc6.c b/source/compiler/sc6.c index 0216f41..21b5806 100644 --- a/source/compiler/sc6.c +++ b/source/compiler/sc6.c @@ -102,7 +102,7 @@ static ucell getparam(const char *s,char **n) char name[sNAMEMAX+1]; symbol *sym; - if (*s=='.') { + if (s[0]=='.') { /* this is a function, find it in the global symbol table */ for (i=0; !isspace(*(++s)); i++) { assert(*s!='\0'); @@ -115,6 +115,12 @@ static ucell getparam(const char *s,char **n) assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC); assert(sym->vclass==sGLOBAL); result=sym->addr; + } else if (s[0]=='l' && s[1]=='.') { + /* this is a label */ + i=(int)hex2long(s+2,NULL); + assert(i>=0 && i Date: Thu, 1 Feb 2018 02:43:54 +0700 Subject: [PATCH 17/88] emit: Minor fixes/adjustments --- source/compiler/sc.h | 6 +++--- source/compiler/sc1.c | 41 +++++++++++++++++++++-------------------- source/compiler/sc6.c | 2 +- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index e38b147..15fa2da 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -476,9 +476,9 @@ typedef enum s_optmark { #define MAX_INSTR_LEN 30 -#define eotNUMBER 0 -#define eotFUNCTION 1 -#define eotLABEL 2 +#define eotNUMBER 0 +#define eotFUNCTION 1 +#define eotLABEL 2 typedef struct s_emit_outval { int type; union { diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 5d7ff97..dea9010 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -137,7 +137,6 @@ static void dostate(void); static void addwhile(int *ptr); static void delwhile(void); static int *readwhile(void); -static void doemit(void); typedef void (SC_FASTCALL *OPCODE_PROC)(char *name); typedef struct { @@ -5295,7 +5294,7 @@ static void statement(int *lastindent,int allow_decl) lexclr(FALSE); tok=lex(&val,&st); } /* case */ - /* drop through */ + /* fallthrough */ default: /* non-empty expression */ sc_allowproccall=optproccall; lexpush(); /* analyze token later */ @@ -5959,18 +5958,18 @@ static void SC_FASTCALL emit_param_any(emit_outval *p) cell val,cidx; symbol *sym; extern char *sc_tokens[]; - int tok,neg,ident,index; + int tok,negate,ident,index; - neg=FALSE; + negate=FALSE; p->type=eotNUMBER; fetchtok: tok=lex(&val,&str); switch (tok) { case tNUMBER: - p->value.ucell=(ucell)((neg!=FALSE) ? -val : val); + p->value.ucell=(ucell)(negate ? -val : val); break; case tRATIONAL: - p->value.ucell=(ucell)((neg!=FALSE) ? (val|((cell)1 << (PAWN_CELL_SIZE-1))) : val); + p->value.ucell=(ucell)(negate ? (val|((cell)1 << (PAWN_CELL_SIZE-1))) : val); break; case tSYMBOL: sym=findloc(str); @@ -5981,13 +5980,13 @@ fetchtok: break; } /* if */ if (sym->ident==iLABEL) { - if (neg!=FALSE) + if (negate) goto invalid_token_neg; sym->usage|=uREAD; p->type=eotLABEL; p->value.ucell=(ucell)sym->addr; } else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { - if (neg!=FALSE) + if (negate) goto invalid_token_neg; if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)==0 && sym->addr>=0) sym->addr=ntv_funcid++; @@ -5996,7 +5995,7 @@ fetchtok: p->value.string=str; } else { markusage(sym,uREAD | uWRITTEN); - p->value.ucell=(ucell)((neg!=FALSE) ? -sym->addr : sym->addr); + p->value.ucell=(ucell)(negate ? -sym->addr : sym->addr); } /* if */ break; case '(': @@ -6012,11 +6011,11 @@ fetchtok: if ((emit_flags & efEXPR)==0) stgset(FALSE); needtoken(')'); - p->value.ucell=(ucell)((neg!=FALSE) ? -val : val); + p->value.ucell=(ucell)(negate ? -val : val); break; case '-': - if (neg==FALSE) { - neg=TRUE; + if (!negate) { + negate=TRUE; goto fetchtok; } else { char ival[sNAMEMAX+2]; @@ -6120,18 +6119,18 @@ static void SC_FASTCALL emit_param_index(emit_outval *p,int isrange,const cell * char *str; symbol *sym; int tok,i,global; - int neg=FALSE; + int negate=FALSE; assert(isrange ? (numvalues==2) : (numvalues>0)); fetchtok: tok=lex(&val,&str); switch (tok) { case tNUMBER: - if (neg!=FALSE) + if (negate) val=-val; break; case tRATIONAL: - if (neg!=FALSE) + if (negate) val=val|((cell)1 << (PAWN_CELL_SIZE-1)); break; case tSYMBOL: @@ -6160,14 +6159,14 @@ fetchtok: goto invalid_token; } /* switch */ markusage(sym,uREAD); - val=(neg!=FALSE) ? -sym->addr : sym->addr; + val=negate ? -sym->addr : sym->addr; break; case '-': - if (neg==FALSE) { - neg=TRUE; + if (!negate) { + negate=TRUE; goto fetchtok; } /* if */ - /* drop through */ + /* fallthrough */ default: invalid_token: emit_invalid_token(teNUMERIC,tok); @@ -6224,6 +6223,8 @@ static void SC_FASTCALL emit_param_nonneg(emit_outval *p) goto invalid_token; } /* switch */ markusage(sym,uREAD); + val=sym->addr; + break; default: invalid_token: emit_invalid_token(teNONNEG,tok); @@ -6273,7 +6274,7 @@ static void SC_FASTCALL emit_param_function(emit_outval *p,int isnative) } else { tok=(sym->ident==iCONSTEXPR) ? teNUMERIC : teDATA; } /* if */ - /* drop through */ + /* fallthrough */ default: emit_invalid_token((isnative!=FALSE) ? teNATIVE : teFUNCTN,tok); return; diff --git a/source/compiler/sc6.c b/source/compiler/sc6.c index 21b5806..06e979e 100644 --- a/source/compiler/sc6.c +++ b/source/compiler/sc6.c @@ -444,7 +444,7 @@ static cell SC_FASTCALL do_dumpn(FILE *fbin,char *params,cell opcode) value=hex2long(params,¶ms); num=(int)hex2long(params,NULL); if (fbin!=NULL) - write_encoded_n(fbin,value,num); + write_encoded_n(fbin,value,num); return num*sizeof(cell); } From 7de402d997e81c5ef4a93cd8fcdf2861aac9e51c Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Sun, 4 Feb 2018 00:48:55 +0700 Subject: [PATCH 18/88] emit: Fix "extra characters on line" error on single-line 'emit{}' statements --- source/compiler/sc1.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index dea9010..ef76056 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -5285,7 +5285,6 @@ static void statement(int *lastindent,int allow_decl) extern char *sc_tokens[]; const unsigned char *bck_lptr=lptr-strlen(sc_tokens[tok-tFIRST]); if (matchtoken('{')) { - lexpush(); emit_flags |= efBLOCK; lastst=tEMIT; break; @@ -6808,7 +6807,7 @@ SC_FUNC void emit_parse_line(void) * and copy the instruction name */ lptr-=len; - for(i=0; i Date: Sun, 4 Feb 2018 18:20:12 +0700 Subject: [PATCH 19/88] emit: Add optional ':' prefix for labels as instruction arguments --- source/compiler/sc1.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index ef76056..1b52149 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -6012,6 +6012,15 @@ fetchtok: needtoken(')'); p->value.ucell=(ucell)(negate ? -val : val); break; + case ':': + tok=lex(&val,&str); + if (tok!=tSYMBOL) + emit_invalid_token(tSYMBOL,tok); + sym=fetchlab(str); + sym->usage|=uREAD; + p->type=eotLABEL; + p->value.ucell=(ucell)sym->addr; + break; case '-': if (!negate) { negate=TRUE; @@ -6242,12 +6251,23 @@ static void SC_FASTCALL emit_param_label(emit_outval *p) int tok; tok=lex(&val,&str); - if (tok!=tSYMBOL) - emit_invalid_token(tSYMBOL,tok); - sym=fetchlab(str); - sym->usage|=uREAD; - p->type=eotNUMBER; - p->value.ucell=(ucell)sym->addr; + switch (tok) + { + case ':': + tok=lex(&val,&str); + if (tok!=tSYMBOL) + emit_invalid_token(tSYMBOL,tok); + /* fallthrough */ + case tSYMBOL: + sym=fetchlab(str); + sym->usage|=uREAD; + p->type=eotNUMBER; + p->value.ucell=(ucell)sym->addr; + break; + default: + invalid_token: + emit_invalid_token(tSYMBOL, tok); + } } static void SC_FASTCALL emit_param_function(emit_outval *p,int isnative) From eb4f6ea6249007bba314967df981c4ce65d379dd Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Wed, 7 Feb 2018 17:47:12 +0700 Subject: [PATCH 20/88] emit: Remove duplicate code from 'emit_param_index()' and 'emit_param_nonneg()', reuse the code from 'emit_param_any()' instead --- source/compiler/sc1.c | 209 ++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 130 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 1b52149..ddf5377 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -5951,7 +5951,8 @@ static void SC_FASTCALL emit_invalid_token(int expected_token,int found_token) } /* if */ } -static void SC_FASTCALL emit_param_any(emit_outval *p) +static int SC_FASTCALL emit_param_any_internal(emit_outval *p,int expected_tok, + int allow_nonint,int allow_expr) { char *str; cell val,cidx; @@ -5968,6 +5969,8 @@ fetchtok: p->value.ucell=(ucell)(negate ? -val : val); break; case tRATIONAL: + if (!allow_nonint) + goto invalid_token; p->value.ucell=(ucell)(negate ? (val|((cell)1 << (PAWN_CELL_SIZE-1))) : val); break; case tSYMBOL: @@ -5976,46 +5979,64 @@ fetchtok: sym=findglb(str,sSTATEVAR); if (sym==NULL || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC && (sym->usage & uDEFINE)==0)) { error(17,str); /* undefined symbol */ - break; + return FALSE; } /* if */ if (sym->ident==iLABEL) { if (negate) goto invalid_token_neg; + if (!allow_nonint) { + tok=tLABEL; + goto invalid_token; + } /* if */ sym->usage|=uREAD; p->type=eotLABEL; p->value.ucell=(ucell)sym->addr; } else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { if (negate) goto invalid_token_neg; + if (!allow_nonint) { + tok=(sym->usage & uNATIVE) ? teNATIVE : teFUNCTN; + goto invalid_token; + } /* if */ if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)==0 && sym->addr>=0) sym->addr=ntv_funcid++; markusage(sym,uREAD); p->type=eotFUNCTION; p->value.string=str; } else { + if (!allow_nonint && sym->ident!=iCONSTEXPR) { + tok=(sym->vclass==sLOCAL) ? teLOCAL : teDATA; + goto invalid_token; + } /* if */ markusage(sym,uREAD | uWRITTEN); p->value.ucell=(ucell)(negate ? -sym->addr : sym->addr); } /* if */ break; case '(': + if (!allow_expr) + goto invalid_token; if ((emit_flags & efEXPR)==0) stgset(TRUE); stgget(&index,&cidx); errorset(sEXPRMARK,0); ident=expression(&val,NULL,NULL,FALSE); - if (ident!=iCONSTEXPR) - error(8); /* must be constant expression */ errorset(sEXPRRELEASE,0); stgdel(index,cidx); if ((emit_flags & efEXPR)==0) stgset(FALSE); needtoken(')'); p->value.ucell=(ucell)(negate ? -val : val); + if (ident!=iCONSTEXPR) { + error(8); /* must be constant expression */ + return FALSE; + } /* if */ break; case ':': tok=lex(&val,&str); - if (tok!=tSYMBOL) + if (tok!=tSYMBOL) { emit_invalid_token(tSYMBOL,tok); + return FALSE; + } /* if */ sym=fetchlab(str); sym->usage|=uREAD; p->type=eotLABEL; @@ -6029,12 +6050,62 @@ fetchtok: char ival[sNAMEMAX+2]; invalid_token_neg: sprintf(ival,"-%s",str); - error(1,sc_tokens[teNUMERIC-tFIRST],ival); - break; + error(1,sc_tokens[expected_tok-tFIRST],ival); + return FALSE; } /* if */ default: - emit_invalid_token(teNUMERIC,tok); + invalid_token: + emit_invalid_token(expected_tok,tok); + return FALSE; } /* switch */ + return TRUE; +} + +static void SC_FASTCALL emit_param_any(emit_outval *p) +{ + emit_param_any_internal(p,teNUMERIC,TRUE,TRUE); +} + +static void SC_FASTCALL emit_param_index(emit_outval *p,int isrange,const cell *valid_values,int numvalues) +{ + int i; + cell val; + + assert(isrange ? (numvalues==2) : (numvalues>0)); + if (!emit_param_any_internal(p,tNUMBER,FALSE,FALSE)) + return; + val=(cell)p->value.ucell; + if (isrange) { + if (valid_values[0]<=val && val<=valid_values[1]) + return; + } else { + for (i=0; ivalue.ucell<(cell)0) { + extern char *sc_tokens[]; +#if PAWN_CELL_SIZE==16 + char ival[7]; + sprintf(ival,"%ld",(long)p->value.ucell); +#elif PAWN_CELL_SIZE==32 + char ival[12]; + sprintf(ival,"%ld",(long)p->value.ucell); +#elif PAWN_CELL_SIZE==64 + char ival[21]; + sprintf(ival,"%lld",(long long)p->value.ucell); +#else + #error Unsupported cell size +#endif + error(1,sc_tokens[teNONNEG-tFIRST],ival); + } /* if */ } static void SC_FASTCALL emit_param_data(emit_outval *p) @@ -6121,128 +6192,6 @@ static void SC_FASTCALL emit_param_local(emit_outval *p) } /* switch */ } -static void SC_FASTCALL emit_param_index(emit_outval *p,int isrange,const cell *valid_values,int numvalues) -{ - cell val; - char *str; - symbol *sym; - int tok,i,global; - int negate=FALSE; - - assert(isrange ? (numvalues==2) : (numvalues>0)); -fetchtok: - tok=lex(&val,&str); - switch (tok) { - case tNUMBER: - if (negate) - val=-val; - break; - case tRATIONAL: - if (negate) - val=val|((cell)1 << (PAWN_CELL_SIZE-1)); - break; - case tSYMBOL: - global=FALSE; - sym=findloc(str); - if (sym==NULL) { - global=TRUE; - sym=findglb(str,sSTATEVAR); - } /* if */ - if (sym==NULL) { - error(17,str); /* undefined symbol */ - return; - } /* if */ - switch (sym->ident) { - case iCONSTEXPR: - break; - case iLABEL: - tok=tLABEL; - goto invalid_token; - case iFUNCTN: - case iREFFUNC: - tok=((sym->usage & uNATIVE)!=0) ? teNATIVE : teFUNCTN; - goto invalid_token; - default: - tok=(global==FALSE && sym->vclass!=sSTATIC) ? teLOCAL : teDATA; - goto invalid_token; - } /* switch */ - markusage(sym,uREAD); - val=negate ? -sym->addr : sym->addr; - break; - case '-': - if (!negate) { - negate=TRUE; - goto fetchtok; - } /* if */ - /* fallthrough */ - default: - invalid_token: - emit_invalid_token(teNUMERIC,tok); - return; - } /* switch */ - - p->type=eotNUMBER; - p->value.ucell=(ucell)val; - if (isrange) { - if (valid_values[0]<=val && val<=valid_values[1]) - return; - } else { - for (i=0; iident) { - case iCONSTEXPR: - break; - case iLABEL: - tok=tLABEL; - goto invalid_token; - case iFUNCTN: - case iREFFUNC: - tok=((sym->usage & uNATIVE)!=0) ? teNATIVE : teFUNCTN; - goto invalid_token; - default: - tok=(global==FALSE && sym->vclass!=sSTATIC) ? teLOCAL : teDATA; - goto invalid_token; - } /* switch */ - markusage(sym,uREAD); - val=sym->addr; - break; - default: - invalid_token: - emit_invalid_token(teNONNEG,tok); - return; - } /* switch */ - - p->type=eotNUMBER; - p->value.ucell=(ucell)val; -} - static void SC_FASTCALL emit_param_label(emit_outval *p) { cell val; From 3c252211f0453ce4cf59c76c6b84c6ddfaa2cb65 Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Wed, 7 Feb 2018 22:42:49 +0700 Subject: [PATCH 21/88] emit: Minor adjustments --- source/compiler/sc.h | 2 +- source/compiler/sc1.c | 65 +++++++++++++++++++++++-------------------- source/compiler/sc4.c | 2 +- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index 15fa2da..f1382e7 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -711,7 +711,7 @@ SC_FUNC void dec(value *lval); SC_FUNC void jmp_ne0(int number); SC_FUNC void jmp_eq0(int number); SC_FUNC void outval(cell val,int newline); -SC_FUNC void outinstr(const char *name, emit_outval params[],int numparams); +SC_FUNC void outinstr(const char *name,emit_outval params[],int numparams); /* function prototypes in SC5.C */ SC_FUNC int error(int number,...); diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index ddf5377..44b33ab 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -5957,7 +5957,6 @@ static int SC_FASTCALL emit_param_any_internal(emit_outval *p,int expected_tok, char *str; cell val,cidx; symbol *sym; - extern char *sc_tokens[]; int tok,negate,ident,index; negate=FALSE; @@ -5982,16 +5981,17 @@ fetchtok: return FALSE; } /* if */ if (sym->ident==iLABEL) { + sym->usage|=uREAD; if (negate) goto invalid_token_neg; if (!allow_nonint) { tok=tLABEL; goto invalid_token; } /* if */ - sym->usage|=uREAD; p->type=eotLABEL; p->value.ucell=(ucell)sym->addr; } else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { + markusage(sym,uREAD); if (negate) goto invalid_token_neg; if (!allow_nonint) { @@ -6000,15 +6000,14 @@ fetchtok: } /* if */ if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)==0 && sym->addr>=0) sym->addr=ntv_funcid++; - markusage(sym,uREAD); p->type=eotFUNCTION; p->value.string=str; } else { + markusage(sym,uREAD | uWRITTEN); if (!allow_nonint && sym->ident!=iCONSTEXPR) { tok=(sym->vclass==sLOCAL) ? teLOCAL : teDATA; goto invalid_token; } /* if */ - markusage(sym,uREAD | uWRITTEN); p->value.ucell=(ucell)(negate ? -sym->addr : sym->addr); } /* if */ break; @@ -6047,6 +6046,7 @@ fetchtok: negate=TRUE; goto fetchtok; } else { + extern char *sc_tokens[]; char ival[sNAMEMAX+2]; invalid_token_neg: sprintf(ival,"-%s",str); @@ -6124,6 +6124,7 @@ static void SC_FASTCALL emit_param_data(emit_outval *p) case tSYMBOL: sym=findloc(str); if (sym!=NULL) { + markusage(sym,uREAD | uWRITTEN); if (sym->ident==iLABEL) { tok=tLABEL; goto invalid_token; @@ -6138,12 +6139,12 @@ static void SC_FASTCALL emit_param_data(emit_outval *p) error(17,str); /* undefined symbol */ break; } /* if */ + markusage(sym,uREAD | uWRITTEN); if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { tok=((sym->usage & uNATIVE)!=0) ? teNATIVE : teFUNCTN; goto invalid_token; } /* if */ } /* if */ - markusage(sym,uREAD | uWRITTEN); p->value.ucell=(ucell)sym->addr; break; default: @@ -6168,6 +6169,7 @@ static void SC_FASTCALL emit_param_local(emit_outval *p) case tSYMBOL: sym=findloc(str); if (sym!=NULL) { + markusage(sym,uREAD | uWRITTEN); if (sym->ident==iLABEL) { tok=tLABEL; goto invalid_token; @@ -6178,12 +6180,15 @@ static void SC_FASTCALL emit_param_local(emit_outval *p) } /* if */ } else { sym=findglb(str,sSTATEVAR); - if (sym==NULL || sym->ident!=iCONSTEXPR) { + if (sym==NULL) { + undefined_sym: error(17,str); /* undefined symbol */ break; } /* if */ + markusage(sym,uREAD | uWRITTEN); + if (sym->ident!=iCONSTEXPR) + goto undefined_sym; } /* if */ - markusage(sym,uREAD | uWRITTEN); p->value.ucell=(ucell)sym->addr; break; default: @@ -6199,23 +6204,23 @@ static void SC_FASTCALL emit_param_label(emit_outval *p) symbol *sym; int tok; + p->type=eotNUMBER; tok=lex(&val,&str); switch (tok) { case ':': tok=lex(&val,&str); if (tok!=tSYMBOL) - emit_invalid_token(tSYMBOL,tok); + goto invalid_token; /* fallthrough */ case tSYMBOL: sym=fetchlab(str); sym->usage|=uREAD; - p->type=eotNUMBER; p->value.ucell=(ucell)sym->addr; break; default: invalid_token: - emit_invalid_token(tSYMBOL, tok); + emit_invalid_token(tSYMBOL,tok); } } @@ -6226,6 +6231,7 @@ static void SC_FASTCALL emit_param_function(emit_outval *p,int isnative) symbol *sym; int tok; + p->type=eotNUMBER; tok=lex(&val,&str); switch (tok) { @@ -6235,6 +6241,7 @@ static void SC_FASTCALL emit_param_function(emit_outval *p,int isnative) error(17,str); /* undefined symbol */ return; } /* if */ + markusage(sym,uREAD); if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { if (!!(sym->usage & uNATIVE)==isnative) break; @@ -6251,13 +6258,11 @@ static void SC_FASTCALL emit_param_function(emit_outval *p,int isnative) if (isnative!=FALSE) { if ((sym->usage & uREAD)==0 && sym->addr>=0) sym->addr=ntv_funcid++; - p->type=eotNUMBER; p->value.ucell=(ucell)sym->addr; } else { p->type=eotFUNCTION; p->value.string=str; } /* if */ - markusage(sym,uREAD); } static void SC_FASTCALL emit_noop(char *name) @@ -6278,6 +6283,23 @@ static void SC_FASTCALL emit_parm1_any(char *name) outinstr(name,p,(sizeof p / sizeof p[0])); } +static void SC_FASTCALL emit_parm1_nonneg(char *name) +{ + emit_outval p[1]; + + emit_param_nonneg(&p[0]); + outinstr(name,p,(sizeof p / sizeof p[0])); +} + +static void SC_FASTCALL emit_parm1_shift(char *name) +{ + static const cell valid_values[] = { 0,sizeof(cell)*8-1 }; + emit_outval p[1]; + + emit_param_index(&p[0],TRUE,valid_values,(sizeof valid_values / sizeof valid_values[0])); + outinstr(name,p,(sizeof p / sizeof p[0])); +} + static void SC_FASTCALL emit_parm1_data(char *name) { emit_outval p[1]; @@ -6302,23 +6324,6 @@ static void SC_FASTCALL emit_parm1_label(char *name) outinstr(name,p,(sizeof p / sizeof p[0])); } -static void SC_FASTCALL emit_parm1_nonneg(char *name) -{ - emit_outval p[1]; - - emit_param_nonneg(&p[0]); - outinstr(name,p,(sizeof p / sizeof p[0])); -} - -static void SC_FASTCALL emit_parm1_shift(char *name) -{ - static const cell valid_values[] = { 0,sizeof(cell)*8-1 }; - emit_outval p[1]; - - emit_param_index(&p[0],TRUE,valid_values,(sizeof valid_values / sizeof valid_values[0])); - outinstr(name,p,(sizeof p / sizeof p[0])); -} - static void SC_FASTCALL emit_do_casetbl(char *name) { emit_outval p[2]; @@ -6757,12 +6762,12 @@ static int emit_findopcode(const char *instr,int maxlen) SC_FUNC void emit_parse_line(void) { + extern char *sc_tokens[]; cell val; char* st; int tok,len,i; symbol *sym; char name[MAX_INSTR_LEN]; - extern char *sc_tokens[]; tok=tokeninfo(&val,&st); if (tok==tSYMBOL || (tok>tMIDDLE && tok<=tLAST)) { diff --git a/source/compiler/sc4.c b/source/compiler/sc4.c index 410f7a9..8a39ab9 100644 --- a/source/compiler/sc4.c +++ b/source/compiler/sc4.c @@ -1379,7 +1379,7 @@ SC_FUNC void outval(cell val,int newline) } /* write an instruction with arguments */ -SC_FUNC void outinstr(const char *name, emit_outval params[],int numparams) +SC_FUNC void outinstr(const char *name,emit_outval params[],int numparams) { int i; From 7a0e966edf3483beb67f8b7cac44f1a259cc45e0 Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Thu, 8 Feb 2018 00:30:06 +0700 Subject: [PATCH 22/88] emit: Add new argument type: 'integer value' --- source/compiler/sc1.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 44b33ab..0d89c7f 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -6066,6 +6066,11 @@ static void SC_FASTCALL emit_param_any(emit_outval *p) emit_param_any_internal(p,teNUMERIC,TRUE,TRUE); } +static void SC_FASTCALL emit_param_integer(emit_outval *p) +{ + emit_param_any_internal(p,teNUMERIC,FALSE,TRUE); +} + static void SC_FASTCALL emit_param_index(emit_outval *p,int isrange,const cell *valid_values,int numvalues) { int i; @@ -6283,6 +6288,14 @@ static void SC_FASTCALL emit_parm1_any(char *name) outinstr(name,p,(sizeof p / sizeof p[0])); } +static void SC_FASTCALL emit_parm1_integer(char *name) +{ + emit_outval p[1]; + + emit_param_integer(&p[0]); + outinstr(name,p,(sizeof p / sizeof p[0])); +} + static void SC_FASTCALL emit_parm1_nonneg(char *name) { emit_outval p[1]; @@ -6586,7 +6599,7 @@ static EMIT_OPCODE emit_opcodelist[] = { { 30, "align.alt", emit_parm1_any }, { 29, "align.pri", emit_parm1_any }, { 81, "and", emit_parm0 }, - {121, "bounds", emit_parm1_nonneg }, + {121, "bounds", emit_parm1_integer }, {137, "break", emit_parm0 }, { 49, "call", emit_do_call }, { 50, "call.pri", emit_parm0 }, @@ -6609,7 +6622,7 @@ static EMIT_OPCODE emit_opcodelist[] = { {100, "geq", emit_parm0 }, { 99, "grtr", emit_parm0 }, {120, "halt", emit_parm1_nonneg }, - { 45, "heap", emit_parm1_any }, + { 45, "heap", emit_parm1_integer }, { 27, "idxaddr", emit_parm0 }, { 28, "idxaddr.b", emit_parm1_any }, {109, "inc", emit_parm1_data }, @@ -6666,7 +6679,7 @@ static EMIT_OPCODE emit_opcodelist[] = { { 37, "push.alt", emit_parm0 }, { 39, "push.c", emit_parm1_any }, { 36, "push.pri", emit_parm0 }, - { 38, "push.r", emit_parm1_any }, + { 38, "push.r", emit_parm1_integer }, { 41, "push.s", emit_parm1_local }, {139, "push2", emit_do_pushn }, {141, "push2.adr", emit_do_pushn_s_adr }, @@ -6702,13 +6715,13 @@ static EMIT_OPCODE emit_opcodelist[] = { {102, "sleq", emit_parm0 }, {101, "sless", emit_parm0 }, { 72, "smul", emit_parm0 }, - { 88, "smul.c", emit_parm1_any }, + { 88, "smul.c", emit_parm1_integer }, { 20, "sref.alt", emit_parm1_data }, { 19, "sref.pri", emit_parm1_data }, { 22, "sref.s.alt", emit_parm1_local }, { 21, "sref.s.pri", emit_parm1_local }, { 67, "sshr", emit_parm0 }, - { 44, "stack", emit_parm1_any }, + { 44, "stack", emit_parm1_integer }, { 16, "stor.alt", emit_parm1_data }, { 23, "stor.i", emit_parm0 }, { 15, "stor.pri", emit_parm1_data }, From 78f69596300e5fd14bbf453875a7c7d50da6dfad Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Thu, 8 Feb 2018 00:50:05 +0700 Subject: [PATCH 23/88] emit: Change the argument type in 'lidx.b' and 'idxaddr.b' to 'shift' --- source/compiler/sc1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 0d89c7f..93a2d2f 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -6624,7 +6624,7 @@ static EMIT_OPCODE emit_opcodelist[] = { {120, "halt", emit_parm1_nonneg }, { 45, "heap", emit_parm1_integer }, { 27, "idxaddr", emit_parm0 }, - { 28, "idxaddr.b", emit_parm1_any }, + { 28, "idxaddr.b", emit_parm1_shift }, {109, "inc", emit_parm1_data }, {108, "inc.alt", emit_parm0 }, {111, "inc.i", emit_parm0 }, @@ -6650,7 +6650,7 @@ static EMIT_OPCODE emit_opcodelist[] = { { 98, "leq", emit_parm0 }, { 97, "less", emit_parm0 }, { 25, "lidx", emit_parm0 }, - { 26, "lidx.b", emit_parm1_any }, + { 26, "lidx.b", emit_parm1_shift }, { 2, "load.alt", emit_parm1_data }, {154, "load.both", emit_do_load_both }, { 9, "load.i", emit_parm0 }, From b0026d8ce65028e19d15d58ddea0c7af00765a58 Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Sun, 11 Feb 2018 20:54:51 +0700 Subject: [PATCH 24/88] emit: Check if the argument of 'align.pri/alt' is in range from 0 to (sizeof(cell)-1) --- source/compiler/sc1.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 93a2d2f..432c997 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -6367,6 +6367,15 @@ static void SC_FASTCALL emit_do_lodb_strb(char *name) outinstr(name,p,(sizeof p / sizeof p[0])); } +static void SC_FASTCALL emit_do_align(char *name) +{ + static const cell valid_values[] = { 0,sizeof(cell)-1 }; + emit_outval p[1]; + + emit_param_index(&p[0],TRUE,valid_values,(sizeof valid_values / sizeof valid_values[0])); + outinstr(name,p,(sizeof p / sizeof p[0])); +} + static void SC_FASTCALL emit_do_lctrl(char *name) { static const cell valid_values[] = { 0,9 }; @@ -6596,8 +6605,8 @@ static EMIT_OPCODE emit_opcodelist[] = { { 87, "add.c", emit_parm1_any }, { 14, "addr.alt", emit_parm1_local }, { 13, "addr.pri", emit_parm1_local }, - { 30, "align.alt", emit_parm1_any }, - { 29, "align.pri", emit_parm1_any }, + { 30, "align.alt", emit_do_align }, + { 29, "align.pri", emit_do_align }, { 81, "and", emit_parm0 }, {121, "bounds", emit_parm1_integer }, {137, "break", emit_parm0 }, @@ -6751,10 +6760,7 @@ static int emit_findopcode(const char *instr,int maxlen) { int low,high,mid,cmp; - /* look up the instruction with a binary search - * the assembler is case insensitive to instructions (but case sensitive - * to symbols) - */ + /* look up the instruction with a binary search */ low=1; /* entry 0 is reserved (for "not found") */ high=(sizeof emit_opcodelist / sizeof emit_opcodelist[0])-1; while (low Date: Sun, 11 Feb 2018 23:15:26 +0700 Subject: [PATCH 25/88] emit: Make the compiler tell it expects "any value" for arguments of type 'any' --- source/compiler/sc.h | 17 +++++++++-------- source/compiler/sc1.c | 2 +- source/compiler/sc2.c | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index f1382e7..92ba3c2 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -398,15 +398,16 @@ typedef struct s_valuepair { #define tLABEL 337 #define tSTRING 338 /* argument types for emit/__emit */ -#define teNUMERIC 339 /* integer/rational number */ -#define teDATA 340 /* data (variable name or address) */ -#define teLOCAL 341 /* local variable (name or offset) */ -#define teFUNCTN 342 /* Pawn function */ -#define teNATIVE 343 /* native function */ -#define teNONNEG 344 /* nonnegative integer */ +#define teANY 339 /* any value */ +#define teNUMERIC 340 /* integer/rational number */ +#define teDATA 341 /* data (variable name or address) */ +#define teLOCAL 342 /* local variable (name or offset) */ +#define teFUNCTN 343 /* Pawn function */ +#define teNATIVE 344 /* native function */ +#define teNONNEG 345 /* nonnegative integer */ /* for assigment to "lastst" only (see SC1.C) */ -#define tEXPR 345 -#define tENDLESS 346 /* endless loop */ +#define tEXPR 346 +#define tENDLESS 347 /* endless loop */ /* (reversed) evaluation of staging buffer */ #define sSTARTREORDER 0x01 diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 432c997..602d8c7 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -6063,7 +6063,7 @@ fetchtok: static void SC_FASTCALL emit_param_any(emit_outval *p) { - emit_param_any_internal(p,teNUMERIC,TRUE,TRUE); + emit_param_any_internal(p,teANY,TRUE,TRUE); } static void SC_FASTCALL emit_param_integer(emit_outval *p) diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index b32141a..66b84d7 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -2097,8 +2097,8 @@ char *sc_tokens[] = { "#tryinclude", "#undef", "#warning", ";", ";", "-integer value-", "-rational value-", "-identifier-", "-label-", "-string-", - "-numeric value-", "-data offset-", "-local variable-", "-function-", - "-native function-", "-nonnegative integer-" + "-any value-", "-numeric value-", "-data offset-", "-local variable-", + "-function-", "-native function-", "-nonnegative integer-" }; SC_FUNC int lex(cell *lexvalue,char **lexsym) From 900043e6950855b177d2718abaffd0a8c4663fd0 Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Mon, 12 Feb 2018 02:30:21 +0700 Subject: [PATCH 26/88] emit: Apply 'integer value' type to the argument of 'jrel' --- source/compiler/sc1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 602d8c7..2ae98f4 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -6068,7 +6068,7 @@ static void SC_FASTCALL emit_param_any(emit_outval *p) static void SC_FASTCALL emit_param_integer(emit_outval *p) { - emit_param_any_internal(p,teNUMERIC,FALSE,TRUE); + emit_param_any_internal(p,tNUMBER,FALSE,TRUE); } static void SC_FASTCALL emit_param_index(emit_outval *p,int isrange,const cell *valid_values,int numvalues) @@ -6647,7 +6647,7 @@ static EMIT_OPCODE emit_opcodelist[] = { { 57, "jless", emit_parm1_label }, { 56, "jneq", emit_parm1_label }, { 54, "jnz", emit_parm1_label }, - { 52, "jrel", emit_parm1_any }, + { 52, "jrel", emit_parm1_integer }, { 64, "jsgeq", emit_parm1_label }, { 63, "jsgrtr", emit_parm1_label }, { 62, "jsleq", emit_parm1_label }, From 9ca1b4a61e80a10bcd28d7e399a9de899599e115 Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Thu, 22 Feb 2018 03:22:21 +0700 Subject: [PATCH 27/88] Redo constvalue list optimisation --- source/compiler/sc.h | 20 ++--- source/compiler/sc1.c | 160 ++++++++++++++++++++------------------ source/compiler/sc2.c | 10 +-- source/compiler/sc3.c | 4 +- source/compiler/sc4.c | 12 +-- source/compiler/sc6.c | 20 ++--- source/compiler/scstate.c | 10 +-- source/compiler/scvars.c | 8 +- 8 files changed, 126 insertions(+), 118 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index b9e16ea..60e993b 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -114,7 +114,7 @@ typedef struct s_constvalue { } constvalue; typedef struct s_constvalue_root { - constvalue *next,*last; + constvalue *first,*last; } constvalue_root; /* Symbol table format @@ -152,13 +152,13 @@ typedef struct s_symbol { } x; /* 'x' for 'extra' */ union { arginfo *arglist; /* types of all parameters for functions */ - constvalue *enumlist;/* list of names for the "root" of an enumeration */ + constvalue_root *enumlist;/* list of names for the "root" of an enumeration */ struct { cell length; /* arrays: length (size) */ short level; /* number of dimensions below this level */ } array; } dim; /* for 'dimension', both functions and arrays */ - constvalue *states; /* list of state function/state variable ids + addresses */ + constvalue_root *states;/* list of state function/state variable ids + addresses */ int fnumber; /* static global variables: file number in which the declaration is visible */ int lnumber; /* line number (in the current source file) for the declaration */ struct s_symbol **refer; /* referrer list, functions that "use" this symbol */ @@ -555,9 +555,9 @@ SC_FUNC symbol *fetchfunc(char *name,int tag); SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag); SC_FUNC char *funcdisplayname(char *dest,char *funcname); SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr); -SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index); -SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index); -SC_FUNC void delete_consttable(constvalue *table); +SC_FUNC constvalue *append_constval(constvalue_root *table,const char *name,cell val,int index); +SC_FUNC constvalue *find_constval(constvalue_root *table,char *name,int index); +SC_FUNC void delete_consttable(constvalue_root *table); SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag); SC_FUNC symbol *add_builtin_constant(char *name,cell val,int vclass,int tag); SC_FUNC symbol *add_builtin_string_constant(char *name,const char *val,int vclass); @@ -802,8 +802,8 @@ SC_VDECL symbol *line_sym; SC_VDECL cell *litq; /* the literal queue */ SC_VDECL unsigned char pline[]; /* the line read from the input file */ SC_VDECL const unsigned char *lptr;/* points to the current position in "pline" */ -SC_VDECL constvalue tagname_tab;/* tagname table */ -SC_VDECL constvalue libname_tab;/* library table (#pragma library "..." syntax) */ +SC_VDECL constvalue_root tagname_tab;/* tagname table */ +SC_VDECL constvalue_root libname_tab;/* library table (#pragma library "..." syntax) */ SC_VDECL constvalue *curlibrary;/* current library */ SC_VDECL int pc_addlibtable; /* is the library table added to the AMX file? */ SC_VDECL symbol *curfunc; /* pointer to current function */ @@ -860,8 +860,8 @@ SC_VDECL int pc_naked; /* if true mark following function as naked */ SC_VDECL int pc_compat; /* running in compatibility mode? */ SC_VDECL int pc_recursion; /* enable detailed recursion report? */ -SC_VDECL constvalue sc_automaton_tab; /* automaton table */ -SC_VDECL constvalue sc_state_tab; /* state table */ +SC_VDECL constvalue_root sc_automaton_tab; /* automaton table */ +SC_VDECL constvalue_root sc_state_tab; /* state table */ SC_VDECL FILE *inpf; /* file read from (source or include) */ SC_VDECL FILE *inpf_org; /* main source file */ diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 0192d91..463ec3e 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -92,14 +92,14 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic, static int declloc(int fstatic); static void decl_const(int table); static void decl_enum(int table,int fstatic); -static cell needsub(int *tag,constvalue **enumroot); +static cell needsub(int *tag,constvalue_root **enumroot); static void initials(int ident,int tag,cell *size,int dim[],int numdim, - constvalue *enumroot); + constvalue_root *enumroot); static cell initarray(int ident,int tag,int dim[],int numdim,int cur, - int startlit,int counteddim[],constvalue *lastdim, - constvalue *enumroot,int *errorfound); + int startlit,int counteddim[],constvalue_root *lastdim, + constvalue_root *enumroot,int *errorfound); static cell initvector(int ident,int tag,cell size,int startlit,int fillzero, - constvalue *enumroot,int *errorfound); + constvalue_root *enumroot,int *errorfound); static cell init(int ident,int *tag,int *errorfound); static int getstates(const char *funcname); static void attachstatelist(symbol *sym, int state_id); @@ -113,7 +113,7 @@ static void reduce_referrers(symbol *root); static long max_stacksize(symbol *root,int *recursion); static int testsymbols(symbol *root,int level,int testlabs,int testconst); static void destructsymbols(symbol *root,int level); -static constvalue *find_constval_byval(constvalue *table,cell val); +static constvalue *find_constval_byval(constvalue_root *table,cell val); static symbol *fetchlab(char *name); static void statement(int *lastindent,int allow_decl); static void compound(int stmt_sameline,int starttok); @@ -842,7 +842,7 @@ int pc_addtag(char *name) assert(strchr(name,':')==NULL); /* colon should already have been stripped */ last=0; - ptr=tagname_tab.next; + ptr=tagname_tab.first; while (ptr!=NULL) { tag=(int)(ptr->value & TAGMASK); if (strcmp(name,ptr->name)==0) @@ -938,8 +938,8 @@ static void initglobals(void) glbtab.next=NULL; /* clear global variables/constants table */ loctab.next=NULL; /* " local " / " " */ hashtable_init(&symbol_cache_ht, sizeof(symbol *),(16384/3*2),NULL); /* 16384 slots */ - tagname_tab.next=NULL; /* tagname table */ - libname_tab.next=NULL; /* library table (#pragma library "..." syntax) */ + tagname_tab.first=tagname_tab.last=NULL; /* tagname table */ + libname_tab.first=libname_tab.last=NULL; /* library table (#pragma library "..." syntax) */ pline[0]='\0'; /* the line read from the input file */ lptr=NULL; /* points to the current position in "pline" */ @@ -1983,7 +1983,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst int numdim; short filenum; symbol *sym; - constvalue *enumroot; + constvalue_root *enumroot; #if !defined NDEBUG cell glbdecl=0; #endif @@ -2054,11 +2054,11 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst */ assert(sym==NULL || sym->states==NULL && sc_curstates==0 - || sym->states!=NULL && sym->next!=NULL && sym->states->next->index==sc_curstates); + || sym->states!=NULL && sym->next!=NULL && sym->states->first->index==sc_curstates); /* a state variable may only have a single id in its list (so either this * variable has no states, or it has a single list) */ - assert(sym==NULL || sym->states==NULL || sym->states->next->next==NULL); + assert(sym==NULL || sym->states==NULL || sym->states->first->next==NULL); /* it is okay for the (global) variable to exist, as long as it belongs to * a different automaton */ @@ -2116,7 +2116,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst continue; /* a function or a constant */ if ((sweep->usage & uDEFINE)==0) continue; /* undefined variable, ignore */ - if (fsa!=state_getfsa(sweep->states->next->index)) + if (fsa!=state_getfsa(sweep->states->first->index)) continue; /* wrong automaton */ /* when arrived here, this is a global variable, with states and * belonging to the same automaton as the variable we are declaring @@ -2138,7 +2138,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst continue; /* a function or a constant */ if ((sweep->usage & uDEFINE)==0) continue; /* undefined variable, ignore */ - if (fsa!=state_getfsa(sweep->states->next->index)) + if (fsa!=state_getfsa(sweep->states->first->index)) continue; /* wrong automaton */ /* when arrived here, this is a global variable, with states and * belonging to the same automaton as the variable we are declaring @@ -2147,7 +2147,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst * variable have a non-empty intersection, this is not a suitable * overlap point -> wipe the address range */ - if (state_conflict_id(sc_curstates,sweep->states->next->index)) { + if (state_conflict_id(sc_curstates,sweep->states->first->index)) { sweepsize=(sweep->ident==iVARIABLE) ? 1 : array_totalsize(sweep); assert(sweep->addr % sizeof(cell) == 0); addr=sweep->addr/sizeof(cell); @@ -2194,7 +2194,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst attachstatelist(sym,sc_curstates); } else { /* if declared but not yet defined, adjust the variable's address */ assert(sym->states==NULL && sc_curstates==0 - || sym->states->next!=NULL && sym->states->next->index==sc_curstates && sym->states->next->next==NULL); + || sym->states->first!=NULL && sym->states->first->index==sc_curstates && sym->states->first->next==NULL); sym->addr=address; sym->codeaddr=code_idx; sym->usage|=uDEFINE; @@ -2236,7 +2236,7 @@ static int declloc(int fstatic) int idxtag[sDIMEN_MAX]; char name[sNAMEMAX+1]; symbol *sym; - constvalue *enumroot; + constvalue_root *enumroot; cell val,size; char *str; value lval = {0}; @@ -2419,7 +2419,7 @@ static cell calc_arraysize(int dim[],int numdim,int cur) } static void adjust_indirectiontables(int dim[],int numdim,int startlit, - constvalue *lastdim,int *skipdim) + constvalue_root *lastdim,int *skipdim) { static int base; int cur; @@ -2445,7 +2445,7 @@ static int base; accum=0; for (i=0; inext; d<*skipdim; d++,ld=ld->next) { + for (d=0,ld=lastdim->first; d<*skipdim; d++,ld=ld->next) { assert(ld!=NULL); } /* for */ for (d=0; dnext : NULL; + constvalue *enumfield=(enumroot!=NULL) ? enumroot->first : NULL; do { int fieldlit=litidx; int matchbrace,i; @@ -2800,7 +2800,7 @@ static cell init(int ident,int *tag,int *errorfound) * * Get required array size */ -static cell needsub(int *tag,constvalue **enumroot) +static cell needsub(int *tag,constvalue_root **enumroot) { cell val; symbol *sym; @@ -2877,7 +2877,7 @@ static void decl_enum(int vclass,int fstatic) char *str; int tag,explicittag; cell increment,multiplier; - constvalue *enumroot; + constvalue_root *enumroot; symbol *enumsym; short filenum; @@ -2931,9 +2931,9 @@ static void decl_enum(int vclass,int fstatic) enumsym->fnumber=filenum; } /* start a new list for the element names */ - if ((enumroot=(constvalue*)malloc(sizeof(constvalue)))==NULL) + if ((enumroot=(constvalue_root*)malloc(sizeof(constvalue_root)))==NULL) error(103); /* insufficient memory (fatal error) */ - memset(enumroot,0,sizeof(constvalue)); + memset(enumroot,0,sizeof(constvalue_root)); } else { enumsym=NULL; enumroot=NULL; @@ -3085,15 +3085,15 @@ static void attachstatelist(symbol *sym, int state_id) /* add the state list id */ constvalue *stateptr; if (sym->states==NULL) { - if ((sym->states=(constvalue*)malloc(sizeof(constvalue)))==NULL) + if ((sym->states=(constvalue_root*)malloc(sizeof(constvalue_root)))==NULL) error(103); /* insufficient memory (fatal error) */ - memset(sym->states,0,sizeof(constvalue)); + memset(sym->states,0,sizeof(constvalue_root)); } /* if */ /* see whether the id already exists (add new state only if it does not * yet exist */ assert(sym->states!=NULL); - for (stateptr=sym->states->next; stateptr!=NULL && stateptr->index!=state_id; stateptr=stateptr->next) + for (stateptr=sym->states->first; stateptr!=NULL && stateptr->index!=state_id; stateptr=stateptr->next) /* nothing */; assert(state_id<=SHRT_MAX); if (stateptr==NULL) @@ -3108,7 +3108,7 @@ static void attachstatelist(symbol *sym, int state_id) if (state_id==-1 && sc_status!=statFIRST) { /* in the second round, all states should have been accumulated */ assert(sym->states!=NULL); - for (stateptr=sym->states->next; stateptr!=NULL && stateptr->index==-1; stateptr=stateptr->next) + for (stateptr=sym->states->first; stateptr!=NULL && stateptr->index==-1; stateptr=stateptr->next) /* nothing */; if (stateptr==NULL) error(85,sym->name); /* no states are defined for this function */ @@ -3703,7 +3703,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc sym->usage &= ~uDEFINE; /* if the function has states, dump the label to the start of the function */ if (state_id!=0) { - constvalue *ptr=sym->states->next; + constvalue *ptr=sym->states->first; while (ptr!=NULL) { assert(sc_status!=statWRITE || strlen(ptr->name)>0); if (ptr->index==state_id) { @@ -4027,7 +4027,7 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, int fpublic,int fconst,int chkshadow,arginfo *arg) { symbol *argsym; - constvalue *enumroot; + constvalue_root *enumroot; cell size; strcpy(arg->name,name); @@ -4291,7 +4291,7 @@ static void make_report(symbol *root,FILE *log,char *sourcefile) int i,arg; symbol *sym,*ref; constvalue *tagsym; - constvalue *enumroot; + constvalue_root *enumroot; char *ptr; /* adapt the installation directory */ @@ -4345,11 +4345,11 @@ static void make_report(symbol *root,FILE *log,char *sourcefile) } /* if */ /* browse through all fields */ if ((enumroot=sym->dim.enumlist)!=NULL) { - enumroot=enumroot->next; /* skip root */ - while (enumroot!=NULL) { - fprintf(log,"\t\t\t\n",funcdisplayname(symname,enumroot->name),enumroot->value); + constvalue *cur=enumroot->first; /* skip root */ + while (cur!=NULL) { + fprintf(log,"\t\t\t\n",funcdisplayname(symname,cur->name),cur->value); /* find the constant with this name and get the tag */ - ref=findglb(enumroot->name,sGLOBAL); + ref=findglb(cur->name,sGLOBAL); if (ref!=NULL) { if (ref->x.tags.index!=0) { tagsym=find_tag_byval(ref->x.tags.index); @@ -4360,7 +4360,7 @@ static void make_report(symbol *root,FILE *log,char *sourcefile) fprintf(log,"\t\t\t\t\n",(long)ref->dim.array.length); } /* if */ fprintf(log,"\t\t\t\n"); - enumroot=enumroot->next; + cur=cur->next; } /* while */ } /* if */ assert(sym->refer!=NULL); @@ -4474,7 +4474,7 @@ static void make_report(symbol *root,FILE *log,char *sourcefile) if ((sym->usage & uNATIVE)==0) fprintf(log,"\t\t\t\n",(long)sym->x.stacksize); if (sym->states!=NULL) { - constvalue *stlist=sym->states->next; + constvalue *stlist=sym->states->first; assert(stlist!=NULL); /* there should be at least one state item */ while (stlist!=NULL && stlist->index==-1) stlist=stlist->next; @@ -4921,23 +4921,29 @@ static constvalue *insert_constval(constvalue *prev,constvalue *next, cur->value=val; cur->index=index; cur->next=next; - prev->next=cur; + if (prev!=NULL) + prev->next=cur; return cur; } -SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val,int index) +SC_FUNC constvalue *append_constval(constvalue_root *table,const char *name, + cell val,int index) { - constvalue_root *root=(constvalue_root *)table; constvalue *newvalue; - newvalue=insert_constval(((root->last!=NULL) ? root->last : table),NULL,name,val,index); - root->last=newvalue; + if (table->last!=NULL) { + newvalue=insert_constval(table->last,NULL,name,val,index); + } else { + newvalue=insert_constval(NULL,NULL,name,val,index); + table->first=newvalue; + } /* if */ + table->last=newvalue; return newvalue; } -SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index) +SC_FUNC constvalue *find_constval(constvalue_root *table,char *name,int index) { - constvalue *ptr = table->next; + constvalue *ptr = table->first; while (ptr!=NULL) { if (strcmp(name,ptr->name)==0 && ptr->index==index) @@ -4947,9 +4953,9 @@ SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index) return NULL; } -static constvalue *find_constval_byval(constvalue *table,cell val) +static constvalue *find_constval_byval(constvalue_root *table,cell val) { - constvalue *ptr = table->next; + constvalue *ptr = table->first; while (ptr!=NULL) { if (ptr->value==val) @@ -4960,17 +4966,19 @@ static constvalue *find_constval_byval(constvalue *table,cell val) } #if 0 /* never used */ -static int delete_constval(constvalue *table,char *name) +static int delete_constval(constvalue_root *table,char *name) { - constvalue *prev=table; - constvalue *cur=prev->next; - constvalue_root *root=(constvalue_root *)table; + constvalue *prev=NULL; + constvalue *cur=table->first; while (cur!=NULL) { if (strcmp(name,cur->name)==0) { - prev->next=cur->next; - if (root->last==cur) - root->last=prev; + if (prev!=NULL) + prev->next=cur->next; + else + table->first=cur->next; + if (table->last==cur) + table->last=prev; free(cur); return TRUE; } /* if */ @@ -4981,16 +4989,16 @@ static int delete_constval(constvalue *table,char *name) } #endif -SC_FUNC void delete_consttable(constvalue *table) +SC_FUNC void delete_consttable(constvalue_root *table) { - constvalue *cur=table->next, *next; + constvalue *cur=table->first, *next; while (cur!=NULL) { next=cur->next; free(cur); cur=next; } /* while */ - memset(table,0,sizeof(constvalue)); + memset(table,0,sizeof(constvalue_root)); } /* add_constant @@ -5665,8 +5673,8 @@ static void doswitch(void) int tok,endtok; cell val; char *str; - constvalue caselist = { NULL, "", 0, 0}; /* case list starts empty */ - constvalue *cse,*csp; + constvalue_root caselist = { NULL, NULL}; /* case list starts empty */ + constvalue *cse,*csp,*newval; char labelname[sNAMEMAX+1]; endtok= matchtoken('(') ? ')' : tDO; @@ -5714,7 +5722,7 @@ static void doswitch(void) * that advanced abstract machines can sift the case table with a * binary search). Check for duplicate case values at the same time. */ - for (csp=&caselist, cse=caselist.next; + for (csp=NULL, cse=caselist.first; cse!=NULL && cse->valuenext) /* nothing */; @@ -5727,9 +5735,10 @@ static void doswitch(void) #if sNAMEMAX < 8 #error Length of identifier (sNAMEMAX) too small. #endif - assert(csp!=NULL); - assert(csp->next==cse); - insert_constval(csp,cse,itoh(lbl_case),val,0); + assert(csp==NULL || csp->next==cse); + newval=insert_constval(csp,cse,itoh(lbl_case),val,0); + if (csp==NULL) + caselist.first=newval; if (matchtoken(tDBLDOT)) { cell end; constexpr(&end,NULL,NULL); @@ -5738,14 +5747,13 @@ static void doswitch(void) while (++val<=end) { casecount++; /* find the new insertion point */ - for (csp=&caselist, cse=caselist.next; + for (csp=NULL, cse=caselist.first; cse!=NULL && cse->valuenext) /* nothing */; if (cse!=NULL && cse->value==val) error(40,val); /* duplicate "case" label */ - assert(csp!=NULL); - assert(csp->next==cse); + assert(csp==NULL || csp->next==cse); insert_constval(csp,cse,itoh(lbl_case),val,0); } /* if */ } /* if */ @@ -5783,7 +5791,7 @@ static void doswitch(void) /* verify that the case table is sorted (unfortunatly, duplicates can * occur; there really shouldn't be duplicate cases, but the compiler * may not crash or drop into an assertion for a user error). */ - for (cse=caselist.next; cse!=NULL && cse->next!=NULL; cse=cse->next) + for (cse=caselist.first; cse!=NULL && cse->next!=NULL; cse=cse->next) assert(cse->value <= cse->next->value); #endif /* generate the table here, before lbl_exit (general jump target) */ @@ -5798,7 +5806,7 @@ static void doswitch(void) } /* if */ ffcase(casecount,labelname,TRUE); /* generate the rest of the table */ - for (cse=caselist.next; cse!=NULL; cse=cse->next) + for (cse=caselist.first; cse!=NULL; cse=cse->next) ffcase(cse->value,cse->name,FALSE); setlabel(lbl_exit); @@ -6922,7 +6930,7 @@ SC_FUNC void exporttag(int tag) */ if (tag!=0 && (tag & PUBLICTAG)==0) { constvalue *ptr; - for (ptr=tagname_tab.next; ptr!=NULL && tag!=(int)(ptr->value & TAGMASK); ptr=ptr->next) + for (ptr=tagname_tab.first; ptr!=NULL && tag!=(int)(ptr->value & TAGMASK); ptr=ptr->next) /* nothing */; if (ptr!=NULL) ptr->value |= PUBLICTAG; @@ -7002,7 +7010,7 @@ static void dostate(void) /* find the optional entry() function for the state */ sym=findglb(uENTRYFUNC,sGLOBAL); if (sc_status==statWRITE && sym!=NULL && sym->ident==iFUNCTN && sym->states!=NULL) { - for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { + for (stlist=sym->states->first; stlist!=NULL; stlist=stlist->next) { assert(strlen(stlist->name)!=0); if (state_getfsa(stlist->index)==automaton->index && state_inlist(stlist->index,(int)state->value)) break; /* found! */ @@ -7024,7 +7032,7 @@ static void dostate(void) /* get the last list id attached to the function, this contains the source states */ assert(curfunc!=NULL); if (curfunc->states!=NULL) { - stlist=curfunc->states->next; + stlist=curfunc->states->first; assert(stlist!=NULL); while (stlist->next!=NULL) stlist=stlist->next; diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index 291d086..f716b8f 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -2949,7 +2949,7 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_ sym->usage &= ~uDEFINE; /* clear "defined" flag */ /* set all states as "undefined" too */ if (sym->states!=NULL) - for (stateptr=sym->states->next; stateptr!=NULL; stateptr=stateptr->next) + for (stateptr=sym->states->first; stateptr!=NULL; stateptr=stateptr->next) stateptr->value=0; /* for user defined operators, also remove the "prototyped" flag, as * user-defined operators *must* be declared before use @@ -2989,10 +2989,10 @@ static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int a && (sym->parent==NULL || sym->ident==iCONSTEXPR) /* sub-types (hierarchical types) are skipped, except for enum fields */ && (sym->fnumber<0 || sym->fnumber==fnumber)) /* check file number for scope */ { - assert(sym->states==NULL || sym->states->next!=NULL); /* first element of the state list is the "root" */ + assert(sym->states==NULL || sym->states->first!=NULL); /* first element of the state list is the "root" */ if (sym->ident==iFUNCTN || (automaton<0 && sym->states==NULL) - || (automaton>=0 && sym->states!=NULL && state_getfsa(sym->states->next->index)==automaton)) + || (automaton>=0 && sym->states!=NULL && state_getfsa(sym->states->first->index)==automaton)) { if (cmptag==NULL && sym->fnumber==fnumber) return sym; /* return first match */ @@ -3110,8 +3110,8 @@ SC_FUNC symbol *findglb(const char *name,int filter) * also verify whether there is an intersection between the symbol's * state list and the current state list */ - assert(sym->states!=NULL && sym->states->next!=NULL); - if (!state_conflict_id(sc_curstates,sym->states->next->index)) + assert(sym->states!=NULL && sym->states->first!=NULL); + if (!state_conflict_id(sc_curstates,sym->states->first->index)) sym=NULL; } /* if */ } /* if */ diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 3421f46..5d9c013 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -1985,8 +1985,8 @@ static int nesting=0; value lval = {0}; arginfo *arg; char arglist[sMAXARGS]; - constvalue arrayszlst = { NULL, "", 0, 0};/* array size list starts empty */ - constvalue taglst = { NULL, "", 0, 0}; /* tag list starts empty */ + constvalue_root arrayszlst = { NULL, NULL};/* array size list starts empty */ + constvalue_root taglst = { NULL, NULL}; /* tag list starts empty */ symbol *symret; cell lexval; char *lexstr; diff --git a/source/compiler/sc4.c b/source/compiler/sc4.c index 2d9e2b8..9ef44a3 100644 --- a/source/compiler/sc4.c +++ b/source/compiler/sc4.c @@ -75,7 +75,7 @@ SC_FUNC void writeleader(symbol *root) */ assert(glb_declared==0); begdseg(); - for (fsa=sc_automaton_tab.next; fsa!=NULL; fsa=fsa->next) { + for (fsa=sc_automaton_tab.first; fsa!=NULL; fsa=fsa->next) { defstorage(); stgwrite("0\t; automaton "); if (strlen(fsa->name)==0) @@ -91,7 +91,7 @@ SC_FUNC void writeleader(symbol *root) begcseg(); for (sym=root->next; sym!=NULL; sym=sym->next) { if (sym->ident==iFUNCTN && (sym->usage & (uPUBLIC | uREAD))!=0 && sym->states!=NULL) { - stlist=sym->states->next; + stlist=sym->states->first; assert(stlist!=NULL); /* there should be at least one state item */ listid=stlist->index; assert(listid==-1 || listid>0); @@ -109,7 +109,7 @@ SC_FUNC void writeleader(symbol *root) continue; } /* if */ /* generate label numbers for all statelist ids */ - for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { + for (stlist=sym->states->first; stlist!=NULL; stlist=stlist->next) { assert(strlen(stlist->name)==0); strcpy(stlist->name,itoh(getlabel())); } /* for */ @@ -126,7 +126,7 @@ SC_FUNC void writeleader(symbol *root) */ statecount=0; strcpy(lbl_default,itoh(lbl_nostate)); - for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { + for (stlist=sym->states->first; stlist!=NULL; stlist=stlist->next) { if (stlist->index==-1) { assert(strlen(stlist->name)name); @@ -146,10 +146,10 @@ SC_FUNC void writeleader(symbol *root) /* generate the jump table */ setlabel(lbl_table); ffcase(statecount,lbl_default,TRUE); - for (state=sc_state_tab.next; state!=NULL; state=state->next) { + for (state=sc_state_tab.first; state!=NULL; state=state->next) { if (state->index==fsa_id) { /* find the label for this list id */ - for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { + for (stlist=sym->states->first; stlist!=NULL; stlist=stlist->next) { if (stlist->index!=-1 && state_inlist(stlist->index,(int)state->value)) { ffcase(state->value,stlist->name,FALSE); break; diff --git a/source/compiler/sc6.c b/source/compiler/sc6.c index 0216f41..bcca653 100644 --- a/source/compiler/sc6.c +++ b/source/compiler/sc6.c @@ -813,7 +813,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) /* count number of libraries */ numlibraries=0; if (pc_addlibtable) { - for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=libname_tab.first; constptr!=NULL; constptr=constptr->next) { if (constptr->value>0) { assert(strlen(constptr->name)>0); numlibraries++; @@ -824,7 +824,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) /* count number of public tags */ numtags=0; - for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=tagname_tab.first; constptr!=NULL; constptr=constptr->next) { if ((constptr->value & PUBLICTAG)!=0) { assert(strlen(constptr->name)>0); numtags++; @@ -950,7 +950,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) /* write the libraries table */ if (pc_addlibtable) { count=0; - for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=libname_tab.first; constptr!=NULL; constptr=constptr->next) { if (constptr->value>0) { assert(strlen(constptr->name)>0); func.address=0; @@ -994,7 +994,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) /* write the public tagnames table */ count=0; - for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=tagname_tab.first; constptr!=NULL; constptr=constptr->next) { if ((constptr->value & PUBLICTAG)!=0) { assert(strlen(constptr->name)>0); func.address=constptr->value & TAGMASK; @@ -1214,21 +1214,21 @@ static void append_dbginfo(FILE *fout) } /* for */ /* tag table */ - for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=tagname_tab.first; constptr!=NULL; constptr=constptr->next) { assert(strlen(constptr->name)>0); dbghdr.tags++; dbghdr.size+=sizeof(AMX_DBG_TAG)+strlen(constptr->name); } /* for */ /* automaton table */ - for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=sc_automaton_tab.first; constptr!=NULL; constptr=constptr->next) { assert(constptr->index==0 && strlen(constptr->name)==0 || strlen(constptr->name)>0); dbghdr.automatons++; dbghdr.size+=sizeof(AMX_DBG_MACHINE)+strlen(constptr->name); } /* for */ /* state table */ - for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=sc_state_tab.first; constptr!=NULL; constptr=constptr->next) { assert(strlen(constptr->name)>0); dbghdr.states++; dbghdr.size+=sizeof(AMX_DBG_STATE)+strlen(constptr->name); @@ -1347,7 +1347,7 @@ static void append_dbginfo(FILE *fout) } /* for */ /* tag table */ - for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=tagname_tab.first; constptr!=NULL; constptr=constptr->next) { assert(strlen(constptr->name)>0); id1=(int16_t)(constptr->value & TAGMASK); #if BYTE_ORDER==BIG_ENDIAN @@ -1358,7 +1358,7 @@ static void append_dbginfo(FILE *fout) } /* for */ /* automaton table */ - for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=sc_automaton_tab.first; constptr!=NULL; constptr=constptr->next) { assert(constptr->index==0 && strlen(constptr->name)==0 || strlen(constptr->name)>0); id1=(int16_t)constptr->index; address=(ucell)constptr->value; @@ -1372,7 +1372,7 @@ static void append_dbginfo(FILE *fout) } /* for */ /* state table */ - for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) { + for (constptr=sc_state_tab.first; constptr!=NULL; constptr=constptr->next) { assert(strlen(constptr->name)>0); id1=(int16_t)constptr->value; id2=(int16_t)constptr->index; diff --git a/source/compiler/scstate.c b/source/compiler/scstate.c index a1fdfb3..53a3ebe 100644 --- a/source/compiler/scstate.c +++ b/source/compiler/scstate.c @@ -76,7 +76,7 @@ static constvalue *find_automaton(const char *name,int *last) assert(last!=NULL); *last=0; - ptr=sc_automaton_tab.next; + ptr=sc_automaton_tab.first; while (ptr!=NULL) { if (strcmp(name,ptr->name)==0) return ptr; @@ -110,7 +110,7 @@ SC_FUNC constvalue *automaton_find(const char *name) SC_FUNC constvalue *automaton_findid(int id) { constvalue *ptr; - for (ptr=sc_automaton_tab.next; ptr!=NULL && ptr->index!=id; ptr=ptr->next) + for (ptr=sc_automaton_tab.first; ptr!=NULL && ptr->index!=id; ptr=ptr->next) /* nothing */; return ptr; } @@ -122,7 +122,7 @@ static constvalue *find_state(const char *name,int fsa,int *last) assert(last!=NULL); *last=0; - ptr=sc_state_tab.next; + ptr=sc_state_tab.first; while (ptr!=NULL) { if (ptr->index==fsa) { if (strcmp(name,ptr->name)==0) @@ -158,7 +158,7 @@ SC_FUNC constvalue *state_find(const char *name,int fsa_id) SC_FUNC constvalue *state_findid(int id) { constvalue *ptr; - for (ptr=sc_state_tab.next; ptr!=NULL && ptr->value!=id; ptr=ptr->next) + for (ptr=sc_state_tab.first; ptr!=NULL && ptr->value!=id; ptr=ptr->next) /* nothing */; return ptr; } @@ -341,7 +341,7 @@ SC_FUNC void state_conflict(symbol *root) continue; /* hierarchical data type or no function */ if (sym->states==NULL) continue; /* this function has no states */ - for (srcptr=sym->states->next; srcptr!=NULL; srcptr=srcptr->next) { + for (srcptr=sym->states->first; srcptr!=NULL; srcptr=srcptr->next) { if (srcptr->index==-1) continue; /* state list id -1 is a special case */ psrc=state_getlist_ptr(srcptr->index); diff --git a/source/compiler/scvars.c b/source/compiler/scvars.c index 43de38a..d37551f 100644 --- a/source/compiler/scvars.c +++ b/source/compiler/scvars.c @@ -37,8 +37,8 @@ SC_VDEFINE struct hashtable_t symbol_cache_ht; SC_VDEFINE cell *litq; /* the literal queue */ SC_VDEFINE unsigned char pline[sLINEMAX+1]; /* the line read from the input file */ SC_VDEFINE const unsigned char *lptr; /* points to the current position in "pline" */ -SC_VDEFINE constvalue tagname_tab={ NULL, "", 0, 0}; /* tagname table */ -SC_VDEFINE constvalue libname_tab={ NULL, "", 0, 0}; /* library table (#pragma library "..." syntax) */ +SC_VDEFINE constvalue_root tagname_tab={ NULL, NULL}; /* tagname table */ +SC_VDEFINE constvalue_root libname_tab={ NULL, NULL}; /* library table (#pragma library "..." syntax) */ SC_VDEFINE constvalue *curlibrary=NULL; /* current library */ SC_VDEFINE int pc_addlibtable=TRUE; /* is the library table added to the AMX file? */ SC_VDEFINE symbol *curfunc; /* pointer to current function */ @@ -96,8 +96,8 @@ SC_VDEFINE int pc_naked=FALSE; /* if true mark following function a SC_VDEFINE int pc_compat=FALSE; /* running in compatibility mode? */ SC_VDEFINE int pc_recursion=FALSE; /* enable detailed recursion report? */ -SC_VDEFINE constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */ -SC_VDEFINE constvalue sc_state_tab = { NULL, "", 0, 0}; /* state table */ +SC_VDEFINE constvalue_root sc_automaton_tab = { NULL, NULL}; /* automaton table */ +SC_VDEFINE constvalue_root sc_state_tab = { NULL, NULL}; /* state table */ SC_VDEFINE FILE *inpf = NULL; /* file read from (source or include) */ SC_VDEFINE FILE *inpf_org= NULL; /* main source file */ From 7863adff4da674142e45be2d2df994d7ffea2d87 Mon Sep 17 00:00:00 2001 From: Southclaws Date: Fri, 20 Apr 2018 12:18:52 +0100 Subject: [PATCH 28/88] added definitions for Pawn to avoid SourcePawn affiliation --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitattributes b/.gitattributes index 176a458..5802459 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,3 @@ * text=auto +*.pwn linguist-language=Pawn +*.inc linguist-language=Pawn From 7a53a93574ab24fbb1eb5661bfd7e2352a293dc0 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 22 Apr 2018 18:48:31 +0600 Subject: [PATCH 29/88] Fix crash when number of arguments exceeds sMAXARGS During first pass the call to error() is ignored and therefore doesn't break ouf of the loop. This causes stack courrption because of OBB write to arglist. Fixes #298. --- source/compiler/sc3.c | 4 +++- source/compiler/tests/CMakeLists.txt | 3 +++ source/compiler/tests/too_many_args_crash_gh_298.pwn | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 source/compiler/tests/too_many_args_crash_gh_298.pwn diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 235680e..e583c3f 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -2078,8 +2078,10 @@ static int nesting=0; * of the function; check it again for functions with a variable * argument list */ - if (argpos>=sMAXARGS) + if (argpos>=sMAXARGS) { error(45); /* too many function arguments */ + break; + } /* if */ stgmark((char)(sEXPRSTART+argpos));/* mark beginning of new expression in stage */ if (arglist[argpos]!=ARG_UNHANDLED) error(58); /* argument already set */ diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index a341039..9b3d52c 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -45,6 +45,9 @@ set_tests_properties(gh_283 PROPERTIES PASS_REGULAR_EXPRESSION "\ .*\\.pwn\\(5\\) : warning 234: function is deprecated \\(symbol \"print\"\\)\ ") +add_compiler_test(too_many_args_crash_gh_298 ${CMAKE_CURRENT_SOURCE_DIR}/too_many_args_crash_gh_298.pwn) +set_tests_properties(too_many_args_crash_gh_298 PROPERTIES PASS_REGULAR_EXPRESSION "too many function arguments") + # Crashers # # These tests simply check that the compiler doesn't crash. diff --git a/source/compiler/tests/too_many_args_crash_gh_298.pwn b/source/compiler/tests/too_many_args_crash_gh_298.pwn new file mode 100644 index 0000000..525936c --- /dev/null +++ b/source/compiler/tests/too_many_args_crash_gh_298.pwn @@ -0,0 +1,5 @@ +native printf(const format[], ...); + +main() { + printf("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +} From f73e04e7603e31e725021362f22a3e4b63892b17 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 22 Apr 2018 18:55:34 +0600 Subject: [PATCH 30/88] Fix build error on AppVeyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index bdcd9a5..642cb00 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ version: '{build}' -image: Visual Studio 2015 +image: Visual Studio 2017 configuration: - RelWithDebInfo From 7b85d3bdf05413aaffe8420b4605f35db5a4b1ec Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 22 Apr 2018 18:58:14 +0600 Subject: [PATCH 31/88] Fix build error on AppVeyor --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 642cb00..4f88ef2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,11 +1,11 @@ version: '{build}' -image: Visual Studio 2017 +image: Visual Studio 2015 configuration: - RelWithDebInfo before_build: - - cmake -G "Visual Studio 15 2017" source/compiler -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 + - cmake -G "Visual Studio 14 2015" source/compiler -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 build_script: - cmake --build . --config %CONFIGURATION% From 70da4e12ef2d01139bcd1d4a3ff490b0c1dfed41 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 22 Apr 2018 19:37:15 +0600 Subject: [PATCH 32/88] Make #pragma option also update builtin constants If you used #pragma option -d3 or #pragma option -Z the corresponding constants (debug and __compat respectively) were not updated; now the are. Fixes #253. --- source/compiler/sc1.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 06e5030..3efa472 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -993,7 +993,7 @@ static int toggle_option(const char *optptr, int option) { switch (*option_value(optptr)) { case '\0': - option=!option; + option=TRUE; break; case '-': option=FALSE; @@ -1064,7 +1064,8 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam if (chdir(ptr)==-1) ; /* silently ignore chdir() errors */ break; - case 'd': + case 'd': { + int debug; switch (*option_value(ptr)) { case '0': sc_debug=0; @@ -1083,7 +1084,14 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam default: about(); } /* switch */ + debug=0; + if ((sc_debug & (sCHKBOUNDS | sSYMBOLIC))==(sCHKBOUNDS | sSYMBOLIC)) + debug=2; + else if ((sc_debug & sCHKBOUNDS)==sCHKBOUNDS) + debug=1; + add_builtin_constant("debug",debug,sGLOBAL,0); break; + } /* case */ case 'e': if (ename) strlcpy(ename,option_value(ptr),_MAX_PATH); /* set name of error file */ @@ -1207,9 +1215,16 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam about(); } /* if */ break; - case 'Z': + case 'Z': { + symbol *sym; pc_compat=toggle_option(ptr,pc_compat); + sym=findconst("__compat",NULL); + if (sym!=NULL) { + assert(sym!=NULL); + sym->addr=pc_compat; + } /* if */ break; + } /* case */ case '\\': /* use \ instead for escape characters */ sc_ctrlchar='\\'; break; From eb0159d6623ba88c6249e7fae3801323504f7af0 Mon Sep 17 00:00:00 2001 From: Zeex Date: Tue, 24 Apr 2018 15:26:17 +0600 Subject: [PATCH 33/88] v3.10.7 --- source/compiler/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index 146d8d9..1a2ff83 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -5,7 +5,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake) set(VERSION_MAJOR 3) set(VERSION_MINOR 10) -set(VERSION_BUILD 6) +set(VERSION_BUILD 7) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}) set(VERSION_STR ${VERSION}) math(EXPR VERSION_INT "${VERSION_MAJOR} << 8 | ${VERSION_MINOR}") From 40286c07e83082cb99a16ad74c29560180c18c71 Mon Sep 17 00:00:00 2001 From: Zeex Date: Tue, 24 Apr 2018 15:33:31 +0600 Subject: [PATCH 34/88] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 19667c9..11160e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,4 +38,4 @@ deploy: skip_cleanup: true on: tags: true - repo: Zeex/pawn + repo: pawn-lang/compiler From 27fd9c21800eb95545934479d81e7f1452187fdc Mon Sep 17 00:00:00 2001 From: Zeex Date: Tue, 24 Apr 2018 15:48:40 +0600 Subject: [PATCH 35/88] Update AppVeyor auth token --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 4f88ef2..ec678af 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,7 +25,7 @@ deploy: description: '' provider: GitHub auth_token: - secure: ++mk9GhXTpN/hdVjIIi/nHpu0gYpDybMJNDPB3lld8r1UyfoPbz08SVGeSS84HjR + secure: dEyljMC1z2hb032HYJQY+CIZIdQ382cuHU/3LJA96nbqOl5xfGYPVP/TGbJANbtz artifact: /pawnc-.*-windows\.zip/ draft: true prerelease: true From bed755dcb7962d9fba0bb36519938a819d334111 Mon Sep 17 00:00:00 2001 From: Zeex Date: Fri, 27 Apr 2018 12:10:09 +0600 Subject: [PATCH 36/88] Fix build error with CMake < 3.0 --- source/compiler/tests/CMakeLists.txt | 46 +++++++++++++--------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index 55ce454..ef77935 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -4,10 +4,10 @@ set(DEFAULT_COMPILER_OPTIONS "-(+") function(add_compiler_test test_name options) - add_test(NAME ${test_name} - COMMAND $ ${DEFAULT_COMPILER_OPTIONS} ${options}) - set_tests_properties(${test_name} PROPERTIES - ENVIRONMENT PATH=$) + add_test(NAME ${test_name} + COMMAND $ ${DEFAULT_COMPILER_OPTIONS} ${options}) + set_tests_properties(${test_name} PROPERTIES + ENVIRONMENT PATH=$) endfunction() # Compile tests @@ -16,42 +16,40 @@ endfunction() # doesn't match the expected pattern. add_compiler_test(gh_217 ${CMAKE_CURRENT_SOURCE_DIR}/gh_217.pwn) -set_tests_properties(gh_217 PROPERTIES PASS_REGULAR_EXPRESSION "\ -.*\\.pwn\\(11\\) : warning 237: user warning: this is warning 1\ -.*\\.pwn\\(13\\) : warning 237: user warning: this iswarning 2\ -.*\\.pwn\\(15\\) : warning 237: user warning: this is warning 3\ -.*\\.pwn\\(17\\) : warning 237: user warning: this is warning 4\ -.*\\.pwn\\(27\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this functionplease\ -.*\\.pwn\\(32\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this functionplease\ +set_tests_properties(gh_217 PROPERTIES PASS_REGULAR_EXPRESSION ".*\\.pwn\\(11\\) : warning 237: user warning: this is warning 1 +.*\\.pwn\\(13\\) : warning 237: user warning: this iswarning 2 +.*\\.pwn\\(15\\) : warning 237: user warning: this is warning 3 +.*\\.pwn\\(17\\) : warning 237: user warning: this is warning 4 +.*\\.pwn\\(27\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this functionplease +.*\\.pwn\\(32\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this functionplease ") add_compiler_test(reset_errline_gh_230 ${CMAKE_CURRENT_SOURCE_DIR}/reset_errline_gh_230.pwn) -set_tests_properties(reset_errline_gh_230 PROPERTIES PASS_REGULAR_EXPRESSION "\ -.*\\.pwn\\(2\\) : error 017: undefined symbol \\\"undefined\\\"\ -.*\\.pwn\\(2\\) : warning 215: expression has no effect\ -.*\\.pwn\\(7\\) : warning 204: symbol is assigned a value that is never used: \\\"y\\\"\ -.*\\.pwn\\(4\\) : warning 204: symbol is assigned a value that is never used: \\\"x\\\"\ +set_tests_properties(reset_errline_gh_230 PROPERTIES PASS_REGULAR_EXPRESSION +".*\\.pwn\\(2\\) : error 017: undefined symbol \\\"undefined\\\" +.*\\.pwn\\(2\\) : warning 215: expression has no effect +.*\\.pwn\\(7\\) : warning 204: symbol is assigned a value that is never used: \\\"y\\\" +.*\\.pwn\\(4\\) : warning 204: symbol is assigned a value that is never used: \\\"x\\\" ") add_compiler_test(unused_symbol_line_gh_252 ${CMAKE_CURRENT_SOURCE_DIR}/unused_symbol_line_gh_252.pwn) -set_tests_properties(unused_symbol_line_gh_252 PROPERTIES PASS_REGULAR_EXPRESSION "\ -.*\\.pwn\\(4\\) : warning 203: symbol is never used: \\\"y\\\" +set_tests_properties(unused_symbol_line_gh_252 PROPERTIES PASS_REGULAR_EXPRESSION +".*\\.pwn\\(4\\) : warning 203: symbol is never used: \\\"y\\\" .*\\.pwn\\(8\\) : warning 203: symbol is never used: \\\"z\\\" .*\\.pwn\\(1\\) : warning 203: symbol is never used: \\\"x\\\" ") add_compiler_test(gh_283 ${CMAKE_CURRENT_SOURCE_DIR}/gh_283.pwn) -set_tests_properties(gh_283 PROPERTIES PASS_REGULAR_EXPRESSION "\ -.*\\.pwn\\(5\\) : warning 234: function is deprecated \\(symbol \"print\"\\)\ -") +set_tests_properties(gh_283 PROPERTIES PASS_REGULAR_EXPRESSION + ".*\\.pwn\\(5\\) : warning 234: function is deprecated \\(symbol \"print\"\\)") add_compiler_test(too_many_args_crash_gh_298 ${CMAKE_CURRENT_SOURCE_DIR}/too_many_args_crash_gh_298.pwn) set_tests_properties(too_many_args_crash_gh_298 PROPERTIES PASS_REGULAR_EXPRESSION "too many function arguments") add_compiler_test(meaningless_class_specifiers_gh_172 ${CMAKE_CURRENT_SOURCE_DIR}/meaningless_class_specifiers_gh_172.pwn) -set_tests_properties(meaningless_class_specifiers_gh_172 PROPERTIES PASS_REGULAR_EXPRESSION "\ -.*\\.pwn\\(1\\) : warning 238: meaningless combination of class specifiers \\(const reference\\)\ -.*\\.pwn\\(1 \\-\\- 2\\) : warning 238: meaningless combination of class specifiers \\(const variable arguments\\)\ +set_tests_properties(meaningless_class_specifiers_gh_172 PROPERTIES PASS_REGULAR_EXPRESSION +".*\\.pwn\\(1\\) : warning 238: meaningless combination of class specifiers \\(const reference\\) +.*\\.pwn\\(1 \\-\\- 2\\) : warning 238: meaningless combination of class specifiers \\(const variable arguments\\) ") # Crashers From fd4369e67b2c9bbf5b9fbceb277a1d6f1f61cab4 Mon Sep 17 00:00:00 2001 From: Yashas Date: Tue, 8 May 2018 09:43:34 +0530 Subject: [PATCH 37/88] debug info for index tagmm warnings This commit makes the compiler display debug information for "index" tag mismatch warnings. --- source/compiler/sc.h | 1 + source/compiler/sc1.c | 24 +++++++++++++++++++++++- source/compiler/sc3.c | 16 ++++++++-------- source/compiler/sc5.c | 2 +- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index ab085fe..1a517a4 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -566,6 +566,7 @@ long pc_lengthbin(void *handle); /* return the length of the file */ SC_FUNC void set_extension(char *filename,char *extension,int force); SC_FUNC symbol *fetchfunc(char *name,int tag); SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag); +SC_FUNC void check_index_tagmismatch(char *symname,int expectedtag,int actualtag,int allowcoerce,int errline); SC_FUNC void check_tagmismatch(int formaltag,int actualtag,int allowcoerce,int errline); SC_FUNC void check_tagmismatch_multiple(int formaltags[],int numtags,int actualtag,int errline); SC_FUNC char *funcdisplayname(char *dest,char *funcname); diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index fb79c17..99717bd 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -3410,6 +3410,28 @@ static constvalue *find_tag_byval(int tag) return tagsym; } +SC_FUNC void check_index_tagmismatch(char *symname,int expectedtag,int actualtag,int allowcoerce,int errline) +{ + assert(symname!=NULL); + if (!matchtag(expectedtag,actualtag,allowcoerce)) { + constvalue *tagsym; + char expected_tagname[sNAMEMAX+3]="none (\"_\"),",actual_tagname[sNAMEMAX+2]="none (\"_\")"; /* two extra characters for quotes */ + if(expectedtag!=0) { + tagsym=find_tag_byval(expectedtag); + sprintf(expected_tagname,"\"%s\",",(tagsym!=NULL) ? tagsym->name : "-unknown-"); + } /* if */ + if(actualtag!=0) { + tagsym=find_tag_byval(actualtag); + sprintf(actual_tagname,"\"%s\"",(tagsym!=NULL) ? tagsym->name : "-unknown-"); + } /* if */ + if(errline>0) + errorset(sSETPOS,errline); + error(229,symname,expected_tagname,actual_tagname); /* index tag mismatch */ + if(errline>0) + errorset(sSETPOS,-1); + } /* if */ +} + SC_FUNC void check_tagmismatch(int formaltag,int actualtag,int allowcoerce,int errline) { if (!matchtag(formaltag,actualtag,allowcoerce)) { @@ -3417,7 +3439,7 @@ SC_FUNC void check_tagmismatch(int formaltag,int actualtag,int allowcoerce,int e char formal_tagname[sNAMEMAX+3]="none (\"_\"),",actual_tagname[sNAMEMAX+2]="none (\"_\")"; /* two extra characters for quotes */ if(formaltag!=0) { tagsym=find_tag_byval(formaltag); - sprintf(formal_tagname,"\"%s\",", (tagsym!=NULL) ? tagsym->name : "-unknown-"); + sprintf(formal_tagname,"\"%s\",",(tagsym!=NULL) ? tagsym->name : "-unknown-"); } /* if */ if(actualtag!=0) { tagsym=find_tag_byval(actualtag); diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index cc86bfa..d9a8c23 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -1014,8 +1014,8 @@ static int hier14(value *lval1) return error(48); /* array dimensions must match */ else if (ltlengthval) || val==0) return error(47); /* array sizes must match */ - else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE)) - error(229,(lval2.sym!=NULL) ? lval2.sym->name : lval3.sym->name); /* index tag mismatch */ + else if (lval3.ident!=iARRAYCELL) + check_index_tagmismatch((lval2.sym!=NULL) ? lval2.sym->name : lval3.sym->name,lval3.sym->x.tags.index,idxtag,TRUE,0); if (level>0) { /* check the sizes of all sublevels too */ symbol *sym1 = lval3.sym; @@ -1036,8 +1036,8 @@ static int hier14(value *lval1) */ if (sym1->dim.array.length!=sym2->dim.array.length) error(47); /* array sizes must match */ - else if (!matchtag(sym1->x.tags.index,sym2->x.tags.index,TRUE)) - error(229,sym2->name); /* index tag mismatch */ + else + check_index_tagmismatch(sym2->name,sym1->x.tags.index,sym2->x.tags.index,TRUE,0); } /* for */ /* get the total size in cells of the multi-dimensional array */ val=array_totalsize(lval3.sym); @@ -2250,8 +2250,8 @@ static int nesting=0; assert(leveldim.array.length!=arg[argidx].dim[level]) error(47); /* array sizes must match */ - else if (!matchtag(arg[argidx].idxtag[level],sym->x.tags.index,TRUE)) - error(229,sym->name); /* index tag mismatch */ + else + check_index_tagmismatch(sym->name,arg[argidx].idxtag[level],sym->x.tags.index,TRUE,0); append_constval(&arrayszlst,arg[argidx].name,sym->dim.array.length,level); sym=finddepend(sym); assert(sym!=NULL); @@ -2262,8 +2262,8 @@ static int nesting=0; assert(sym!=NULL); if (arg[argidx].dim[level]!=0 && sym->dim.array.length!=arg[argidx].dim[level]) error(47); /* array sizes must match */ - else if (!matchtag(arg[argidx].idxtag[level],sym->x.tags.index,TRUE)) - error(229,sym->name); /* index tag mismatch */ + else + check_index_tagmismatch(sym->name,arg[argidx].idxtag[level],sym->x.tags.index,TRUE,0); append_constval(&arrayszlst,arg[argidx].name,sym->dim.array.length,level); } /* if */ /* address already in PRI */ diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index 3f91485..61631f6 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -183,7 +183,7 @@ static char *warnmsg[] = { /*226*/ "a variable is assigned to itself (symbol \"%s\")\n", /*227*/ "more initiallers than enum fields\n", /*228*/ "length of initialler exceeds size of the enum field\n", -/*229*/ "index tag mismatch (symbol \"%s\")\n", +/*229*/ "index tag mismatch (symbol \"%s\"): expected tag %s but found %s\n", /*230*/ "no implementation for state \"%s\" in function \"%s\", no fall-back\n", /*231*/ "state specification on forward declaration is ignored\n", /*232*/ "output file is written, but with compact encoding disabled\n", From 29669858b32312d26bd9f324ca07fbaadf115608 Mon Sep 17 00:00:00 2001 From: Yashas Date: Thu, 10 May 2018 09:45:10 +0530 Subject: [PATCH 38/88] enable warning 214 warning 214: possibly a "const" array argument was intended: --- source/compiler/sc1.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index fb79c17..54787e9 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -4881,12 +4881,10 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst) errorset(sSETPOS,sym->lnumber); error(204,sym->name); /* value assigned to symbol is never used */ errorset(sSETPOS,-1); -#if 0 // ??? not sure whether it is a good idea to force people use "const" } else if ((sym->usage & (uWRITTEN | uPUBLIC | uCONST))==0 && sym->ident==iREFARRAY) { errorset(sSETPOS,sym->lnumber); error(214,sym->name); /* make array argument "const" */ errorset(sSETPOS,-1); -#endif } /* if */ /* also mark the variable (local or global) to the debug information */ if ((sym->usage & (uWRITTEN | uREAD))!=0 && (sym->usage & uNATIVE)==0) From c363c5b1de7bc34d6acb440f21b305df9a710d36 Mon Sep 17 00:00:00 2001 From: Yashas Date: Thu, 10 May 2018 10:44:36 +0530 Subject: [PATCH 39/88] add warning for literal passed to non-const parameter Adds a new warning to warn users when they pass an array/string literal to a non-const qualified parameter. ``` f1(arr[]) { new a = arr[0]; #pragma unused a } f2(arr[5]) { new a = arr[0]; #pragma unused a } f3(const arr[]) { new a = arr[0]; #pragma unused a } f4(const arr[5]) { new a = arr[0]; #pragma unused a } main () { f1("test"); f2("test"); f3("test"); f4("test"); new arr[5]; f1(arr); f2(arr); f3(arr); f4(arr); f1(arr[0]); //f2(arr[0]); - array size must match f3(arr[0]); //f4(arr[0]); - array size must match } ``` ``` test.pwn(1) : warning 214: possibly a "const" array argument was intended: "arr" test.pwn(6) : warning 214: possibly a "const" array argument was intended: "arr" test.pwn(20) : warning 239: literal array/string passed to a non-const parameter test.pwn(21) : warning 239: literal array/string passed to a non-const parameter ``` --- source/compiler/sc3.c | 30 +++++++++++++++++------------- source/compiler/sc5.c | 3 ++- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index cc86bfa..c3d9584 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -2214,19 +2214,23 @@ static int nesting=0; if (lval.sym==NULL || lval.ident==iARRAYCELL) { if (arg[argidx].numdim!=1) { error(48); /* array dimensions must match */ - } else if (arg[argidx].dim[0]!=0) { - assert(arg[argidx].dim[0]>0); - if (lval.ident==iARRAYCELL) { - error(47); /* array sizes must match */ - } else { - assert(lval.constval!=0); /* literal array must have a size */ - /* A literal array must have exactly the same size as the - * function argument; a literal string may be smaller than - * the function argument. - */ - if ((lval.constval>0 && arg[argidx].dim[0]!=lval.constval) - || (lval.constval<0 && arg[argidx].dim[0] < -lval.constval)) - error(47); /* array sizes must match */ + } else { + if (lval.sym==NULL && (arg[argidx].usage & uCONST)==0) + error(239); + if (arg[argidx].dim[0]!=0) { + assert(arg[argidx].dim[0]>0); + if (lval.ident==iARRAYCELL) { + error(7); /* array sizes must match */ + } else { + assert(lval.constval!=0); /* literal array must have a size */ + /* A literal array must have exactly the same size as the + * function argument; a literal string may be smaller than + * the function argument. + */ + if ((lval.constval>0 && arg[argidx].dim[0]!=lval.constval) + || (lval.constval<0 && arg[argidx].dim[0]<-lval.constval)) + error(47); /* array sizes must match */ + } /* if */ } /* if */ } /* if */ if (lval.ident!=iARRAYCELL || lval.constval > 0) { diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index 3f91485..9979d90 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -192,7 +192,8 @@ static char *warnmsg[] = { /*235*/ "public function lacks forward declaration (symbol \"%s\")\n", /*236*/ "unknown parameter in substitution (incorrect #define pattern)\n", /*237*/ "user warning: %s\n", -/*238*/ "meaningless combination of class specifiers (%s)\n" +/*238*/ "meaningless combination of class specifiers (%s)\n", +/*239*/ "literal array/string passed to a non-const parameter\n" }; #define NUM_WARNINGS (sizeof warnmsg / sizeof warnmsg[0]) From 293c9a3b315d27a44e0c025b0c189adc8f5fd91d Mon Sep 17 00:00:00 2001 From: Yashas Date: Thu, 10 May 2018 23:01:52 +0530 Subject: [PATCH 40/88] mark symbols passed as non-const args modified This commit makes the compiler mark array symbols which are passed as non-const argument modified. --- source/compiler/sc3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index c3d9584..af3f2b8 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -2274,7 +2274,8 @@ static int nesting=0; check_tagmismatch_multiple(arg[argidx].tags,arg[argidx].numtags,lval.tag,-1); if (lval.tag!=0) append_constval(&taglst,arg[argidx].name,lval.tag,0); - // ??? set uWRITTEN? + if (lval.sym!=NULL && (arg[argidx].usage & uCONST)==0) + markusage(lval.sym,uWRITTEN); argidx++; /* argument done */ break; } /* switch */ From 1578ab15a32aafe6ea2cf909abe8cecd112726ff Mon Sep 17 00:00:00 2001 From: Yashas Date: Sat, 9 Jun 2018 10:58:20 +0530 Subject: [PATCH 41/88] fix result propogation in constexpr operator chains ## compile-time chained operator evaluation mechanism Constants are stored in `value` object. The object has two members: `constval` and `boolresult`. The `constval` member stores the actual value which the object represents: `15` and `10` for example in `15 < 20`. All operators are in a chain of operators. On most occasions, there is just one operator in the chain but it is still a valid singleton chain. The `boolresult` member stores the result of the previous operations which the constant was involved in if any. For example, in `15 < 20 < 30`, the `boolresult` member of object representing `20` stores the result of `15 < 20`. In more complex expressions such as, `15 < 20 < 30 < 40 < 50`, the `boolresult` member of object representing `40` stores the result of the `15 < 20 < 30 < 40`. The `boolresult` of the first constant in a chain is set to `TRUE` by default. **Details:** The processing of chains begins at `plnge_rel` which maintains two `value` objects: `lval` and `lval2`. The `lval` is taken by `plnge_rel` as an argument of the first constant (stored in `constval` field) value in the operator chain. The result of the full chain is also passed through it by storing the result in the `constval` field (like `15 < 20` evaluates to the constant `1`; the result of `15 < 20` is `1` which is also a constant). The `boolresult` of `lval` is set to `TRUE` as this is the first constant in the chain. The `plnge_rel` progresses through the chain one by one with `lval` and `lval2` always being the left operand and the right operand respectively. For each operator it calls `plnge2` which dumps instructions for loading constant and the right operand into the staging buffer. If the right operand turns out to be a constant, the staging buffer is flushed and `static cell calc(cell left,void (*oper)(),cell right,char *boolresult);` is called to evaluate the compile-time expression with the constant value of the left and right operand passed as `left` and `right` arguments along with the operator and `boolresult` of the left operand. `calc` evluates the expression and returns the right operand and sets the `boolresult` to the result of the operator chain. After the call returns, `constval` of `lval` (left operand) is set to the `constval` of `lval2` (right operand). As of now, the `lval` now stores the right operand and the result of the operator chain uptil now. `plnge2` returns and control is transfered back to `plnge_rel`. `plnge_rel` copies the value stored in `lval2` into `lval`. This implies that the `boolresult` and `constval` fields of `lval2` are copied into `lval` as the previous right operand is now the left operand for the next operator in the chain. **Oops! BUG!** The `boolresult` which was stored in `lval` is lost and is replaced by `FALSE` which was stored in `lval2` which is the default for `value` objets (set by `clear_value`). The compiler should've ensured that the `boolresult` of `lval` was retained. `plnge2` is again called to process the right operand and evaluate the expression. This keeps repeating until the entire chain has been evaluated. After the entire chain has been evaluated, `lval` has `constval` as the most recent right operand and `boolresult` has the result of the entire chain. The compiler sets `constval` of `lval` to `boolresult` of `lval` and its tag to `bool`. Note that this is done in the last step. The `lval` now is a constant representing the result of the entire chain of operators, i.e. `1` if the chain evaluated to `TRUE` or `0` otherwise. **Relavant bugged code:** ``` static int plnge_rel(int *opstr,int opoff,int (*hier)(value *lval),value *lval) { . . . lval->boolresult=TRUE; do { /* same check as in plnge(), but "chkbitwise" is always TRUE */ if (count>0 && bitwise_opercount!=0) error(212); if (count>0) { relop_prefix(); *lval=lval2; /* copy right hand expression of the previous iteration */ } /* if */ opidx+=opoff; plnge2(op1[opidx],hier,lval,&lval2); if (count++>0) relop_suffix(); } while (nextop(&opidx,opstr)); /* enddo */ lval->constval=lval->boolresult; lval->tag=pc_addtag("bool"); /* force tag to be "bool" */ return FALSE; /* result of expression is not an lvalue */ } ``` ``` static void plnge2(void (*oper)(void), int (*hier)(value *lval), value *lval1,value *lval2) { . . . if (check_userop(oper,lval1->tag,lval2->tag,2,NULL,&lval1->tag)) { lval1->ident=iEXPRESSION; lval1->constval=0; } else if (lval1->ident==iCONSTEXPR && lval2->ident==iCONSTEXPR) { /* only constant expression if both constant */ stgdel(index,cidx); /* scratch generated code and calculate */ check_tagmismatch(lval1->tag,lval2->tag,FALSE,-1); lval1->constval=calc(lval1->constval,oper,lval2->constval,&lval1->boolresult); } else { . . . } ``` ``` static cell calc(cell left,void (*oper)(),cell right,char *boolresult) { . . . else if (oper==os_le) return *boolresult &= (char)(left <= right), right; else if (oper==os_ge) return *boolresult &= (char)(left >= right), right; else if (oper==os_lt) return *boolresult &= (char)(left < right), right; else if (oper==os_gt) return *boolresult &= (char)(left > right), right; . . . } ``` As you can see, the `boolresult` is ANDed with the result of the current operation. If one of the operators in the chain earlier had evaluated to false, the `&` will force `boolresult` to remain `FALSE` irrespective of whether the current expression evaluates to true or not. ### What's the bug? The compiler loses the `boolresult` of `lval` in `plnge_rel` and replaces it with the `boolresult` of `lval2` which is always initalized to `FALSE` by `clear_val`. The fix is to ensure that `lval` retains the value. This commits does this by copying the `boolresult` of `lval2` into `lval` before `*lval=lval2`. This ensures that the `boolresult` is retained in `lval`. --- source/compiler/sc3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index c632b40..5895db9 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -512,6 +512,7 @@ static int plnge_rel(int *opstr,int opoff,int (*hier)(value *lval),value *lval) error(212); if (count>0) { relop_prefix(); + lval2.boolresult=lval->boolresult; *lval=lval2; /* copy right hand expression of the previous iteration */ } /* if */ opidx+=opoff; From 836d4d9e355f7a0136bc1f966bfe8232f0a8975c Mon Sep 17 00:00:00 2001 From: Y_Less Date: Sat, 16 Jun 2018 09:53:14 +0100 Subject: [PATCH 42/88] Fix #317 --- source/compiler/sc1.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 54878fc..b3eddeb 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -3150,8 +3150,7 @@ SC_FUNC symbol *fetchfunc(char *name,int tag) sym=addsym(name,code_idx,iFUNCTN,sGLOBAL,tag,0); assert(sym!=NULL); /* fatal error 103 must be given on error */ /* assume no arguments */ - sym->dim.arglist=(arginfo*)malloc(1*sizeof(arginfo)); - sym->dim.arglist[0].ident=0; + sym->dim.arglist=(arginfo*)calloc(1,sizeof(arginfo)); /* set library ID to NULL (only for native functions) */ sym->x.lib=NULL; /* set the required stack size to zero (only for non-native functions) */ From 9136cf29461bc2c1dfa68bd0aeff895bfa3e6340 Mon Sep 17 00:00:00 2001 From: Y_Less Date: Sat, 30 Jun 2018 16:41:50 +0200 Subject: [PATCH 43/88] Partially revert #c325ca3e028388ae6f934df2a4057229d24d021e to strip spaces in strings again. --- source/compiler/sc2.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index 7a123f8..fa3fdfe 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -396,8 +396,11 @@ static void readline(unsigned char *line) *line='\0'; /* delete line */ cont=FALSE; } else { - /* check whether to erase leading whitespace after '\\' on next line */ + /* check whether to erase leading spaces */ if (cont) { + unsigned char *ptr=line; + while (*ptr<=' ' && *ptr!='\0') + ptr++; if (ptr!=line) memmove(line,ptr,strlen((char*)ptr)+1); } /* if */ @@ -512,6 +515,8 @@ static void stripcomment(unsigned char *line) if (icomment==2) *line++=' '; } else if (*line=='/' && *(line+1)=='/'){ /* comment to end of line */ + if (strchr((char*)line,'\a')!=NULL) + error(49); /* invalid line continuation */ #if !defined SC_LIGHT if (*(line+2)=='/' && *(line+3)<=' ') { /* documentation comment */ @@ -903,6 +908,23 @@ static const unsigned char *getstring(unsigned char *dest,int max,const unsigned return line; } +/* strdupwithouta + * + * Duplicate a string, stripping out `\a`s. + */ +static char* strdupwithouta(const char* sourcestring) +{ + char* result=strdup(sourcestring); + char* a=result; + if (result==NULL) { + return NULL; + } + while ((a=strchr(a,'\a'))!=NULL) { + strcpy(a,a+1); + } + return result; +} + enum { CMD_NONE, CMD_TERM, @@ -1115,7 +1137,7 @@ static int command(void) /* remove leading whitespace */ while (*lptr<=' ' && *lptr!='\0') lptr++; - pc_deprecate=strdup((const char *)lptr); + pc_deprecate=strdupwithouta((const char *)lptr); if (pc_deprecate!=NULL) { char *ptr=pc_deprecate+strlen(pc_deprecate)-1; /* remove trailing whitespace */ @@ -1499,7 +1521,7 @@ static int command(void) while (*lptr<=' ' && *lptr!='\0') lptr++; if (!SKIPPING) { - char *usermsg=strdup((const char *)lptr); + char *usermsg=strdupwithouta((const char *)lptr); if (usermsg!=NULL) { char *ptr=usermsg+strlen(usermsg)-1; /* remove trailing whitespace and newlines */ @@ -1893,6 +1915,10 @@ static const unsigned char *unpackedstring(const unsigned char *lptr,int *flags) while (*lptr==' ' || *lptr=='\t') /* this is as defines with parameters may add them */ lptr++; /* when you use a space after , in a match pattern */ while (*lptr!='\0') { + if (*lptr=='\a') { + lptr++; + continue; + } /* if */ if (!instring) { if (*lptr=='\"') { instring=1; @@ -1963,6 +1989,10 @@ static const unsigned char *packedstring(const unsigned char *lptr,int *flags) i=sizeof(ucell)-(sCHARBITS/8); /* start at most significant byte */ val=0; while (*lptr!='\0') { + if (*lptr=='\a') { /* ignore '\a' (which was inserted at a line concatenation) */ + lptr++; + continue; + } /* if */ if (!instring) { if (*lptr=='\"') { instring=1; From 62805cb4000f1ce784628d07b114ec8a50de0bc6 Mon Sep 17 00:00:00 2001 From: Y_Less Date: Sat, 30 Jun 2018 16:47:47 +0200 Subject: [PATCH 44/88] Redetect error 49, and make `deprecated` auto-insert spaces. --- source/compiler/sc2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index fa3fdfe..c726aac 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -417,6 +417,10 @@ static void readline(unsigned char *line) ptr--; /* skip trailing whitespace */ if (*ptr=='\\') { cont=TRUE; + /* set '\a' at the position of '\\' to make it possible to check + * for a line continuation in a single line comment (error 49) + */ + *ptr++='\a'; *ptr='\0'; /* erase '\n' (and any trailing whitespace) */ } /* if */ } /* if */ @@ -920,7 +924,7 @@ static char* strdupwithouta(const char* sourcestring) return NULL; } while ((a=strchr(a,'\a'))!=NULL) { - strcpy(a,a+1); + *a=' '; } return result; } From 23485cfeda023d4bd9161801e815ddb9a3148556 Mon Sep 17 00:00:00 2001 From: Y_Less Date: Sat, 30 Jun 2018 17:00:46 +0200 Subject: [PATCH 45/88] Allow line continuations in single-line comments only when they are followed by another comment: It is quite annoying to get an error for commenting out a define using: // // #define LONG_MACRO\ // did span \ // multiple lines // --- source/compiler/sc2.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index c726aac..ffa5e25 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -448,6 +448,7 @@ static void readline(unsigned char *line) static void stripcomment(unsigned char *line) { char c; + char* continuation; #if !defined SC_LIGHT #define COMMENT_LIMIT 100 #define COMMENT_MARGIN 40 /* length of the longest word */ @@ -519,8 +520,24 @@ static void stripcomment(unsigned char *line) if (icomment==2) *line++=' '; } else if (*line=='/' && *(line+1)=='/'){ /* comment to end of line */ - if (strchr((char*)line,'\a')!=NULL) - error(49); /* invalid line continuation */ + continuation=line; + while ((continuation=strchr(continuation,'\a'))!=NULL){ + /* don't give the error if the next line is also commented out. + it is quite annoying to get an error for commenting out a define using: + + // + // #define LONG_MACRO\ + // did span \ + // multiple lines + // + */ + while (*continuation<=' ' && *continuation!='\0') + continuation++; /* skip whitespace */ + if (*continuation!='/' || *(continuation+1)!='/') { + error(49); /* invalid line continuation */ + break; + } + } #if !defined SC_LIGHT if (*(line+2)=='/' && *(line+3)<=' ') { /* documentation comment */ @@ -2062,7 +2079,7 @@ static const unsigned char *packedstring(const unsigned char *lptr,int *flags) if (*lptr==',' || *lptr==')' || *lptr=='}' || *lptr==';' || *lptr==':' || *lptr=='\n' || *lptr=='\r') - lptr=stringize; /* backtrack to end of last string for closing " */ + lptr=stringize; /* backtrack to end of last string for closing " */ return lptr; } From aa71219b8d6320dd16c44348095d892a28d752de Mon Sep 17 00:00:00 2001 From: Y_Less Date: Sat, 30 Jun 2018 17:09:53 +0200 Subject: [PATCH 46/88] Remove multi-line comment test. --- source/compiler/tests/gh_217.pwn | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/compiler/tests/gh_217.pwn b/source/compiler/tests/gh_217.pwn index 2d2d24c..c84af2c 100644 --- a/source/compiler/tests/gh_217.pwn +++ b/source/compiler/tests/gh_217.pwn @@ -17,7 +17,8 @@ warning 3 warning 4 // single-line comments can span \ -multiple lines if you really want it +//multiple lines if you really want it +// no they can't, only with more //s. #pragma deprecated don't\ use \ From 2f33bbae7672011287542d5f96a7ecab9b725d05 Mon Sep 17 00:00:00 2001 From: Y_Less Date: Sat, 30 Jun 2018 17:14:12 +0200 Subject: [PATCH 47/88] Fix test 217 again... --- source/compiler/tests/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index ef77935..57538fc 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -16,12 +16,12 @@ endfunction() # doesn't match the expected pattern. add_compiler_test(gh_217 ${CMAKE_CURRENT_SOURCE_DIR}/gh_217.pwn) -set_tests_properties(gh_217 PROPERTIES PASS_REGULAR_EXPRESSION ".*\\.pwn\\(11\\) : warning 237: user warning: this is warning 1 -.*\\.pwn\\(13\\) : warning 237: user warning: this iswarning 2 -.*\\.pwn\\(15\\) : warning 237: user warning: this is warning 3 -.*\\.pwn\\(17\\) : warning 237: user warning: this is warning 4 -.*\\.pwn\\(27\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this functionplease -.*\\.pwn\\(32\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this functionplease +set_tests_properties(gh_217 PROPERTIES PASS_REGULAR_EXPRESSION ".*\\.pwn\\(11\\) : warning 237: user warning: this is warning 1 +.*\\.pwn\\(13\\) : warning 237: user warning: this is warning 2 +.*\\.pwn\\(15\\) : warning 237: user warning: this is warning 3 +.*\\.pwn\\(17\\) : warning 237: user warning: this is warning 4 +.*\\.pwn\\(27\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this function please +.*\\.pwn\\(32\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this function please ") add_compiler_test(reset_errline_gh_230 ${CMAKE_CURRENT_SOURCE_DIR}/reset_errline_gh_230.pwn) From 000b4d52b98ae26e7acb83cd1642dee7dbcc7e38 Mon Sep 17 00:00:00 2001 From: Y_Less Date: Sat, 30 Jun 2018 17:23:12 +0200 Subject: [PATCH 48/88] Cast error on mac. Yet again fixing the tests... --- source/compiler/sc2.c | 2 +- source/compiler/tests/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index ffa5e25..ef9151e 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -520,7 +520,7 @@ static void stripcomment(unsigned char *line) if (icomment==2) *line++=' '; } else if (*line=='/' && *(line+1)=='/'){ /* comment to end of line */ - continuation=line; + continuation=(char*)line; while ((continuation=strchr(continuation,'\a'))!=NULL){ /* don't give the error if the next line is also commented out. it is quite annoying to get an error for commenting out a define using: diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index 57538fc..5d22a65 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -20,8 +20,8 @@ set_tests_properties(gh_217 PROPERTIES PASS_REGULAR_EXPRESSION ".*\\.pwn\\(11\\) .*\\.pwn\\(13\\) : warning 237: user warning: this is warning 2 .*\\.pwn\\(15\\) : warning 237: user warning: this is warning 3 .*\\.pwn\\(17\\) : warning 237: user warning: this is warning 4 -.*\\.pwn\\(27\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this function please -.*\\.pwn\\(32\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this function please +.*\\.pwn\\(28\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this function please +.*\\.pwn\\(33\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this function please ") add_compiler_test(reset_errline_gh_230 ${CMAKE_CURRENT_SOURCE_DIR}/reset_errline_gh_230.pwn) From 116ec5f0fd9c8a5e0ce55752b1343c6154792239 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 17 Jun 2018 12:07:24 +0530 Subject: [PATCH 49/88] mark array arguments of public functions modified The arguments of public functions are marked as READ by default to prevent 203/204 warnings. The reason is probably that there is no requirement imposed by the host on the user that they read all the arguments. Smilarly the array/reference arguments need not be modified but the forward takes both cases into consideration. This prevents warning 214 on array arguments of public functions. --- source/compiler/sc1.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index b3eddeb..4f1d7bc 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -4223,8 +4223,12 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, assert(numtags>0); argsym=addvariable(name,offset,ident,sLOCAL,tags[0], arg->dim,arg->numdim,arg->idxtag,0); - if (fpublic) + if (fpublic) { argsym->usage|=uREAD; /* arguments of public functions are always "used" */ + if(argsym->ident==iREFARRAY || argsym->ident==iREFERENCE) + argsym->usage|=uWRITTEN; + } + if (fconst) argsym->usage|=uCONST; } /* if */ From ffb161ad955f04f5ca59a3c60fa4d9e35c5a67d7 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 24 Jun 2018 10:15:03 +0530 Subject: [PATCH 50/88] check array depends for modifications for W214 --- source/compiler/sc1.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 4f1d7bc..de4796a 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -4907,9 +4907,20 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst) error(204,sym->name); /* value assigned to symbol is never used */ errorset(sSETPOS,-1); } else if ((sym->usage & (uWRITTEN | uPUBLIC | uCONST))==0 && sym->ident==iREFARRAY) { - errorset(sSETPOS,sym->lnumber); - error(214,sym->name); /* make array argument "const" */ - errorset(sSETPOS,-1); + int warn = 1; + symbol* depend = finddepend(sym); + while (depend != NULL) { + if ((depend->usage & (uWRITTEN | uPUBLIC | uCONST)) != 0) { + warn = 0; + break; + } + depend = finddepend(depend); + } /* while */ + if (warn) { + errorset(sSETPOS, sym->lnumber); + error(214, sym->name); /* make array argument "const" */ + errorset(sSETPOS, -1); + } /* if */ } /* if */ /* also mark the variable (local or global) to the debug information */ if ((sym->usage & (uWRITTEN | uREAD))!=0 && (sym->usage & uNATIVE)==0) From 8948f207ea9c7cef4e7808751a499310d1407148 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 24 Jun 2018 10:20:30 +0530 Subject: [PATCH 51/88] disable 239 for native functions --- source/compiler/sc3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index c632b40..c61a04c 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -2215,7 +2215,7 @@ static int nesting=0; if (arg[argidx].numdim!=1) { error(48); /* array dimensions must match */ } else { - if (lval.sym==NULL && (arg[argidx].usage & uCONST)==0) + if (lval.sym==NULL && (arg[argidx].usage & uCONST)==0 && (sym->usage & uNATIVE)==0) error(239); if (arg[argidx].dim[0]!=0) { assert(arg[argidx].dim[0]>0); From 1cdb8b7d6b90910bb08e6444e0c729dbf6d57f42 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 8 Jul 2018 13:29:52 +0530 Subject: [PATCH 52/88] add tests for i276 --- source/compiler/tests/CMakeLists.txt | 10 +++ .../const_array_args_and_literals_gh_276.pwn | 61 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 source/compiler/tests/const_array_args_and_literals_gh_276.pwn diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index 5d22a65..6da0c00 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -52,6 +52,16 @@ set_tests_properties(meaningless_class_specifiers_gh_172 PROPERTIES PASS_REGULAR .*\\.pwn\\(1 \\-\\- 2\\) : warning 238: meaningless combination of class specifiers \\(const variable arguments\\) ") +add_compiler_test(const_array_args_and_literals_gh_276 ${CMAKE_CURRENT_SOURCE_DIR}/const_array_args_and_literals_gh_276.pwn) +set_tests_properties(const_array_args_and_literals_gh_276 PROPERTIES PASS_REGULAR_EXPRESSION +".*\\.pwn\\(13\\) : warning 214: possibly a \\\"const\\\" array argument was intended: \\\"arr\\\" +.*\\.pwn\\(18\\) : warning 214: possibly a \\\"const\\\" array argument was intended: \\\"arr\\\" +.*\\.pwn\\(30\\) : warning 214: possibly a \\\"const\\\" array argument was intended: \\\"arr\\\" +.*\\.pwn\\(39\\) : warning 239: literal array/string passed to a non-const parameter +.*\\.pwn\\(40\\) : warning 239: literal array/string passed to a non-const parameter +.*\\.pwn\\(41\\) : warning 239: literal array/string passed to a non-const parameter +") + # Crashers # # These tests simply check that the compiler doesn't crash. diff --git a/source/compiler/tests/const_array_args_and_literals_gh_276.pwn b/source/compiler/tests/const_array_args_and_literals_gh_276.pwn new file mode 100644 index 0000000..fdc990d --- /dev/null +++ b/source/compiler/tests/const_array_args_and_literals_gh_276.pwn @@ -0,0 +1,61 @@ +forward OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]); + +native SetTimer(funcname[], interval, repeating); +public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) +{ + +} + +f0(arr[]) { + #pragma unused arr +} + +f1(arr[]) { // line 13 + new a = arr[0]; + #pragma unused a +} + +f2(arr[5]) {// line 18 + new a = arr[0]; + #pragma unused a +} +f3(const arr[]) { + new a = arr[0]; + #pragma unused a +} +f4(const arr[5]) { + new a = arr[0]; + #pragma unused a +} +f5(arr[][]) { // line 30 + new a = arr[0][0]; + #pragma unused a +} +f6(arr[][]) { + arr[0][0] = 0; +} + +main () { + f0("test"); // line 39 + f1("test"); // line 40 + f2("test"); // line 41 + f3("test"); + f4("test"); + + new arr[5]; + f1(arr); + f2(arr); + f3(arr); + f4(arr); + + f1(arr[0]); + //f2(arr[0]); - array size must match + f3(arr[0]); + //f4(arr[0]); - array size must match + + new arr2[1][1]; + f5(arr2); + f6(arr2); + + SetTimer("test", 0, 0); +} From 394330854b8f27ec4b4061c9091509cfa6a242d9 Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 8 Jul 2018 14:47:23 +0530 Subject: [PATCH 53/88] add test for i308 --- source/compiler/tests/CMakeLists.txt | 8 ++++++++ .../tests/constexpr_result_prop_gh_308.pwn | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 source/compiler/tests/constexpr_result_prop_gh_308.pwn diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index ef77935..bad72be 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -52,6 +52,14 @@ set_tests_properties(meaningless_class_specifiers_gh_172 PROPERTIES PASS_REGULAR .*\\.pwn\\(1 \\-\\- 2\\) : warning 238: meaningless combination of class specifiers \\(const variable arguments\\) ") +add_compiler_test(constexpr_result_prop_gh_308 ${CMAKE_CURRENT_SOURCE_DIR}/constexpr_result_prop_gh_308.pwn) +set_tests_properties(constexpr_result_prop_gh_308 PROPERTIES PASS_REGULAR_EXPRESSION +".*\\.pwn\\(2\\) : warning 237: user warning: \\\"Test passed.\\\" +.*\\.pwn\\(6\\) : warning 237: user warning: \\\"Test passed.\\\" +.*\\.pwn\\(10\\) : warning 237: user warning: \\\"Test passed.\\\" +.*\\.pwn\\(14\\) : warning 237: user warning: \\\"Test passed.\\\" +") + # Crashers # # These tests simply check that the compiler doesn't crash. diff --git a/source/compiler/tests/constexpr_result_prop_gh_308.pwn b/source/compiler/tests/constexpr_result_prop_gh_308.pwn new file mode 100644 index 0000000..0592bad --- /dev/null +++ b/source/compiler/tests/constexpr_result_prop_gh_308.pwn @@ -0,0 +1,19 @@ +#if (30 < 40 < 50) + #warning "Test passed." +#endif + +#if !(30 < 40 < 35) + #warning "Test passed." +#endif + +#if (30 < 40) + #warning "Test passed." +#endif + +#if !(40 < 35) + #warning "Test passed." +#endif + +main () { + +} From 0c9ddcfad1b58d29dccf7867d5a87e2dfa1fda65 Mon Sep 17 00:00:00 2001 From: Adrian Graber Date: Sun, 8 Jul 2018 18:00:15 +0200 Subject: [PATCH 54/88] Don't generate function preamble on naked functions --- source/compiler/sc.h | 2 +- source/compiler/sc1.c | 2 +- source/compiler/sc4.c | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index 1a517a4..e6e5a26 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -640,7 +640,7 @@ SC_FUNC void setlinedirect(int line); SC_FUNC void setlineconst(int line); SC_FUNC void setlabel(int index); SC_FUNC void markexpr(optmark type,const char *name,cell offset); -SC_FUNC void startfunc(char *fname); +SC_FUNC void startfunc(char *fname,int generateproc); SC_FUNC void endfunc(void); SC_FUNC void alignframe(int numbytes); SC_FUNC void rvalue(value *lval); diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index b3eddeb..3cb0eff 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -3798,7 +3798,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc ptr=ptr->next; } /* while */ } /* if */ - startfunc(sym->name); /* creates stack frame */ + startfunc(sym->name,(sym->flags & flagNAKED)==0); /* creates stack frame */ insert_dbgline(funcline); setline(FALSE); if (sc_alignnext) { diff --git a/source/compiler/sc4.c b/source/compiler/sc4.c index f2dd349..576c16b 100644 --- a/source/compiler/sc4.c +++ b/source/compiler/sc4.c @@ -343,9 +343,12 @@ SC_FUNC void markexpr(optmark type,const char *name,cell offset) * * Global references: funcstatus (referred to only) */ -SC_FUNC void startfunc(char *fname) +SC_FUNC void startfunc(char *fname,int generateproc) { - stgwrite("\tproc"); + if (generateproc) { + stgwrite("\tproc"); + code_idx+=opcodes(1); + } /* if */ if (sc_asmfile) { char symname[2*sNAMEMAX+16]; funcdisplayname(symname,fname); @@ -353,7 +356,6 @@ SC_FUNC void startfunc(char *fname) stgwrite(symname); } /* if */ stgwrite("\n"); - code_idx+=opcodes(1); } /* endfunc From 529b43d4dd75d0b7e23415649214b052d3ebad84 Mon Sep 17 00:00:00 2001 From: Barnaby Keene Date: Tue, 24 Jul 2018 18:48:46 +0100 Subject: [PATCH 55/88] Create CODEOWNERS --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..530f772 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @pawn-lang/compiler From ad4ad64a8b0cd55b7c273f6a9ea097746f492b33 Mon Sep 17 00:00:00 2001 From: Yashas Date: Thu, 14 Jun 2018 21:54:49 +0530 Subject: [PATCH 56/88] check dimensions of uninitialized array declarations Fix for #314 --- source/compiler/sc1.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 116a65e..09d25df 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -2490,17 +2490,21 @@ static void initials(int ident,int tag,cell *size,int dim[],int numdim, cell tablesize; int curlit=litidx; int err=0; + int i; if (!matchtoken('=')) { assert(ident!=iARRAY || numdim>0); - if (ident==iARRAY && dim[numdim-1]==0) { - /* declared as "myvar[];" which is senseless (note: this *does* make - * sense in the case of a iREFARRAY, which is a function parameter) - */ - error(9); /* array has zero length -> invalid size */ - } /* if */ if (ident==iARRAY) { assert(numdim>0 && numdim<=sDIMEN_MAX); + for (i=0; i invalid size */ + return; + } /* if */ + } /* for */ *size=calc_arraysize(dim,numdim,0); if (*size==(cell)CELL_MAX) { error(9); /* array is too big -> invalid size */ From 1ca89fa8644e096e841f3f239d6fc19544948a9c Mon Sep 17 00:00:00 2001 From: Yashas Date: Sun, 29 Jul 2018 16:33:34 +0530 Subject: [PATCH 57/88] add test for i314 --- source/compiler/tests/CMakeLists.txt | 10 +++++ .../tests/md_array_size_chk_gh_314.pwn | 40 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 source/compiler/tests/md_array_size_chk_gh_314.pwn diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index 2cf5a31..b1538ce 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -70,6 +70,16 @@ set_tests_properties(const_array_args_and_literals_gh_276 PROPERTIES PASS_REGULA .*\\.pwn\\(41\\) : warning 239: literal array/string passed to a non-const parameter ") +add_compiler_test(md_array_size_chk_gh_314 ${CMAKE_CURRENT_SOURCE_DIR}/md_array_size_chk_gh_314.pwn) +set_tests_properties(md_array_size_chk_gh_314 PROPERTIES PASS_REGULAR_EXPRESSION +"*\\.pwn\\(1\\) : error 009: invalid array size \\(negative, zero or out of bounds\\) +.*\\.pwn\\(2\\) : error 009: invalid array size \\(negative, zero or out of bounds\\) +.*\\.pwn\\(3\\) : error 009: invalid array size \\(negative, zero or out of bounds\\) +.*\\.pwn\\(5\\) : error 009: invalid array size \\(negative, zero or out of bounds\\) +.*\\.pwn\\(30\\) : warning 224: indeterminate array size in \"sizeof\" expression \\(symbol \"\"\\) +") +set_tests_properties(md_array_size_chk_gh_314 PROPERTIES WILL_FAIL TRUE) + # Crashers # # These tests simply check that the compiler doesn't crash. diff --git a/source/compiler/tests/md_array_size_chk_gh_314.pwn b/source/compiler/tests/md_array_size_chk_gh_314.pwn new file mode 100644 index 0000000..368833d --- /dev/null +++ b/source/compiler/tests/md_array_size_chk_gh_314.pwn @@ -0,0 +1,40 @@ +new arr1[] = {}; +new arr2[5][]; +new arr3[5][][5]; +new arr4[5][5]; +new arr5[][]= { { } }; + +f1(arr[]) { + #pragma unused arr +} +f2(arr[5][]) { + #pragma unused arr +} +f3(arr[5][][5]) { + #pragma unused arr +} +f4(arr[5][5]) { + #pragma unused arr +} +f5(arr[][]) { + #pragma unused arr +} + +main () { + arr1[0] = 0; + arr2[0][0] = 0; + arr3[0][0][0] = 0; + arr4[0][0] = 0; + arr5[0][0] = 0; + + new a = sizeof(arr1); + a = sizeof(arr1[]); + a = sizeof(arr5[][]); + #pragma unused a + + f1(arr1); + f2(arr2); + f3(arr3); + f4(arr4); + f5(arr5); +} From ce17cff7f725fef6ed670ecf02ae92ee4dba79dc Mon Sep 17 00:00:00 2001 From: Yashas Date: Fri, 8 Jun 2018 21:17:11 +0530 Subject: [PATCH 58/88] trigger destructor not implemented error ``` #include forward operator~(Error:right[], size); main() { new Error:e; } ``` ``` CODE 0 ; 0 ;program exit point halt 0 proc ; main ; line 4 ; line 5 break ; c ;$lcl e fffffffc push.c 0 ;$exp push.pri push.c 1 addr.pri fffffffc push.pri push.c 8 call .~4000000f ; operator~(Error:) pop.pri stack 4 zero.pri retn STKSIZE 1000 ``` The compiler tries to call a non-existent function. This commit instead throws "function not implemented" error when destructor definition is missing. --- source/compiler/sc1.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 116a65e..655678b 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -4967,6 +4967,14 @@ static void destructsymbols(symbol *root,int level) /* check that the '~' operator is defined for this tag */ operator_symname(symbolname,"~",sym->tag,0,1,0); if ((opsym=findglb(symbolname,sGLOBAL))!=NULL) { + if ((opsym->usage & uMISSING)!=0 || (opsym->usage & uPROTOTYPED)==0) { + char symname[2*sNAMEMAX+16]; /* allow space for user defined operators */ + funcdisplayname(symname,opsym->name); + if ((opsym->usage & uMISSING)!=0) + error(4,symname); /* function not defined */ + if ((opsym->usage & uPROTOTYPED)==0) + error(71,symname); /* operator must be declared before use */ + } /* if */ /* save PRI, in case of a return statment */ if (!savepri) { pushreg(sPRI); /* right-hand operand is in PRI */ From 6e2f17fa5365cca5a349785dc5f2ce2e45a5fcb0 Mon Sep 17 00:00:00 2001 From: Yashas Date: Wed, 1 Aug 2018 14:11:45 +0530 Subject: [PATCH 59/88] add test for i310 --- source/compiler/tests/CMakeLists.txt | 6 ++++++ source/compiler/tests/destructor_not_impl_gh_310.pwn | 4 ++++ 2 files changed, 10 insertions(+) create mode 100644 source/compiler/tests/destructor_not_impl_gh_310.pwn diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index 2cf5a31..7f92852 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -70,6 +70,12 @@ set_tests_properties(const_array_args_and_literals_gh_276 PROPERTIES PASS_REGULA .*\\.pwn\\(41\\) : warning 239: literal array/string passed to a non-const parameter ") +add_compiler_test(destructor_not_impl_gh_310 ${CMAKE_CURRENT_SOURCE_DIR}/destructor_not_impl_gh_310.pwn) +set_tests_properties(destructor_not_impl_gh_310 PROPERTIES PASS_REGULAR_EXPRESSION +".*\\.pwn\\(6\\) : error 004: function \"operator~(Error:)\" is not implemented +") +set_tests_properties(destructor_not_impl_gh_310 PROPERTIES WILL_FAIL TRUE) + # Crashers # # These tests simply check that the compiler doesn't crash. diff --git a/source/compiler/tests/destructor_not_impl_gh_310.pwn b/source/compiler/tests/destructor_not_impl_gh_310.pwn new file mode 100644 index 0000000..7855e78 --- /dev/null +++ b/source/compiler/tests/destructor_not_impl_gh_310.pwn @@ -0,0 +1,4 @@ +forward operator~(Error:right[], size); +main() { + new Error:e; +} From 018f1f65f380701db4ce212bc18b01ac5a2d1068 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 5 Aug 2018 20:06:53 +0600 Subject: [PATCH 60/88] Squash-and-Merge 3.10.8 (#352) * debug info for index tagmm warnings This commit makes the compiler display debug information for "index" tag mismatch warnings. * Fix #317 * Partially revert #c325ca3e028388ae6f934df2a4057229d24d021e to strip spaces in strings again. * Redetect error 49, and make `deprecated` auto-insert spaces. * Allow line continuations in single-line comments only when they are followed by another comment: It is quite annoying to get an error for commenting out a define using: // // #define LONG_MACRO\ // did span \ // multiple lines // * v3.10.8 * Remove multi-line comment test. * Fix test 217 again... * Yet again fixing the tests... * Cast error on mac. * Release 3.10.8 * Sorry for messing up the commit history... I'm trying to figure out releases. --- source/compiler/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index 1a2ff83..68e5bb5 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -5,7 +5,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake) set(VERSION_MAJOR 3) set(VERSION_MINOR 10) -set(VERSION_BUILD 7) +set(VERSION_BUILD 8) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}) set(VERSION_STR ${VERSION}) math(EXPR VERSION_INT "${VERSION_MAJOR} << 8 | ${VERSION_MINOR}") From c7cde7ad8ffcca6d7a579d6910034fd3299581b6 Mon Sep 17 00:00:00 2001 From: Yashas Samaga B L Date: Mon, 6 Aug 2018 21:18:59 +0530 Subject: [PATCH 61/88] Update ISSUE_TEMPLATE.md (#345) --- .github/ISSUE_TEMPLATE.md | 53 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index bafd4db..67f59ca 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,36 +1,37 @@ + + -**Is this a BUG REPORT, FEATURE REQUEST or QUESTION?**: +### Issue description: + -* [ ] Bug Report -* [ ] Feature Request -* [ ] Question +### Minimal complete verifiable example (MCVE): + -**How to reproduce it (as minimally and precisely as possible)**: +``` +``` -**Anything else we need to know?**: + -**Environment**: +### Workspace Information: -* Operating System -* Compiler version -* How are you invoking the compiler? Pawno, Sublime, vscode, sampctl or command-line? -* If using sampctl, the version number +* Compiler version: +* Command line arguments provided (or sampctl version): +* Operating System: From 29a6df8163cc664b5f3e4612987a04968b5abbc3 Mon Sep 17 00:00:00 2001 From: Zeex Date: Fri, 10 Aug 2018 23:43:02 +0600 Subject: [PATCH 62/88] Add a custom test runner script (#355) * Add a custom test runner script At the moment it supports only tests that output warnings or errors (test type = output_check). More types can be added in the future. --- .travis.yml | 5 +- appveyor.yml | 2 +- source/compiler/tests/CMakeLists.txt | 103 ++------------ .../const_array_args_and_literals_gh_276.meta | 11 ++ .../tests/constexpr_result_prop_gh_308.meta | 9 ++ .../tests/destructor_not_impl_gh_310.meta | 6 + source/compiler/tests/gh_217.meta | 11 ++ source/compiler/tests/gh_217.pwn | 2 +- source/compiler/tests/gh_283.meta | 6 + source/compiler/tests/gh_283.pwn | 4 +- .../compiler/tests/md_array_crash_gh_220.meta | 7 + .../compiler/tests/md_array_crash_gh_220.pwn | 3 +- .../tests/md_array_size_chk_gh_314.meta | 10 ++ .../tests/md_array_size_chk_gh_314.pwn | 4 +- .../meaningless_class_specifiers_gh_172.meta | 7 + .../meaningless_class_specifiers_gh_172.pwn | 10 +- .../compiler/tests/reset_errline_gh_230.meta | 9 ++ source/compiler/tests/run_tests.py | 132 ++++++++++++++++++ .../tests/too_many_args_crash_gh_298.meta | 11 ++ .../tests/too_many_args_crash_gh_298.pwn | 2 - .../tests/unused_symbol_line_gh_252.meta | 8 ++ 21 files changed, 251 insertions(+), 111 deletions(-) create mode 100644 source/compiler/tests/const_array_args_and_literals_gh_276.meta create mode 100644 source/compiler/tests/constexpr_result_prop_gh_308.meta create mode 100644 source/compiler/tests/destructor_not_impl_gh_310.meta create mode 100644 source/compiler/tests/gh_217.meta create mode 100644 source/compiler/tests/gh_283.meta create mode 100644 source/compiler/tests/md_array_crash_gh_220.meta create mode 100644 source/compiler/tests/md_array_size_chk_gh_314.meta create mode 100644 source/compiler/tests/meaningless_class_specifiers_gh_172.meta create mode 100644 source/compiler/tests/reset_errline_gh_230.meta create mode 100644 source/compiler/tests/run_tests.py create mode 100644 source/compiler/tests/too_many_args_crash_gh_298.meta create mode 100644 source/compiler/tests/unused_symbol_line_gh_252.meta diff --git a/.travis.yml b/.travis.yml index 11160e4..2378ac5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,12 +20,9 @@ before_script: script: - make - - make test + - make pawncc_tests - make package -after_failure: - - cat Testing/Temporary/LastTest.log - deploy: provider: releases api_key: diff --git a/appveyor.yml b/appveyor.yml index ec678af..78713fb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,7 +12,7 @@ build_script: - cmake --build . --config %CONFIGURATION% --target package test_script: - - ctest --build-config %CONFIGURATION% + - cmake --build . --config %CONFIGURATION% --target pawncc_tests on_failure: - type Testing\Temporary\LastTest.log diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index 02110b4..26d4d97 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -1,96 +1,9 @@ -set(DEFAULT_COMPILER_OPTIONS - -i${CMAKE_SOURCE_DIR}/include - "-\;+" - "-(+") +find_package(PythonInterp 2.7 REQUIRED) -function(add_compiler_test test_name options) - add_test(NAME ${test_name} - COMMAND $ ${DEFAULT_COMPILER_OPTIONS} ${options}) - set_tests_properties(${test_name} PROPERTIES - ENVIRONMENT PATH=$) -endfunction() - -# Compile tests -# -# These tests compare compile output against a regular expression and fail if the output -# doesn't match the expected pattern. - -add_compiler_test(gh_217 ${CMAKE_CURRENT_SOURCE_DIR}/gh_217.pwn) -set_tests_properties(gh_217 PROPERTIES PASS_REGULAR_EXPRESSION ".*\\.pwn\\(11\\) : warning 237: user warning: this is warning 1 -.*\\.pwn\\(13\\) : warning 237: user warning: this is warning 2 -.*\\.pwn\\(15\\) : warning 237: user warning: this is warning 3 -.*\\.pwn\\(17\\) : warning 237: user warning: this is warning 4 -.*\\.pwn\\(28\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this function please -.*\\.pwn\\(33\\) : warning 234: function is deprecated \\(symbol \"f\"\\) don't use this function please -") - -add_compiler_test(reset_errline_gh_230 ${CMAKE_CURRENT_SOURCE_DIR}/reset_errline_gh_230.pwn) -set_tests_properties(reset_errline_gh_230 PROPERTIES PASS_REGULAR_EXPRESSION -".*\\.pwn\\(2\\) : error 017: undefined symbol \\\"undefined\\\" -.*\\.pwn\\(2\\) : warning 215: expression has no effect -.*\\.pwn\\(7\\) : warning 204: symbol is assigned a value that is never used: \\\"y\\\" -.*\\.pwn\\(4\\) : warning 204: symbol is assigned a value that is never used: \\\"x\\\" -") - -add_compiler_test(unused_symbol_line_gh_252 ${CMAKE_CURRENT_SOURCE_DIR}/unused_symbol_line_gh_252.pwn) -set_tests_properties(unused_symbol_line_gh_252 PROPERTIES PASS_REGULAR_EXPRESSION -".*\\.pwn\\(4\\) : warning 203: symbol is never used: \\\"y\\\" -.*\\.pwn\\(8\\) : warning 203: symbol is never used: \\\"z\\\" -.*\\.pwn\\(1\\) : warning 203: symbol is never used: \\\"x\\\" -") - -add_compiler_test(gh_283 ${CMAKE_CURRENT_SOURCE_DIR}/gh_283.pwn) -set_tests_properties(gh_283 PROPERTIES PASS_REGULAR_EXPRESSION - ".*\\.pwn\\(5\\) : warning 234: function is deprecated \\(symbol \"print\"\\)") - -add_compiler_test(too_many_args_crash_gh_298 ${CMAKE_CURRENT_SOURCE_DIR}/too_many_args_crash_gh_298.pwn) -set_tests_properties(too_many_args_crash_gh_298 PROPERTIES PASS_REGULAR_EXPRESSION "too many function arguments") - -add_compiler_test(meaningless_class_specifiers_gh_172 ${CMAKE_CURRENT_SOURCE_DIR}/meaningless_class_specifiers_gh_172.pwn) -set_tests_properties(meaningless_class_specifiers_gh_172 PROPERTIES PASS_REGULAR_EXPRESSION -".*\\.pwn\\(1\\) : warning 238: meaningless combination of class specifiers \\(const reference\\) -.*\\.pwn\\(1 \\-\\- 2\\) : warning 238: meaningless combination of class specifiers \\(const variable arguments\\) -") - -add_compiler_test(constexpr_result_prop_gh_308 ${CMAKE_CURRENT_SOURCE_DIR}/constexpr_result_prop_gh_308.pwn) -set_tests_properties(constexpr_result_prop_gh_308 PROPERTIES PASS_REGULAR_EXPRESSION -".*\\.pwn\\(2\\) : warning 237: user warning: \\\"Test passed.\\\" -.*\\.pwn\\(6\\) : warning 237: user warning: \\\"Test passed.\\\" -.*\\.pwn\\(10\\) : warning 237: user warning: \\\"Test passed.\\\" -.*\\.pwn\\(14\\) : warning 237: user warning: \\\"Test passed.\\\" -") - -add_compiler_test(const_array_args_and_literals_gh_276 ${CMAKE_CURRENT_SOURCE_DIR}/const_array_args_and_literals_gh_276.pwn) -set_tests_properties(const_array_args_and_literals_gh_276 PROPERTIES PASS_REGULAR_EXPRESSION -".*\\.pwn\\(13\\) : warning 214: possibly a \\\"const\\\" array argument was intended: \\\"arr\\\" -.*\\.pwn\\(18\\) : warning 214: possibly a \\\"const\\\" array argument was intended: \\\"arr\\\" -.*\\.pwn\\(30\\) : warning 214: possibly a \\\"const\\\" array argument was intended: \\\"arr\\\" -.*\\.pwn\\(39\\) : warning 239: literal array/string passed to a non-const parameter -.*\\.pwn\\(40\\) : warning 239: literal array/string passed to a non-const parameter -.*\\.pwn\\(41\\) : warning 239: literal array/string passed to a non-const parameter -") - -add_compiler_test(md_array_size_chk_gh_314 ${CMAKE_CURRENT_SOURCE_DIR}/md_array_size_chk_gh_314.pwn) -set_tests_properties(md_array_size_chk_gh_314 PROPERTIES PASS_REGULAR_EXPRESSION -"*\\.pwn\\(1\\) : error 009: invalid array size \\(negative, zero or out of bounds\\) -.*\\.pwn\\(2\\) : error 009: invalid array size \\(negative, zero or out of bounds\\) -.*\\.pwn\\(3\\) : error 009: invalid array size \\(negative, zero or out of bounds\\) -.*\\.pwn\\(5\\) : error 009: invalid array size \\(negative, zero or out of bounds\\) -.*\\.pwn\\(30\\) : warning 224: indeterminate array size in \"sizeof\" expression \\(symbol \"\"\\) -") -set_tests_properties(md_array_size_chk_gh_314 PROPERTIES WILL_FAIL TRUE) - -add_compiler_test(destructor_not_impl_gh_310 ${CMAKE_CURRENT_SOURCE_DIR}/destructor_not_impl_gh_310.pwn) -set_tests_properties(destructor_not_impl_gh_310 PROPERTIES PASS_REGULAR_EXPRESSION -".*\\.pwn\\(6\\) : error 004: function \"operator~(Error:)\" is not implemented -") -set_tests_properties(destructor_not_impl_gh_310 PROPERTIES WILL_FAIL TRUE) - -# Crashers -# -# These tests simply check that the compiler doesn't crash. -# -# TODO: Probably need to support tests that exist with a non-zero code but don't crash? -# Right now this will cause a failure. - -add_compiler_test(md_array_crash_gh_220 ${CMAKE_CURRENT_SOURCE_DIR}/md_array_crash_gh_220.pwn) +add_custom_target(pawncc_tests COMMAND + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/run_tests.py + -c $ + -i ../../../include + DEPENDS pawncc + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/source/compiler/tests/const_array_args_and_literals_gh_276.meta b/source/compiler/tests/const_array_args_and_literals_gh_276.meta new file mode 100644 index 0000000..861e659 --- /dev/null +++ b/source/compiler/tests/const_array_args_and_literals_gh_276.meta @@ -0,0 +1,11 @@ +{ + 'test_type': 'output_check', + 'errors': """ +const_array_args_and_literals_gh_276.pwn(13) : warning 214: possibly a "const" array argument was intended: "arr" +const_array_args_and_literals_gh_276.pwn(18) : warning 214: possibly a "const" array argument was intended: "arr" +const_array_args_and_literals_gh_276.pwn(30) : warning 214: possibly a "const" array argument was intended: "arr" +const_array_args_and_literals_gh_276.pwn(39) : warning 239: literal array/string passed to a non-const parameter +const_array_args_and_literals_gh_276.pwn(40) : warning 239: literal array/string passed to a non-const parameter +const_array_args_and_literals_gh_276.pwn(41) : warning 239: literal array/string passed to a non-const parameter +""" +} diff --git a/source/compiler/tests/constexpr_result_prop_gh_308.meta b/source/compiler/tests/constexpr_result_prop_gh_308.meta new file mode 100644 index 0000000..197d682 --- /dev/null +++ b/source/compiler/tests/constexpr_result_prop_gh_308.meta @@ -0,0 +1,9 @@ +{ + 'test_type': 'output_check', + 'errors': """ +constexpr_result_prop_gh_308.pwn(2) : warning 237: user warning: "Test passed." +constexpr_result_prop_gh_308.pwn(6) : warning 237: user warning: "Test passed." +constexpr_result_prop_gh_308.pwn(10) : warning 237: user warning: "Test passed." +constexpr_result_prop_gh_308.pwn(14) : warning 237: user warning: "Test passed." +""" +} diff --git a/source/compiler/tests/destructor_not_impl_gh_310.meta b/source/compiler/tests/destructor_not_impl_gh_310.meta new file mode 100644 index 0000000..3e1e1be --- /dev/null +++ b/source/compiler/tests/destructor_not_impl_gh_310.meta @@ -0,0 +1,6 @@ +{ + 'test_type': 'output_check', + 'errors': """ +destructor_not_impl_gh_310.pwn(4) : error 004: function "operator~(Error:)" is not implemented +""" +} diff --git a/source/compiler/tests/gh_217.meta b/source/compiler/tests/gh_217.meta new file mode 100644 index 0000000..f40a838 --- /dev/null +++ b/source/compiler/tests/gh_217.meta @@ -0,0 +1,11 @@ +{ + 'test_type': 'output_check', + 'errors': """ +gh_217.pwn(11) : warning 237: user warning: this is warning 1 +gh_217.pwn(13) : warning 237: user warning: this is warning 2 +gh_217.pwn(15) : warning 237: user warning: this is warning 3 +gh_217.pwn(17) : warning 237: user warning: this is warning 4 +gh_217.pwn(28) : warning 234: function is deprecated (symbol "f") don't use this function please +gh_217.pwn(33) : warning 234: function is deprecated (symbol "f") don't use this function please +""" +} diff --git a/source/compiler/tests/gh_217.pwn b/source/compiler/tests/gh_217.pwn index c84af2c..9b6fe6e 100644 --- a/source/compiler/tests/gh_217.pwn +++ b/source/compiler/tests/gh_217.pwn @@ -1,6 +1,6 @@ // TODO: Check that string literals are concatenated correctly -native print(const s[]); +#include #define d1\ print("ok") diff --git a/source/compiler/tests/gh_283.meta b/source/compiler/tests/gh_283.meta new file mode 100644 index 0000000..3fcfc5f --- /dev/null +++ b/source/compiler/tests/gh_283.meta @@ -0,0 +1,6 @@ +{ + 'test_type': 'output_check', + 'errors': """ + gh_283.pwn(5) : warning 234: function is deprecated (symbol "f") + """ +} diff --git a/source/compiler/tests/gh_283.pwn b/source/compiler/tests/gh_283.pwn index 87645ac..0cc57dd 100644 --- a/source/compiler/tests/gh_283.pwn +++ b/source/compiler/tests/gh_283.pwn @@ -1,6 +1,6 @@ #pragma deprecated -native print(const string[]); +native f(); main() { - print("Hello World"); + f(); } diff --git a/source/compiler/tests/md_array_crash_gh_220.meta b/source/compiler/tests/md_array_crash_gh_220.meta new file mode 100644 index 0000000..69deb64 --- /dev/null +++ b/source/compiler/tests/md_array_crash_gh_220.meta @@ -0,0 +1,7 @@ +{ + 'test_type': 'output_check', + 'errors': """ +md_array_crash_gh_220.pwn(6) : fatal error 111: user error: OK +Compilation aborted. +""" +} diff --git a/source/compiler/tests/md_array_crash_gh_220.pwn b/source/compiler/tests/md_array_crash_gh_220.pwn index 74f27c7..20f2a75 100644 --- a/source/compiler/tests/md_array_crash_gh_220.pwn +++ b/source/compiler/tests/md_array_crash_gh_220.pwn @@ -3,4 +3,5 @@ new b[2000][500] = { { 0, -1, ... }, ... }; main() { a[0][0] = b[0][0]; -} \ No newline at end of file + #error OK +} diff --git a/source/compiler/tests/md_array_size_chk_gh_314.meta b/source/compiler/tests/md_array_size_chk_gh_314.meta new file mode 100644 index 0000000..44b8595 --- /dev/null +++ b/source/compiler/tests/md_array_size_chk_gh_314.meta @@ -0,0 +1,10 @@ +{ + 'test_type': 'output_check', + 'errors': """ +md_array_size_chk_gh_314.pwn(1) : error 009: invalid array size (negative, zero or out of bounds) +md_array_size_chk_gh_314.pwn(2) : error 009: invalid array size (negative, zero or out of bounds) +md_array_size_chk_gh_314.pwn(3) : error 009: invalid array size (negative, zero or out of bounds) +md_array_size_chk_gh_314.pwn(5) : error 009: invalid array size (negative, zero or out of bounds) +md_array_size_chk_gh_314.pwn(30) : warning 224: indeterminate array size in "sizeof" expression (symbol "") +""" +} diff --git a/source/compiler/tests/md_array_size_chk_gh_314.pwn b/source/compiler/tests/md_array_size_chk_gh_314.pwn index 368833d..f926648 100644 --- a/source/compiler/tests/md_array_size_chk_gh_314.pwn +++ b/source/compiler/tests/md_array_size_chk_gh_314.pwn @@ -1,8 +1,8 @@ -new arr1[] = {}; +new arr1[]; new arr2[5][]; new arr3[5][][5]; new arr4[5][5]; -new arr5[][]= { { } }; +new arr5[][]; f1(arr[]) { #pragma unused arr diff --git a/source/compiler/tests/meaningless_class_specifiers_gh_172.meta b/source/compiler/tests/meaningless_class_specifiers_gh_172.meta new file mode 100644 index 0000000..d6ccf1a --- /dev/null +++ b/source/compiler/tests/meaningless_class_specifiers_gh_172.meta @@ -0,0 +1,7 @@ +{ + 'test_type': 'output_check', + 'errors': """ +meaningless_class_specifiers_gh_172.pwn(1) : warning 238: meaningless combination of class specifiers (const reference) +meaningless_class_specifiers_gh_172.pwn(4) : warning 238: meaningless combination of class specifiers (const variable arguments) +""" +} diff --git a/source/compiler/tests/meaningless_class_specifiers_gh_172.pwn b/source/compiler/tests/meaningless_class_specifiers_gh_172.pwn index 68bfd02..1fd4d91 100755 --- a/source/compiler/tests/meaningless_class_specifiers_gh_172.pwn +++ b/source/compiler/tests/meaningless_class_specifiers_gh_172.pwn @@ -1,4 +1,6 @@ -f1(const &v) { } +f1(const &v) { + #pragma unused v +} f2(const ...) { } f3(const v) { #pragma unused v @@ -7,7 +9,9 @@ f4(...) { } f5(v) { #pragma unused v } -f6(&v) { } +f6(&v) { + #pragma unused v +} main() { new a; @@ -17,4 +21,4 @@ main() { f4(a); f5(a); f6(a); -} \ No newline at end of file +} diff --git a/source/compiler/tests/reset_errline_gh_230.meta b/source/compiler/tests/reset_errline_gh_230.meta new file mode 100644 index 0000000..8b754d7 --- /dev/null +++ b/source/compiler/tests/reset_errline_gh_230.meta @@ -0,0 +1,9 @@ +{ + 'test_type': 'output_check', + 'errors': """ +reset_errline_gh_230.pwn(2) : error 017: undefined symbol \"undefined\" +reset_errline_gh_230.pwn(2) : warning 215: expression has no effect +reset_errline_gh_230.pwn(7) : warning 204: symbol is assigned a value that is never used: "y" +reset_errline_gh_230.pwn(4) : warning 204: symbol is assigned a value that is never used: "x" +""" +} diff --git a/source/compiler/tests/run_tests.py b/source/compiler/tests/run_tests.py new file mode 100644 index 0000000..2280c74 --- /dev/null +++ b/source/compiler/tests/run_tests.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python + +import argparse +import glob +import os.path +import re +import subprocess +import sys + +parser = argparse.ArgumentParser() +parser.add_argument('-c', '--compiler', + required=True, + help='path to the pawncc executable') +parser.add_argument('-i', '--include', + dest='include_dirs', + action='append', + help='add specified directory to include path') +options = parser.parse_args(sys.argv[1:]) + +def run_compiler(args): + process_args = [';+', '-(+'] + if options.include_dirs is not None: + for dir in options.include_dirs: + process_args.append('-i' + dir) + if args is not None: + process_args += args + return subprocess.Popen(executable=options.compiler, + args=process_args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + +class OutputCheckTest: + def __init__(self, + name, + source_file, + errors=None, + extra_args=None): + self.name = name + self.source_file = source_file + self.errors = errors + self.extra_args = extra_args + + def run(self): + args = [self.source_file] + if self.extra_args is not None: + args += extra_args + process = run_compiler(args=args) + stdout, stderr = process.communicate() + result = True + if self.errors is None: + if process.returncode != 0: + result = False + self.fail_reason = """ + No errors specified and process exited with non-zero status + """ + else: + errors = stderr.decode('utf-8').splitlines() + errors = [e.strip() for e in errors if e.strip()] + expected_errors = self.errors.splitlines() + expected_errors = [e.strip() for e in expected_errors if e.strip()] + if errors != expected_errors: + result = False + self.fail_reason = ( + 'Error output didn\'t match\n\nExpected errors:\n\n{}\n\n' + 'Actual errors:\n\n{}' + ).format( + '\n'.join(expected_errors).strip(' \t\r\n'), + '\n'.join(errors).strip(' \t\r\n') + ) + return result + +class CrashTest: + def __init__(self, name, source_file, extra_args=None): + self.name = name + self.source_file = source_file + self.extra_args = extra_args + + def run(self): + # TODO: Check if the process crashed. + return True + +test_types = { + 'output_check': OutputCheckTest, + 'crash': CrashTest +} + +tests = [] +num_tests_disabled = 0 +for meta_file in glob.glob('*.meta'): + name = os.path.splitext(meta_file)[0] + metadata = eval(open(meta_file).read(), None, None) + if metadata.get('disabled'): + num_tests_disabled += 1 + continue + test_type = metadata['test_type'] + if test_type == 'output_check': + tests.append(OutputCheckTest(name=name, + source_file=name + '.pwn', + errors=metadata.get('errors'), + extra_args=metadata.get('extra_args'))) + elif test_type == 'crash': + tests.append(CrashTest(name=name, source_file=name + '.pwn')) + else: + raise KeyError('Unknown test type: ' + test_type) + +num_tests = len(tests) +sys.stdout.write('DISCOVERED {} TEST{}'.format(num_tests, '' if num_tests == 1 else 'S')) +if num_tests_disabled > 0: + sys.stdout.write(' ({} DISABLED)'.format(num_tests_disabled)) +sys.stdout.write('\n\n') + +num_tests_failed = 0 +for test in tests: + sys.stdout.write('Running ' + test.name + '... ') + if not test.run(): + sys.stdout.write('FAILED\n') + print('Test {} failed for the following reason: {}'.format( + test.name, test.fail_reason)) + print('') + num_tests_failed += 1 + else: + sys.stdout.write('PASSED\n') + +num_tests_passed = len(tests) - num_tests_failed +if num_tests_failed > 0: + print('\n{} TEST{} PASSED, {} FAILED'.format( + num_tests_passed, + '' if num_tests_passed == 1 else 'S', + num_tests_failed)) + sys.exit(1) +else: + print('\nALL TESTS PASSED') diff --git a/source/compiler/tests/too_many_args_crash_gh_298.meta b/source/compiler/tests/too_many_args_crash_gh_298.meta new file mode 100644 index 0000000..131078f --- /dev/null +++ b/source/compiler/tests/too_many_args_crash_gh_298.meta @@ -0,0 +1,11 @@ +{ + 'test_type': 'output_check', + 'errors': """ +too_many_args_crash_gh_298.pwn(2) : error 045: too many function arguments +too_many_args_crash_gh_298.pwn(2) : warning 215: expression has no effect +too_many_args_crash_gh_298.pwn(2) : error 001: expected token: ";", but found ")" +too_many_args_crash_gh_298.pwn(2) : error 029: invalid expression, assumed zero +too_many_args_crash_gh_298.pwn(2) : fatal error 107: too many error messages on one line +Compilation aborted. +""" +} diff --git a/source/compiler/tests/too_many_args_crash_gh_298.pwn b/source/compiler/tests/too_many_args_crash_gh_298.pwn index 525936c..5c07367 100644 --- a/source/compiler/tests/too_many_args_crash_gh_298.pwn +++ b/source/compiler/tests/too_many_args_crash_gh_298.pwn @@ -1,5 +1,3 @@ -native printf(const format[], ...); - main() { printf("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } diff --git a/source/compiler/tests/unused_symbol_line_gh_252.meta b/source/compiler/tests/unused_symbol_line_gh_252.meta new file mode 100644 index 0000000..4cfffc8 --- /dev/null +++ b/source/compiler/tests/unused_symbol_line_gh_252.meta @@ -0,0 +1,8 @@ +{ + 'test_type': 'output_check', + 'errors': """ +unused_symbol_line_gh_252.pwn(4) : warning 203: symbol is never used: "y" +unused_symbol_line_gh_252.pwn(8) : warning 203: symbol is never used: "z" +unused_symbol_line_gh_252.pwn(1) : warning 203: symbol is never used: "x" +""" +} From 0a574d5f25cd03a024b54b0faae2c4196bba783a Mon Sep 17 00:00:00 2001 From: Zeex Date: Sat, 11 Aug 2018 20:03:37 +0600 Subject: [PATCH 63/88] Remove CTest and add a top-level CMakeLists.txt --- .travis.yml | 6 +++--- CMakeLists.txt | 8 ++++++++ appveyor.yml | 5 +---- source/amx/CMakeLists.txt | 1 + source/compiler/CMakeLists.txt | 8 ++------ 5 files changed, 15 insertions(+), 13 deletions(-) create mode 100644 CMakeLists.txt diff --git a/.travis.yml b/.travis.yml index 2378ac5..4b71685 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,9 @@ addons: - cmake before_script: - - cmake source/compiler -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DCMAKE_C_FLAGS="-m32 -Werror -Wno-address-of-packed-member" - -DCPACK_GENERATOR="TGZ;ZIP" + - cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DCMAKE_C_FLAGS="-m32 -Werror -Wno-address-of-packed-member" + -DCPACK_GENERATOR="TGZ;ZIP" script: - make diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b386580 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +project(pawn C) +cmake_minimum_required(VERSION 2.8) + +# For the compiler we only utilize headers from source/amx, i.e. we don't +# actually build any of the AMX modules. +# add_subdirectory(source/amx) + +add_subdirectory(source/compiler) diff --git a/appveyor.yml b/appveyor.yml index 78713fb..bf09638 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ configuration: - RelWithDebInfo before_build: - - cmake -G "Visual Studio 14 2015" source/compiler -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 + - cmake . -G "Visual Studio 14 2015" -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 build_script: - cmake --build . --config %CONFIGURATION% @@ -14,9 +14,6 @@ build_script: test_script: - cmake --build . --config %CONFIGURATION% --target pawncc_tests -on_failure: - - type Testing\Temporary\LastTest.log - artifacts: - path: pawnc-*-windows.zip name: Binary package diff --git a/source/amx/CMakeLists.txt b/source/amx/CMakeLists.txt index a3bfb0f..bc68454 100644 --- a/source/amx/CMakeLists.txt +++ b/source/amx/CMakeLists.txt @@ -68,6 +68,7 @@ if(WIN32) set_target_properties(amxDGram PROPERTIES LINK_FLAGS "/export:amx_DGramInit /export:amx_DGramCleanup") endif() + target_link_libraries(amxDGram ws2_32) endif() # amxFile diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index 1a2ff83..51cee48 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -160,12 +160,8 @@ if(MSVC) DESTINATION bin) endif() -# Generate tests (only if enabled, i.e. BUILD_TESTING=ON) -include(CTest) -if(BUILD_TESTING) - enable_testing() - add_subdirectory(tests) -endif() +# Generate targets for running compiler tests +add_subdirectory(tests) # Generate a binary package with CPack set(CPACK_PACKAGE_NAME pawnc) From 038bf419ffb96658db8e1644d3bb8fac4575f02c Mon Sep 17 00:00:00 2001 From: Zeex Date: Sat, 11 Aug 2018 23:12:13 +0600 Subject: [PATCH 64/88] Add support for runtime compiler tests --- .travis.yml | 4 +- CMakeLists.txt | 9 ++- appveyor.yml | 5 +- source/compiler/CMakeLists.txt | 12 ++++ source/compiler/pawnruns.c | 55 ++++++++++++++++ source/compiler/tests/CMakeLists.txt | 21 +++--- .../compiler/tests/md_array_crash_gh_220.meta | 1 + source/compiler/tests/run_tests.py | 64 +++++++++++++------ .../compiler/tests/runtime_test_example.meta | 7 ++ .../compiler/tests/runtime_test_example.pwn | 10 +++ .../tests/too_many_args_crash_gh_298.meta | 1 + 11 files changed, 155 insertions(+), 34 deletions(-) create mode 100644 source/compiler/pawnruns.c create mode 100644 source/compiler/tests/runtime_test_example.meta create mode 100644 source/compiler/tests/runtime_test_example.pwn diff --git a/.travis.yml b/.travis.yml index 4b71685..d318aee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,8 +29,8 @@ deploy: secure: gDAuRNlF2uVhVHyZtJrX6MwNxnkfkQzohrC/6UcKAgqt+NKs4vZyq5FzTUceiDAkB0se70ZVx08e9ibAiXP/b7D1MPkAEiRxt9J6Vu3x6Bi1kPPuK5RfjFeT3gc1SbrULAP8Nz0NdU0chUhei6/V5NGhTegwp925DJOISq7+Ibw= file_glob: true file: - - 'pawnc-*-linux.tar.gz' - - 'pawnc-*-macos.zip' + - 'build/pawnc-*-linux.tar.gz' + - 'build/pawnc-*-macos.zip' draft: true skip_cleanup: true on: diff --git a/CMakeLists.txt b/CMakeLists.txt index b386580..1a2c664 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,11 @@ project(pawn C) cmake_minimum_required(VERSION 2.8) +set(OUTPUT_DIR ${CMAKE_BINARY_DIR}/products) +add_subdirectory(source/compiler ${OUTPUT_DIR}) + # For the compiler we only utilize headers from source/amx, i.e. we don't # actually build any of the AMX modules. -# add_subdirectory(source/amx) - -add_subdirectory(source/compiler) +if(BUILD_AMX) + add_subdirectory(source/amx ${OUTPUT_DIR}) +endif() diff --git a/appveyor.yml b/appveyor.yml index bf09638..b185ace 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,8 @@ configuration: - RelWithDebInfo before_build: - - cmake . -G "Visual Studio 14 2015" -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 + - mkdir build && cd build + - cmake ../source -G "Visual Studio 14 2015" -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 build_script: - cmake --build . --config %CONFIGURATION% @@ -15,7 +16,7 @@ test_script: - cmake --build . --config %CONFIGURATION% --target pawncc_tests artifacts: - - path: pawnc-*-windows.zip + - path: build/pawnc-*-windows.zip name: Binary package deploy: diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index 51cee48..f7c5c56 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -139,6 +139,9 @@ target_link_libraries(pawncc pawnc) # The Pawn disassembler set(PAWNDISASM_SRCS pawndisasm.c + sc.h + ../amx/amx.h + ../amx/amxdbg.h ../amx/amxdbg.c ) add_executable(pawndisasm ${PAWNDISASM_SRCS}) @@ -161,6 +164,15 @@ if(MSVC) endif() # Generate targets for running compiler tests +set(PAWNRUNS_SRCS + pawnruns.c + ../amx/amx.c + ../amx/amx.h + ../amx/amxaux.c + ../amx/amxaux.h + ../amx/amxcons.c + ../amx/amxcore.c) +add_executable(pawnruns ${PAWNRUNS_SRCS}) add_subdirectory(tests) # Generate a binary package with CPack diff --git a/source/compiler/pawnruns.c b/source/compiler/pawnruns.c new file mode 100644 index 0000000..cc955fe --- /dev/null +++ b/source/compiler/pawnruns.c @@ -0,0 +1,55 @@ +/* A simpler runner based on source/amx/pawnrun/prun1.c. + * + * Copyright (c) ITB CompuPhase, 2001-2005 + * + * This file may be freely used. No warranties of any kind. + */ + +#include +#include /* for exit() */ +#include +#include /* for memset() (on some compilers) */ +#include "../amx/amx.h" +#include "../amx/amxaux.h" + +static void ErrorExit(AMX *amx, int errorcode) +{ + printf("Run time error %d: \"%s\"\n", errorcode, aux_StrError(errorcode)); + exit(1); +} + +static void PrintUsage(char *program) +{ + printf("Usage: %s \n is a compiled script.\n", program); + exit(1); +} + +int main(int argc,char *argv[]) +{ + extern AMX_NATIVE_INFO console_Natives[]; + extern AMX_NATIVE_INFO core_Natives[]; + + AMX amx; + cell ret = 0; + int err; + + if (argc != 2) + PrintUsage(argv[0]); + + err = aux_LoadProgram(&amx, argv[1], NULL); + if (err != AMX_ERR_NONE) + ErrorExit(&amx, err); + + amx_Register(&amx, console_Natives, -1); + err = amx_Register(&amx, core_Natives, -1); + if (err != AMX_ERR_NONE) + ErrorExit(&amx, err); + + err = amx_Exec(&amx, &ret, AMX_EXEC_MAIN); + if (err != AMX_ERR_NONE) + ErrorExit(&amx, err); + printf("%s returns %ld\n", argv[1], (long)ret); + + aux_FreeProgram(&amx); + return 0; +} diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index 26d4d97..1921ab6 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -1,9 +1,14 @@ -find_package(PythonInterp 2.7 REQUIRED) +find_package(PythonInterp 2.7) -add_custom_target(pawncc_tests COMMAND - COMMAND ${PYTHON_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/run_tests.py - -c $ - -i ../../../include - DEPENDS pawncc - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +if(PYTHONINTERP_FOUND) + add_custom_target(pawncc_tests COMMAND + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/run_tests.py + -c $ + -r $ + -i ../../../include + DEPENDS pawncc + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +else() + message("Python was not found, you will not be able to run the compiler tests") +endif() diff --git a/source/compiler/tests/md_array_crash_gh_220.meta b/source/compiler/tests/md_array_crash_gh_220.meta index 69deb64..065c642 100644 --- a/source/compiler/tests/md_array_crash_gh_220.meta +++ b/source/compiler/tests/md_array_crash_gh_220.meta @@ -2,6 +2,7 @@ 'test_type': 'output_check', 'errors': """ md_array_crash_gh_220.pwn(6) : fatal error 111: user error: OK + Compilation aborted. """ } diff --git a/source/compiler/tests/run_tests.py b/source/compiler/tests/run_tests.py index 2280c74..946bbce 100644 --- a/source/compiler/tests/run_tests.py +++ b/source/compiler/tests/run_tests.py @@ -10,11 +10,14 @@ import sys parser = argparse.ArgumentParser() parser.add_argument('-c', '--compiler', required=True, - help='path to the pawncc executable') + help='path to compiler executable (pawncc or pawncc.exe)') parser.add_argument('-i', '--include', dest='include_dirs', action='append', - help='add specified directory to include path') + help='add custom include directories for compile tests') +parser.add_argument('-r', '--runner', + required=True, + help='path to runner executable (pawnrun or pawnrun.exe)') options = parser.parse_args(sys.argv[1:]) def run_compiler(args): @@ -30,11 +33,7 @@ def run_compiler(args): stderr=subprocess.PIPE) class OutputCheckTest: - def __init__(self, - name, - source_file, - errors=None, - extra_args=None): + def __init__(self, name, source_file, errors=None, extra_args=None): self.name = name self.source_file = source_file self.errors = errors @@ -54,19 +53,14 @@ class OutputCheckTest: No errors specified and process exited with non-zero status """ else: - errors = stderr.decode('utf-8').splitlines() - errors = [e.strip() for e in errors if e.strip()] - expected_errors = self.errors.splitlines() - expected_errors = [e.strip() for e in expected_errors if e.strip()] + errors = stderr.decode('utf-8').strip(' \t\r\n').replace('\r', '') + expected_errors = self.errors.strip(' \t\r\n').replace('\r', '') if errors != expected_errors: result = False self.fail_reason = ( 'Error output didn\'t match\n\nExpected errors:\n\n{}\n\n' 'Actual errors:\n\n{}' - ).format( - '\n'.join(expected_errors).strip(' \t\r\n'), - '\n'.join(errors).strip(' \t\r\n') - ) + ).format(expected_errors, errors) return result class CrashTest: @@ -79,10 +73,37 @@ class CrashTest: # TODO: Check if the process crashed. return True -test_types = { - 'output_check': OutputCheckTest, - 'crash': CrashTest -} +class RuntimeTest: + def __init__(self, name, amx_file, output, should_fail): + self.name = name + self.amx_file = amx_file + self.output = output + self.should_fail = should_fail + + def run(self): + process = subprocess.Popen([options.runner, self.amx_file], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + output = '' + if stdout is not None: + output = stdout.decode('utf-8') + if stderr is not None: + output += stderr.decode('utf-8') + output = output.strip(' \t\r\n').replace('\r', '') + expected_output = self.output.strip(' \t\r\n').replace('\r', '') + if not self.should_fail and process.returncode != 0: + self.fail_reason = ( + 'Runner exited with status {}\n\nOutput: {}' + ).format(process.returncode, output) + return False + if output != expected_output: + self.fail_reason = ( + 'Output didn\'t match\n\nExpected output:\n\n{}\n\n' + 'Actual output:\n\n{}' + ).format(expected_output, output) + return False + return True tests = [] num_tests_disabled = 0 @@ -100,6 +121,11 @@ for meta_file in glob.glob('*.meta'): extra_args=metadata.get('extra_args'))) elif test_type == 'crash': tests.append(CrashTest(name=name, source_file=name + '.pwn')) + elif test_type == 'runtime': + tests.append(RuntimeTest(name=name, + amx_file=name + '.amx', + output=metadata.get('output'), + should_fail=metadata.get('should_fail'))) else: raise KeyError('Unknown test type: ' + test_type) diff --git a/source/compiler/tests/runtime_test_example.meta b/source/compiler/tests/runtime_test_example.meta new file mode 100644 index 0000000..49f67ed --- /dev/null +++ b/source/compiler/tests/runtime_test_example.meta @@ -0,0 +1,7 @@ +{ + 'test_type': 'runtime', + 'output': """ + Run time error 4: "Array index out of bounds" + """, + 'should_fail': True +} diff --git a/source/compiler/tests/runtime_test_example.pwn b/source/compiler/tests/runtime_test_example.pwn new file mode 100644 index 0000000..9907096 --- /dev/null +++ b/source/compiler/tests/runtime_test_example.pwn @@ -0,0 +1,10 @@ +#include + +main() { + new a[1] = {1}; + new i = 1; + + // When compiled with at least debug level 1 (default) the line below should produce: + // Run time error 4: "Array index out of bounds" + printf("%d", a[i]); +} diff --git a/source/compiler/tests/too_many_args_crash_gh_298.meta b/source/compiler/tests/too_many_args_crash_gh_298.meta index 131078f..9017075 100644 --- a/source/compiler/tests/too_many_args_crash_gh_298.meta +++ b/source/compiler/tests/too_many_args_crash_gh_298.meta @@ -6,6 +6,7 @@ too_many_args_crash_gh_298.pwn(2) : warning 215: expression has no effect too_many_args_crash_gh_298.pwn(2) : error 001: expected token: ";", but found ")" too_many_args_crash_gh_298.pwn(2) : error 029: invalid expression, assumed zero too_many_args_crash_gh_298.pwn(2) : fatal error 107: too many error messages on one line + Compilation aborted. """ } From 16995c5ee16518ee1009fc453607f3ab0a462eb0 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sat, 11 Aug 2018 23:12:45 +0600 Subject: [PATCH 65/88] Whitespace cleanup --- source/amx/amxargs.c | 1 + source/amx/amxaux.c | 1 + source/amx/amxaux.h | 1 + source/amx/amxcore.c | 1 + source/amx/amxdbg.c | 1 + source/amx/amxdgram.c | 1 + source/amx/amxfile.c | 1 + source/amx/amxgc.c | 1 + source/amx/amxprocess.c | 1 + source/amx/amxstring.c | 1 + source/amx/amxtime.c | 1 + source/amx/fixed.c | 1 + source/amx/float.c | 1 + source/amx/pawndbg.c | 1 + source/amx/pawnrun.c | 1 + source/amx/pawnrun/prun1.c | 1 + source/amx/pawnrun/prun2.c | 1 + source/amx/pawnrun/prun3.c | 1 + source/amx/pawnrun/prun4.c | 1 + source/amx/pawnrun/prun5.c | 1 + source/amx/pawnrun/prun_jit.c | 1 + source/compiler/libpawnc.c | 1 + source/compiler/pawncc.c | 1 + source/compiler/pawndisasm.c | 1 + source/compiler/sc.h | 1 + source/compiler/sc1.c | 25 +++++++++++++------------ source/compiler/sc2.c | 7 ++++--- source/compiler/sc3.c | 1 + source/compiler/sc4.c | 1 + source/compiler/sc5.c | 1 + source/compiler/sc6.c | 1 + source/compiler/sc7.c | 1 + source/compiler/sci18n.c | 1 + source/compiler/sclist.c | 1 + source/compiler/scstate.c | 1 + source/compiler/scvars.c | 1 + 36 files changed, 51 insertions(+), 15 deletions(-) diff --git a/source/amx/amxargs.c b/source/amx/amxargs.c index b556b69..b1b00f0 100644 --- a/source/amx/amxargs.c +++ b/source/amx/amxargs.c @@ -20,6 +20,7 @@ * * Version: $Id: amxargs.c 3649 2006-10-12 13:13:57Z thiadmer $ */ + #if defined _UNICODE || defined __UNICODE__ || defined UNICODE # if !defined UNICODE /* for Windows */ # define UNICODE diff --git a/source/amx/amxaux.c b/source/amx/amxaux.c index 6a35bab..437e0ee 100644 --- a/source/amx/amxaux.c +++ b/source/amx/amxaux.c @@ -20,6 +20,7 @@ * * Version: $Id: amxaux.c 3612 2006-07-22 09:59:46Z thiadmer $ */ + #include #include #include diff --git a/source/amx/amxaux.h b/source/amx/amxaux.h index 08d9efd..b9d2148 100644 --- a/source/amx/amxaux.h +++ b/source/amx/amxaux.h @@ -20,6 +20,7 @@ * * Version: $Id: amxaux.h 3612 2006-07-22 09:59:46Z thiadmer $ */ + #ifndef AMXAUX_H_INCLUDED #define AMXAUX_H_INCLUDED diff --git a/source/amx/amxcore.c b/source/amx/amxcore.c index e1c14a2..d355e52 100644 --- a/source/amx/amxcore.c +++ b/source/amx/amxcore.c @@ -20,6 +20,7 @@ * * Version: $Id: amxcore.c 3657 2006-10-24 20:09:50Z thiadmer $ */ + #if defined _UNICODE || defined __UNICODE__ || defined UNICODE # if !defined UNICODE /* for Windows */ # define UNICODE diff --git a/source/amx/amxdbg.c b/source/amx/amxdbg.c index 69dff00..b0adcd6 100644 --- a/source/amx/amxdbg.c +++ b/source/amx/amxdbg.c @@ -22,6 +22,7 @@ * * Version: $Id: amxdbg.c 3612 2006-07-22 09:59:46Z thiadmer $ */ + #include #include #include diff --git a/source/amx/amxdgram.c b/source/amx/amxdgram.c index d1636a5..51345a2 100644 --- a/source/amx/amxdgram.c +++ b/source/amx/amxdgram.c @@ -22,6 +22,7 @@ * * Version: $Id: amxdgram.c 3664 2006-11-08 12:09:25Z thiadmer $ */ + #include #include #if defined LINUX diff --git a/source/amx/amxfile.c b/source/amx/amxfile.c index 4dab381..b183e2d 100644 --- a/source/amx/amxfile.c +++ b/source/amx/amxfile.c @@ -20,6 +20,7 @@ * * Version: $Id: amxfile.c 3660 2006-11-05 13:05:09Z thiadmer $ */ + #if defined _UNICODE || defined __UNICODE__ || defined UNICODE # if !defined UNICODE /* for Windows */ # define UNICODE diff --git a/source/amx/amxgc.c b/source/amx/amxgc.c index 06a729b..e1dc1f0 100644 --- a/source/amx/amxgc.c +++ b/source/amx/amxgc.c @@ -20,6 +20,7 @@ * * Version: $Id: amxgc.c 3660 2006-11-05 13:05:09Z thiadmer $ */ + #include #include #include /* for malloc()/free() */ diff --git a/source/amx/amxprocess.c b/source/amx/amxprocess.c index 1c2cb65..c5c7cf6 100644 --- a/source/amx/amxprocess.c +++ b/source/amx/amxprocess.c @@ -20,6 +20,7 @@ * * Version: $Id: amxprocess.c 3664 2006-11-08 12:09:25Z thiadmer $ */ + #if defined _UNICODE || defined __UNICODE__ || defined UNICODE # if !defined UNICODE /* for Windows */ # define UNICODE diff --git a/source/amx/amxstring.c b/source/amx/amxstring.c index 8651e60..e1ff9a4 100644 --- a/source/amx/amxstring.c +++ b/source/amx/amxstring.c @@ -20,6 +20,7 @@ * * Version: $Id: amxstring.c 3656 2006-10-24 07:20:26Z thiadmer $ */ + #include #include #include diff --git a/source/amx/amxtime.c b/source/amx/amxtime.c index 0340855..c63bf44 100644 --- a/source/amx/amxtime.c +++ b/source/amx/amxtime.c @@ -20,6 +20,7 @@ * * Version: $Id: amxtime.c 3649 2006-10-12 13:13:57Z thiadmer $ */ + #include #include #include "amx.h" diff --git a/source/amx/fixed.c b/source/amx/fixed.c index c5365cd..b5707b9 100644 --- a/source/amx/fixed.c +++ b/source/amx/fixed.c @@ -24,6 +24,7 @@ * * Version: $Id: fixed.c 3662 2006-11-07 08:44:33Z thiadmer $ */ + #include #include /* for NULL */ #include "amx.h" diff --git a/source/amx/float.c b/source/amx/float.c index 02cb4f6..68ca46b 100644 --- a/source/amx/float.c +++ b/source/amx/float.c @@ -17,6 +17,7 @@ * 2004-01-09: Adaptions for 64-bit cells (using "double precision"), by * Thiadmer Riemersma */ + #include /* for atof() */ #include /* for NULL */ #include diff --git a/source/amx/pawndbg.c b/source/amx/pawndbg.c index cde9942..76ada77 100644 --- a/source/amx/pawndbg.c +++ b/source/amx/pawndbg.c @@ -50,6 +50,7 @@ * needs only to transfer a file: * pawndbg myprog.amx -rs232=1 -transfer -quit */ + #include #include #include diff --git a/source/amx/pawnrun.c b/source/amx/pawnrun.c index 9bc9b9d..a345c4f 100644 --- a/source/amx/pawnrun.c +++ b/source/amx/pawnrun.c @@ -20,6 +20,7 @@ * * Version: $Id: pawnrun.c 3615 2006-07-27 07:49:08Z thiadmer $ */ + #include #include #include diff --git a/source/amx/pawnrun/prun1.c b/source/amx/pawnrun/prun1.c index d9bb5ae..c37e929 100644 --- a/source/amx/pawnrun/prun1.c +++ b/source/amx/pawnrun/prun1.c @@ -4,6 +4,7 @@ * * This file may be freely used. No warranties of any kind. */ + #include #include /* for exit() */ #include diff --git a/source/amx/pawnrun/prun2.c b/source/amx/pawnrun/prun2.c index e3b0864..465c4c5 100644 --- a/source/amx/pawnrun/prun2.c +++ b/source/amx/pawnrun/prun2.c @@ -4,6 +4,7 @@ * * This file may be freely used. No warranties of any kind. */ + #include #include #include diff --git a/source/amx/pawnrun/prun3.c b/source/amx/pawnrun/prun3.c index 657b8df..878dff1 100644 --- a/source/amx/pawnrun/prun3.c +++ b/source/amx/pawnrun/prun3.c @@ -4,6 +4,7 @@ * * This file may be freely used. No warranties of any kind. */ + #include #include /* for exit() */ #include diff --git a/source/amx/pawnrun/prun4.c b/source/amx/pawnrun/prun4.c index f308ddd..e88305c 100644 --- a/source/amx/pawnrun/prun4.c +++ b/source/amx/pawnrun/prun4.c @@ -4,6 +4,7 @@ * * This file may be freely used. No warranties of any kind. */ + #include #include /* for exit() */ #include /* for memset() (on some compilers) */ diff --git a/source/amx/pawnrun/prun5.c b/source/amx/pawnrun/prun5.c index 9301e8b..c84c09a 100644 --- a/source/amx/pawnrun/prun5.c +++ b/source/amx/pawnrun/prun5.c @@ -5,6 +5,7 @@ * * This file may be freely used. No warranties of any kind. */ + #include #include #include diff --git a/source/amx/pawnrun/prun_jit.c b/source/amx/pawnrun/prun_jit.c index 7c5e12e..7ac4ab4 100644 --- a/source/amx/pawnrun/prun_jit.c +++ b/source/amx/pawnrun/prun_jit.c @@ -19,6 +19,7 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ + #include #include #include diff --git a/source/compiler/libpawnc.c b/source/compiler/libpawnc.c index b3d56c8..33ddc1a 100644 --- a/source/compiler/libpawnc.c +++ b/source/compiler/libpawnc.c @@ -22,6 +22,7 @@ * * Version: $Id: libpawnc.c 3612 2006-07-22 09:59:46Z thiadmer $ */ + #include #include #include diff --git a/source/compiler/pawncc.c b/source/compiler/pawncc.c index a6d19c5..bd52518 100644 --- a/source/compiler/pawncc.c +++ b/source/compiler/pawncc.c @@ -22,6 +22,7 @@ * * Version: $Id: pawncc.c 3612 2006-07-22 09:59:46Z thiadmer $ */ + #include "sc.h" int main(int argc, char *argv[]) diff --git a/source/compiler/pawndisasm.c b/source/compiler/pawndisasm.c index f5ec6f4..a5db3e6 100644 --- a/source/compiler/pawndisasm.c +++ b/source/compiler/pawndisasm.c @@ -20,6 +20,7 @@ * * Version: $Id$ */ + #include #include #include diff --git a/source/compiler/sc.h b/source/compiler/sc.h index e6e5a26..beda684 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -27,6 +27,7 @@ * * Version: $Id: sc.h 3660 2006-11-05 13:05:09Z thiadmer $ */ + #ifndef SC_H_INCLUDED #define SC_H_INCLUDED #include diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 616da3c..5f76b13 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -22,6 +22,7 @@ * * Version: $Id: sc1.c 3664 2006-11-08 12:09:25Z thiadmer $ */ + #include #include #include @@ -2504,7 +2505,7 @@ static void initials(int ident,int tag,cell *size,int dim[],int numdim, error(9); /* array has zero length -> invalid size */ return; } /* if */ - } /* for */ + } /* for */ *size=calc_arraysize(dim,numdim,0); if (*size==(cell)CELL_MAX) { error(9); /* array is too big -> invalid size */ @@ -3418,7 +3419,7 @@ SC_FUNC void check_index_tagmismatch(char *symname,int expectedtag,int actualtag assert(symname!=NULL); if (!matchtag(expectedtag,actualtag,allowcoerce)) { constvalue *tagsym; - char expected_tagname[sNAMEMAX+3]="none (\"_\"),",actual_tagname[sNAMEMAX+2]="none (\"_\")"; /* two extra characters for quotes */ + char expected_tagname[sNAMEMAX+3]="none (\"_\"),",actual_tagname[sNAMEMAX+2]="none (\"_\")"; /* two extra characters for quotes */ if(expectedtag!=0) { tagsym=find_tag_byval(expectedtag); sprintf(expected_tagname,"\"%s\",",(tagsym!=NULL) ? tagsym->name : "-unknown-"); @@ -3431,7 +3432,7 @@ SC_FUNC void check_index_tagmismatch(char *symname,int expectedtag,int actualtag errorset(sSETPOS,errline); error(229,symname,expected_tagname,actual_tagname); /* index tag mismatch */ if(errline>0) - errorset(sSETPOS,-1); + errorset(sSETPOS,-1); } /* if */ } @@ -3439,7 +3440,7 @@ SC_FUNC void check_tagmismatch(int formaltag,int actualtag,int allowcoerce,int e { if (!matchtag(formaltag,actualtag,allowcoerce)) { constvalue *tagsym; - char formal_tagname[sNAMEMAX+3]="none (\"_\"),",actual_tagname[sNAMEMAX+2]="none (\"_\")"; /* two extra characters for quotes */ + char formal_tagname[sNAMEMAX+3]="none (\"_\"),",actual_tagname[sNAMEMAX+2]="none (\"_\")"; /* two extra characters for quotes */ if(formaltag!=0) { tagsym=find_tag_byval(formaltag); sprintf(formal_tagname,"\"%s\",",(tagsym!=NULL) ? tagsym->name : "-unknown-"); @@ -3452,7 +3453,7 @@ SC_FUNC void check_tagmismatch(int formaltag,int actualtag,int allowcoerce,int e errorset(sSETPOS,errline); error(213,"tag",formal_tagname,actual_tagname); /* tag mismatch */ if(errline>0) - errorset(sSETPOS,-1); + errorset(sSETPOS,-1); } /* if */ } @@ -3463,7 +3464,7 @@ SC_FUNC void check_tagmismatch_multiple(int formaltags[],int numtags,int actualt constvalue *tagsym; char formal_tagnames[sLINEMAX]="",actual_tagname[sNAMEMAX+2]="none (\"_\")"; int notag_allowed=FALSE,add_comma=FALSE; - for (i=0; iname : "-unknown-"); + sprintf(formal_tagnames,"%s\"%s\"",formal_tagnames,(tagsym!=NULL) ? tagsym->name : "-unknown-"); } else { notag_allowed=TRUE; - } /* if */ + } /* if */ } /* for */ if(notag_allowed==TRUE) { if(add_comma==TRUE) @@ -3485,12 +3486,12 @@ SC_FUNC void check_tagmismatch_multiple(int formaltags[],int numtags,int actualt if(actualtag!=0) { tagsym=find_tag_byval(actualtag); sprintf(actual_tagname,"\"%s\"",(tagsym!=NULL) ? tagsym->name : "-unknown-"); - } /* if */ + } /* if */ if(errline>0) errorset(sSETPOS,errline); error(213,(numtags==1) ? "tag" : "tags",formal_tagnames,actual_tagname); /* tag mismatch */ if(errline>0) - errorset(sSETPOS,-1); + errorset(sSETPOS,-1); } /* if */ } @@ -4206,7 +4207,7 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, } else { constexpr(&arg->defvalue.val,&arg->defvalue_tag,NULL); assert(numtags>0); - check_tagmismatch(tags[0],arg->defvalue_tag,TRUE,-1); + check_tagmismatch(tags[0],arg->defvalue_tag,TRUE,-1); } /* if */ } /* if */ } /* if */ @@ -4232,7 +4233,7 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, if(argsym->ident==iREFARRAY || argsym->ident==iREFERENCE) argsym->usage|=uWRITTEN; } - + if (fconst) argsym->usage|=uCONST; } /* if */ diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index ef9151e..821f2a8 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -20,6 +20,7 @@ * * Version: $Id: sc2.c 3655 2006-10-23 20:17:52Z thiadmer $ */ + #include #include #include @@ -524,12 +525,12 @@ static void stripcomment(unsigned char *line) while ((continuation=strchr(continuation,'\a'))!=NULL){ /* don't give the error if the next line is also commented out. it is quite annoying to get an error for commenting out a define using: - - // + + // // #define LONG_MACRO\ // did span \ // multiple lines - // + // */ while (*continuation<=' ' && *continuation!='\0') continuation++; /* skip whitespace */ diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 719d054..e22de2c 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -20,6 +20,7 @@ * * Version: $Id: sc3.c 3660 2006-11-05 13:05:09Z thiadmer $ */ + #include #include #include /* for _MAX_PATH */ diff --git a/source/compiler/sc4.c b/source/compiler/sc4.c index 576c16b..0f5d1af 100644 --- a/source/compiler/sc4.c +++ b/source/compiler/sc4.c @@ -20,6 +20,7 @@ * * Version: $Id: sc4.c 3633 2006-08-11 16:20:18Z thiadmer $ */ + #include #include #include diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index 2083174..cd24e87 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -21,6 +21,7 @@ * * Version: $Id: sc5.c 3579 2006-06-06 13:35:29Z thiadmer $ */ + #include #if defined __WIN32__ || defined _WIN32 || defined __MSDOS__ #include diff --git a/source/compiler/sc6.c b/source/compiler/sc6.c index f933dea..5e95a04 100644 --- a/source/compiler/sc6.c +++ b/source/compiler/sc6.c @@ -20,6 +20,7 @@ * * Version: $Id: sc6.c 3648 2006-10-12 11:24:50Z thiadmer $ */ + #include #include #include /* for macro max() */ diff --git a/source/compiler/sc7.c b/source/compiler/sc7.c index 1f897c3..5a0ed28 100644 --- a/source/compiler/sc7.c +++ b/source/compiler/sc7.c @@ -47,6 +47,7 @@ * * Version: $Id: sc7.c 3579 2006-06-06 13:35:29Z thiadmer $ */ + #include #include #include /* for atoi() */ diff --git a/source/compiler/sci18n.c b/source/compiler/sci18n.c index fa94025..78c1a36 100644 --- a/source/compiler/sci18n.c +++ b/source/compiler/sci18n.c @@ -32,6 +32,7 @@ * * Version: $Id: sci18n.c 3612 2006-07-22 09:59:46Z thiadmer $ */ + #include #include #include diff --git a/source/compiler/sclist.c b/source/compiler/sclist.c index a9f0279..60fd248 100644 --- a/source/compiler/sclist.c +++ b/source/compiler/sclist.c @@ -26,6 +26,7 @@ * * Version: $Id: sclist.c 3660 2006-11-05 13:05:09Z thiadmer $ */ + #include #include #include diff --git a/source/compiler/scstate.c b/source/compiler/scstate.c index 53a3ebe..6e87202 100644 --- a/source/compiler/scstate.c +++ b/source/compiler/scstate.c @@ -45,6 +45,7 @@ * * Version: $Id: scstate.c 3579 2006-06-06 13:35:29Z thiadmer $ */ + #include #include #include diff --git a/source/compiler/scvars.c b/source/compiler/scvars.c index d37551f..05fefa1 100644 --- a/source/compiler/scvars.c +++ b/source/compiler/scvars.c @@ -22,6 +22,7 @@ * * Version: $Id: scvars.c 3655 2006-10-23 20:17:52Z thiadmer $ */ + #include #include /* for _MAX_PATH */ #include "sc.h" From 6e6f37b54a4afb5b628d7e2643cd035836e1508a Mon Sep 17 00:00:00 2001 From: Zeex Date: Sat, 11 Aug 2018 23:20:13 +0600 Subject: [PATCH 66/88] Update CI build script --- .travis.yml | 7 ++++--- appveyor.yml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d318aee..f12426d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,10 @@ addons: - cmake before_script: - - cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DCMAKE_C_FLAGS="-m32 -Werror -Wno-address-of-packed-member" - -DCPACK_GENERATOR="TGZ;ZIP" + - mkdir build && cd build + - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DCMAKE_C_FLAGS="-m32 -Werror -Wno-address-of-packed-member" + -DCPACK_GENERATOR="TGZ;ZIP" script: - make diff --git a/appveyor.yml b/appveyor.yml index b185ace..bffa5e9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ configuration: before_build: - mkdir build && cd build - - cmake ../source -G "Visual Studio 14 2015" -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 + - cmake .. -G "Visual Studio 14 2015" -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 build_script: - cmake --build . --config %CONFIGURATION% From 357cd6f43be4c38e71c096d8617edfa67e2d894b Mon Sep 17 00:00:00 2001 From: Zeex Date: Sat, 11 Aug 2018 23:41:46 +0600 Subject: [PATCH 67/88] Fix build errors on Linux --- source/amx/amxaux.c | 6 +++--- source/compiler/CMakeLists.txt | 14 +++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/source/amx/amxaux.c b/source/amx/amxaux.c index 437e0ee..3ff77e9 100644 --- a/source/amx/amxaux.c +++ b/source/amx/amxaux.c @@ -34,7 +34,7 @@ size_t AMXAPI aux_ProgramSize(char *filename) if ((fp=fopen(filename,"rb")) == NULL) return 0; - fread(&hdr, sizeof hdr, 1, fp); + (void)fread(&hdr, sizeof hdr, 1, fp); fclose(fp); amx_Align16(&hdr.magic); @@ -51,7 +51,7 @@ int AMXAPI aux_LoadProgram(AMX *amx, char *filename, void *memblock) /* open the file, read and check the header */ if ((fp = fopen(filename, "rb")) == NULL) return AMX_ERR_NOTFOUND; - fread(&hdr, sizeof hdr, 1, fp); + (void)fread(&hdr, sizeof hdr, 1, fp); amx_Align16(&hdr.magic); amx_Align32((uint32_t *)&hdr.size); amx_Align32((uint32_t *)&hdr.stp); @@ -73,7 +73,7 @@ int AMXAPI aux_LoadProgram(AMX *amx, char *filename, void *memblock) /* read in the file */ rewind(fp); - fread(memblock, 1, (size_t)hdr.size, fp); + (void)fread(memblock, 1, (size_t)hdr.size, fp); fclose(fp); /* initialize the abstract machine */ diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index f7c5c56..b7d8b5e 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -171,8 +171,20 @@ set(PAWNRUNS_SRCS ../amx/amxaux.c ../amx/amxaux.h ../amx/amxcons.c - ../amx/amxcore.c) + ../amx/amxcore.c +) +if(UNIX) + set(PAWNRUN_SRCS + ${PAWNRUN_SRCS} + ../linux/getch.c + ../linux/getch.h + ../linux/binreloc.c + ) +endif() add_executable(pawnruns ${PAWNRUNS_SRCS}) +if(UNIX) + target_link_libraries(pawnruns dl) +endif() add_subdirectory(tests) # Generate a binary package with CPack From 44312b96532cc1056a9f6e46bec82525d5a53229 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sat, 11 Aug 2018 23:50:58 +0600 Subject: [PATCH 68/88] Fix build errors on Linux --- source/amx/amxaux.c | 9 ++++++--- source/compiler/CMakeLists.txt | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/source/amx/amxaux.c b/source/amx/amxaux.c index 3ff77e9..0ff0f75 100644 --- a/source/amx/amxaux.c +++ b/source/amx/amxaux.c @@ -34,7 +34,8 @@ size_t AMXAPI aux_ProgramSize(char *filename) if ((fp=fopen(filename,"rb")) == NULL) return 0; - (void)fread(&hdr, sizeof hdr, 1, fp); + if (fread(&hdr, sizeof hdr, 1, fp) < 1) + return 0; fclose(fp); amx_Align16(&hdr.magic); @@ -51,7 +52,8 @@ int AMXAPI aux_LoadProgram(AMX *amx, char *filename, void *memblock) /* open the file, read and check the header */ if ((fp = fopen(filename, "rb")) == NULL) return AMX_ERR_NOTFOUND; - (void)fread(&hdr, sizeof hdr, 1, fp); + if (fread(&hdr, sizeof hdr, 1, fp) < 1) + return AMX_ERR_INIT; amx_Align16(&hdr.magic); amx_Align32((uint32_t *)&hdr.size); amx_Align32((uint32_t *)&hdr.stp); @@ -73,7 +75,8 @@ int AMXAPI aux_LoadProgram(AMX *amx, char *filename, void *memblock) /* read in the file */ rewind(fp); - (void)fread(memblock, 1, (size_t)hdr.size, fp); + if (fread(memblock, 1, (size_t)hdr.size, fp) < (size_t)hdr.size) + return AMX_ERR_INIT; fclose(fp); /* initialize the abstract machine */ diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index b7d8b5e..5d6d9a9 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -174,8 +174,8 @@ set(PAWNRUNS_SRCS ../amx/amxcore.c ) if(UNIX) - set(PAWNRUN_SRCS - ${PAWNRUN_SRCS} + set(PAWNRUNS_SRCS + ${PAWNRUNS_SRCS} ../linux/getch.c ../linux/getch.h ../linux/binreloc.c From 1e6e6f0fbf35bae4086a17c66568a963dec50f38 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 12 Aug 2018 01:14:27 +0600 Subject: [PATCH 69/88] Compile runtime tests before running --- source/compiler/tests/run_tests.py | 33 +++++++++++++----------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/source/compiler/tests/run_tests.py b/source/compiler/tests/run_tests.py index 946bbce..157898d 100644 --- a/source/compiler/tests/run_tests.py +++ b/source/compiler/tests/run_tests.py @@ -33,14 +33,13 @@ def run_compiler(args): stderr=subprocess.PIPE) class OutputCheckTest: - def __init__(self, name, source_file, errors=None, extra_args=None): + def __init__(self, name, errors=None, extra_args=None): self.name = name - self.source_file = source_file self.errors = errors self.extra_args = extra_args def run(self): - args = [self.source_file] + args = [self.name + '.pwn'] if self.extra_args is not None: args += extra_args process = run_compiler(args=args) @@ -63,25 +62,23 @@ class OutputCheckTest: ).format(expected_errors, errors) return result -class CrashTest: - def __init__(self, name, source_file, extra_args=None): - self.name = name - self.source_file = source_file - self.extra_args = extra_args - - def run(self): - # TODO: Check if the process crashed. - return True - class RuntimeTest: - def __init__(self, name, amx_file, output, should_fail): + def __init__(self, name, output, should_fail): self.name = name - self.amx_file = amx_file self.output = output self.should_fail = should_fail def run(self): - process = subprocess.Popen([options.runner, self.amx_file], + process = run_compiler([self.name + '.pwn']) + stdout, stderr = process.communicate() + if process.returncode != 0: + self.fail_reason = \ + 'Compiler exited with status {}'.format(process.returncode) + errors = stderr.decode('utf-8') + if errors: + self.fail_reason += '\n\nErrors:\n\n{}'.format(errors) + return False + process = subprocess.Popen([options.runner, self.name + '.amx'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() @@ -116,14 +113,12 @@ for meta_file in glob.glob('*.meta'): test_type = metadata['test_type'] if test_type == 'output_check': tests.append(OutputCheckTest(name=name, - source_file=name + '.pwn', errors=metadata.get('errors'), extra_args=metadata.get('extra_args'))) elif test_type == 'crash': - tests.append(CrashTest(name=name, source_file=name + '.pwn')) + tests.append(CrashTest(name=name)) elif test_type == 'runtime': tests.append(RuntimeTest(name=name, - amx_file=name + '.amx', output=metadata.get('output'), should_fail=metadata.get('should_fail'))) else: From 23d35625fd9aeb03a9b44260efeb91c3a2245a75 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 12 Aug 2018 02:19:51 +0600 Subject: [PATCH 70/88] Fix Clang warnings/errors --- source/amx/amx.c | 90 +++++++++++++++++++-------------------- source/amx/amxcons.c | 2 +- source/amx/amxcore.c | 2 +- source/compiler/lstring.h | 4 +- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/source/amx/amx.c b/source/amx/amx.c index 78ab989..675576f 100644 --- a/source/amx/amx.c +++ b/source/amx/amx.c @@ -1860,7 +1860,7 @@ int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char * supports this too. */ -#define NEXT(cip) goto **cip++ +#define NEXT(cip) goto **(void **)cip++ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) { @@ -2047,14 +2047,14 @@ static const void * const amx_opcodelist[] = { NEXT(cip); op_load_i: /* verify address */ - if (pri>=hea && pri=(ucell)amx->stp) + if ((pri>=hea && pri=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); pri=_R(data,pri); NEXT(cip); op_lodb_i: GETPARAM(offs); /* verify address */ - if (pri>=hea && pri=(ucell)amx->stp) + if ((pri>=hea && pri=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); switch (offs) { case 1: @@ -2120,14 +2120,14 @@ static const void * const amx_opcodelist[] = { NEXT(cip); op_stor_i: /* verify address */ - if (alt>=hea && alt=(ucell)amx->stp) + if ((alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); _W(data,alt,pri); NEXT(cip); op_strb_i: GETPARAM(offs); /* verify address */ - if (alt>=hea && alt=(ucell)amx->stp) + if ((alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); switch (offs) { case 1: @@ -2144,7 +2144,7 @@ static const void * const amx_opcodelist[] = { op_lidx: offs=pri*sizeof(cell)+alt; /* implicit shift value for a cell */ /* verify address */ - if (offs>=hea && offs=(ucell)amx->stp) + if ((offs>=hea && offs=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); pri=_R(data,offs); NEXT(cip); @@ -2152,7 +2152,7 @@ static const void * const amx_opcodelist[] = { GETPARAM(offs); offs=(pri << (int)offs)+alt; /* verify address */ - if (offs>=hea && offs=(ucell)amx->stp) + if ((offs>=hea && offs=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); pri=_R(data,offs); NEXT(cip); @@ -2641,13 +2641,13 @@ static const void * const amx_opcodelist[] = { /* verify top & bottom memory addresses, for both source and destination * addresses */ - if (pri>=hea && pri=(ucell)amx->stp) + if ((pri>=hea && pri=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if ((pri+offs)>hea && (pri+offs)(ucell)amx->stp) + if (((pri+offs)>hea && (pri+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if (alt>=hea && alt=(ucell)amx->stp) + if ((alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) + if (((alt+offs)>hea && (alt+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); #if defined _R_DEFAULT memcpy(data+(int)alt, data+(int)pri, (int)offs); @@ -2667,13 +2667,13 @@ static const void * const amx_opcodelist[] = { /* verify top & bottom memory addresses, for both source and destination * addresses */ - if (pri>=hea && pri=(ucell)amx->stp) + if ((pri>=hea && pri=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if ((pri+offs)>hea && (pri+offs)(ucell)amx->stp) + if (((pri+offs)>hea && (pri+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if (alt>=hea && alt=(ucell)amx->stp) + if ((alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) + if (((alt+offs)>hea && (alt+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); #if defined _R_DEFAULT pri=memcmp(data+(int)alt, data+(int)pri, (int)offs); @@ -2688,9 +2688,9 @@ static const void * const amx_opcodelist[] = { op_fill: GETPARAM(offs); /* verify top & bottom memory addresses */ - if (alt>=hea && alt=(ucell)amx->stp) + if ((alt>=hea && alt=(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); - if ((alt+offs)>hea && (alt+offs)(ucell)amx->stp) + if (((alt+offs)>hea && (alt+offs)(ucell)amx->stp) ABORT(amx,AMX_ERR_MEMACCESS); for (i=(int)alt; offs>=(int)sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell)) _W32(data,i,pri); @@ -4242,7 +4242,7 @@ int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr) data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat; assert(phys_addr!=NULL); - if (amx_addr>=amx->hea && amx_addrstk || amx_addr<0 || amx_addr>=amx->stp) { + if ((amx_addr>=amx->hea && amx_addrstk) || amx_addr<0 || amx_addr>=amx->stp) { *phys_addr=NULL; return AMX_ERR_MEMACCESS; } /* if */ @@ -4491,19 +4491,19 @@ static const long utf8_lowmark[5] = { 0x80, 0x800, 0x10000L, 0x200000L, 0x400000 switch (followup) { case 4: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | c & 0x3f; + result = (result << 6) | (c & 0x3f); case 3: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | c & 0x3f; + result = (result << 6) | (c & 0x3f); case 2: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | c & 0x3f; + result = (result << 6) | (c & 0x3f); case 1: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | c & 0x3f; + result = (result << 6) | (c & 0x3f); case 0: if (((c=*string++) & 0xc0) != 0x80) goto error; - result = (result << 6) | c & 0x3f; + result = (result << 6) | (c & 0x3f); } /* switch */ /* Do additional checks: shortest encoding & reserved positions. The * lowmark limits also depends on the code length; it can be read from @@ -4511,7 +4511,7 @@ static const long utf8_lowmark[5] = { 0x80, 0x800, 0x10000L, 0x200000L, 0x400000 */ if (result=0xd800 && result<=0xdfff || result==0xfffe || result==0xffff) + if ((result>=0xd800 && result<=0xdfff) || result==0xfffe || result==0xffff) goto error; } /* if */ @@ -4546,40 +4546,40 @@ int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value) } else if (value<0x800) { /* 110xxxxx 10xxxxxx */ if (maxchars < 2) goto error; - *string++ = (char)((value>>6) & 0x1f | 0xc0); - *string++ = (char)(value & 0x3f | 0x80); + *string++ = (char)(((value>>6) & 0x1f) | 0xc0); + *string++ = (char)((value & 0x3f) | 0x80); } else if (value<0x10000) { /* 1110xxxx 10xxxxxx 10xxxxxx (16 bits, BMP plane) */ if (maxchars < 3) goto error; - if (value>=0xd800 && value<=0xdfff || value==0xfffe || value==0xffff) + if ((value>=0xd800 && value<=0xdfff) || value==0xfffe || value==0xffff) goto error; /* surrogate pairs and invalid characters */ - *string++ = (char)((value>>12) & 0x0f | 0xe0); - *string++ = (char)((value>>6) & 0x3f | 0x80); - *string++ = (char)(value & 0x3f | 0x80); + *string++ = (char)(((value>>12) & 0x0f) | 0xe0); + *string++ = (char)(((value>>6) & 0x3f) | 0x80); + *string++ = (char)((value & 0x3f) | 0x80); } else if (value<0x200000) { /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (maxchars < 4) goto error; - *string++ = (char)((value>>18) & 0x07 | 0xf0); - *string++ = (char)((value>>12) & 0x3f | 0x80); - *string++ = (char)((value>>6) & 0x3f | 0x80); - *string++ = (char)(value & 0x3f | 0x80); + *string++ = (char)(((value>>18) & 0x07) | 0xf0); + *string++ = (char)(((value>>12) & 0x3f) | 0x80); + *string++ = (char)(((value>>6) & 0x3f) | 0x80); + *string++ = (char)((value & 0x3f) | 0x80); } else if (value<0x4000000) { /* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (maxchars < 5) goto error; - *string++ = (char)((value>>24) & 0x03 | 0xf8); - *string++ = (char)((value>>18) & 0x3f | 0x80); - *string++ = (char)((value>>12) & 0x3f | 0x80); - *string++ = (char)((value>>6) & 0x3f | 0x80); - *string++ = (char)(value & 0x3f | 0x80); + *string++ = (char)(((value>>24) & 0x03) | 0xf8); + *string++ = (char)(((value>>18) & 0x3f) | 0x80); + *string++ = (char)(((value>>12) & 0x3f) | 0x80); + *string++ = (char)(((value>>6) & 0x3f) | 0x80); + *string++ = (char)((value & 0x3f) | 0x80); } else { /* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (31 bits) */ if (maxchars < 6) goto error; - *string++ = (char)((value>>30) & 0x01 | 0xfc); - *string++ = (char)((value>>24) & 0x3f | 0x80); - *string++ = (char)((value>>18) & 0x3f | 0x80); - *string++ = (char)((value>>12) & 0x3f | 0x80); - *string++ = (char)((value>>6) & 0x3f | 0x80); - *string++ = (char)(value & 0x3f | 0x80); + *string++ = (char)(((value>>30) & 0x01) | 0xfc); + *string++ = (char)(((value>>24) & 0x3f) | 0x80); + *string++ = (char)(((value>>18) & 0x3f) | 0x80); + *string++ = (char)(((value>>12) & 0x3f) | 0x80); + *string++ = (char)(((value>>6) & 0x3f) | 0x80); + *string++ = (char)((value & 0x3f) | 0x80); } /* if */ if (endptr!=NULL) diff --git a/source/amx/amxcons.c b/source/amx/amxcons.c index b4e3659..51cd327 100644 --- a/source/amx/amxcons.c +++ b/source/amx/amxcons.c @@ -1100,7 +1100,7 @@ static cell AMX_NATIVE_CALL n_getvalue(AMX *amx,const cell *params) if (c=='\n' && inlist(amx,'\r',params+2,(int)params[0]/sizeof(cell)-1)!=0) c='\r'; #endif - if ((chars>1 || chars>0 && sign>0) + if ((chars>1 || (chars>0 && sign>0)) && (n=inlist(amx,c,params+2,(int)params[0]/sizeof(cell)-1))!=0) { if (n>0) diff --git a/source/amx/amxcore.c b/source/amx/amxcore.c index d355e52..5b04413 100644 --- a/source/amx/amxcore.c +++ b/source/amx/amxcore.c @@ -179,7 +179,7 @@ static cell AMX_NATIVE_CALL setarg(AMX *amx,const cell *params) /* adjust the address in "value" in case of an array access */ value+=params[2]*sizeof(cell); /* verify the address */ - if (value<0 || value>=amx->hea && valuestk) + if (value<0 || (value>=amx->hea && valuestk)) return 0; /* set the value indirectly */ * (cell *)(data+(int)value) = params[3]; diff --git a/source/compiler/lstring.h b/source/compiler/lstring.h index 9d011ec..5216390 100644 --- a/source/compiler/lstring.h +++ b/source/compiler/lstring.h @@ -7,10 +7,10 @@ #define HAVE_SAFESTR #endif -#if defined strlcpy +#if defined strlcpy && !defined HAVE_STRLCPY #define HAVE_STRLCPY #endif -#if defined strlcat +#if defined strlcat && !defined HAVE_STRLCAT #define HAVE_STRLCAT #endif From 5e4da789332adc484db2affb5790fb596dde248b Mon Sep 17 00:00:00 2001 From: Zeex Date: Tue, 28 Aug 2018 22:09:26 +0600 Subject: [PATCH 71/88] Fix uninitialized variable `enumroot` was used before initialized in declglb() when compiling code such as tests/unused_symbol_line_gh_252.pwn. --- source/compiler/sc1.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 5f76b13..d96e4e0 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -1998,7 +1998,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst int numdim; short filenum; symbol *sym; - constvalue_root *enumroot; + constvalue_root *enumroot=NULL; #if !defined NDEBUG cell glbdecl=0; #endif @@ -2251,7 +2251,7 @@ static int declloc(int fstatic) int idxtag[sDIMEN_MAX]; char name[sNAMEMAX+1]; symbol *sym; - constvalue_root *enumroot; + constvalue_root *enumroot=NULL; cell val,size; char *str; value lval = {0}; @@ -2887,8 +2887,8 @@ static void decl_enum(int vclass,int fstatic) char *str; int tag,explicittag; cell increment,multiplier; - constvalue_root *enumroot; - symbol *enumsym; + constvalue_root *enumroot=NULL; + symbol *enumsym=NULL; short filenum; filenum=fcurrent; @@ -2944,9 +2944,6 @@ static void decl_enum(int vclass,int fstatic) if ((enumroot=(constvalue_root*)malloc(sizeof(constvalue_root)))==NULL) error(103); /* insufficient memory (fatal error) */ memset(enumroot,0,sizeof(constvalue_root)); - } else { - enumsym=NULL; - enumroot=NULL; } /* if */ needtoken('{'); @@ -4122,7 +4119,7 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, int fpublic,int fconst,int chkshadow,arginfo *arg) { symbol *argsym; - constvalue_root *enumroot; + constvalue_root *enumroot=NULL; cell size; strcpy(arg->name,name); From dbc116d18eef5cfc569392153fdb40ab7d0cddd8 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 2 Sep 2018 06:00:06 +0600 Subject: [PATCH 72/88] Remove extra space after instructions without parameters --- source/compiler/pawndisasm.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/source/compiler/pawndisasm.c b/source/compiler/pawndisasm.c index a5db3e6..7d6532f 100644 --- a/source/compiler/pawndisasm.c +++ b/source/compiler/pawndisasm.c @@ -222,7 +222,8 @@ static OPCODE opcodelist[] = { void print_opcode(FILE *ftxt,cell opcode,cell cip) { - fprintf(ftxt,"%08"PRIxC" %s ",cip,opcodelist[(int)(opcode &0x0000ffff)].name); + fprintf(ftxt,"%08"PRIxC" %s", + cip,opcodelist[(int)(opcode &0x0000ffff)].name); } void print_funcname(FILE *ftxt,cell address) @@ -264,21 +265,21 @@ cell parm0(FILE *ftxt,const cell *params,cell opcode,cell cip) cell parm1(FILE *ftxt,const cell *params,cell opcode,cell cip) { print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC"\n",*params); + fprintf(ftxt," %08"PRIxC"\n",*params); return 2; } cell parm2(FILE *ftxt,const cell *params,cell opcode,cell cip) { print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC" %08"PRIxC"\n",params[0],params[1]); + fprintf(ftxt," %08"PRIxC" %08"PRIxC"\n",params[0],params[1]); return 3; } cell parm3(FILE *ftxt,const cell *params,cell opcode,cell cip) { print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC" %08"PRIxC" %08"PRIxC"\n", + fprintf(ftxt," %08"PRIxC" %08"PRIxC" %08"PRIxC"\n", params[0],params[1],params[2]); return 4; } @@ -286,7 +287,7 @@ cell parm3(FILE *ftxt,const cell *params,cell opcode,cell cip) cell parm4(FILE *ftxt,const cell *params,cell opcode,cell cip) { print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC" %08"PRIxC" %08"PRIxC" %08"PRIxC"\n", + fprintf(ftxt," %08"PRIxC" %08"PRIxC" %08"PRIxC" %08"PRIxC"\n", params[0],params[1],params[2],params[3]); return 5; } @@ -294,7 +295,7 @@ cell parm4(FILE *ftxt,const cell *params,cell opcode,cell cip) cell parm5(FILE *ftxt,const cell *params,cell opcode,cell cip) { print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC" %08"PRIxC" %08"PRIxC" %08"PRIxC" %08"PRIxC"\n", + fprintf(ftxt," %08"PRIxC" %08"PRIxC" %08"PRIxC" %08"PRIxC" %08"PRIxC"\n", params[0],params[1],params[2],params[3],params[4]); return 6; } @@ -310,7 +311,7 @@ cell do_proc(FILE *ftxt,const cell *params,cell opcode,cell cip) cell do_call(FILE *ftxt,const cell *params,cell opcode,cell cip) { print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC,*params); + fprintf(ftxt," %08"PRIxC,*params); print_funcname(ftxt,*params); fputs("\n",ftxt); return 2; @@ -319,7 +320,7 @@ cell do_call(FILE *ftxt,const cell *params,cell opcode,cell cip) cell do_jump(FILE *ftxt,const cell *params,cell opcode,cell cip) { print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC"\n",*params); + fprintf(ftxt," %08"PRIxC"\n",*params); return 2; } @@ -346,7 +347,7 @@ cell do_sysreq(FILE *ftxt,const cell *params,cell opcode,cell cip) } /* if */ print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC,*params); + fprintf(ftxt," %08"PRIxC,*params); if (namelen>0) fprintf(ftxt,"\t; %s",name); fprintf(ftxt,"\n"); @@ -356,7 +357,7 @@ cell do_sysreq(FILE *ftxt,const cell *params,cell opcode,cell cip) cell do_switch(FILE *ftxt,const cell *params,cell opcode,cell cip) { print_opcode(ftxt,opcode,cip); - fprintf(ftxt,"%08"PRIxC"\n",*params); + fprintf(ftxt," %08"PRIxC"\n",*params); return 2; } @@ -367,7 +368,7 @@ cell casetbl(FILE *ftxt,const cell *params,cell opcode,cell cip) print_opcode(ftxt,opcode,cip); num=params[0]+1; - fprintf(ftxt,"%08"PRIxC" %08"PRIxC"\n",params[0],params[1]); + fprintf(ftxt," %08"PRIxC" %08"PRIxC"\n",params[0],params[1]); for (idx=1; idx Date: Sun, 2 Sep 2018 08:11:55 +0600 Subject: [PATCH 73/88] Add new test type pcode_check for checking generated bytecode --- .gitignore | 1 - source/compiler/tests/.gitignore | 3 + source/compiler/tests/CMakeLists.txt | 1 + source/compiler/tests/pcode_test_example.meta | 12 ++ source/compiler/tests/pcode_test_example.pwn | 5 + source/compiler/tests/run_tests.py | 185 +++++++++++++----- 6 files changed, 157 insertions(+), 50 deletions(-) create mode 100644 source/compiler/tests/.gitignore create mode 100644 source/compiler/tests/pcode_test_example.meta create mode 100644 source/compiler/tests/pcode_test_example.pwn diff --git a/.gitignore b/.gitignore index 14b6cae..becd9cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ build .vs .vscode -source/compiler/tests/*.amx diff --git a/source/compiler/tests/.gitignore b/source/compiler/tests/.gitignore new file mode 100644 index 0000000..e96bec9 --- /dev/null +++ b/source/compiler/tests/.gitignore @@ -0,0 +1,3 @@ +*.amx +*.asm +*.lst diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index 1921ab6..e49e05e 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -5,6 +5,7 @@ if(PYTHONINTERP_FOUND) COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/run_tests.py -c $ + -d $ -r $ -i ../../../include DEPENDS pawncc diff --git a/source/compiler/tests/pcode_test_example.meta b/source/compiler/tests/pcode_test_example.meta new file mode 100644 index 0000000..efcbc92 --- /dev/null +++ b/source/compiler/tests/pcode_test_example.meta @@ -0,0 +1,12 @@ +{ + 'test_type': 'pcode_check', + 'code_pattern': r""" +[0-9a-f]+ proc +[0-9a-f]+ push.c 00000000 +[0-9a-f]+ push.c 00000004 +[0-9a-f]+ sysreq.c 00000000 +[0-9a-f]+ stack 00000008 +[0-9a-f]+ zero.pri +[0-9a-f]+ retn +""" +} diff --git a/source/compiler/tests/pcode_test_example.pwn b/source/compiler/tests/pcode_test_example.pwn new file mode 100644 index 0000000..bf6507d --- /dev/null +++ b/source/compiler/tests/pcode_test_example.pwn @@ -0,0 +1,5 @@ +#include + +main() { + printf("Hello World!"); +} diff --git a/source/compiler/tests/run_tests.py b/source/compiler/tests/run_tests.py index 157898d..d3d33f5 100644 --- a/source/compiler/tests/run_tests.py +++ b/source/compiler/tests/run_tests.py @@ -10,27 +10,56 @@ import sys parser = argparse.ArgumentParser() parser.add_argument('-c', '--compiler', required=True, - help='path to compiler executable (pawncc or pawncc.exe)') + help='path to compiler executable (pawncc)') +parser.add_argument('-d', '--disassembler', + help='path to disassembler executable (pawndisasm)') parser.add_argument('-i', '--include', dest='include_dirs', action='append', help='add custom include directories for compile tests') parser.add_argument('-r', '--runner', - required=True, - help='path to runner executable (pawnrun or pawnrun.exe)') + help='path to runner executable (pawnruns)') options = parser.parse_args(sys.argv[1:]) +def run_command(args, executable=None, merge_stderr=False): + process = subprocess.Popen(args, + executable=executable, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + stdout, stderr = process.communicate() + stdout = stdout.decode('utf-8') + stderr = stderr.decode('utf-8') + if merge_stderr: + output = '' + if stdout: + output += stdout + if stderr: + output += stderr + return (process, output) + else: + return (process, stdout, stderr) + def run_compiler(args): - process_args = [';+', '-(+'] - if options.include_dirs is not None: - for dir in options.include_dirs: - process_args.append('-i' + dir) - if args is not None: - process_args += args - return subprocess.Popen(executable=options.compiler, - args=process_args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + final_args = [';+', '-(+'] + if options.include_dirs is not None: + for dir in options.include_dirs: + final_args.append('-i' + dir) + if args is not None: + final_args += args + return run_command(executable=options.compiler, args=final_args) + +def normalize_newlines(s): + return s.replace('\r', '') + +def remove_asm_comments(s): + return re.sub(r'\s*;.*\n', '\n', s) + +def strip(s): + return s.strip(' \t\r\n') + +def parse_asm_listing(dump): + return None class OutputCheckTest: def __init__(self, name, errors=None, extra_args=None): @@ -42,25 +71,75 @@ class OutputCheckTest: args = [self.name + '.pwn'] if self.extra_args is not None: args += extra_args - process = run_compiler(args=args) - stdout, stderr = process.communicate() - result = True + process, stdout, stderr = run_compiler(args=args) if self.errors is None: if process.returncode != 0: result = False self.fail_reason = """ No errors specified and process exited with non-zero status """ - else: - errors = stderr.decode('utf-8').strip(' \t\r\n').replace('\r', '') - expected_errors = self.errors.strip(' \t\r\n').replace('\r', '') - if errors != expected_errors: - result = False - self.fail_reason = ( - 'Error output didn\'t match\n\nExpected errors:\n\n{}\n\n' - 'Actual errors:\n\n{}' - ).format(expected_errors, errors) - return result + return False + + errors = strip(stderr) + expected_errors = strip(self.errors) + if errors != expected_errors: + self.fail_reason = ( + 'Error output didn\'t match\n\nExpected errors:\n\n{}\n\n' + 'Actual errors:\n\n{}' + ).format(expected_errors, errors) + return False + return True + +class PCodeCheckTest: + def __init__(self, + name, + code_pattern=None, + extra_args=None): + self.name = name + self.code_pattern = code_pattern + self.extra_args = extra_args + + def run(self): + args = ['-d0', self.name + '.pwn'] + if self.extra_args is not None: + args += extra_args + process, stdout, stderr = run_compiler(args=args) + if process.returncode != 0: + self.fail_reason = \ + 'Compiler exited with status {}'.format(process.returncode) + errors = stderr + if errors: + self.fail_reason += '\n\nErrors:\n\n{}'.format(errors) + return False + + if options.disassembler is None: + self.fail_reason = 'Disassembler path is not set, can\'t run this test' + return False + process, output = run_command([ + options.disassembler, + self.name + '.amx' + ], merge_stderr=True) + if process.returncode != 0: + self.fail_reason = \ + 'Disassembler exited with status {}'.format(process.returncode) + if output: + self.fail_reason += '\n\nOutput:\n\n{}'.format(output) + return False + with open(self.name + '.lst', 'r') as dump_file: + dump = dump_file.read() + if self.code_pattern: + dump = remove_asm_comments(dump) + code_pattern = strip(normalize_newlines(self.code_pattern)) + if re.search(code_pattern, dump, re.MULTILINE) is None: + self.fail_reason = ( + 'Code didn\'t match\n\nExpected code:\n\n{}\n\n' + 'Actual code:\n\n{}' + ).format(code_pattern, dump) + return False + else: + self.fail_reason = 'Code pattern is required' + return False + return True class RuntimeTest: def __init__(self, name, output, should_fail): @@ -69,31 +148,29 @@ class RuntimeTest: self.should_fail = should_fail def run(self): - process = run_compiler([self.name + '.pwn']) - stdout, stderr = process.communicate() + process, stdout, stderr = run_compiler([self.name + '.pwn']) if process.returncode != 0: self.fail_reason = \ 'Compiler exited with status {}'.format(process.returncode) - errors = stderr.decode('utf-8') + errors = stderr if errors: self.fail_reason += '\n\nErrors:\n\n{}'.format(errors) return False - process = subprocess.Popen([options.runner, self.name + '.amx'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = process.communicate() - output = '' - if stdout is not None: - output = stdout.decode('utf-8') - if stderr is not None: - output += stderr.decode('utf-8') - output = output.strip(' \t\r\n').replace('\r', '') - expected_output = self.output.strip(' \t\r\n').replace('\r', '') + + if options.runner is None: + self.fail_reason = 'Runner path is not set, can\'t run this test' + return False + process, output = run_command([ + options.runner, self.name + '.amx' + ], merge_stderr=True) if not self.should_fail and process.returncode != 0: self.fail_reason = ( 'Runner exited with status {}\n\nOutput: {}' ).format(process.returncode, output) return False + + output = strip(output) + expected_output = strip(self.output) if output != expected_output: self.fail_reason = ( 'Output didn\'t match\n\nExpected output:\n\n{}\n\n' @@ -104,33 +181,42 @@ class RuntimeTest: tests = [] num_tests_disabled = 0 + for meta_file in glob.glob('*.meta'): name = os.path.splitext(meta_file)[0] metadata = eval(open(meta_file).read(), None, None) if metadata.get('disabled'): num_tests_disabled += 1 continue + test_type = metadata['test_type'] if test_type == 'output_check': - tests.append(OutputCheckTest(name=name, - errors=metadata.get('errors'), - extra_args=metadata.get('extra_args'))) - elif test_type == 'crash': - tests.append(CrashTest(name=name)) + tests.append(OutputCheckTest( + name=name, + errors=metadata.get('errors'), + extra_args=metadata.get('extra_args'))) + elif test_type == 'pcode_check': + tests.append(PCodeCheckTest( + name=name, + code_pattern=metadata.get('code_pattern'), + extra_args=metadata.get('extra_args'))) elif test_type == 'runtime': - tests.append(RuntimeTest(name=name, - output=metadata.get('output'), - should_fail=metadata.get('should_fail'))) + tests.append(RuntimeTest( + name=name, + output=metadata.get('output'), + should_fail=metadata.get('should_fail'))) else: raise KeyError('Unknown test type: ' + test_type) num_tests = len(tests) -sys.stdout.write('DISCOVERED {} TEST{}'.format(num_tests, '' if num_tests == 1 else 'S')) +sys.stdout.write( + 'DISCOVERED {} TEST{}'.format(num_tests, '' if num_tests == 1 else 'S')) if num_tests_disabled > 0: sys.stdout.write(' ({} DISABLED)'.format(num_tests_disabled)) sys.stdout.write('\n\n') num_tests_failed = 0 + for test in tests: sys.stdout.write('Running ' + test.name + '... ') if not test.run(): @@ -143,6 +229,7 @@ for test in tests: sys.stdout.write('PASSED\n') num_tests_passed = len(tests) - num_tests_failed + if num_tests_failed > 0: print('\n{} TEST{} PASSED, {} FAILED'.format( num_tests_passed, From 0affc419db2a1934cac5a184b4f9d54bf59118fa Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 2 Sep 2018 08:36:12 +0600 Subject: [PATCH 74/88] Make it possible to run specific tests by name --- source/compiler/tests/run_tests.py | 49 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/source/compiler/tests/run_tests.py b/source/compiler/tests/run_tests.py index d3d33f5..820f3c9 100644 --- a/source/compiler/tests/run_tests.py +++ b/source/compiler/tests/run_tests.py @@ -19,6 +19,7 @@ parser.add_argument('-i', '--include', help='add custom include directories for compile tests') parser.add_argument('-r', '--runner', help='path to runner executable (pawnruns)') +parser.add_argument('tests', metavar='test_name', nargs='*') options = parser.parse_args(sys.argv[1:]) def run_command(args, executable=None, merge_stderr=False): @@ -58,9 +59,6 @@ def remove_asm_comments(s): def strip(s): return s.strip(' \t\r\n') -def parse_asm_listing(dump): - return None - class OutputCheckTest: def __init__(self, name, errors=None, extra_args=None): self.name = name @@ -184,6 +182,8 @@ num_tests_disabled = 0 for meta_file in glob.glob('*.meta'): name = os.path.splitext(meta_file)[0] + if options.tests and name not in options.tests: + continue metadata = eval(open(meta_file).read(), None, None) if metadata.get('disabled'): num_tests_disabled += 1 @@ -213,28 +213,27 @@ sys.stdout.write( 'DISCOVERED {} TEST{}'.format(num_tests, '' if num_tests == 1 else 'S')) if num_tests_disabled > 0: sys.stdout.write(' ({} DISABLED)'.format(num_tests_disabled)) -sys.stdout.write('\n\n') -num_tests_failed = 0 +if num_tests > 0: + sys.stdout.write('\n\n') -for test in tests: - sys.stdout.write('Running ' + test.name + '... ') - if not test.run(): - sys.stdout.write('FAILED\n') - print('Test {} failed for the following reason: {}'.format( - test.name, test.fail_reason)) - print('') - num_tests_failed += 1 + num_tests_failed = 0 + for test in tests: + sys.stdout.write('Running ' + test.name + '... ') + if not test.run(): + sys.stdout.write('FAILED\n') + print('Test {} failed for the following reason: {}'.format( + test.name, test.fail_reason)) + print('') + num_tests_failed += 1 + else: + sys.stdout.write('PASSED\n') + num_tests_passed = len(tests) - num_tests_failed + if num_tests_failed > 0: + print('\n{} TEST{} PASSED, {} FAILED'.format( + num_tests_passed, + '' if num_tests_passed == 1 else 'S', + num_tests_failed)) + sys.exit(1) else: - sys.stdout.write('PASSED\n') - -num_tests_passed = len(tests) - num_tests_failed - -if num_tests_failed > 0: - print('\n{} TEST{} PASSED, {} FAILED'.format( - num_tests_passed, - '' if num_tests_passed == 1 else 'S', - num_tests_failed)) - sys.exit(1) -else: - print('\nALL TESTS PASSED') + print('\nALL TESTS PASSED') From 641169e053048ca791d817ecd0ade2a394bc029a Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 2 Sep 2018 09:33:03 +0600 Subject: [PATCH 75/88] Add CTest wrappers for tests With CTest it's much easier to run the tests via command line - no need to specify path to compiler, etc. Simply run this command (from the build directory): ctest -C Debug or ctest -C Debug -R pcode.* to run tests matching a regexp (it will run pcode_test_example in this case)). It is still possible to use the run_tests.py script directly. --- .travis.yml | 5 +++- appveyor.yml | 5 +++- source/compiler/CMakeLists.txt | 41 +++++++++++++++------------- source/compiler/tests/CMakeLists.txt | 18 ++++++++++-- 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index f12426d..7e81701 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,9 +21,12 @@ before_script: script: - make - - make pawncc_tests + - make test - make package +after_failure: + - cat Testing/Temporary/LastTest.log + deploy: provider: releases api_key: diff --git a/appveyor.yml b/appveyor.yml index bffa5e9..85529fa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,7 +13,10 @@ build_script: - cmake --build . --config %CONFIGURATION% --target package test_script: - - cmake --build . --config %CONFIGURATION% --target pawncc_tests + - ctest --build-config %CONFIGURATION% + +on_failure: + - type Testing\Temporary\LastTest.log artifacts: - path: build/pawnc-*-windows.zip diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index 018c03e..236ca68 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -164,28 +164,31 @@ if(MSVC) endif() # Generate targets for running compiler tests -set(PAWNRUNS_SRCS - pawnruns.c - ../amx/amx.c - ../amx/amx.h - ../amx/amxaux.c - ../amx/amxaux.h - ../amx/amxcons.c - ../amx/amxcore.c -) -if(UNIX) +include(CTest) +if(BUILD_TESTING) set(PAWNRUNS_SRCS - ${PAWNRUNS_SRCS} - ../linux/getch.c - ../linux/getch.h - ../linux/binreloc.c + pawnruns.c + ../amx/amx.c + ../amx/amx.h + ../amx/amxaux.c + ../amx/amxaux.h + ../amx/amxcons.c + ../amx/amxcore.c ) + if(UNIX) + set(PAWNRUNS_SRCS + ${PAWNRUNS_SRCS} + ../linux/getch.c + ../linux/getch.h + ../linux/binreloc.c + ) + endif() + add_executable(pawnruns ${PAWNRUNS_SRCS}) + if(UNIX) + target_link_libraries(pawnruns dl) + endif() + add_subdirectory(tests) endif() -add_executable(pawnruns ${PAWNRUNS_SRCS}) -if(UNIX) - target_link_libraries(pawnruns dl) -endif() -add_subdirectory(tests) # Generate a binary package with CPack set(CPACK_PACKAGE_NAME pawnc) diff --git a/source/compiler/tests/CMakeLists.txt b/source/compiler/tests/CMakeLists.txt index e49e05e..282f668 100644 --- a/source/compiler/tests/CMakeLists.txt +++ b/source/compiler/tests/CMakeLists.txt @@ -1,7 +1,7 @@ find_package(PythonInterp 2.7) if(PYTHONINTERP_FOUND) - add_custom_target(pawncc_tests COMMAND + add_custom_target(pawncc_tests COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/run_tests.py -c $ @@ -10,6 +10,20 @@ if(PYTHONINTERP_FOUND) -i ../../../include DEPENDS pawncc WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + + file(GLOB_RECURSE meta_files "*.meta") + foreach(meta_file IN LISTS meta_files) + get_filename_component(test_name ${meta_file} NAME_WE) + add_test(NAME ${test_name} + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/run_tests.py + -c $ + -d $ + -r $ + -i ../../../include + ${test_name} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + endforeach() else() - message("Python was not found, you will not be able to run the compiler tests") + message("Python was not found, you will not be able to run the tests") endif() From f64500c355a0d80280bb23a4d45ace00122d8578 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 2 Sep 2018 09:45:57 +0600 Subject: [PATCH 76/88] Remove top-level CMakeListst.txt It was a bad idea... --- .travis.yml | 7 ++++--- CMakeLists.txt | 11 ----------- appveyor.yml | 2 +- 3 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 CMakeLists.txt diff --git a/.travis.yml b/.travis.yml index 7e81701..5851319 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,9 +15,10 @@ addons: before_script: - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DCMAKE_C_FLAGS="-m32 -Werror -Wno-address-of-packed-member" - -DCPACK_GENERATOR="TGZ;ZIP" + - cmake ../source/compiler + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DCMAKE_C_FLAGS="-m32 -Werror -Wno-address-of-packed-member" + -DCPACK_GENERATOR="TGZ;ZIP" script: - make diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 1a2c664..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -project(pawn C) -cmake_minimum_required(VERSION 2.8) - -set(OUTPUT_DIR ${CMAKE_BINARY_DIR}/products) -add_subdirectory(source/compiler ${OUTPUT_DIR}) - -# For the compiler we only utilize headers from source/amx, i.e. we don't -# actually build any of the AMX modules. -if(BUILD_AMX) - add_subdirectory(source/amx ${OUTPUT_DIR}) -endif() diff --git a/appveyor.yml b/appveyor.yml index 85529fa..70a6428 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ configuration: before_build: - mkdir build && cd build - - cmake .. -G "Visual Studio 14 2015" -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 + - cmake ../source/compiler -G "Visual Studio 14 2015" -DCPACK_GENERATOR=ZIP -DCMAKE_GENERATOR_TOOLSET=v100 build_script: - cmake --build . --config %CONFIGURATION% From 6dec728efe5b8c394b4059e6845d394392c68605 Mon Sep 17 00:00:00 2001 From: Adrian Graber Date: Sun, 2 Sep 2018 19:40:35 +0200 Subject: [PATCH 77/88] Check if function is naked before adding +1 for PROC opcide (#357) --- source/compiler/sc1.c | 14 +++++++++++--- source/compiler/sc3.c | 5 +++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index d96e4e0..27b4fe0 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -2337,8 +2337,13 @@ static int declloc(int fstatic) modstk(-(int)size*sizeof(cell)); assert(curfunc!=NULL); assert((curfunc->usage & uNATIVE)==0); - if (curfunc->x.stacksizex.stacksize=declared+1; /* +1 for PROC opcode */ + if (curfunc->flags & flagNAKED) { + if (curfunc->x.stacksizex.stacksize=declared; + } else { + if (curfunc->x.stacksizex.stacksize=declared+1; /* +1 for PROC opcode */ + } /* if */ } /* if */ /* now that we have reserved memory for the variable, we can proceed * to initialize it */ @@ -3156,7 +3161,10 @@ SC_FUNC symbol *fetchfunc(char *name,int tag) /* set library ID to NULL (only for native functions) */ sym->x.lib=NULL; /* set the required stack size to zero (only for non-native functions) */ - sym->x.stacksize=1; /* 1 for PROC opcode */ + if (sym->flags & flagNAKED) + sym->x.stacksize=0; /* zero for naked functions */ + else + sym->x.stacksize=1; /* 1 for PROC opcode */ } /* if */ if (pc_deprecate!=NULL) { assert(sym!=NULL); diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index e22de2c..9cec309 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -2421,8 +2421,9 @@ static int nesting=0; /* maintain max. amount of memory used */ { long totalsize; - totalsize=declared+decl_heap+1; /* local variables & return value size, - * +1 for PROC opcode */ + totalsize=declared+decl_heap; /* local variables & return value size */ + if ((sym->flags & flagNAKED)==0) + totalsize++; /* +1 for PROC opcode */ if (lval_result->ident==iREFARRAY) totalsize++; /* add hidden parameter (on the stack) */ if ((sym->usage & uNATIVE)==0) From 27bdc075b28a0e03a3a9f6bc0b35263fea788976 Mon Sep 17 00:00:00 2001 From: Barnaby Keene Date: Sun, 2 Sep 2018 18:49:49 +0100 Subject: [PATCH 78/88] Revert "Check if function is naked before adding +1 for PROC opcide (#357)" (#361) This reverts commit 6dec728efe5b8c394b4059e6845d394392c68605. --- source/compiler/sc1.c | 14 +++----------- source/compiler/sc3.c | 5 ++--- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 27b4fe0..d96e4e0 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -2337,13 +2337,8 @@ static int declloc(int fstatic) modstk(-(int)size*sizeof(cell)); assert(curfunc!=NULL); assert((curfunc->usage & uNATIVE)==0); - if (curfunc->flags & flagNAKED) { - if (curfunc->x.stacksizex.stacksize=declared; - } else { - if (curfunc->x.stacksizex.stacksize=declared+1; /* +1 for PROC opcode */ - } /* if */ + if (curfunc->x.stacksizex.stacksize=declared+1; /* +1 for PROC opcode */ } /* if */ /* now that we have reserved memory for the variable, we can proceed * to initialize it */ @@ -3161,10 +3156,7 @@ SC_FUNC symbol *fetchfunc(char *name,int tag) /* set library ID to NULL (only for native functions) */ sym->x.lib=NULL; /* set the required stack size to zero (only for non-native functions) */ - if (sym->flags & flagNAKED) - sym->x.stacksize=0; /* zero for naked functions */ - else - sym->x.stacksize=1; /* 1 for PROC opcode */ + sym->x.stacksize=1; /* 1 for PROC opcode */ } /* if */ if (pc_deprecate!=NULL) { assert(sym!=NULL); diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 9cec309..e22de2c 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -2421,9 +2421,8 @@ static int nesting=0; /* maintain max. amount of memory used */ { long totalsize; - totalsize=declared+decl_heap; /* local variables & return value size */ - if ((sym->flags & flagNAKED)==0) - totalsize++; /* +1 for PROC opcode */ + totalsize=declared+decl_heap+1; /* local variables & return value size, + * +1 for PROC opcode */ if (lval_result->ident==iREFARRAY) totalsize++; /* add hidden parameter (on the stack) */ if ((sym->usage & uNATIVE)==0) From 912c45c968416490ae1bb6d59849fd9d7380a174 Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Thu, 6 Sep 2018 22:33:36 +0700 Subject: [PATCH 79/88] amxaux.c: Don't forget to close the program file before returning --- source/amx/amxaux.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/source/amx/amxaux.c b/source/amx/amxaux.c index 0ff0f75..762b5b5 100644 --- a/source/amx/amxaux.c +++ b/source/amx/amxaux.c @@ -30,13 +30,15 @@ size_t AMXAPI aux_ProgramSize(char *filename) { FILE *fp; + size_t size; AMX_HEADER hdr; if ((fp=fopen(filename,"rb")) == NULL) return 0; - if (fread(&hdr, sizeof hdr, 1, fp) < 1) - return 0; + size = fread(&hdr, sizeof hdr, 1, fp); fclose(fp); + if (size < 1) + return 0; amx_Align16(&hdr.magic); amx_Align32((uint32_t *)&hdr.stp); @@ -46,21 +48,24 @@ size_t AMXAPI aux_ProgramSize(char *filename) int AMXAPI aux_LoadProgram(AMX *amx, char *filename, void *memblock) { FILE *fp; + size_t size; AMX_HEADER hdr; int result, didalloc; /* open the file, read and check the header */ if ((fp = fopen(filename, "rb")) == NULL) return AMX_ERR_NOTFOUND; - if (fread(&hdr, sizeof hdr, 1, fp) < 1) - return AMX_ERR_INIT; - amx_Align16(&hdr.magic); - amx_Align32((uint32_t *)&hdr.size); - amx_Align32((uint32_t *)&hdr.stp); - if (hdr.magic != AMX_MAGIC) { + size = fread(&hdr, sizeof hdr, 1, fp); + if (size < 1) { +err_format: fclose(fp); return AMX_ERR_FORMAT; } /* if */ + amx_Align16(&hdr.magic); + amx_Align32((uint32_t *)&hdr.size); + amx_Align32((uint32_t *)&hdr.stp); + if (hdr.magic != AMX_MAGIC) + goto err_format; /* allocate the memblock if it is NULL */ didalloc = 0; @@ -75,9 +80,10 @@ int AMXAPI aux_LoadProgram(AMX *amx, char *filename, void *memblock) /* read in the file */ rewind(fp); - if (fread(memblock, 1, (size_t)hdr.size, fp) < (size_t)hdr.size) - return AMX_ERR_INIT; + size = fread(memblock, 1, (size_t)hdr.size, fp); fclose(fp); + if (size < (size_t)hdr.size) + return AMX_ERR_FORMAT; /* initialize the abstract machine */ memset(amx, 0, sizeof *amx); From 9d5f82ed6c1b2545ccd6fb4a08c641136f0371db Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Fri, 7 Sep 2018 02:06:06 +0700 Subject: [PATCH 80/88] amxaux.c: Get rid of a goto statement --- source/amx/amxaux.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/amx/amxaux.c b/source/amx/amxaux.c index 762b5b5..10a92ea 100644 --- a/source/amx/amxaux.c +++ b/source/amx/amxaux.c @@ -57,15 +57,16 @@ int AMXAPI aux_LoadProgram(AMX *amx, char *filename, void *memblock) return AMX_ERR_NOTFOUND; size = fread(&hdr, sizeof hdr, 1, fp); if (size < 1) { -err_format: fclose(fp); return AMX_ERR_FORMAT; } /* if */ amx_Align16(&hdr.magic); amx_Align32((uint32_t *)&hdr.size); amx_Align32((uint32_t *)&hdr.stp); - if (hdr.magic != AMX_MAGIC) - goto err_format; + if (hdr.magic != AMX_MAGIC) { + fclose(fp); + return AMX_ERR_FORMAT; + } /* if */ /* allocate the memblock if it is NULL */ didalloc = 0; From ab446ee2ce9a80cb397f214c6efec82fbb30d8a3 Mon Sep 17 00:00:00 2001 From: Barnaby Keene Date: Mon, 10 Sep 2018 09:15:55 +0100 Subject: [PATCH 81/88] Updated readme.md file and added forum thread bbcode (#334) * updated readme to make it easier to read for beginners added a bbcode rendering of the readme for a forum thread * added "Community Compiler" to heading * made some changes as per Yashas request * moved long URLs to references area * fixed minor grammar and word usage fixed appveyor links * bbcode * added compatibility note * Delete readme.bbcode * Fix typo in readme * some final tweaks removed build from source instructions fixed some minor grammar fixes * moved -Z note to the general how to use section and changed the wording slightly * Change -Z+ to just -Z --- readme.md | 184 +++++++++++++++++++++++++----------------------------- 1 file changed, 84 insertions(+), 100 deletions(-) diff --git a/readme.md b/readme.md index db0ba47..09097b7 100644 --- a/readme.md +++ b/readme.md @@ -1,135 +1,119 @@ -# Pawn +# Pawn Community Compiler -[![Build Status][build_status]][build] [![Build Status - Windows][build_status_win]][build_win] +[![Build Status][build_status_linux]][build_linux] +[![Build Status - Windows][build_status_win]][build_win] -[Original readme](readme_compuphase.txt) +## What -## What is this? +This is a modified version of the Pawn 3.2.3664 compiler with many bug fixes and +enhancements. -This is a modified copy of the Pawn compiler version 3.2.3664 by Compuphase that fixes some bugs and adds a few features. +This project was originally started by Zeex but on 2017-12-31, the project was +taken over by some members of the SA:MP community. Zeex still contributes to the +project, along with the [Compiler Team][team]. -This project was originally maintained and managed by Zeex who left the project due to lack of time on 2017-12-31. Thank you for all your hard work on keeping this project alive Zeex! +The original readme is available [here][original_readme] -The project is now maintained by the [Compiler Team](https://github.com/orgs/pawn-lang/teams/compiler) here at the pawn-lang GitHub org. +## Why -## List of changes +This project exists to: -See [Known compiler bugs](../../wiki/Known-compiler-bugs) for the list of fixed bugs and [What's new](../../wiki/What's-new) for the list of features and other notable changes. +- Fix known bugs with the original compiler +- Provide a better development experience for the SA:MP community -[Release notes](https://github.com/pawn-lang/compiler/releases) descibe changes in each version of the compiler. +If you find problem, you can [open an issue][issues] and contributors can work +on a fix. This isn't true with the original compiler that comes with the SA:MP +server distribution. -## Download +There are also new features that enhance the development experience, such as +telling you which tags are involved in a "tag mismatch" or showing you where +that pesky "symbol is never used" is actually declared. -Binary packages can be downloads from [Releases](https://github.com/pawn-lang/compiler/releases). +There are plenty of features and fixes that are documented, see below for links: -You can also get the latest development binaries for Windows on [AppVeyor](https://ci.appveyor.com/project/pawn-lang/compiler/branch/master/artifacts). This archive is built automatically on every Git commit and can be pretty unstable, so use at your own risk. +- [Known compiler bugs][bugs] contains a list of bugs that the team are aware of + with their status. -## Installation on Windows +- [What's new][new] contains features and other notable changes. -Download the ZIP archive and extract `pawnc.dll`, `pawncc.exe`, `pawndisasmsm.exe` to your pawno directory or another directory of your choice if you're using a different editor. +- [Release notes][releases] list of all official releases of the compiler + binaries. -## Installation on openSUSE/SLES +## How to Use -There is an installation package available for openSUSE/SLES users so that you can easily install the compiler on your distribution. Please follow these steps: +Binary packages can be downloaded from [Releases][releases], see the below +sections for platform-specific installation instructions. -1. Go to https://build.opensuse.org/package/show/home:mschnitzer/pawncc -2. On the right side, select your distribution (only if it's not disabled!) -3. Click "Go to download repository" -4. Copy the link and enter in sudo mode in your shell: `zypper ar $COPIED_LINK home:mschnitzer` -5. Again as root, type: `zypper ref` -6. Install the package with `zypper in pawncc` -7. Run `pawncc` in your shell to test if it's working +**Note:** You will _probably_ get warnings/errors/fatals when you first build +with this compiler — you need to add the `-Z` flag to your build configuration +or add `#pragma compat`. See [this page][compat] for more information. -## Building from source code +You can also get the latest development binaries for Windows on +[AppVeyor][artifacts]. This archive is built automatically on every Git commit +and can be pretty unstable, so use at your own risk. -In general you will need [CMake](https://cmake.org/) and a C compiller to build Pawn from source code. +### Windows -### Building on Windows +If you just use an editor configured to run `pawncc` such as Pawno, Sublime Text +or VS Code you can simply delete your existing `pawncc.exe` and replace it with +the new one. -* Clone this repo: `git clone https://github.com/Zeex/pawn.git C:\pawn` (you can use another directory instead of `C:\Pawn`, but make sure the path doesn't have spaces). -* Install [Visual Studio Community](https://www.visualstudio.com/vs/community/), it's free. -* Install [CMake](https://cmake.org/). +Download the ZIP archive and extract `pawnc.dll`, `pawncc.exe`, +`pawndisasmsm.exe` to your original `pawncc` directory. If you use Pawno, this +will be in the `pawno/` folder that's inside your server directory. - When installing make sure to check "Add CMake to system PATH" to make your life easier. +### openSUSE/SLES -* Generate a Visual Studio project. +There is an installation package available for openSUSE/SLES users so that you +can easily install the compiler on your distribution. Please follow these steps: - In Command promprt or Powershell execute the following: +1. Go to +2. On the right side, select your distribution (only if it's not disabled!) +3. Click "Go to download repository" +4. Copy the link and enter in sudo mode in your shell: + `zypper ar $COPIED_LINK home:mschnitzer` +5. Again as root, type: `zypper ref` +6. Install the package with `zypper in pawncc` +7. Run `pawncc` in your shell to test if it's working - ```cmd - cd C:\Pawn - mkdir build && cd build - cmake ..\source\compiler -G "Visual Studio 15 2017" - ``` +### With sampctl -* From the same directory as in the previous step run: +If you are a [sampctl][sampctl] user, you are already using this compiler! - ``` - cmake --build . --config Release - ``` +### Build From Source - or open the pawnc.sln in Visual Studio and build from there (but make sure to choose the "Release" configuration). - - This will create `pawnc.dll` and `pawncc.exe` in the `Release` folder. You can now copy these files to your `pawno` folder for convenience or put them in a separate folder and configure your code editor accordingly. - -### Building on Linux - -Use your distribution's package manager to install the required dependencies. For example, in Ubuntu you would do: - -```sh -sudo apt install gcc gcc-multilib make cmake -``` - -`gcc-multilib` is needed for compiling a 32-bit binary (64-bit is not supported). - -Now you can clone this repo and build the compiler: - -```sh -git clone https://github.com/Zeex/pawn.git ~/pawn -cd ~/pawn -mkdir build && cd build -cmake ../source/compiler -DCMAKE_C_FLAGS=-m32 -DCMAKE_BUILD_TYPE=Release -make -``` - -Replace "Release" with "Debug" if you want to build a debug executable for development or submitting bugs. - -### Building on macOS - -* Install Xcode: https://developer.apple.com/xcode/ - -* Install Command Line Tools for Xcode: - -```sh -xcode-select --install -``` - -* Install CMake: - -```sh -brew install cmake -``` - -* Now you can clone this repo and build the compiler: - -```sh -git clone https://github.com/Zeex/pawn.git ~/pawn -cd ~/pawn -mkdir build && cd build -cmake ../source/compiler -DCMAKE_C_FLAGS=-m32 -DCMAKE_BUILD_TYPE=Release -make -``` +If you are interested in contributing or just using a specific version, check +out [this page][build_source] for instructions for compiling for your platform. ## Background -The project was originally started as a set of patches aimed to create a compiler that would be compatible with the compiler used in [SA-MP (San Andreas Multiplayer)](http://sa-mp.com/). +The project was originally started as a set of patches aimed to create a +compiler that would be compatible with the compiler used in +[SA-MP (San Andreas Multiplayer)](http://sa-mp.com/). -SA-MP uses a modified version of Pawn 3.2.3664 [1] with Windows-only executables, and the developers said that they lost the source code for it which means it can't be ported to other platforms (e.g. Linux) and newly discovered bugs can't be fixed. So the main goal of the project is to re-create changes that were previously made by the devs as well as fix all known compiler bugs. +SA-MP uses a modified version of Pawn 3.2.3664 [1] with Windows-only +executables, and the developers said that they lost the source code for it which +means it can't be ported to other platforms (e.g. Linux) and newly discovered +bugs can't be fixed. So the main goal of the project is to re-create changes +that were previously made by the devs as well as fix all known compiler bugs. -[1] It's worth noting that the version of the AMX embedded into the SA-MP server seems to be based on an older release of Pawn. +[1] It's worth noting that the version of the AMX embedded into the SA-MP server +seems to be based on an older release of Pawn. -[build]: https://travis-ci.org/pawn-lang/compiler -[build_status]: https://travis-ci.org/pawn-lang/compiler.svg?branch=master +[build_linux]: https://travis-ci.org/pawn-lang/compiler +[build_status_linux]: https://travis-ci.org/pawn-lang/compiler.svg?branch=master [build_win]: https://ci.appveyor.com/project/Southclaws/compiler/branch/master -[build_status_win]: https://ci.appveyor.com/api/projects/status/k112tbr1afrkif0n?svg=true - +[build_status_win]: + https://ci.appveyor.com/api/projects/status/k112tbr1afrkif0n?svg=true +[team]: https://github.com/orgs/pawn-lang/teams/compiler +[original_readme]: + https://github.com/pawn-lang/tree/master/readme_compuphase.txt +[issues]: https://github.com/pawn-lang/compiler/issues +[bugs]: https://github.com/pawn-lang/compiler/wiki/Known-compiler-bugs +[new]: https://github.com/pawn-lang/compiler/wiki/What's-new +[releases]: https://github.com/pawn-lang/compiler/releases +[artifacts]: + https://ci.appveyor.com/project/Southclaws/compiler/branch/master/artifacts +[compat]: https://github.com/pawn-lang/compiler/wiki/Compatibility-mode +[sampctl]: http://bit.ly/sampctl +[build_source]: https://github.com/pawn-lang/compiler/wiki/Building-From-Source From bc04b2ef048a02a7f4030d807d97a7fc10cb760a Mon Sep 17 00:00:00 2001 From: Daniel_Cortez Date: Tue, 7 Aug 2018 09:25:07 +0700 Subject: [PATCH 82/88] Show suggestions for mistyped identifiers (#353) --- source/compiler/sc.h | 26 ++- source/compiler/sc1.c | 8 +- source/compiler/sc3.c | 30 ++-- source/compiler/sc5.c | 278 +++++++++++++++++++++++++++++- source/compiler/tests/gh_353.inc | 2 + source/compiler/tests/gh_353.meta | 24 +++ source/compiler/tests/gh_353.pwn | 118 +++++++++++++ 7 files changed, 458 insertions(+), 28 deletions(-) create mode 100644 source/compiler/tests/gh_353.inc create mode 100644 source/compiler/tests/gh_353.meta create mode 100644 source/compiler/tests/gh_353.pwn diff --git a/source/compiler/sc.h b/source/compiler/sc.h index beda684..e417ae9 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -308,6 +308,11 @@ typedef struct s_valuepair { #define opcodes(n) ((n)*sizeof(cell)) /* opcode size */ #define opargs(n) ((n)*sizeof(cell)) /* size of typical argument */ +/* general purpose macros */ +#if !defined makelong + #define makelong(low,high) ((long)(low) | ((long)(high) << (sizeof(long)*4))) +#endif + /* Tokens recognized by lex() * Some of these constants are assigned as well to the variable "lastst" (see SC1.C) */ @@ -493,6 +498,24 @@ typedef struct s_emit_outval { } value; } emit_outval; +/* constants for error_suggest() */ +#define MAX_EDIT_DIST 2 /* allow two mis-typed characters; when there are more, + * the names are too different, and no match is returned */ +enum { /* identifier types */ + estSYMBOL = 0, + estNONSYMBOL, + estAUTOMATON, + estSTATE +}; +enum { /* symbol types */ + essNONLABEL, /* find symbols of any type but labels */ + essVARCONST, /* array, single variable or named constant */ + essARRAY, + essCONST, + essFUNCTN, + essLABEL +}; + /* interface functions */ #if defined __cplusplus extern "C" { @@ -721,8 +744,9 @@ SC_FUNC void outval(cell val,int newline); SC_FUNC void outinstr(const char *name,emit_outval params[],int numparams); /* function prototypes in SC5.C */ -SC_FUNC int error(int number,...); +SC_FUNC int error(long number,...); SC_FUNC void errorset(int code,int line); +SC_FUNC int error_suggest(int error,const char *name,const char *name2,int type,int subtype); /* function prototypes in SC6.C */ SC_FUNC int assemble(FILE *fout,FILE *fin); diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index d96e4e0..fcec5ec 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -2018,7 +2018,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst } else { tag=pc_addtag(NULL); if (lex(&val,&str)!=tSYMBOL) /* read in (new) token */ - error(20,str); /* invalid symbol name */ + error_suggest(20,str,NULL,estSYMBOL,essFUNCTN); /* invalid symbol name */ assert(strlen(str)<=sNAMEMAX); strcpy(name,str); /* save symbol name */ } /* if */ @@ -4869,7 +4869,7 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst) case iLABEL: if (testlabs) { if ((sym->usage & uDEFINE)==0) { - error(19,sym->name); /* not a label: ... */ + error_suggest(19,sym->name,NULL,estSYMBOL,essLABEL); /* not a label: ... */ } else if ((sym->usage & uREAD)==0) { errorset(sSETPOS,sym->lnumber); error(203,sym->name); /* symbol isn't used: ... */ @@ -5973,7 +5973,7 @@ static void dogoto(void) // sym->compound (nesting level of the label) against nestlevel; // if sym->compound < nestlevel, call the destructor operator } else { - error(20,st); /* illegal symbol name */ + error_suggest(20,st,NULL,estSYMBOL,essLABEL); /* illegal symbol name */ } /* if */ needtoken(tTERM); } @@ -6013,7 +6013,7 @@ static symbol *fetchlab(char *name) sym=findloc(name); /* labels are local in scope */ if (sym) { if (sym->ident!=iLABEL) - error(19,sym->name); /* not a label: ... */ + error_suggest(19,sym->name,NULL,estSYMBOL,essLABEL); /* not a label: ... */ } else { sym=addsym(name,getlabel(),iLABEL,sLOCAL,0,0); assert(sym!=NULL); /* fatal error 103 must be given on error */ diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index e22de2c..f4bef71 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -749,7 +749,7 @@ SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state) return 0; tokeninfo(&val,&str); /* do not copy the name yet, must check automaton first */ if (*automaton==NULL) { - error(86,name); /* unknown automaton */ + error_suggest(86,name,NULL,estAUTOMATON,0); /* unknown automaton */ return 0; } /* if */ assert((*automaton)->index>0); @@ -769,7 +769,7 @@ SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state) char *fsaname=(*automaton)->name; if (*fsaname=='\0') fsaname="
"; - error(87,name,fsaname); /* unknown state for automaton */ + error_suggest(87,name,fsaname,estSTATE,fsa); /* unknown state for automaton */ return 0; } /* if */ @@ -1321,7 +1321,7 @@ static int hier2(value *lval) paranthese++; tok=lex(&val,&st); if (tok!=tSYMBOL) - return error(20,st); /* illegal symbol name */ + return error_suggest(20,st,NULL,estNONSYMBOL,tok); /* illegal symbol name */ sym=findloc(st); if (sym==NULL) sym=findglb(st,sSTATEVAR); @@ -1344,18 +1344,18 @@ static int hier2(value *lval) paranthese++; tok=lex(&val,&st); if (tok!=tSYMBOL) - return error(20,st); /* illegal symbol name */ + return error_suggest(20,st,NULL,estNONSYMBOL,tok); /* illegal symbol name */ sym=findloc(st); if (sym==NULL) sym=findglb(st,sSTATEVAR); if (sym==NULL) - return error(17,st); /* undefined symbol */ + return error_suggest(17,st,NULL,estSYMBOL,essVARCONST); /* undefined symbol */ if (sym->ident==iCONSTEXPR) error(39); /* constant symbol has no size */ else if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) error(72); /* "function" symbol has no size */ else if ((sym->usage & uDEFINE)==0) - return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */ + return error_suggest(17,st,NULL,estSYMBOL,essVARCONST); /* undefined symbol (symbol is in the table, but it is "used" only) */ clear_value(lval); lval->ident=iCONSTEXPR; lval->constval=1; /* preset */ @@ -1370,7 +1370,7 @@ static int hier2(value *lval) int cmptag=subsym->x.tags.index; tokeninfo(&val,&idxname); if ((idxsym=findconst(idxname,&cmptag))==NULL) - error(80,idxname); /* unknown symbol, or non-constant */ + error_suggest(80,idxname,NULL,estSYMBOL,essCONST); /* unknown symbol, or non-constant */ else if (cmptag>1) error(91,idxname); /* ambiguous constant */ } /* if */ @@ -1397,7 +1397,7 @@ static int hier2(value *lval) paranthese++; tok=lex(&val,&st); if (tok!=tSYMBOL && tok!=tLABEL) - return error(20,st); /* illegal symbol name */ + return error_suggest(20,st,NULL,estNONSYMBOL,tok); /* illegal symbol name */ if (tok==tLABEL) { constvalue *tagsym=find_constval(&tagname_tab,st,0); tag=(int)((tagsym!=NULL) ? tagsym->value : 0); @@ -1406,9 +1406,9 @@ static int hier2(value *lval) if (sym==NULL) sym=findglb(st,sSTATEVAR); if (sym==NULL) - return error(17,st); /* undefined symbol */ + return error_suggest(17,st,NULL,estSYMBOL,essNONLABEL); /* undefined symbol */ if ((sym->usage & uDEFINE)==0) - return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */ + return error_suggest(17,st,NULL,estSYMBOL,essNONLABEL); /* undefined symbol (symbol is in the table, but it is "used" only) */ tag=sym->tag; } /* if */ if (sym!=NULL && (sym->ident==iARRAY || sym->ident==iREFARRAY)) { @@ -1422,7 +1422,7 @@ static int hier2(value *lval) int cmptag=subsym->x.tags.index; tokeninfo(&val,&idxname); if ((idxsym=findconst(idxname,&cmptag))==NULL) - error(80,idxname); /* unknown symbol, or non-constant */ + error_suggest(80,idxname,NULL,estSYMBOL,essCONST); /* unknown symbol, or non-constant */ else if (cmptag>1) error(91,idxname); /* ambiguous constant */ } /* if */ @@ -1601,7 +1601,7 @@ restart: needtoken(close); return FALSE; } else if (sym->ident!=iARRAY && sym->ident!=iREFARRAY){ - error(28,sym->name); /* cannot subscript, variable is not an array */ + error_suggest(28,sym->name,NULL,estSYMBOL,essARRAY);/* cannot subscript, variable is not an array */ needtoken(close); return FALSE; } else if (sym->dim.array.level>0 && close!=']') { @@ -1854,10 +1854,10 @@ static int primary(value *lval) * implemented, issue an error */ if ((sym->usage & uPROTOTYPED)==0) - error(17,st); + error_suggest(17,st,NULL,estSYMBOL,essFUNCTN); /* undefined symbol */ } else { if ((sym->usage & uDEFINE)==0) - error(17,st); + error_suggest(17,st,NULL,estSYMBOL,essVARCONST); /* undefined symbol */ lval->sym=sym; lval->ident=sym->ident; lval->tag=sym->tag; @@ -1870,7 +1870,7 @@ static int primary(value *lval) } /* if */ } else { if (!sc_allowproccall) - return error(17,st); /* undefined symbol */ + return error_suggest(17,st,NULL,estSYMBOL,essVARCONST); /* undefined symbol */ /* an unknown symbol, but used in a way compatible with the "procedure * call" syntax. So assume that the symbol refers to a function. */ diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index cd24e87..ae05425 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -29,6 +29,7 @@ #if defined LINUX || defined __GNUC__ #include #endif +#include #include #include #include /* ANSI standardized variable argument list functions */ @@ -197,6 +198,10 @@ static char *warnmsg[] = { /*239*/ "literal array/string passed to a non-const parameter\n" }; +static char *noticemsg[] = { +/*001*/ "; did you mean \"%s\"?\n" +}; + #define NUM_WARNINGS (sizeof warnmsg / sizeof warnmsg[0]) static struct s_warnstack { unsigned char disable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char */ @@ -220,13 +225,22 @@ static int errwarn; * fcurrent (reffered to only) * errflag (altered) */ -SC_FUNC int error(int number,...) +SC_FUNC int error(long number,...) { static char *prefix[3]={ "error", "fatal error", "warning" }; static int lastline,errorcount; static short lastfile; char *msg,*pre; va_list argptr; + char string[128]; + int notice; + + /* split the error field between the real error/warning number and an optional + * "notice" number + */ + notice=(unsigned long)number >> (sizeof(long)*4); + number&=(~(unsigned long)0) >> (sizeof(long)*4); + assert(number>0 && number<300); /* errflag is reset on each semicolon. * In a two-pass compiler, an error should not be reported twice. Therefore @@ -244,26 +258,37 @@ static short lastfile; return 0; } /* if */ - if (number<100){ + if (number<100) { + assert(number>0 && number<(1+arraysize(errmsg))); msg=errmsg[number-1]; pre=prefix[0]; errflag=TRUE; /* set errflag (skip rest of erroneous expression) */ errnum++; - } else if (number<200){ + } else if (number<200) { + assert(number>=100 && number<(100+arraysize(fatalmsg))); msg=fatalmsg[number-100]; pre=prefix[1]; errnum++; /* a fatal error also counts as an error */ } else if (errwarn) { + assert(number>=200 && number<(200+arraysize(warnmsg))); msg=warnmsg[number-200]; pre=prefix[0]; errflag=TRUE; errnum++; } else { + assert(number>=200 && number<(200+arraysize(warnmsg))); msg=warnmsg[number-200]; pre=prefix[2]; warnnum++; } /* if */ + if (notice!=0) { + assert(notice>0 && notice<(1+arraysize(noticemsg)) && noticemsg[notice-1][0]!='\0'); + strcpy(string,msg); + strcpy(&string[strlen(string)-1],noticemsg[notice-1]); + msg=string; + } /* if */ + assert(errstart<=fline); if (errline>0) errstart=errline; @@ -271,9 +296,9 @@ static short lastfile; errline=fline; assert(errstart<=errline); va_start(argptr,number); - if (strlen(errfname)==0) { + if (errfname[0]=='\0') { int start=(errstart==errline) ? -1 : errstart; - if (pc_error(number,msg,inpfname,start,errline,argptr)) { + if (pc_error((int)number,msg,inpfname,start,errline,argptr)) { if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; @@ -284,9 +309,9 @@ static short lastfile; FILE *fp=fopen(errfname,"a"); if (fp!=NULL) { if (errstart>=0 && errstart!=errline) - fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,number); + fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,(int)number); else - fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,number); + fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,(int)number); vfprintf(fp,msg,argptr); fclose(fp); } /* if */ @@ -294,7 +319,7 @@ static short lastfile; va_end(argptr); if ((number>=100 && number<200) || errnum>25){ - if (strlen(errfname)==0) { + if (errfname[0]=='\0') { va_start(argptr,number); pc_error(0,"\nCompilation aborted.\n\n",NULL,0,0,argptr); va_end(argptr); @@ -423,3 +448,240 @@ int pc_geterrorwarnings() return errwarn; } +/* Implementation of Levenshtein distance, by Lorenzo Seidenari + */ +static int minimum(int a,int b,int c) +{ + int min=a; + if(b0 && m>0); + d=(int*)malloc((sizeof(int))*(m+1)*(n+1)); + m++; + n++; + //Step 2 + for (k=0;kMAX_EDIT_DIST) + maxdist=MAX_EDIT_DIST; + return maxdist; +} + +static int find_closestsymbol_table(const char *name,const symbol *root,int symboltype,symbol **closestsym) +{ + int dist,maxdist,closestdist=INT_MAX; + char symname[2*sNAMEMAX+16]; + symbol *sym; + int ident; + assert(closestsym!=NULL); + *closestsym=NULL; + assert(name!=NULL); + maxdist=get_maxdist(name); + for (sym=root->next; sym!=NULL; sym=sym->next) { + if (sym->fnumber!=-1 && sym->fnumber!=fcurrent) + continue; + ident=sym->ident; + if (symboltype==essNONLABEL) { + if (ident==iLABEL) + continue; + } else if (symboltype==essVARCONST) { + if (ident!=iCONSTEXPR && ident!=iVARIABLE && ident!=iREFERENCE && ident!=iARRAY && ident!=iREFARRAY) + continue; + } else if (symboltype==essARRAY) { + if (ident!=iARRAY && ident!=iREFARRAY) + continue; + } else if (symboltype==essCONST) { + if (ident!=iCONSTEXPR) + continue; + } else if (symboltype==essFUNCTN) { + if ((ident!=iFUNCTN && ident!=iREFFUNC) || (sym->usage & uDEFINE)==0) + continue; + } else if (symboltype==essLABEL) { + if (ident!=iLABEL || (sym->usage & uDEFINE)==0) + continue; + } /* if */ + funcdisplayname(symname,sym->name); + dist=levenshtein_distance(name,symname); + if (dist>maxdist || dist>=closestdist) + continue; + *closestsym=sym; + closestdist=dist; + if (closestdist<=1) + break; + } /* for */ + return closestdist; +} + +static symbol *find_closestsymbol(const char *name,int symboltype) +{ + symbol *symloc,*symglb; + int distloc,distglb; + + if (sc_status==statFIRST) + return NULL; + assert(name!=NULL); + if (name[0]=='\0') + return NULL; + distloc=find_closestsymbol_table(name,&loctab,symboltype,&symloc); + if (distloc<=1) + distglb=INT_MAX; /* don't bother searching in the global table */ + else + distglb=find_closestsymbol_table(name,&glbtab,symboltype,&symglb); + return (distglbname[0]!='\0') { + dist=levenshtein_distance(name,ptr->name); + if (distnext; + } /* while */ + return closestmatch; +} + +static constvalue *find_closeststate(const char *name,int fsa) +{ + constvalue *ptr=sc_state_tab.first; + constvalue *closestmatch=NULL; + int dist,maxdist,closestdist=INT_MAX; + + assert(name!=NULL); + maxdist=get_maxdist(name); + while (ptr!=NULL) { + if (ptr->index==fsa && ptr->name[0]!='\0') { + dist=levenshtein_distance(name,ptr->name); + if (distnext; + } /* while */ + return closestmatch; +} + +static constvalue *findclosest_automaton_for_state(const char *statename,int fsa) +{ + constvalue *ptr=sc_state_tab.first; + constvalue *closestmatch=NULL; + constvalue *automaton; + const char *fsaname; + int dist,maxdist,closestdist=INT_MAX; + + assert(statename!=NULL); + maxdist=get_maxdist(statename); + automaton=automaton_findid(ptr->index); + assert(automaton!=NULL); + fsaname=automaton->name; + while (ptr!=NULL) { + if (fsa!=ptr->index && ptr->name[0]!='\0' && strcmp(statename,ptr->name)==0) { + automaton=automaton_findid(ptr->index); + assert(automaton!=NULL); + dist=levenshtein_distance(fsaname,automaton->name); + if (distnext; + } /* while */ + return closestmatch; +} + +SC_FUNC int error_suggest(int number,const char *name,const char *name2,int type,int subtype) +{ + char string[sNAMEMAX*2+2]; /* for ":" */ + const char *closestname=NULL; + + /* don't bother finding the closest names on errors + * that aren't going to be shown on the 1'st pass + */ + if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200)) + return 0; + + if (type==estSYMBOL || (type==estNONSYMBOL && tMIDDLEname; + } else if (type==estAUTOMATON) { + constvalue *closestautomaton=find_closestautomaton(name); + if (closestautomaton!=NULL) + closestname=closestautomaton->name; + } else if (type==estSTATE) { + constvalue *closeststate=find_closeststate(name,subtype); + if (closeststate!=NULL) { + closestname=closeststate->name; + } else { + constvalue *closestautomaton=findclosest_automaton_for_state(name,subtype); + if (closestautomaton!=NULL) { + sprintf(string,"%s:%s",closestautomaton->name,name); + closestname=string; + } /* if */ + } /* if */ + } else { + assert(0); + } /* if */ + + if (closestname==NULL) { + error(number,name,name2); + } else if (name2!=NULL) { + error(makelong(number,1),name,name2,closestname); + } else { + error(makelong(number,1),name,closestname); + } /* if */ + return 0; +} diff --git a/source/compiler/tests/gh_353.inc b/source/compiler/tests/gh_353.inc new file mode 100644 index 0000000..8f07b7f --- /dev/null +++ b/source/compiler/tests/gh_353.inc @@ -0,0 +1,2 @@ +static staticvar; +#pragma unused staticvar \ No newline at end of file diff --git a/source/compiler/tests/gh_353.meta b/source/compiler/tests/gh_353.meta new file mode 100644 index 0000000..7c2391d --- /dev/null +++ b/source/compiler/tests/gh_353.meta @@ -0,0 +1,24 @@ +{ + 'test_type': 'output_check', + 'errors': """ +gh_353.pwn(12) : error 017: undefined symbol "abcxyz" +gh_353.pwn(20) : error 017: undefined symbol "length" +gh_353.pwn(30) : error 017: undefined symbol "float" +gh_353.pwn(40) : error 017: undefined symbol "ab" +gh_353.pwn(41) : error 017: undefined symbol "ab" +gh_353.pwn(50) : error 017: undefined symbol "staticval" +gh_353.pwn(58) : error 017: undefined symbol "val"; did you mean "var"? +gh_353.pwn(62) : error 017: undefined symbol "celmax"; did you mean "cellmax"? +gh_353.pwn(66) : error 017: undefined symbol "strcaf"; did you mean "strcat"? +gh_353.pwn(69) : error 017: undefined symbol "test_e17"; did you mean "test_e017"? +gh_353.pwn(78) : error 019: not a label: "lb"; did you mean "lbl"? +gh_353.pwn(85) : error 020: invalid symbol name "assert"; did you mean "asset"? +gh_353.pwn(96) : error 080: unknown symbol, or not a constant symbol (symbol "idx"); did you mean "id"? +gh_353.pwn(107) : error 086: unknown automaton "automaton1"; did you mean "automaton_1"? +gh_353.pwn(107) : error 036: empty statement +gh_353.pwn(114) : error 087: unknown state "BEING1" for automaton "automaton_2"; did you mean "BEING_1"? +gh_353.pwn(114) : error 036: empty statement +gh_353.pwn(117) : error 087: unknown state "STATE_1" for automaton "automaton_2"; did you mean "automaton_1:STATE_1"? +gh_353.pwn(117) : error 036: empty statement + """ +} diff --git a/source/compiler/tests/gh_353.pwn b/source/compiler/tests/gh_353.pwn new file mode 100644 index 0000000..e604b47 --- /dev/null +++ b/source/compiler/tests/gh_353.pwn @@ -0,0 +1,118 @@ +#include +#include +#include +#include "gh_353.inc" + +forward test_nosuggest1(); +public test_nosuggest1() +{ + // The compiler shouldn't suggest any name for this error + // since "abcxyz" and "abcd" differ by more than 2 symbols. + const abcd = 1; + printf("%d\n", abcxyz); + #pragma unused abcd +} + +forward test_nosuggest2(); +public test_nosuggest2() +{ + // There are no "()" after "length", so the compiler shouldn't suggest "flength". + printf("%d\n", length); +} + +forward test_nosuggest3(); +public test_nosuggest3() +{ + // float.inc is not #included, so float() is not defined. + // After the 1'st pass the compiler thinks float() is an unimplemented function, + // so it shouldn't suggest variable "flt" in this case. + new Float:flt; + return float(0); + #pragma unused flt +} + +forward test_nosuggest4(); +public test_nosuggest4() +{ + // "abc" is a label so the compiler shouldn't suggest its name + // where a variable or named constant is expected. +abc: + printf("%d\n", ab); + printf("%d\n", tagof ab); + #pragma unused abc +} + +forward test_nosuggest5(); +public test_nosuggest5() +{ + // As the name suggests, variable "staticvar" is defined as static + // within another file, so the compiler shouldn't suggest its name here. + return staticval; +} + +forward test_e017(); +public test_e017() +{ + // error 017: undefined symbol "val"; did you mean "var"? + new var = 1; + printf("%d\n", val); + #pragma unused var + + // error 017: undefined symbol "celmax"; did you mean "cellmax"? + printf("%d\n", celmax); + + // error 017: undefined symbol "strcaf"; did you mean "strcat"? + new str[4] = "a"; + strcaf(str, "b"); + + // error 017: undefined symbol "test_e17"; did you mean "test_e017"? + printf("%d\n", tagof test_e17); +} + +forward test_e019(); +public test_e019() +{ + // error 019: not a label: "lb"; did you mean "lbl"? +lbl: + goto lb; +} + +forward test_e020(); +public test_e020() +{ + // error 020: invalid symbol name "assert"; did you mean "asset"? + new asset = 0; + printf("%d\n", defined assert); + #pragma unused asset +} + +forward test_e080(); +public test_e080() +{ + // error 080: unknown symbol, or not a constant symbol (symbol "idx"); did you mean "id"? + new values[1]; + new idx = 0; + const id = 0; + printf("%d\n", sizeof values[idx]); + #pragma unused values, idx, id +} + +stock func1(){} +stock func2(){} + +forward test_e086(); +public test_e086() +{ + // error 086: unknown automaton "automaton1"; did you mean "automaton_1"? + state automaton1:STATE_1; +} + +forward test_e087(); +public test_e087() +{ + // error 087: unknown state BEING1" for automaton "automaton_2"; did you mean "BEING_1"? + state automaton_2:BEING1; + + // error 087: unknown state "STATE_1" for automaton "automaton_2"; did you mean "automaton_1:STATE_1"? + state automaton_2:STATE_1; +} From aabd3a5d5d07df52f0c5aa012150ee611a4fc679 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sat, 29 Sep 2018 06:59:12 +0600 Subject: [PATCH 83/88] Fix naming and improve test name (#353) --- source/compiler/sc5.c | 126 +++++++++--------- source/compiler/tests/gh_353.meta | 24 ---- ..._353.inc => gh_353_symbol_suggestions.inc} | 0 .../tests/gh_353_symbol_suggestions.meta | 24 ++++ ..._353.pwn => gh_353_symbol_suggestions.pwn} | 2 +- 5 files changed, 88 insertions(+), 88 deletions(-) delete mode 100644 source/compiler/tests/gh_353.meta rename source/compiler/tests/{gh_353.inc => gh_353_symbol_suggestions.inc} (100%) create mode 100644 source/compiler/tests/gh_353_symbol_suggestions.meta rename source/compiler/tests/{gh_353.pwn => gh_353_symbol_suggestions.pwn} (98%) diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index ae05425..5af6d61 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -489,24 +489,24 @@ static int levenshtein_distance(const char *s,const char*t) return distance; } -static int get_maxdist(const char *name) +static int get_max_dist(const char *name) { - int maxdist=strlen(name)/2; /* for short names, allow only a single edit */ - if (maxdist>MAX_EDIT_DIST) - maxdist=MAX_EDIT_DIST; - return maxdist; + int max_dist=strlen(name)/2; /* for short names, allow only a single edit */ + if (max_dist>MAX_EDIT_DIST) + max_dist=MAX_EDIT_DIST; + return max_dist; } -static int find_closestsymbol_table(const char *name,const symbol *root,int symboltype,symbol **closestsym) +static int find_closest_symbol_table(const char *name,const symbol *root,int symboltype,symbol **closest_sym) { - int dist,maxdist,closestdist=INT_MAX; + int dist,max_dist,closest_dist=INT_MAX; char symname[2*sNAMEMAX+16]; symbol *sym; int ident; - assert(closestsym!=NULL); - *closestsym=NULL; + assert(closest_sym!=NULL); + *closest_sym =NULL; assert(name!=NULL); - maxdist=get_maxdist(name); + max_dist=get_max_dist(name); for (sym=root->next; sym!=NULL; sym=sym->next) { if (sym->fnumber!=-1 && sym->fnumber!=fcurrent) continue; @@ -532,17 +532,17 @@ static int find_closestsymbol_table(const char *name,const symbol *root,int symb } /* if */ funcdisplayname(symname,sym->name); dist=levenshtein_distance(name,symname); - if (dist>maxdist || dist>=closestdist) + if (dist>max_dist || dist>=closest_dist) continue; - *closestsym=sym; - closestdist=dist; - if (closestdist<=1) + *closest_sym =sym; + closest_dist=dist; + if (closest_dist<=1) break; } /* for */ - return closestdist; + return closest_dist; } -static symbol *find_closestsymbol(const char *name,int symboltype) +static symbol *find_closest_symbol(const char *name,int symboltype) { symbol *symloc,*symglb; int distloc,distglb; @@ -552,70 +552,70 @@ static symbol *find_closestsymbol(const char *name,int symboltype) assert(name!=NULL); if (name[0]=='\0') return NULL; - distloc=find_closestsymbol_table(name,&loctab,symboltype,&symloc); + distloc=find_closest_symbol_table(name,&loctab,symboltype,&symloc); if (distloc<=1) distglb=INT_MAX; /* don't bother searching in the global table */ else - distglb=find_closestsymbol_table(name,&glbtab,symboltype,&symglb); + distglb=find_closest_symbol_table(name,&glbtab,symboltype,&symglb); return (distglbname[0]!='\0') { dist=levenshtein_distance(name,ptr->name); - if (distnext; } /* while */ - return closestmatch; + return closest_match; } -static constvalue *find_closeststate(const char *name,int fsa) +static constvalue *find_closest_state(const char *name,int fsa) { constvalue *ptr=sc_state_tab.first; - constvalue *closestmatch=NULL; - int dist,maxdist,closestdist=INT_MAX; + constvalue *closest_match=NULL; + int dist,max_dist,closest_dist=INT_MAX; assert(name!=NULL); - maxdist=get_maxdist(name); + max_dist=get_max_dist(name); while (ptr!=NULL) { if (ptr->index==fsa && ptr->name[0]!='\0') { dist=levenshtein_distance(name,ptr->name); - if (distnext; } /* while */ - return closestmatch; + return closest_match; } -static constvalue *findclosest_automaton_for_state(const char *statename,int fsa) +static constvalue *find_closest_automaton_for_state(const char *statename,int fsa) { constvalue *ptr=sc_state_tab.first; - constvalue *closestmatch=NULL; + constvalue *closest_match=NULL; constvalue *automaton; const char *fsaname; - int dist,maxdist,closestdist=INT_MAX; + int dist,max_dist,closest_dist=INT_MAX; assert(statename!=NULL); - maxdist=get_maxdist(statename); + max_dist=get_max_dist(statename); automaton=automaton_findid(ptr->index); assert(automaton!=NULL); fsaname=automaton->name; @@ -624,22 +624,22 @@ static constvalue *findclosest_automaton_for_state(const char *statename,int fsa automaton=automaton_findid(ptr->index); assert(automaton!=NULL); dist=levenshtein_distance(fsaname,automaton->name); - if (distnext; } /* while */ - return closestmatch; + return closest_match; } SC_FUNC int error_suggest(int number,const char *name,const char *name2,int type,int subtype) { char string[sNAMEMAX*2+2]; /* for ":" */ - const char *closestname=NULL; + const char *closest_name=NULL; /* don't bother finding the closest names on errors * that aren't going to be shown on the 1'st pass @@ -648,40 +648,40 @@ SC_FUNC int error_suggest(int number,const char *name,const char *name2,int type return 0; if (type==estSYMBOL || (type==estNONSYMBOL && tMIDDLEname; + closest_sym =find_closest_symbol(name,subtype); + if (closest_sym !=NULL) + closest_name= closest_sym->name; } else if (type==estAUTOMATON) { - constvalue *closestautomaton=find_closestautomaton(name); - if (closestautomaton!=NULL) - closestname=closestautomaton->name; + constvalue *closest_automaton=find_closest_automaton(name); + if (closest_automaton!=NULL) + closest_name=closest_automaton->name; } else if (type==estSTATE) { - constvalue *closeststate=find_closeststate(name,subtype); - if (closeststate!=NULL) { - closestname=closeststate->name; + constvalue *closest_state=find_closest_state(name,subtype); + if (closest_state !=NULL) { + closest_name=closest_state->name; } else { - constvalue *closestautomaton=findclosest_automaton_for_state(name,subtype); - if (closestautomaton!=NULL) { - sprintf(string,"%s:%s",closestautomaton->name,name); - closestname=string; + constvalue *closest_automaton=find_closest_automaton_for_state(name,subtype); + if (closest_automaton !=NULL) { + sprintf(string,"%s:%s", closest_automaton->name,name); + closest_name=string; } /* if */ } /* if */ } else { assert(0); } /* if */ - if (closestname==NULL) { + if (closest_name==NULL) { error(number,name,name2); } else if (name2!=NULL) { - error(makelong(number,1),name,name2,closestname); + error(makelong(number,1),name,name2,closest_name); } else { - error(makelong(number,1),name,closestname); + error(makelong(number,1),name,closest_name); } /* if */ return 0; } diff --git a/source/compiler/tests/gh_353.meta b/source/compiler/tests/gh_353.meta deleted file mode 100644 index 7c2391d..0000000 --- a/source/compiler/tests/gh_353.meta +++ /dev/null @@ -1,24 +0,0 @@ -{ - 'test_type': 'output_check', - 'errors': """ -gh_353.pwn(12) : error 017: undefined symbol "abcxyz" -gh_353.pwn(20) : error 017: undefined symbol "length" -gh_353.pwn(30) : error 017: undefined symbol "float" -gh_353.pwn(40) : error 017: undefined symbol "ab" -gh_353.pwn(41) : error 017: undefined symbol "ab" -gh_353.pwn(50) : error 017: undefined symbol "staticval" -gh_353.pwn(58) : error 017: undefined symbol "val"; did you mean "var"? -gh_353.pwn(62) : error 017: undefined symbol "celmax"; did you mean "cellmax"? -gh_353.pwn(66) : error 017: undefined symbol "strcaf"; did you mean "strcat"? -gh_353.pwn(69) : error 017: undefined symbol "test_e17"; did you mean "test_e017"? -gh_353.pwn(78) : error 019: not a label: "lb"; did you mean "lbl"? -gh_353.pwn(85) : error 020: invalid symbol name "assert"; did you mean "asset"? -gh_353.pwn(96) : error 080: unknown symbol, or not a constant symbol (symbol "idx"); did you mean "id"? -gh_353.pwn(107) : error 086: unknown automaton "automaton1"; did you mean "automaton_1"? -gh_353.pwn(107) : error 036: empty statement -gh_353.pwn(114) : error 087: unknown state "BEING1" for automaton "automaton_2"; did you mean "BEING_1"? -gh_353.pwn(114) : error 036: empty statement -gh_353.pwn(117) : error 087: unknown state "STATE_1" for automaton "automaton_2"; did you mean "automaton_1:STATE_1"? -gh_353.pwn(117) : error 036: empty statement - """ -} diff --git a/source/compiler/tests/gh_353.inc b/source/compiler/tests/gh_353_symbol_suggestions.inc similarity index 100% rename from source/compiler/tests/gh_353.inc rename to source/compiler/tests/gh_353_symbol_suggestions.inc diff --git a/source/compiler/tests/gh_353_symbol_suggestions.meta b/source/compiler/tests/gh_353_symbol_suggestions.meta new file mode 100644 index 0000000..0344afe --- /dev/null +++ b/source/compiler/tests/gh_353_symbol_suggestions.meta @@ -0,0 +1,24 @@ +{ + 'test_type': 'output_check', + 'errors': """ +gh_353_symbol_suggestions.pwn(12) : error 017: undefined symbol "abcxyz" +gh_353_symbol_suggestions.pwn(20) : error 017: undefined symbol "length" +gh_353_symbol_suggestions.pwn(30) : error 017: undefined symbol "float" +gh_353_symbol_suggestions.pwn(40) : error 017: undefined symbol "ab" +gh_353_symbol_suggestions.pwn(41) : error 017: undefined symbol "ab" +gh_353_symbol_suggestions.pwn(50) : error 017: undefined symbol "staticval" +gh_353_symbol_suggestions.pwn(58) : error 017: undefined symbol "val"; did you mean "var"? +gh_353_symbol_suggestions.pwn(62) : error 017: undefined symbol "celmax"; did you mean "cellmax"? +gh_353_symbol_suggestions.pwn(66) : error 017: undefined symbol "strcaf"; did you mean "strcat"? +gh_353_symbol_suggestions.pwn(69) : error 017: undefined symbol "test_e17"; did you mean "test_e017"? +gh_353_symbol_suggestions.pwn(78) : error 019: not a label: "lb"; did you mean "lbl"? +gh_353_symbol_suggestions.pwn(85) : error 020: invalid symbol name "assert"; did you mean "asset"? +gh_353_symbol_suggestions.pwn(96) : error 080: unknown symbol, or not a constant symbol (symbol "idx"); did you mean "id"? +gh_353_symbol_suggestions.pwn(107) : error 086: unknown automaton "automaton1"; did you mean "automaton_1"? +gh_353_symbol_suggestions.pwn(107) : error 036: empty statement +gh_353_symbol_suggestions.pwn(114) : error 087: unknown state "BEING1" for automaton "automaton_2"; did you mean "BEING_1"? +gh_353_symbol_suggestions.pwn(114) : error 036: empty statement +gh_353_symbol_suggestions.pwn(117) : error 087: unknown state "STATE_1" for automaton "automaton_2"; did you mean "automaton_1:STATE_1"? +gh_353_symbol_suggestions.pwn(117) : error 036: empty statement + """ +} diff --git a/source/compiler/tests/gh_353.pwn b/source/compiler/tests/gh_353_symbol_suggestions.pwn similarity index 98% rename from source/compiler/tests/gh_353.pwn rename to source/compiler/tests/gh_353_symbol_suggestions.pwn index e604b47..3a9e792 100644 --- a/source/compiler/tests/gh_353.pwn +++ b/source/compiler/tests/gh_353_symbol_suggestions.pwn @@ -1,7 +1,7 @@ #include #include #include -#include "gh_353.inc" +#include "gh_353_symbol_suggestions.inc" forward test_nosuggest1(); public test_nosuggest1() From 0f2bd0b282e84e3d6af5f38581ff48738374b6ca Mon Sep 17 00:00:00 2001 From: Zeex Date: Sat, 29 Sep 2018 07:16:42 +0600 Subject: [PATCH 84/88] v3.10.9 --- source/compiler/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index 236ca68..b2aa8a9 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -5,7 +5,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake) set(VERSION_MAJOR 3) set(VERSION_MINOR 10) -set(VERSION_BUILD 8) +set(VERSION_BUILD 9) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}) set(VERSION_STR ${VERSION}) math(EXPR VERSION_INT "${VERSION_MAJOR} << 8 | ${VERSION_MINOR}") From 0c88297b4470d323275c8ad35ba928b6c3fc8070 Mon Sep 17 00:00:00 2001 From: Barnaby Keene Date: Sun, 30 Sep 2018 07:59:45 +0100 Subject: [PATCH 85/88] Update readme.md --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 09097b7..d420f29 100644 --- a/readme.md +++ b/readme.md @@ -105,9 +105,9 @@ seems to be based on an older release of Pawn. [build_win]: https://ci.appveyor.com/project/Southclaws/compiler/branch/master [build_status_win]: https://ci.appveyor.com/api/projects/status/k112tbr1afrkif0n?svg=true -[team]: https://github.com/orgs/pawn-lang/teams/compiler +[team]: https://github.com/pawn-lang/compiler/graphs/contributors [original_readme]: - https://github.com/pawn-lang/tree/master/readme_compuphase.txt + https://github.com/pawn-lang/compiler/tree/master/readme_compuphase.txt [issues]: https://github.com/pawn-lang/compiler/issues [bugs]: https://github.com/pawn-lang/compiler/wiki/Known-compiler-bugs [new]: https://github.com/pawn-lang/compiler/wiki/What's-new From eb35ddf8c6b74d77427dcbb10b63a01f981d82e4 Mon Sep 17 00:00:00 2001 From: Barnaby Keene Date: Fri, 26 Oct 2018 17:05:50 +0100 Subject: [PATCH 86/88] added config for stalebot --- .github/stale.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000..463287a --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,15 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 90 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 30 +# Issues with these labels will never be considered stale +exemptLabels: + - "state: discuss" +# Label to use when marking an issue as stale +staleLabel: "state: stale" +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no + further activity occurs. Thank you for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From 6d4599faf7ebd890277c99ed6af6ccaed44be85b Mon Sep 17 00:00:00 2001 From: Barnaby Keene Date: Fri, 26 Oct 2018 17:35:03 +0100 Subject: [PATCH 87/88] reconfigured stalebot to never close issues, only mark them as stale with the issue label after 90 days --- .github/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/stale.yml b/.github/stale.yml index 463287a..d1cc780 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,7 +1,7 @@ # Number of days of inactivity before an issue becomes stale daysUntilStale: 90 # Number of days of inactivity before a stale issue is closed -daysUntilClose: 30 +daysUntilClose: 9000 # Issues with these labels will never be considered stale exemptLabels: - "state: discuss" From 2e15e645e687bc0ad4a210963de0bfadc56d48fc Mon Sep 17 00:00:00 2001 From: Barnaby Keene Date: Sat, 27 Oct 2018 14:28:25 +0100 Subject: [PATCH 88/88] fixed stale message --- .github/stale.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/stale.yml b/.github/stale.yml index d1cc780..c015ee6 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -9,7 +9,6 @@ exemptLabels: staleLabel: "state: stale" # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > - This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no - further activity occurs. Thank you for your contributions. + This issue has been automatically marked as stale because it has not had recent activity. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false