diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a4d187a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# EditorConfig is awesome: http://EditorConfig.org + +root = true + +[*] +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{def,rc}] +indent_size = 4 diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake deleted file mode 100644 index c8d27f2..0000000 --- a/cmake/GetGitRevisionDescription.cmake +++ /dev/null @@ -1,130 +0,0 @@ -# - Returns a version string from Git -# -# These functions force a re-configure on each git commit so that you can -# trust the values of the variables in your build system. -# -# get_git_head_revision( [ ...]) -# -# Returns the refspec and sha hash of the current head revision -# -# git_describe( [ ...]) -# -# Returns the results of git describe on the source tree, and adjusting -# the output so that it tests false if an error occurs. -# -# git_get_exact_tag( [ ...]) -# -# Returns the results of git describe --exact-match on the source tree, -# and adjusting the output so that it tests false if there was no exact -# matching tag. -# -# Requires CMake 2.6 or newer (uses the 'function' command) -# -# Original Author: -# 2009-2010 Ryan Pavlik -# http://academic.cleardefinition.com -# Iowa State University HCI Graduate Program/VRAC -# -# Copyright Iowa State University 2009-2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -if(__get_git_revision_description) - return() -endif() -set(__get_git_revision_description YES) - -# We must run the following at "include" time, not at function call time, -# to find the path to this module rather than the path to a calling list file -get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) - -function(get_git_head_revision _refspecvar _hashvar) - set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") - set(GIT_DIR "${GIT_PARENT_DIR}/.git") - while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories - set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") - get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) - if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) - # We have reached the root directory, we are not in git - set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) - set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) - return() - endif() - set(GIT_DIR "${GIT_PARENT_DIR}/.git") - endwhile() - # check if this is a submodule - if(NOT IS_DIRECTORY ${GIT_DIR}) - file(READ ${GIT_DIR} submodule) - string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) - get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) - get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) - endif() - set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") - if(NOT EXISTS "${GIT_DATA}") - file(MAKE_DIRECTORY "${GIT_DATA}") - endif() - - if(NOT EXISTS "${GIT_DIR}/HEAD") - return() - endif() - set(HEAD_FILE "${GIT_DATA}/HEAD") - configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) - - configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" - "${GIT_DATA}/grabRef.cmake" - @ONLY) - include("${GIT_DATA}/grabRef.cmake") - - set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) - set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) -endfunction() - -function(git_describe _var) - if(NOT GIT_FOUND) - find_package(Git QUIET) - endif() - get_git_head_revision(refspec hash) - if(NOT GIT_FOUND) - set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) - return() - endif() - if(NOT hash) - set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) - return() - endif() - - # TODO sanitize - #if((${ARGN}" MATCHES "&&") OR - # (ARGN MATCHES "||") OR - # (ARGN MATCHES "\\;")) - # message("Please report the following error to the project!") - # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") - #endif() - - #message(STATUS "Arguments to execute_process: ${ARGN}") - - execute_process(COMMAND - "${GIT_EXECUTABLE}" - describe - ${hash} - ${ARGN} - WORKING_DIRECTORY - "${CMAKE_SOURCE_DIR}" - RESULT_VARIABLE - res - OUTPUT_VARIABLE - out - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(NOT res EQUAL 0) - set(out "${out}-${res}-NOTFOUND") - endif() - - set(${_var} "${out}" PARENT_SCOPE) -endfunction() - -function(git_get_exact_tag _var) - git_describe(out --exact-match ${ARGN}) - set(${_var} "${out}" PARENT_SCOPE) -endfunction() diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in deleted file mode 100644 index 888ce13..0000000 --- a/cmake/GetGitRevisionDescription.cmake.in +++ /dev/null @@ -1,38 +0,0 @@ -# -# Internal file for GetGitRevisionDescription.cmake -# -# Requires CMake 2.6 or newer (uses the 'function' command) -# -# Original Author: -# 2009-2010 Ryan Pavlik -# http://academic.cleardefinition.com -# Iowa State University HCI Graduate Program/VRAC -# -# Copyright Iowa State University 2009-2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -set(HEAD_HASH) - -file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) - -string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) -if(HEAD_CONTENTS MATCHES "ref") - # named branch - string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") - if(EXISTS "@GIT_DIR@/${HEAD_REF}") - configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}") - configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) - set(HEAD_HASH "${HEAD_REF}") - endif() -else() - # detached HEAD - configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) -endif() - -if(NOT HEAD_HASH) - file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) - string(STRIP "${HEAD_HASH}" HEAD_HASH) -endif() diff --git a/readme.md b/readme.md index 46f5293..e88097d 100644 --- a/readme.md +++ b/readme.md @@ -24,8 +24,7 @@ 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/). +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 diff --git a/source/compiler/CMakeLists.txt b/source/compiler/CMakeLists.txt index 1de85ed..9e6d4b5 100644 --- a/source/compiler/CMakeLists.txt +++ b/source/compiler/CMakeLists.txt @@ -5,17 +5,11 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake) set(VERSION_MAJOR 3) set(VERSION_MINOR 10) -set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}) +set(VERSION_BUILD 2) +set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}) set(VERSION_STR ${VERSION}) math(EXPR VERSION_INT "${VERSION_MAJOR} << 8 | ${VERSION_MINOR}") -# Append git commit hash to the version string -include(GetGitRevisionDescription) -git_describe(GIT_COMMIT --always) -if(GIT_COMMIT) - set(VERSION_STR ${VERSION_STR}.${GIT_COMMIT}) -endif() - # check for optional include files include(CheckIncludeFile) check_include_file("unistd.h" HAVE_UNISTD_H) @@ -34,6 +28,10 @@ check_include_file("alloca.h" HAVE_ALLOCA_H) if(HAVE_ALLOCA_H) add_definitions(-DHAVE_ALLOCA_H) endif() +check_include_file("endian.h" HAVE_ENDIAN_H) +if(HAVE_ENDIAN_H) + add_definitions(-DHAVE_ENDIAN_H) +endif() # check for optional library functions include(CheckFunctionExists) @@ -56,7 +54,8 @@ if(UNIX) link_libraries(pthread) endif() -configure_file(version.h.in version.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/version.h) include_directories(${CMAKE_CURRENT_BINARY_DIR}) # The Pawn compiler shared library @@ -79,7 +78,7 @@ set(PAWNC_SRCS scmemfil.c scstate.c scvars.c - ${CMAKE_BINARY_DIR}/version.h) + version.h) set_source_files_properties(sc1.c COMPILE_FLAGS -DNO_MAIN) if(WIN32) set(PAWNC_SRCS ${PAWNC_SRCS} libpawnc.rc) @@ -87,7 +86,7 @@ if(WIN32) if(BORLAND) # Borland linker uses a DEF file if one is in the output directory configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpawnc.def.borland - ${CMAKE_BINARY_DIR}/pawnc.def + ${CMAKE_CURRENT_BINARY_DIR}/pawnc.def COPYONLY) else() # Microsoft Visual C/C++ supports a DEF file as if it were a source file @@ -106,6 +105,7 @@ if(WATCOM) #Watcom C/C++ does not support a .DEF file for the exports elseif(MINGW) set_target_properties(pawnc PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup") + set_target_properties(pawnc PROPERTIES PREFIX "") endif() # The Pawn compiler driver (console program) @@ -115,7 +115,7 @@ if(WIN32) if(BORLAND) # Borland linker uses a DEF file if one is in the output directory configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pawncc.def.borland - ${CMAKE_BINARY_DIR}/pawncc.def + ${CMAKE_CURRENT_BINARY_DIR}/pawncc.def COPYONLY) else() # Microsoft Visual C/C++ supports a DEF file as if it were a source file @@ -139,8 +139,7 @@ endif() # Install compiler and disassembler binaries install(TARGETS pawnc pawncc pawndisasm RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) + LIBRARY DESTINATION lib) if(MSVC) # If building with Microsoft Visual C++ also install corresponding # Program Database files (for debugging) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index 3313ce3..c6e1434 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -198,28 +198,29 @@ typedef struct s_symbol { * 5 (uENUMROOT) the constant is the "root" of an enumeration * 6 (uENUMFIELD) the constant is a field in a named enumeration */ -#define uDEFINE 0x001 -#define uREAD 0x002 -#define uWRITTEN 0x004 -#define uRETVALUE 0x004 /* function returns (or should return) a value */ -#define uCONST 0x008 +#define uDEFINE 0x001 +#define uREAD 0x002 +#define uWRITTEN 0x004 +#define uRETVALUE 0x004 /* function returns (or should return) a value */ +#define uCONST 0x008 #define uPROTOTYPED 0x008 -#define uPREDEF 0x008 /* constant is pre-defined */ -#define uPUBLIC 0x010 -#define uNATIVE 0x020 -#define uENUMROOT 0x020 -#define uSTOCK 0x040 -#define uENUMFIELD 0x040 -#define uMISSING 0x080 -#define uFORWARD 0x100 +#define uPREDEF 0x008 /* constant is pre-defined */ +#define uPUBLIC 0x010 +#define uNATIVE 0x020 +#define uENUMROOT 0x020 +#define uSTOCK 0x040 +#define uENUMFIELD 0x040 +#define uMISSING 0x080 +#define uFORWARD 0x100 /* uRETNONE is not stored in the "usage" field of a symbol. It is * used during parsing a function, to detect a mix of "return;" and * "return value;" in a few special cases. */ -#define uRETNONE 0x10 +#define uRETNONE 0x10 #define flgDEPRECATED 0x01 /* symbol is deprecated (avoid use) */ #define flagNAKED 0x10 /* function is naked */ +#define flagPREDEF 0x20 /* symbol is pre-defined; successor of uPREDEF */ #define uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */ #define uSIZEOF 0x80 /* set in the "hasdefault" field of the arginfo struct */ @@ -527,6 +528,8 @@ SC_FUNC constvalue *append_constval(constvalue *table,const char *name,cell val, SC_FUNC constvalue *find_constval(constvalue *table,char *name,int index); SC_FUNC void delete_consttable(constvalue *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); SC_FUNC void exporttag(int tag); SC_FUNC void sc_attachdocumentation(symbol *sym); @@ -583,7 +586,9 @@ SC_FUNC void begcseg(void); SC_FUNC void begdseg(void); SC_FUNC void setline(int chkbounds); SC_FUNC void setfiledirect(char *name); +SC_FUNC void setfileconst(char *name); 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); diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index af736bd..e069e15 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -29,6 +29,7 @@ #include #include #include +#include #if defined __WIN32__ || defined _WIN32 || defined __MSDOS__ #include @@ -81,6 +82,7 @@ static void setconfig(char *root); static void setcaption(void); static void about(void); static void setconstants(void); +static void setstringconstants(void); static void parse(void); static void dumplits(void); static void dumpzero(int count); @@ -89,7 +91,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic, int stock,int fconst); static int declloc(int fstatic); static void decl_const(int table); -static void decl_enum(int table); +static void decl_enum(int table,int fstatic); static cell needsub(int *tag,constvalue **enumroot); static void initials(int ident,int tag,cell *size,int dim[],int numdim, constvalue *enumroot); @@ -570,8 +572,8 @@ int pc_compile(int argc, char *argv[]) sc_needsemicolon ? "true" : "false", sc_tabsize); pc_writeasm(outf,string); - setfiledirect(inpfname); } /* if */ + setfiledirect(inpfname); /* do the first pass through the file (or possibly two or more "first passes") */ sc_parsenum=0; inpfmark=pc_getpossrc(inpf_org); @@ -596,7 +598,8 @@ int pc_compile(int argc, char *argv[]) fline=skipinput; /* reset line number */ sc_reparse=FALSE; /* assume no extra passes */ sc_status=statFIRST; /* resetglobals() resets it to IDLE */ - + setstringconstants(); + setfileconst(inpfname); if (strlen(incfname)>0) { if (strcmp(incfname,sDEF_PREFIX)==0) { plungefile(incfname,FALSE,TRUE); /* parse "default.inc" */ @@ -660,7 +663,9 @@ int pc_compile(int argc, char *argv[]) fline=skipinput; /* reset line number */ lexinit(); /* clear internal flags of lex() */ sc_status=statWRITE; /* allow to write --this variable was reset by resetglobals() */ + setstringconstants(); writeleader(&glbtab); + setfileconst(inpfname); insert_dbgfile(inpfname); if (strlen(incfname)>0) { if (strcmp(incfname,sDEF_PREFIX)==0) @@ -1457,57 +1462,74 @@ static void setconstants(void) append_constval(&tagname_tab,"_",0,0);/* "untagged" */ append_constval(&tagname_tab,"bool",1,0); - add_constant("true",1,sGLOBAL,1); /* boolean flags */ - add_constant("false",0,sGLOBAL,1); - add_constant("EOS",0,sGLOBAL,0); /* End Of String, or '\0' */ + add_builtin_constant("true",1,sGLOBAL,1); /* boolean flags */ + add_builtin_constant("false",0,sGLOBAL,1); + add_builtin_constant("EOS",0,sGLOBAL,0); /* End Of String, or '\0' */ #if PAWN_CELL_SIZE==16 - add_constant("cellbits",16,sGLOBAL,0); + add_builtin_constant("cellbits",16,sGLOBAL,0); #if defined _I16_MAX - add_constant("cellmax",_I16_MAX,sGLOBAL,0); - add_constant("cellmin",_I16_MIN,sGLOBAL,0); + add_builtin_constant("cellmax",_I16_MAX,sGLOBAL,0); + add_builtin_constant("cellmin",_I16_MIN,sGLOBAL,0); #else - add_constant("cellmax",SHRT_MAX,sGLOBAL,0); - add_constant("cellmin",SHRT_MIN,sGLOBAL,0); + add_builtin_constant("cellmax",SHRT_MAX,sGLOBAL,0); + add_builtin_constant("cellmin",SHRT_MIN,sGLOBAL,0); #endif #elif PAWN_CELL_SIZE==32 - add_constant("cellbits",32,sGLOBAL,0); + add_builtin_constant("cellbits",32,sGLOBAL,0); #if defined _I32_MAX - add_constant("cellmax",_I32_MAX,sGLOBAL,0); - add_constant("cellmin",_I32_MIN,sGLOBAL,0); + add_builtin_constant("cellmax",_I32_MAX,sGLOBAL,0); + add_builtin_constant("cellmin",_I32_MIN,sGLOBAL,0); #else - add_constant("cellmax",INT_MAX,sGLOBAL,0); - add_constant("cellmin",INT_MIN,sGLOBAL,0); + add_builtin_constant("cellmax",INT_MAX,sGLOBAL,0); + add_builtin_constant("cellmin",INT_MIN,sGLOBAL,0); #endif #elif PAWN_CELL_SIZE==64 #if !defined _I64_MIN #define _I64_MIN (-9223372036854775807ULL - 1) #define _I64_MAX 9223372036854775807ULL #endif - add_constant("cellbits",64,sGLOBAL,0); - add_constant("cellmax",_I64_MAX,sGLOBAL,0); - add_constant("cellmin",_I64_MIN,sGLOBAL,0); + add_builtin_constant("cellbits",64,sGLOBAL,0); + add_builtin_constant("cellmax",_I64_MAX,sGLOBAL,0); + add_builtin_constant("cellmin",_I64_MIN,sGLOBAL,0); #else #error Unsupported cell size #endif - add_constant("charbits",sCHARBITS,sGLOBAL,0); - add_constant("charmin",0,sGLOBAL,0); - add_constant("charmax",~(-1 << sCHARBITS) - 1,sGLOBAL,0); - add_constant("ucharmax",(1 << (sizeof(cell)-1)*8)-1,sGLOBAL,0); + add_builtin_constant("charbits",sCHARBITS,sGLOBAL,0); + add_builtin_constant("charmin",0,sGLOBAL,0); + add_builtin_constant("charmax",~((ucell)-1 << sCHARBITS) - 1,sGLOBAL,0); + add_builtin_constant("ucharmax",(1 << (sizeof(cell)-1)*8)-1,sGLOBAL,0); - add_constant("__Pawn",VERSION_INT,sGLOBAL,0); - add_constant("__line",0,sGLOBAL,0); - add_constant("__compat",pc_compat,sGLOBAL,0); + add_builtin_constant("__Pawn",VERSION_INT,sGLOBAL,0); + add_builtin_constant("__PawnBuild",VERSION_BUILD,sGLOBAL,0); + add_builtin_constant("__line",0,sGLOBAL,0); + add_builtin_constant("__compat",pc_compat,sGLOBAL,0); debug=0; if ((sc_debug & (sCHKBOUNDS | sSYMBOLIC))==(sCHKBOUNDS | sSYMBOLIC)) debug=2; else if ((sc_debug & sCHKBOUNDS)==sCHKBOUNDS) debug=1; - add_constant("debug",debug,sGLOBAL,0); + add_builtin_constant("debug",debug,sGLOBAL,0); append_constval(&sc_automaton_tab,"",0,0); /* anonymous automaton */ } +static void setstringconstants() +{ + time_t now; + char timebuf[sizeof("11:22:33")]; + char datebuf[sizeof("10 Jan 2017")]; + + assert(sc_status!=statIDLE); + add_builtin_string_constant("__file","",sGLOBAL); + + now = time(NULL); + strftime(timebuf,sizeof(timebuf),"%H:%M:%S",localtime(&now)); + add_builtin_string_constant("__time",timebuf,sGLOBAL); + strftime(datebuf,sizeof(datebuf),"%d %b %Y",localtime(&now)); + add_builtin_string_constant("__date",datebuf,sGLOBAL); +} + static int getclassspec(int initialtok,int *fpublic,int *fstatic,int *fstock,int *fconst) { int tok,err; @@ -1600,22 +1622,26 @@ static void parse(void) declglb(NULL,0,fpublic,fstatic,fstock,fconst); break; case tSTATIC: - /* This can be a static function or a static global variable; we know - * which of the two as soon as we have parsed up to the point where an - * opening paranthesis of a function would be expected. To back out after - * deciding it was a declaration of a static variable after all, we have - * to store the symbol name and tag. - */ - if (getclassspec(tok,&fpublic,&fstatic,&fstock,&fconst)) { - assert(!fpublic); - declfuncvar(fpublic,fstatic,fstock,fconst); + if (matchtoken(tENUM)) { + decl_enum(sGLOBAL,TRUE); + } else { + /* This can be a static function or a static global variable; we know + * which of the two as soon as we have parsed up to the point where an + * opening paranthesis of a function would be expected. To back out after + * deciding it was a declaration of a static variable after all, we have + * to store the symbol name and tag. + */ + if (getclassspec(tok,&fpublic,&fstatic,&fstock,&fconst)) { + assert(!fpublic); + declfuncvar(fpublic,fstatic,fstock,fconst); + } /* if */ } /* if */ break; case tCONST: decl_const(sGLOBAL); break; case tENUM: - decl_enum(sGLOBAL); + decl_enum(sGLOBAL,matchtoken(tSTATIC)); break; case tPUBLIC: /* This can be a public function or a public variable; see the comment @@ -2181,7 +2207,7 @@ static int declloc(int fstatic) * of a global variable or to that of a local variable at a lower * level might indicate a bug. */ - if ((sym=findloc(name))!=NULL && sym->compound!=nestlevel || findglb(name,sGLOBAL)!=NULL) + if (((sym=findloc(name))!=NULL && sym->compound!=nestlevel) || findglb(name,sGLOBAL)!=NULL) error(219,name); /* variable shadows another symbol */ while (matchtoken('[')){ ident=iARRAY; @@ -2430,12 +2456,18 @@ static void initials(int ident,int tag,cell *size,int dim[],int numdim, constvalue lastdim={NULL,"",0,0}; /* sizes of the final dimension */ int skipdim=0; - if (dim[numdim-1]!=0) - *size=calc_arraysize(dim,numdim,0); /* calc. full size, if known */ + /* check if size specified for all dimensions */ + for (idx=0; idx0; tablesize--) litadd(0); /* now initialize the sub-arrays */ @@ -2489,7 +2521,7 @@ static cell initarray(int ident,int tag,int dim[],int numdim,int cur, constvalue *enumroot,int *errorfound) { cell dsize,totalsize; - int idx,idx_ellips,vidx; + int idx,idx_ellips,vidx,do_insert; int abortparse; int curlit; cell *prev1=NULL,*prev2=NULL; @@ -2499,7 +2531,13 @@ static cell initarray(int ident,int tag,int dim[],int numdim,int cur, assert(cur+2<=numdim); /* there must be 2 dimensions or more to do */ assert(errorfound!=NULL && *errorfound==FALSE); totalsize=0; - needtoken('{'); + needtoken('{'); + for (do_insert=0,idx=0; idx<=cur; idx++) { + if (dim[idx]==0) { + do_insert=TRUE; + break; + } /* if */ + } /* for */ for (idx=0,abortparse=FALSE; !abortparse; idx++) { /* In case the major dimension is zero, we need to store the offset * to the newly detected sub-array into the indirection table; i.e. @@ -2509,7 +2547,7 @@ static cell initarray(int ident,int tag,int dim[],int numdim,int cur, * necessary at this point to reserve space for an extra cell in the * indirection vector. */ - if (dim[cur]==0) { + if (do_insert) { litinsert(0,startlit); } else if (idx>=dim[cur]) { error(18); /* initialization data exceeds array size */ @@ -2768,7 +2806,7 @@ static void decl_const(int vclass) /* decl_enum - declare enumerated constants * */ -static void decl_enum(int vclass) +static void decl_enum(int vclass,int fstatic) { char enumname[sNAMEMAX+1],constname[sNAMEMAX+1]; cell val,value,size; @@ -2777,6 +2815,9 @@ static void decl_enum(int vclass) cell increment,multiplier; constvalue *enumroot; symbol *enumsym; + short filenum; + + filenum=fcurrent; /* get an explicit tag, if any (we need to remember whether an explicit * tag was passed, even if that explicit tag was "_:", so we cannot call @@ -2820,8 +2861,11 @@ static void decl_enum(int vclass) if (strlen(enumname)>0) { /* already create the root symbol, so the fields can have it as their "parent" */ enumsym=add_constant(enumname,0,vclass,tag); - if (enumsym!=NULL) + if (enumsym!=NULL) { enumsym->usage |= uENUMROOT; + if (fstatic) + enumsym->fnumber=filenum; + } /* start a new list for the element names */ if ((enumroot=(constvalue*)malloc(sizeof(constvalue)))==NULL) error(103); /* insufficient memory (fatal error) */ @@ -2868,6 +2912,10 @@ static void decl_enum(int vclass) sym->dim.array.length=size; sym->dim.array.level=0; sym->parent=enumsym; + + if (fstatic) + sym->fnumber=filenum; + /* add the constant to a separate list as well */ if (enumroot!=NULL) { sym->usage |= uENUMFIELD; @@ -3179,7 +3227,7 @@ static int operatoradjust(int opertok,symbol *sym,char *opername,int resulttag) error(62); /* number or placement of the operands does not fit the operator */ } /* switch */ - if (tags[0]==0 && (opertok!='=' && tags[1]==0 || opertok=='=' && resulttag==0)) + if (tags[0]==0 && ((opertok!='=' && tags[1]==0) || (opertok=='=' && resulttag==0))) error(64); /* cannot change predefined operators */ /* change the operator name */ @@ -3324,21 +3372,19 @@ SC_FUNC char *funcdisplayname(char *dest,char *funcname) static void check_reparse(symbol *sym) { - /* if the function was used before being declared, add a third pass (as - * second "skimming" parse) because: - * - * - the function result may have been used with user-defined operators, - * which have now been incorrectly flagged (as the return tag was unknown - * at the time of the call) - * - * - one or more of the function's arguments involve global variables that - * have been declared before the function; in this situation the arguments - * are uknown at the time the funtion is called, so the variable may not - * be marked as read (uREAD) and may therefore be omitted from the - * resulting P-code + /* if the function was used before being declared, and it has a tag for the + * result, add a third pass (as second "skimming" parse) because the function + * result may have been used with user-defined operators, which have now + * been incorrectly flagged (as the return tag was unknown at the time of + * the call) */ - if ((sym->usage & (uPROTOTYPED | uREAD))==uREAD) - sc_reparse=TRUE; /* must add another pass to "initial scan" phase */ + if ((sym->usage & (uPROTOTYPED | uREAD))==uREAD && sym->tag!=0) { + int curstatus=sc_status; + sc_status=statWRITE; /* temporarily set status to WRITE, so the warning isn't blocked */ + error(208); + sc_status=curstatus; + sc_reparse=TRUE; /* must add another pass to "initial scan" phase */ + } /* if */ } static void funcstub(int fnative) @@ -3381,7 +3427,7 @@ static void funcstub(int fnative) tok=lex(&val,&str); fpublic=(tok==tPUBLIC) || (tok==tSYMBOL && str[0]==PUBLIC_CHAR); if (fnative) { - if (fpublic || tok==tSTOCK || tok==tSTATIC || tok==tSYMBOL && *str==PUBLIC_CHAR) + if (fpublic || tok==tSTOCK || tok==tSTATIC || (tok==tSYMBOL && *str==PUBLIC_CHAR)) error(42); /* invalid combination of class specifiers */ } else { if (tok==tPUBLIC || tok==tSTOCK || tok==tSTATIC) @@ -3506,7 +3552,7 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc tag= (firsttag>=0) ? firsttag : pc_addtag(NULL); tok=lex(&val,&str); assert(!fpublic); - if (tok==tNATIVE || tok==tPUBLIC && stock) + if (tok==tNATIVE || (tok==tPUBLIC && stock)) error(42); /* invalid combination of class specifiers */ if (tok==tOPERATOR) { opertok=operatorname(symbolname); @@ -3741,7 +3787,7 @@ static int declargs(symbol *sym,int chkshadow) ident=iVARIABLE; numtags=0; fconst=FALSE; - fpublic=(sym->usage & uPUBLIC)!=0; + fpublic= (sym->usage & uPUBLIC)!=0; /* the '(' parantheses has already been parsed */ if (!matchtoken(')')){ do { /* there are arguments; process them */ @@ -3855,7 +3901,7 @@ static int declargs(symbol *sym,int chkshadow) error(10); /* illegal function or declaration */ } /* switch */ } while (tok=='&' || tok==tLABEL || tok==tCONST - || tok!=tELLIPS && matchtoken(',')); /* more? */ + || (tok!=tELLIPS && matchtoken(','))); /* more? */ /* if the next token is not ",", it should be ")" */ needtoken(')'); } /* if */ @@ -4885,9 +4931,9 @@ SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag) * constants are stored in the symbols table, this also finds previously * defind constants. */ sym=findglb(name,sSTATEVAR); - if (!sym) + if (sym==NULL) sym=findloc(name); - if (sym) { + if (sym!=NULL) { int redef=0; if (sym->ident!=iCONSTEXPR) redef=1; /* redefinition a function/variable to a constant is not allowed */ @@ -4929,8 +4975,61 @@ SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag) redef_enumfield: sym=addsym(name,val,iCONSTEXPR,vclass,tag,uDEFINE); assert(sym!=NULL); /* fatal error 103 must be given on error */ - if (sc_status == statIDLE) - sym->usage |= uPREDEF; + return sym; +} + +/* add_builtin_constant + * + * Adds a predefined constant to the symbol table. + */ +SC_FUNC symbol *add_builtin_constant(char *name,cell val,int vclass,int tag) +{ + symbol *sym; + + sym=add_constant(name,val,vclass,tag); + sym->flags|=flagPREDEF; + return sym; +} + +/* add_builtin_string_constant + * + * Adds a predefined string constant to the symbol table. + */ +SC_FUNC symbol *add_builtin_string_constant(char *name,const char *val, + int vclass) +{ + symbol *sym; + + /* Test whether a global or local symbol with the same name exists. Since + * constants are stored in the symbols table, this also finds previously + * defind constants. */ + sym=findglb(name,sSTATEVAR); + if (sym==NULL) + sym=findloc(name); + if (sym!=NULL) { + if (sym->ident!=iARRAY) { + error(21,name); /* symbol already defined */ + return NULL; + } /* if */ + } else { + sym=addsym(name,0,iARRAY,vclass,0,uDEFINE | uSTOCK); + } /* if */ + sym->addr=(litidx+glb_declared)*sizeof(cell); + /* Store this constant only if it's used somewhere. This can be detected + * in the second stage. */ + if (sc_status==statIDLE + || (sc_status==statWRITE && (sym->usage & uREAD)!=0)) { + assert(litidx==0); + begdseg(); + while (*val!='\0') + litadd(*val++); + litadd(0); + glb_declared+=litidx; + dumplits(); + litidx=0; + } + sym->usage|=uDEFINE; + sym->flags|=flagPREDEF; return sym; } @@ -4976,7 +5075,9 @@ static void statement(int *lastindent,int allow_decl) } /* if */ break; case tSTATIC: - if (allow_decl) { + if (matchtoken(tENUM)) + decl_enum(sLOCAL,FALSE); + else if (allow_decl) { declloc(TRUE); lastst=tNEW; } else { @@ -5053,7 +5154,8 @@ static void statement(int *lastindent,int allow_decl) decl_const(sLOCAL); break; case tENUM: - decl_enum(sLOCAL); + matchtoken(tSTATIC); + decl_enum(sLOCAL,FALSE); break; default: /* non-empty expression */ sc_allowproccall=optproccall; @@ -5734,7 +5836,7 @@ static void doreturn(void) if ((rettype & uRETVALUE)!=0) { int retarray=(ident==iARRAY || ident==iREFARRAY); /* there was an earlier "return" statement in this function */ - if ((sub==NULL && retarray && sym!=NULL) || sub!=NULL && !retarray) + if ((sub==NULL && retarray && sym!=NULL) || (sub!=NULL && !retarray)) error(79); /* mixing "return array;" and "return value;" */ if (retarray && (curfunc->usage & uPUBLIC)!=0) error(90,curfunc->name); /* public function may not return array */ @@ -5745,7 +5847,7 @@ static void doreturn(void) if (!matchtag(curfunc->tag,tag,TRUE)) error(213); /* tagname mismatch */ if (ident==iARRAY || ident==iREFARRAY) { - int dim[sDIMEN_MAX],numdim; + int dim[sDIMEN_MAX],numdim=0; cell arraysize; if (sym==NULL) { /* array literals cannot be returned directly */ diff --git a/source/compiler/sc2.c b/source/compiler/sc2.c index 54ea437..2d1e94a 100644 --- a/source/compiler/sc2.c +++ b/source/compiler/sc2.c @@ -198,6 +198,7 @@ static char extensions[][6] = { "", ".inc", ".p", ".pawn" }; icomment=0; /* not in a comment */ insert_dbgfile(inpfname); setfiledirect(inpfname); + setfileconst(inpfname); listline=-1; /* force a #line directive when changing the file */ sc_is_utf8=(short)scan_utf8(inpf,real_path); free(real_path); @@ -350,7 +351,6 @@ static void readline(unsigned char *line) { int i,num,cont; unsigned char *ptr; - symbol *sym; if (lptr==term_expr) return; @@ -358,7 +358,6 @@ static void readline(unsigned char *line) cont=FALSE; do { if (inpf==NULL || pc_eofsrc(inpf)) { - pc_writeasm(outf,"\n"); /* insert a newline at the end of file */ if (cont) error(49); /* invalid line continuation */ if (inpf!=NULL && inpf!=inpf_org) @@ -429,9 +428,7 @@ static void readline(unsigned char *line) line+=strlen((char*)line); } /* if */ fline+=1; - sym=findconst("__line",NULL); - assert(sym!=NULL); - sym->addr=fline; + setlineconst(fline); } while (num>=0 && cont); } @@ -484,7 +481,7 @@ static void stripcom(unsigned char *line) #if !defined SC_LIGHT /* collect the comment characters in a string */ if (icomment==2) { - if (skipstar && (*line!='\0' && *line<=' ' || *line=='*')) { + if (skipstar && ((*line!='\0' && *line<=' ') || *line=='*')) { /* ignore leading whitespace and '*' characters */ } else if (commentidxident!=iFUNCTN && sym->ident!=iREFFUNC && (sym->usage & uDEFINE)==0) { + if (sym==NULL || (sym->ident!=iFUNCTN && sym->ident!=iREFFUNC && (sym->usage & uDEFINE)==0)) { error(17,str); /* undefined symbol */ } else { if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { @@ -1357,12 +1354,12 @@ static int command(void) outval(val | 0x80000000,FALSE); code_idx+=opargs(1); break; - } else { + } else { strcpy(s2+1, str); error(1,sc_tokens[tSYMBOL-tFIRST],s2); break; } /* if */ - } /* if */ + } /* if */ if (tok<256) sprintf(s2,"%c",(char)tok); else @@ -1787,7 +1784,7 @@ static void substallpatterns(unsigned char *line,int buffersize) if (strncmp((char*)start,"defined",7)==0 && *(start+7)<=' ') { start+=7; /* skip "defined" */ /* skip white space & parantheses */ - while (*start<=' ' && *start!='\0' || *start=='(') + while ((*start<=' ' && *start!='\0') || *start=='(') start++; /* skip the symbol behind it */ while (alphanum(*start)) @@ -2201,11 +2198,11 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym) error(220); } /* if */ } /* if */ - } else if (*lptr=='\"' || *lptr=='#' || *lptr==sc_ctrlchar && (*(lptr+1)=='\"' || *(lptr+1)=='#')) + } else if (*lptr=='\"' || *lptr=='#' || (*lptr==sc_ctrlchar && (*(lptr+1)=='\"' || *(lptr+1)=='#'))) { /* unpacked string literal */ _lextok=tSTRING; - stringflags= (*lptr==sc_ctrlchar) ? RAWMODE : 0; - stringflags |= (*lptr=='#' || (*lptr==sc_ctrlchar && *(lptr+1)=='#')) ? STRINGIZE : 0; + stringflags=(*lptr==sc_ctrlchar) ? RAWMODE : 0; + stringflags|=(*lptr=='#' || (*lptr==sc_ctrlchar && *(lptr+1)=='#')) ? STRINGIZE : 0; *lexvalue=_lexval=litidx; lptr+=1; /* skip double quote */ if ((stringflags & RAWMODE)!=0) @@ -2215,9 +2212,9 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym) lptr+=1; /* skip final quote */ else if (!(stringflags & STRINGIZE)) error(37); /* invalid (non-terminated) string */ - } else if (*lptr=='!' && (*(lptr+1)=='\"' || *(lptr+1)=='#') - || *lptr=='!' && *(lptr+1)==sc_ctrlchar && (*(lptr+2)=='\"' || *(lptr+2)=='#') - || *lptr==sc_ctrlchar && *(lptr+1)=='!' && (*(lptr+2)=='\"' || *(lptr+2)=='#')) + } else if ((*lptr=='!' && (*(lptr+1)=='\"' || *(lptr+1)=='#')) + || (*lptr=='!' && *(lptr+1)==sc_ctrlchar && (*(lptr+2)=='\"' || *(lptr+2)=='#')) + || (*lptr==sc_ctrlchar && *(lptr+1)=='!' && (*(lptr+2)=='\"' || *(lptr+2)=='#'))) { /* packed string literal */ _lextok=tSTRING; stringflags=0; @@ -2315,7 +2312,7 @@ SC_FUNC int matchtoken(int token) int tok; tok=lex(&val,&str); - if (tok==token || token==tTERM && (tok==';' || tok==tENDEXPR)) { + if (tok==token || (token==tTERM && (tok==';' || tok==tENDEXPR))) { return 1; } else if (!sc_needsemicolon && token==tTERM && (_lexnewline || !freading)) { /* Push "tok" back, because it is the token following the implicit statement @@ -2749,7 +2746,7 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_ assert(0); break; } /* switch */ - if (mustdelete) { + if (mustdelete && (sym->flags & flagPREDEF)==0) { root->next=sym->next; free_symbol(sym); } else { @@ -2758,7 +2755,8 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_ */ if (sym->ident==iFUNCTN && (sym->usage & uDEFINE)==0) sym->usage |= uMISSING; - if (sym->ident==iFUNCTN || sym->ident==iVARIABLE || sym->ident==iARRAY) + if ((sym->ident==iFUNCTN || sym->ident==iVARIABLE || sym->ident==iARRAY) + && (sym->flags & flagPREDEF)==0) sym->usage &= ~uDEFINE; /* clear "defined" flag */ /* set all states as "undefined" too */ if (sym->states!=NULL) @@ -2771,7 +2769,7 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_ sym->usage &= ~uPROTOTYPED; root=sym; /* skip the symbol */ } /* if */ - } /* if */ + } /* while */ } /* The purpose of the hash is to reduce the frequency of a "name" @@ -2801,8 +2799,8 @@ static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int a { assert(sym->states==NULL || sym->states->next!=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) + || (automaton>=0 && sym->states!=NULL && state_getfsa(sym->states->next->index)==automaton)) { if (cmptag==NULL && sym->fnumber==fnumber) return sym; /* return first match */ diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 8dde140..c1430e3 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -592,8 +592,8 @@ static void plnge2(void (*oper)(void), * has no side effects. This may not be accurate, but it does allow * the compiler to check the effect of the entire expression. */ - if (lval1->sym!=NULL && (lval1->sym->ident==iFUNCTN || lval1->sym->ident==iREFFUNC) - || lval2->sym!=NULL && (lval2->sym->ident==iFUNCTN || lval2->sym->ident==iREFFUNC)) + if ((lval1->sym!=NULL && (lval1->sym->ident==iFUNCTN || lval1->sym->ident==iREFFUNC)) + || (lval2->sym!=NULL && (lval2->sym->ident==iFUNCTN || lval2->sym->ident==iREFFUNC))) pc_sideeffect=FALSE; if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) { char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-"; @@ -820,7 +820,7 @@ static int hier14(value *lval1) * negative value would do). */ for (i=0; iarrayidx; /* save current pointer, to reset later */ if (lval1->arrayidx==NULL) lval1->arrayidx=arrayidx1; @@ -921,27 +921,28 @@ static int hier14(value *lval1) { int same=TRUE; assert(lval2.arrayidx==arrayidx2); - for (i=0; iname); /* self-assignment */ + } /* for */ + if (same) + error(226,lval3.sym->name); /* self-assignment */ } /* if */ } else { - if (oper){ + if (oper) { rvalue(lval1); plnge2(oper,hier14,lval1,&lval2); } else { /* if direct fetch and simple assignment: no "push" * and "pop" needed -> call hier14() directly, */ if (hier14(&lval2)) - rvalue(&lval2); /* instead of plnge2(). */ + rvalue(&lval2); /* instead of plnge2(). */ else if (lval2.ident==iVARIABLE) - lval2.ident=iEXPRESSION;/* mark as "rvalue" if it is not an "lvalue" */ + lval2.ident=iEXPRESSION; /* mark as "rvalue" if it is not an "lvalue" */ checkfunction(&lval2); /* check whether lval2 and lval3 (old lval1) refer to the same variable */ if (lval2.ident==iVARIABLE && lval3.ident==lval2.ident && lval3.sym==lval2.sym) { assert(lval3.sym!=NULL); - error(226,lval3.sym->name); /* self-assignment */ + error(226,lval3.sym->name); /* self-assignment */ } /* if */ } /* if */ } /* if */ @@ -1001,7 +1002,7 @@ static int hier14(value *lval1) } /* if */ if (lval3.sym->dim.array.level!=level) return error(48); /* array dimensions must match */ - else if (ltlengthval || val==0) + 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 */ @@ -1250,6 +1251,8 @@ static int hier2(value *lval) rvalue(lval); invert(); /* bitwise NOT */ lval->constval=~lval->constval; + if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL) + lval->ident=iEXPRESSION; return FALSE; case '!': /* ! (logical negate) */ if (hier2(lval)) @@ -1261,6 +1264,8 @@ static int hier2(value *lval) lneg(); /* 0 -> 1, !0 -> 0 */ lval->constval=!lval->constval; lval->tag=pc_addtag("bool"); + if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL) + lval->ident=iEXPRESSION; } /* if */ return FALSE; case '-': /* unary - (two's complement) */ @@ -1289,6 +1294,8 @@ static int hier2(value *lval) } else { neg(); /* arithmic negation */ lval->constval=-lval->constval; + if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL) + lval->ident=iEXPRESSION; } /* if */ return FALSE; case tLABEL: /* tagname override */ @@ -1588,7 +1595,7 @@ restart: } /* if */ if (close==']') { /* normal array index */ - if (lval2.constval<0 || sym->dim.array.length!=0 && sym->dim.array.length<=lval2.constval) + if (lval2.constval<0 || (sym->dim.array.length!=0 && sym->dim.array.length<=lval2.constval)) error(32,sym->name); /* array index out of bounds */ if (lval2.constval!=0) { /* don't add offsets for zero subscripts */ @@ -1605,8 +1612,9 @@ restart: } /* if */ } else { /* character index */ - if (lval2.constval<0 || sym->dim.array.length!=0 - && sym->dim.array.length*((8*sizeof(cell))/sCHARBITS)<=(ucell)lval2.constval) + if (lval2.constval<0 + || (sym->dim.array.length!=0 + && sym->dim.array.length*((8*sizeof(cell))/sCHARBITS)<=(ucell)lval2.constval)) error(32,sym->name); /* array index out of bounds */ if (lval2.constval!=0) { /* don't add offsets for zero subscripts */ @@ -2077,7 +2085,14 @@ static int nesting=0; if (arg[argidx].ident!=0 && arg[argidx].numtags==1) lval.cmptag=arg[argidx].tags[0]; /* set the expected tag, if any */ lvalue=hier14(&lval); - assert(sc_status==statFIRST || arg[argidx].ident== 0 || arg[argidx].tags!=NULL); + /* Mark the symbol as "read" so it won't be omitted from P-code. + * Native functions are marked as read at the point of their call, + * so we don't handle them here; see ffcall(). + */ + if (lval.sym!=NULL && (lval.sym->usage & uNATIVE)==0) { + markusage(lval.sym,uREAD); + } /* if */ + assert(sc_status==statFIRST || arg[argidx].ident==0 || arg[argidx].tags!=NULL); switch (arg[argidx].ident) { case 0: error(202); /* argument count mismatch */ @@ -2190,8 +2205,8 @@ static int nesting=0; * 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) + 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 */ diff --git a/source/compiler/sc4.c b/source/compiler/sc4.c index 30f6190..4ee5972 100644 --- a/source/compiler/sc4.c +++ b/source/compiler/sc4.c @@ -249,7 +249,7 @@ SC_FUNC void setline(int chkbounds) stgwrite("\t; line "); outval(fline,TRUE); } /* if */ - if ((sc_debug & sSYMBOLIC)!=0 || chkbounds && (sc_debug & sCHKBOUNDS)!=0) { + if ((sc_debug & sSYMBOLIC)!=0 || (chkbounds && (sc_debug & sCHKBOUNDS)!=0)) { /* generate a "break" (start statement) opcode rather than a "line" opcode * because earlier versions of Small/Pawn have an incompatible version of the * line opcode @@ -264,12 +264,20 @@ SC_FUNC void setfiledirect(char *name) { if (sc_status==statFIRST && sc_listing) { assert(name!=NULL); - pc_writeasm(outf,"#file \""); + pc_writeasm(outf,"\n#file \""); pc_writeasm(outf,name); pc_writeasm(outf,"\"\n"); } /* if */ } +SC_FUNC void setfileconst(char *name) +{ + symbol *sym; + + sym=add_builtin_string_constant("__file",name,sGLOBAL); + sym->fnumber=fcurrent; +} + SC_FUNC void setlinedirect(int line) { if (sc_status==statFIRST && sc_listing) { @@ -279,6 +287,15 @@ SC_FUNC void setlinedirect(int line) } /* if */ } +SC_FUNC void setlineconst(int line) +{ + symbol *sym; + + sym=findconst("__line",NULL); + assert(sym!=NULL); + sym->addr=fline; +} + /* setlabel * * Post a code label (specified as a number), on a new line. @@ -758,7 +775,7 @@ SC_FUNC void ffcall(symbol *sym,const char *label,int numargs) stgwrite(sym->name); } /* if */ if (sc_asmfile - && (label!=NULL || !isalpha(sym->name[0]) && sym->name[0]!='_' && sym->name[0]!=sc_ctrlchar)) + && (label!=NULL || (!isalpha(sym->name[0]) && sym->name[0]!='_' && sym->name[0]!=sc_ctrlchar))) { stgwrite("\t; "); stgwrite(symname); diff --git a/source/compiler/sc5.c b/source/compiler/sc5.c index c4a5543..34a1c77 100644 --- a/source/compiler/sc5.c +++ b/source/compiler/sc5.c @@ -283,7 +283,7 @@ static short lastfile; } /* if */ va_end(argptr); - if (number>=100 && number<200 || errnum>25){ + if ((number>=100 && number<200) || errnum>25){ if (strlen(errfname)==0) { va_start(argptr,number); pc_error(0,"\nCompilation aborted.\n\n",NULL,0,0,argptr); diff --git a/source/compiler/sc6.c b/source/compiler/sc6.c index 8e9e2c6..4b9a80a 100644 --- a/source/compiler/sc6.c +++ b/source/compiler/sc6.c @@ -218,9 +218,9 @@ static char *stripwhitespace(char *str) if (*str!='\0') { size_t len = strlen(str); size_t i; - for (i=len-1; i>=0; i--) { - if (!isspace(str[i])) { - str[i+1]='\0'; + for (i=len; i>=1; i--) { + if (!isspace(str[i-1])) { + str[i]='\0'; break; } } @@ -1027,7 +1027,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) instr=skipwhitespace(line); /* ignore empty lines and labels (labels have a special syntax, so these * must be parsed separately) */ - if (*instr=='\0' || tolower(*instr)=='l' && *(instr+1)=='.') + if (*instr=='\0' || (tolower(*instr)=='l') && *(instr+1)=='.') continue; /* get to the end of the instruction (make use of the '\n' that fgets() * added at the end of the line; this way we will *always* drop on a diff --git a/source/compiler/sc7.c b/source/compiler/sc7.c index f68efe0..5981efc 100644 --- a/source/compiler/sc7.c +++ b/source/compiler/sc7.c @@ -1642,7 +1642,7 @@ static int matchsequence(char *start,char *end,char *pattern, assert(*(start+1)=='\0'); start+=2; /* skip '\n' and '\0' */ if (*(pattern+1)!='\0') - while (start=0xd800 && result<=0xdfff || result==0xfffe || result==0xffff) + if ((result>=0xd800 && result<=0xdfff) || result==0xfffe || result==0xffff) return -1; } /* if */ break; diff --git a/source/compiler/version.h.in b/source/compiler/version.h.in index 1839d09..93386a7 100644 --- a/source/compiler/version.h.in +++ b/source/compiler/version.h.in @@ -1,4 +1,5 @@ #define VERSION_MINOR @VERSION_MINOR@ #define VERSION_MAJOR @VERSION_MAJOR@ +#define VERSION_BUILD @VERSION_BUILD@ #define VERSION_STR "@VERSION_STR@" #define VERSION_INT @VERSION_INT@ diff --git a/source/linux/sclinux.h b/source/linux/sclinux.h index 3b4af2c..79c0fad 100644 --- a/source/linux/sclinux.h +++ b/source/linux/sclinux.h @@ -7,11 +7,11 @@ #define SCLINUX_H /* getchar() is not a 'cool' replacement for MSDOS getch: Linux/unix depends on the features activated or not about the - * controlling terminal's tty. This means that ioctl(2) calls must be performed, for instance to have the controlling - * terminal tty's in 'raw' mode, if we want to be able to fetch a single character. This also means that everything must + * controlling terminal's tty. This means that ioctl(2) calls must be performed, for instance to have the controlling + * terminal tty's in 'raw' mode, if we want to be able to fetch a single character. This also means that everything must * be put back correctly when the function ends. See GETCH.C for an implementation. * - * For interactive use of SRUN/SDBG if would be much better to use GNU's readline package: the user would be able to + * For interactive use of SRUN/SDBG if would be much better to use GNU's readline package: the user would be able to * have a complete emacs/vi like line editing system. */ #include "getch.h" @@ -25,6 +25,10 @@ #define DIRECTORY_SEP_CHAR '/' #define DIRECTORY_SEP_STR "/" +#if defined HAVE_ENDIAN_H +# include +#endif + /* * SC assumes that a computer is Little Endian unless told otherwise. It uses * (and defines) the macros BYTE_ORDER and BIG_ENDIAN.