Merge branch 'master' into fix_emit_crash

This commit is contained in:
VVWVV 2017-07-29 22:21:31 +03:00
commit 223838de79
16 changed files with 311 additions and 324 deletions

13
.editorconfig Normal file
View File

@ -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

View File

@ -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(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to 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(<var> [<additional arguments to git describe> ...])
#
# 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 <rpavlik@iastate.edu> <abiryan@ryand.net>
# 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()

View File

@ -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 <rpavlik@iastate.edu> <abiryan@ryand.net>
# 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()

View File

@ -24,8 +24,7 @@ Background
---------- ----------
The project was originally started as a set of patches aimed to create a compiler 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)] that would be compatible with the compiler used in [SA-MP (San Andreas Multiplayer)](http://sa-mp.com/).
(http://sa-mp.com/).
SA-MP uses a modified version of Pawn 3.2.3664 [1] with Windows-only executables, 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 and the developers said that they lost the source code for it which means it can't

View File

@ -5,17 +5,11 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake)
set(VERSION_MAJOR 3) set(VERSION_MAJOR 3)
set(VERSION_MINOR 10) 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}) set(VERSION_STR ${VERSION})
math(EXPR VERSION_INT "${VERSION_MAJOR} << 8 | ${VERSION_MINOR}") 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 # check for optional include files
include(CheckIncludeFile) include(CheckIncludeFile)
check_include_file("unistd.h" HAVE_UNISTD_H) check_include_file("unistd.h" HAVE_UNISTD_H)
@ -34,6 +28,10 @@ check_include_file("alloca.h" HAVE_ALLOCA_H)
if(HAVE_ALLOCA_H) if(HAVE_ALLOCA_H)
add_definitions(-DHAVE_ALLOCA_H) add_definitions(-DHAVE_ALLOCA_H)
endif() endif()
check_include_file("endian.h" HAVE_ENDIAN_H)
if(HAVE_ENDIAN_H)
add_definitions(-DHAVE_ENDIAN_H)
endif()
# check for optional library functions # check for optional library functions
include(CheckFunctionExists) include(CheckFunctionExists)
@ -56,7 +54,8 @@ if(UNIX)
link_libraries(pthread) link_libraries(pthread)
endif() 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}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
# The Pawn compiler shared library # The Pawn compiler shared library
@ -79,7 +78,7 @@ set(PAWNC_SRCS
scmemfil.c scmemfil.c
scstate.c scstate.c
scvars.c scvars.c
${CMAKE_BINARY_DIR}/version.h) version.h)
set_source_files_properties(sc1.c COMPILE_FLAGS -DNO_MAIN) set_source_files_properties(sc1.c COMPILE_FLAGS -DNO_MAIN)
if(WIN32) if(WIN32)
set(PAWNC_SRCS ${PAWNC_SRCS} libpawnc.rc) set(PAWNC_SRCS ${PAWNC_SRCS} libpawnc.rc)
@ -87,7 +86,7 @@ if(WIN32)
if(BORLAND) if(BORLAND)
# Borland linker uses a DEF file if one is in the output directory # Borland linker uses a DEF file if one is in the output directory
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpawnc.def.borland configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpawnc.def.borland
${CMAKE_BINARY_DIR}/pawnc.def ${CMAKE_CURRENT_BINARY_DIR}/pawnc.def
COPYONLY) COPYONLY)
else() else()
# Microsoft Visual C/C++ supports a DEF file as if it were a source file # 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) elseif(MINGW)
set_target_properties(pawnc PROPERTIES LINK_FLAGS set_target_properties(pawnc PROPERTIES LINK_FLAGS
"-Wl,--enable-stdcall-fixup") "-Wl,--enable-stdcall-fixup")
set_target_properties(pawnc PROPERTIES PREFIX "")
endif() endif()
# The Pawn compiler driver (console program) # The Pawn compiler driver (console program)
@ -115,7 +115,7 @@ if(WIN32)
if(BORLAND) if(BORLAND)
# Borland linker uses a DEF file if one is in the output directory # Borland linker uses a DEF file if one is in the output directory
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pawncc.def.borland configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pawncc.def.borland
${CMAKE_BINARY_DIR}/pawncc.def ${CMAKE_CURRENT_BINARY_DIR}/pawncc.def
COPYONLY) COPYONLY)
else() else()
# Microsoft Visual C/C++ supports a DEF file as if it were a source file # 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 compiler and disassembler binaries
install(TARGETS pawnc pawncc pawndisasm install(TARGETS pawnc pawncc pawndisasm
RUNTIME DESTINATION bin RUNTIME DESTINATION bin
LIBRARY DESTINATION lib LIBRARY DESTINATION lib)
ARCHIVE DESTINATION lib)
if(MSVC) if(MSVC)
# If building with Microsoft Visual C++ also install corresponding # If building with Microsoft Visual C++ also install corresponding
# Program Database files (for debugging) # Program Database files (for debugging)

View File

@ -220,6 +220,7 @@ typedef struct s_symbol {
#define flgDEPRECATED 0x01 /* symbol is deprecated (avoid use) */ #define flgDEPRECATED 0x01 /* symbol is deprecated (avoid use) */
#define flagNAKED 0x10 /* function is naked */ #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 uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */
#define uSIZEOF 0x80 /* 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 constvalue *find_constval(constvalue *table,char *name,int index);
SC_FUNC void delete_consttable(constvalue *table); SC_FUNC void delete_consttable(constvalue *table);
SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag); 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 exporttag(int tag);
SC_FUNC void sc_attachdocumentation(symbol *sym); SC_FUNC void sc_attachdocumentation(symbol *sym);
@ -583,7 +586,9 @@ SC_FUNC void begcseg(void);
SC_FUNC void begdseg(void); SC_FUNC void begdseg(void);
SC_FUNC void setline(int chkbounds); SC_FUNC void setline(int chkbounds);
SC_FUNC void setfiledirect(char *name); SC_FUNC void setfiledirect(char *name);
SC_FUNC void setfileconst(char *name);
SC_FUNC void setlinedirect(int line); SC_FUNC void setlinedirect(int line);
SC_FUNC void setlineconst(int line);
SC_FUNC void setlabel(int index); SC_FUNC void setlabel(int index);
SC_FUNC void markexpr(optmark type,const char *name,cell offset); SC_FUNC void markexpr(optmark type,const char *name,cell offset);
SC_FUNC void startfunc(char *fname); SC_FUNC void startfunc(char *fname);

View File

@ -29,6 +29,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#if defined __WIN32__ || defined _WIN32 || defined __MSDOS__ #if defined __WIN32__ || defined _WIN32 || defined __MSDOS__
#include <conio.h> #include <conio.h>
@ -81,6 +82,7 @@ static void setconfig(char *root);
static void setcaption(void); static void setcaption(void);
static void about(void); static void about(void);
static void setconstants(void); static void setconstants(void);
static void setstringconstants(void);
static void parse(void); static void parse(void);
static void dumplits(void); static void dumplits(void);
static void dumpzero(int count); static void dumpzero(int count);
@ -89,7 +91,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,
int stock,int fconst); int stock,int fconst);
static int declloc(int fstatic); static int declloc(int fstatic);
static void decl_const(int table); 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 cell needsub(int *tag,constvalue **enumroot);
static void initials(int ident,int tag,cell *size,int dim[],int numdim, static void initials(int ident,int tag,cell *size,int dim[],int numdim,
constvalue *enumroot); constvalue *enumroot);
@ -570,8 +572,8 @@ int pc_compile(int argc, char *argv[])
sc_needsemicolon ? "true" : "false", sc_needsemicolon ? "true" : "false",
sc_tabsize); sc_tabsize);
pc_writeasm(outf,string); pc_writeasm(outf,string);
setfiledirect(inpfname);
} /* if */ } /* if */
setfiledirect(inpfname);
/* do the first pass through the file (or possibly two or more "first passes") */ /* do the first pass through the file (or possibly two or more "first passes") */
sc_parsenum=0; sc_parsenum=0;
inpfmark=pc_getpossrc(inpf_org); inpfmark=pc_getpossrc(inpf_org);
@ -596,7 +598,8 @@ int pc_compile(int argc, char *argv[])
fline=skipinput; /* reset line number */ fline=skipinput; /* reset line number */
sc_reparse=FALSE; /* assume no extra passes */ sc_reparse=FALSE; /* assume no extra passes */
sc_status=statFIRST; /* resetglobals() resets it to IDLE */ sc_status=statFIRST; /* resetglobals() resets it to IDLE */
setstringconstants();
setfileconst(inpfname);
if (strlen(incfname)>0) { if (strlen(incfname)>0) {
if (strcmp(incfname,sDEF_PREFIX)==0) { if (strcmp(incfname,sDEF_PREFIX)==0) {
plungefile(incfname,FALSE,TRUE); /* parse "default.inc" */ plungefile(incfname,FALSE,TRUE); /* parse "default.inc" */
@ -660,7 +663,9 @@ int pc_compile(int argc, char *argv[])
fline=skipinput; /* reset line number */ fline=skipinput; /* reset line number */
lexinit(); /* clear internal flags of lex() */ lexinit(); /* clear internal flags of lex() */
sc_status=statWRITE; /* allow to write --this variable was reset by resetglobals() */ sc_status=statWRITE; /* allow to write --this variable was reset by resetglobals() */
setstringconstants();
writeleader(&glbtab); writeleader(&glbtab);
setfileconst(inpfname);
insert_dbgfile(inpfname); insert_dbgfile(inpfname);
if (strlen(incfname)>0) { if (strlen(incfname)>0) {
if (strcmp(incfname,sDEF_PREFIX)==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,"_",0,0);/* "untagged" */
append_constval(&tagname_tab,"bool",1,0); append_constval(&tagname_tab,"bool",1,0);
add_constant("true",1,sGLOBAL,1); /* boolean flags */ add_builtin_constant("true",1,sGLOBAL,1); /* boolean flags */
add_constant("false",0,sGLOBAL,1); add_builtin_constant("false",0,sGLOBAL,1);
add_constant("EOS",0,sGLOBAL,0); /* End Of String, or '\0' */ add_builtin_constant("EOS",0,sGLOBAL,0); /* End Of String, or '\0' */
#if PAWN_CELL_SIZE==16 #if PAWN_CELL_SIZE==16
add_constant("cellbits",16,sGLOBAL,0); add_builtin_constant("cellbits",16,sGLOBAL,0);
#if defined _I16_MAX #if defined _I16_MAX
add_constant("cellmax",_I16_MAX,sGLOBAL,0); add_builtin_constant("cellmax",_I16_MAX,sGLOBAL,0);
add_constant("cellmin",_I16_MIN,sGLOBAL,0); add_builtin_constant("cellmin",_I16_MIN,sGLOBAL,0);
#else #else
add_constant("cellmax",SHRT_MAX,sGLOBAL,0); add_builtin_constant("cellmax",SHRT_MAX,sGLOBAL,0);
add_constant("cellmin",SHRT_MIN,sGLOBAL,0); add_builtin_constant("cellmin",SHRT_MIN,sGLOBAL,0);
#endif #endif
#elif PAWN_CELL_SIZE==32 #elif PAWN_CELL_SIZE==32
add_constant("cellbits",32,sGLOBAL,0); add_builtin_constant("cellbits",32,sGLOBAL,0);
#if defined _I32_MAX #if defined _I32_MAX
add_constant("cellmax",_I32_MAX,sGLOBAL,0); add_builtin_constant("cellmax",_I32_MAX,sGLOBAL,0);
add_constant("cellmin",_I32_MIN,sGLOBAL,0); add_builtin_constant("cellmin",_I32_MIN,sGLOBAL,0);
#else #else
add_constant("cellmax",INT_MAX,sGLOBAL,0); add_builtin_constant("cellmax",INT_MAX,sGLOBAL,0);
add_constant("cellmin",INT_MIN,sGLOBAL,0); add_builtin_constant("cellmin",INT_MIN,sGLOBAL,0);
#endif #endif
#elif PAWN_CELL_SIZE==64 #elif PAWN_CELL_SIZE==64
#if !defined _I64_MIN #if !defined _I64_MIN
#define _I64_MIN (-9223372036854775807ULL - 1) #define _I64_MIN (-9223372036854775807ULL - 1)
#define _I64_MAX 9223372036854775807ULL #define _I64_MAX 9223372036854775807ULL
#endif #endif
add_constant("cellbits",64,sGLOBAL,0); add_builtin_constant("cellbits",64,sGLOBAL,0);
add_constant("cellmax",_I64_MAX,sGLOBAL,0); add_builtin_constant("cellmax",_I64_MAX,sGLOBAL,0);
add_constant("cellmin",_I64_MIN,sGLOBAL,0); add_builtin_constant("cellmin",_I64_MIN,sGLOBAL,0);
#else #else
#error Unsupported cell size #error Unsupported cell size
#endif #endif
add_constant("charbits",sCHARBITS,sGLOBAL,0); add_builtin_constant("charbits",sCHARBITS,sGLOBAL,0);
add_constant("charmin",0,sGLOBAL,0); add_builtin_constant("charmin",0,sGLOBAL,0);
add_constant("charmax",~(-1 << sCHARBITS) - 1,sGLOBAL,0); add_builtin_constant("charmax",~((ucell)-1 << sCHARBITS) - 1,sGLOBAL,0);
add_constant("ucharmax",(1 << (sizeof(cell)-1)*8)-1,sGLOBAL,0); add_builtin_constant("ucharmax",(1 << (sizeof(cell)-1)*8)-1,sGLOBAL,0);
add_constant("__Pawn",VERSION_INT,sGLOBAL,0); add_builtin_constant("__Pawn",VERSION_INT,sGLOBAL,0);
add_constant("__line",0,sGLOBAL,0); add_builtin_constant("__PawnBuild",VERSION_BUILD,sGLOBAL,0);
add_constant("__compat",pc_compat,sGLOBAL,0); add_builtin_constant("__line",0,sGLOBAL,0);
add_builtin_constant("__compat",pc_compat,sGLOBAL,0);
debug=0; debug=0;
if ((sc_debug & (sCHKBOUNDS | sSYMBOLIC))==(sCHKBOUNDS | sSYMBOLIC)) if ((sc_debug & (sCHKBOUNDS | sSYMBOLIC))==(sCHKBOUNDS | sSYMBOLIC))
debug=2; debug=2;
else if ((sc_debug & sCHKBOUNDS)==sCHKBOUNDS) else if ((sc_debug & sCHKBOUNDS)==sCHKBOUNDS)
debug=1; debug=1;
add_constant("debug",debug,sGLOBAL,0); add_builtin_constant("debug",debug,sGLOBAL,0);
append_constval(&sc_automaton_tab,"",0,0); /* anonymous automaton */ 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) static int getclassspec(int initialtok,int *fpublic,int *fstatic,int *fstock,int *fconst)
{ {
int tok,err; int tok,err;
@ -1600,6 +1622,9 @@ static void parse(void)
declglb(NULL,0,fpublic,fstatic,fstock,fconst); declglb(NULL,0,fpublic,fstatic,fstock,fconst);
break; break;
case tSTATIC: case tSTATIC:
if (matchtoken(tENUM)) {
decl_enum(sGLOBAL,TRUE);
} else {
/* This can be a static function or a static global variable; we know /* 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 * 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 * opening paranthesis of a function would be expected. To back out after
@ -1610,12 +1635,13 @@ static void parse(void)
assert(!fpublic); assert(!fpublic);
declfuncvar(fpublic,fstatic,fstock,fconst); declfuncvar(fpublic,fstatic,fstock,fconst);
} /* if */ } /* if */
} /* if */
break; break;
case tCONST: case tCONST:
decl_const(sGLOBAL); decl_const(sGLOBAL);
break; break;
case tENUM: case tENUM:
decl_enum(sGLOBAL); decl_enum(sGLOBAL,matchtoken(tSTATIC));
break; break;
case tPUBLIC: case tPUBLIC:
/* This can be a public function or a public variable; see the comment /* 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 * of a global variable or to that of a local variable at a lower
* level might indicate a bug. * 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 */ error(219,name); /* variable shadows another symbol */
while (matchtoken('[')){ while (matchtoken('[')){
ident=iARRAY; 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 */ constvalue lastdim={NULL,"",0,0}; /* sizes of the final dimension */
int skipdim=0; int skipdim=0;
if (dim[numdim-1]!=0) /* check if size specified for all dimensions */
*size=calc_arraysize(dim,numdim,0); /* calc. full size, if known */ for (idx=0; idx<numdim; idx++)
if (dim[idx]==0)
break;
/* already reserve space for the indirection tables (for an array with /* already reserve space for the indirection tables (for an array with
* known dimensions) * known dimensions)
* (do not use dumpzero(), as it bypasses the literal queue) * (do not use dumpzero(), as it bypasses the literal queue)
*/ */
if(idx==numdim)
*size=calc_arraysize(dim,numdim,0);
else
*size=0; /* size of one or more dimensions is unknown */
for (tablesize=calc_arraysize(dim,numdim-1,0); tablesize>0; tablesize--) for (tablesize=calc_arraysize(dim,numdim-1,0); tablesize>0; tablesize--)
litadd(0); litadd(0);
/* now initialize the sub-arrays */ /* 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) constvalue *enumroot,int *errorfound)
{ {
cell dsize,totalsize; cell dsize,totalsize;
int idx,idx_ellips,vidx; int idx,idx_ellips,vidx,do_insert;
int abortparse; int abortparse;
int curlit; int curlit;
cell *prev1=NULL,*prev2=NULL; cell *prev1=NULL,*prev2=NULL;
@ -2500,6 +2532,12 @@ static cell initarray(int ident,int tag,int dim[],int numdim,int cur,
assert(errorfound!=NULL && *errorfound==FALSE); assert(errorfound!=NULL && *errorfound==FALSE);
totalsize=0; 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++) { for (idx=0,abortparse=FALSE; !abortparse; idx++) {
/* In case the major dimension is zero, we need to store the offset /* 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. * 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 * necessary at this point to reserve space for an extra cell in the
* indirection vector. * indirection vector.
*/ */
if (dim[cur]==0) { if (do_insert) {
litinsert(0,startlit); litinsert(0,startlit);
} else if (idx>=dim[cur]) { } else if (idx>=dim[cur]) {
error(18); /* initialization data exceeds array size */ error(18); /* initialization data exceeds array size */
@ -2768,7 +2806,7 @@ static void decl_const(int vclass)
/* decl_enum - declare enumerated constants /* 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]; char enumname[sNAMEMAX+1],constname[sNAMEMAX+1];
cell val,value,size; cell val,value,size;
@ -2777,6 +2815,9 @@ static void decl_enum(int vclass)
cell increment,multiplier; cell increment,multiplier;
constvalue *enumroot; constvalue *enumroot;
symbol *enumsym; symbol *enumsym;
short filenum;
filenum=fcurrent;
/* get an explicit tag, if any (we need to remember whether an explicit /* 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 * 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) { if (strlen(enumname)>0) {
/* already create the root symbol, so the fields can have it as their "parent" */ /* already create the root symbol, so the fields can have it as their "parent" */
enumsym=add_constant(enumname,0,vclass,tag); enumsym=add_constant(enumname,0,vclass,tag);
if (enumsym!=NULL) if (enumsym!=NULL) {
enumsym->usage |= uENUMROOT; enumsym->usage |= uENUMROOT;
if (fstatic)
enumsym->fnumber=filenum;
}
/* start a new list for the element names */ /* start a new list for the element names */
if ((enumroot=(constvalue*)malloc(sizeof(constvalue)))==NULL) if ((enumroot=(constvalue*)malloc(sizeof(constvalue)))==NULL)
error(103); /* insufficient memory (fatal error) */ error(103); /* insufficient memory (fatal error) */
@ -2868,6 +2912,10 @@ static void decl_enum(int vclass)
sym->dim.array.length=size; sym->dim.array.length=size;
sym->dim.array.level=0; sym->dim.array.level=0;
sym->parent=enumsym; sym->parent=enumsym;
if (fstatic)
sym->fnumber=filenum;
/* add the constant to a separate list as well */ /* add the constant to a separate list as well */
if (enumroot!=NULL) { if (enumroot!=NULL) {
sym->usage |= uENUMFIELD; 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 */ error(62); /* number or placement of the operands does not fit the operator */
} /* switch */ } /* 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 */ error(64); /* cannot change predefined operators */
/* change the operator name */ /* change the operator name */
@ -3324,21 +3372,19 @@ SC_FUNC char *funcdisplayname(char *dest,char *funcname)
static void check_reparse(symbol *sym) static void check_reparse(symbol *sym)
{ {
/* if the function was used before being declared, add a third pass (as /* if the function was used before being declared, and it has a tag for the
* second "skimming" parse) because: * result, add a third pass (as second "skimming" parse) because the function
* * result may have been used with user-defined operators, which have now
* - the function result may have been used with user-defined operators, * been incorrectly flagged (as the return tag was unknown at the time of
* which have now been incorrectly flagged (as the return tag was unknown * the call)
* 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 ((sym->usage & (uPROTOTYPED | uREAD))==uREAD) 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 */ sc_reparse=TRUE; /* must add another pass to "initial scan" phase */
} /* if */
} }
static void funcstub(int fnative) static void funcstub(int fnative)
@ -3381,7 +3427,7 @@ static void funcstub(int fnative)
tok=lex(&val,&str); tok=lex(&val,&str);
fpublic=(tok==tPUBLIC) || (tok==tSYMBOL && str[0]==PUBLIC_CHAR); fpublic=(tok==tPUBLIC) || (tok==tSYMBOL && str[0]==PUBLIC_CHAR);
if (fnative) { 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 */ error(42); /* invalid combination of class specifiers */
} else { } else {
if (tok==tPUBLIC || tok==tSTOCK || tok==tSTATIC) 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); tag= (firsttag>=0) ? firsttag : pc_addtag(NULL);
tok=lex(&val,&str); tok=lex(&val,&str);
assert(!fpublic); assert(!fpublic);
if (tok==tNATIVE || tok==tPUBLIC && stock) if (tok==tNATIVE || (tok==tPUBLIC && stock))
error(42); /* invalid combination of class specifiers */ error(42); /* invalid combination of class specifiers */
if (tok==tOPERATOR) { if (tok==tOPERATOR) {
opertok=operatorname(symbolname); opertok=operatorname(symbolname);
@ -3741,7 +3787,7 @@ static int declargs(symbol *sym,int chkshadow)
ident=iVARIABLE; ident=iVARIABLE;
numtags=0; numtags=0;
fconst=FALSE; fconst=FALSE;
fpublic=(sym->usage & uPUBLIC)!=0; fpublic= (sym->usage & uPUBLIC)!=0;
/* the '(' parantheses has already been parsed */ /* the '(' parantheses has already been parsed */
if (!matchtoken(')')){ if (!matchtoken(')')){
do { /* there are arguments; process them */ do { /* there are arguments; process them */
@ -3855,7 +3901,7 @@ static int declargs(symbol *sym,int chkshadow)
error(10); /* illegal function or declaration */ error(10); /* illegal function or declaration */
} /* switch */ } /* switch */
} while (tok=='&' || tok==tLABEL || tok==tCONST } while (tok=='&' || tok==tLABEL || tok==tCONST
|| tok!=tELLIPS && matchtoken(',')); /* more? */ || (tok!=tELLIPS && matchtoken(','))); /* more? */
/* if the next token is not ",", it should be ")" */ /* if the next token is not ",", it should be ")" */
needtoken(')'); needtoken(')');
} /* if */ } /* 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 * constants are stored in the symbols table, this also finds previously
* defind constants. */ * defind constants. */
sym=findglb(name,sSTATEVAR); sym=findglb(name,sSTATEVAR);
if (!sym) if (sym==NULL)
sym=findloc(name); sym=findloc(name);
if (sym) { if (sym!=NULL) {
int redef=0; int redef=0;
if (sym->ident!=iCONSTEXPR) if (sym->ident!=iCONSTEXPR)
redef=1; /* redefinition a function/variable to a constant is not allowed */ 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: redef_enumfield:
sym=addsym(name,val,iCONSTEXPR,vclass,tag,uDEFINE); sym=addsym(name,val,iCONSTEXPR,vclass,tag,uDEFINE);
assert(sym!=NULL); /* fatal error 103 must be given on error */ assert(sym!=NULL); /* fatal error 103 must be given on error */
if (sc_status == statIDLE) return sym;
sym->usage |= uPREDEF; }
/* 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; return sym;
} }
@ -4976,7 +5075,9 @@ static void statement(int *lastindent,int allow_decl)
} /* if */ } /* if */
break; break;
case tSTATIC: case tSTATIC:
if (allow_decl) { if (matchtoken(tENUM))
decl_enum(sLOCAL,FALSE);
else if (allow_decl) {
declloc(TRUE); declloc(TRUE);
lastst=tNEW; lastst=tNEW;
} else { } else {
@ -5053,7 +5154,8 @@ static void statement(int *lastindent,int allow_decl)
decl_const(sLOCAL); decl_const(sLOCAL);
break; break;
case tENUM: case tENUM:
decl_enum(sLOCAL); matchtoken(tSTATIC);
decl_enum(sLOCAL,FALSE);
break; break;
default: /* non-empty expression */ default: /* non-empty expression */
sc_allowproccall=optproccall; sc_allowproccall=optproccall;
@ -5734,7 +5836,7 @@ static void doreturn(void)
if ((rettype & uRETVALUE)!=0) { if ((rettype & uRETVALUE)!=0) {
int retarray=(ident==iARRAY || ident==iREFARRAY); int retarray=(ident==iARRAY || ident==iREFARRAY);
/* there was an earlier "return" statement in this function */ /* 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;" */ error(79); /* mixing "return array;" and "return value;" */
if (retarray && (curfunc->usage & uPUBLIC)!=0) if (retarray && (curfunc->usage & uPUBLIC)!=0)
error(90,curfunc->name); /* public function may not return array */ error(90,curfunc->name); /* public function may not return array */
@ -5745,7 +5847,7 @@ static void doreturn(void)
if (!matchtag(curfunc->tag,tag,TRUE)) if (!matchtag(curfunc->tag,tag,TRUE))
error(213); /* tagname mismatch */ error(213); /* tagname mismatch */
if (ident==iARRAY || ident==iREFARRAY) { if (ident==iARRAY || ident==iREFARRAY) {
int dim[sDIMEN_MAX],numdim; int dim[sDIMEN_MAX],numdim=0;
cell arraysize; cell arraysize;
if (sym==NULL) { if (sym==NULL) {
/* array literals cannot be returned directly */ /* array literals cannot be returned directly */

View File

@ -198,6 +198,7 @@ static char extensions[][6] = { "", ".inc", ".p", ".pawn" };
icomment=0; /* not in a comment */ icomment=0; /* not in a comment */
insert_dbgfile(inpfname); insert_dbgfile(inpfname);
setfiledirect(inpfname); setfiledirect(inpfname);
setfileconst(inpfname);
listline=-1; /* force a #line directive when changing the file */ listline=-1; /* force a #line directive when changing the file */
sc_is_utf8=(short)scan_utf8(inpf,real_path); sc_is_utf8=(short)scan_utf8(inpf,real_path);
free(real_path); free(real_path);
@ -350,7 +351,6 @@ static void readline(unsigned char *line)
{ {
int i,num,cont; int i,num,cont;
unsigned char *ptr; unsigned char *ptr;
symbol *sym;
if (lptr==term_expr) if (lptr==term_expr)
return; return;
@ -358,7 +358,6 @@ static void readline(unsigned char *line)
cont=FALSE; cont=FALSE;
do { do {
if (inpf==NULL || pc_eofsrc(inpf)) { if (inpf==NULL || pc_eofsrc(inpf)) {
pc_writeasm(outf,"\n"); /* insert a newline at the end of file */
if (cont) if (cont)
error(49); /* invalid line continuation */ error(49); /* invalid line continuation */
if (inpf!=NULL && inpf!=inpf_org) if (inpf!=NULL && inpf!=inpf_org)
@ -429,9 +428,7 @@ static void readline(unsigned char *line)
line+=strlen((char*)line); line+=strlen((char*)line);
} /* if */ } /* if */
fline+=1; fline+=1;
sym=findconst("__line",NULL); setlineconst(fline);
assert(sym!=NULL);
sym->addr=fline;
} while (num>=0 && cont); } while (num>=0 && cont);
} }
@ -484,7 +481,7 @@ static void stripcom(unsigned char *line)
#if !defined SC_LIGHT #if !defined SC_LIGHT
/* collect the comment characters in a string */ /* collect the comment characters in a string */
if (icomment==2) { if (icomment==2) {
if (skipstar && (*line!='\0' && *line<=' ' || *line=='*')) { if (skipstar && ((*line!='\0' && *line<=' ') || *line=='*')) {
/* ignore leading whitespace and '*' characters */ /* ignore leading whitespace and '*' characters */
} else if (commentidx<COMMENT_LIMIT+COMMENT_MARGIN-1) { } else if (commentidx<COMMENT_LIMIT+COMMENT_MARGIN-1) {
comment[commentidx++]=(char)((*line!='\n') ? *line : ' '); comment[commentidx++]=(char)((*line!='\n') ? *line : ' ');
@ -1314,7 +1311,7 @@ static int command(void)
sym=findloc(str); sym=findloc(str);
if (sym==NULL) if (sym==NULL)
sym=findglb(str,sSTATEVAR); sym=findglb(str,sSTATEVAR);
if (sym==NULL || sym->ident!=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 */ error(17,str); /* undefined symbol */
} else { } else {
if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) { if (sym->ident==iFUNCTN || sym->ident==iREFFUNC) {
@ -1787,7 +1784,7 @@ static void substallpatterns(unsigned char *line,int buffersize)
if (strncmp((char*)start,"defined",7)==0 && *(start+7)<=' ') { if (strncmp((char*)start,"defined",7)==0 && *(start+7)<=' ') {
start+=7; /* skip "defined" */ start+=7; /* skip "defined" */
/* skip white space & parantheses */ /* skip white space & parantheses */
while (*start<=' ' && *start!='\0' || *start=='(') while ((*start<=' ' && *start!='\0') || *start=='(')
start++; start++;
/* skip the symbol behind it */ /* skip the symbol behind it */
while (alphanum(*start)) while (alphanum(*start))
@ -2201,11 +2198,11 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym)
error(220); error(220);
} /* if */ } /* if */
} /* 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 */ { /* unpacked string literal */
_lextok=tSTRING; _lextok=tSTRING;
stringflags= (*lptr==sc_ctrlchar) ? RAWMODE : 0; stringflags=(*lptr==sc_ctrlchar) ? RAWMODE : 0;
stringflags |= (*lptr=='#' || (*lptr==sc_ctrlchar && *(lptr+1)=='#')) ? STRINGIZE : 0; stringflags|=(*lptr=='#' || (*lptr==sc_ctrlchar && *(lptr+1)=='#')) ? STRINGIZE : 0;
*lexvalue=_lexval=litidx; *lexvalue=_lexval=litidx;
lptr+=1; /* skip double quote */ lptr+=1; /* skip double quote */
if ((stringflags & RAWMODE)!=0) if ((stringflags & RAWMODE)!=0)
@ -2215,9 +2212,9 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym)
lptr+=1; /* skip final quote */ lptr+=1; /* skip final quote */
else if (!(stringflags & STRINGIZE)) else if (!(stringflags & STRINGIZE))
error(37); /* invalid (non-terminated) string */ error(37); /* invalid (non-terminated) string */
} else if (*lptr=='!' && (*(lptr+1)=='\"' || *(lptr+1)=='#') } else if ((*lptr=='!' && (*(lptr+1)=='\"' || *(lptr+1)=='#'))
|| *lptr=='!' && *(lptr+1)==sc_ctrlchar && (*(lptr+2)=='\"' || *(lptr+2)=='#') || (*lptr=='!' && *(lptr+1)==sc_ctrlchar && (*(lptr+2)=='\"' || *(lptr+2)=='#'))
|| *lptr==sc_ctrlchar && *(lptr+1)=='!' && (*(lptr+2)=='\"' || *(lptr+2)=='#')) || (*lptr==sc_ctrlchar && *(lptr+1)=='!' && (*(lptr+2)=='\"' || *(lptr+2)=='#')))
{ /* packed string literal */ { /* packed string literal */
_lextok=tSTRING; _lextok=tSTRING;
stringflags=0; stringflags=0;
@ -2315,7 +2312,7 @@ SC_FUNC int matchtoken(int token)
int tok; int tok;
tok=lex(&val,&str); tok=lex(&val,&str);
if (tok==token || token==tTERM && (tok==';' || tok==tENDEXPR)) { if (tok==token || (token==tTERM && (tok==';' || tok==tENDEXPR))) {
return 1; return 1;
} else if (!sc_needsemicolon && token==tTERM && (_lexnewline || !freading)) { } else if (!sc_needsemicolon && token==tTERM && (_lexnewline || !freading)) {
/* Push "tok" back, because it is the token following the implicit statement /* 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); assert(0);
break; break;
} /* switch */ } /* switch */
if (mustdelete) { if (mustdelete && (sym->flags & flagPREDEF)==0) {
root->next=sym->next; root->next=sym->next;
free_symbol(sym); free_symbol(sym);
} else { } 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) if (sym->ident==iFUNCTN && (sym->usage & uDEFINE)==0)
sym->usage |= uMISSING; 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 */ sym->usage &= ~uDEFINE; /* clear "defined" flag */
/* set all states as "undefined" too */ /* set all states as "undefined" too */
if (sym->states!=NULL) 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; sym->usage &= ~uPROTOTYPED;
root=sym; /* skip the symbol */ root=sym; /* skip the symbol */
} /* if */ } /* if */
} /* if */ } /* while */
} }
/* The purpose of the hash is to reduce the frequency of a "name" /* 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" */ assert(sym->states==NULL || sym->states->next!=NULL); /* first element of the state list is the "root" */
if (sym->ident==iFUNCTN if (sym->ident==iFUNCTN
|| automaton<0 && sym->states==NULL || (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->next->index)==automaton))
{ {
if (cmptag==NULL && sym->fnumber==fnumber) if (cmptag==NULL && sym->fnumber==fnumber)
return sym; /* return first match */ return sym; /* return first match */

View File

@ -592,8 +592,8 @@ static void plnge2(void (*oper)(void),
* has no side effects. This may not be accurate, but it does allow * has no side effects. This may not be accurate, but it does allow
* the compiler to check the effect of the entire expression. * the compiler to check the effect of the entire expression.
*/ */
if (lval1->sym!=NULL && (lval1->sym->ident==iFUNCTN || lval1->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)) || (lval2->sym!=NULL && (lval2->sym->ident==iFUNCTN || lval2->sym->ident==iREFFUNC)))
pc_sideeffect=FALSE; pc_sideeffect=FALSE;
if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) { if (lval1->ident==iARRAY || lval1->ident==iREFARRAY) {
char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-"; char *ptr=(lval1->sym!=NULL) ? lval1->sym->name : "-unknown-";
@ -820,7 +820,7 @@ static int hier14(value *lval1)
* negative value would do). * negative value would do).
*/ */
for (i=0; i<sDIMEN_MAX; i++) for (i=0; i<sDIMEN_MAX; i++)
arrayidx1[i]=arrayidx2[i]=(cell)(-1L << (sizeof(cell)*8-1)); arrayidx1[i]=arrayidx2[i]=(cell)CELL_MAX;
org_arrayidx=lval1->arrayidx; /* save current pointer, to reset later */ org_arrayidx=lval1->arrayidx; /* save current pointer, to reset later */
if (lval1->arrayidx==NULL) if (lval1->arrayidx==NULL)
lval1->arrayidx=arrayidx1; lval1->arrayidx=arrayidx1;
@ -921,13 +921,14 @@ static int hier14(value *lval1)
{ {
int same=TRUE; int same=TRUE;
assert(lval2.arrayidx==arrayidx2); assert(lval2.arrayidx==arrayidx2);
for (i=0; i<sDIMEN_MAX; i++) for (i=0; i<sDIMEN_MAX; i++) {
same=same && (lval3.arrayidx[i]==lval2.arrayidx[i]); same=same && (lval3.arrayidx[i]==lval2.arrayidx[i]);
} /* for */
if (same) if (same)
error(226,lval3.sym->name); /* self-assignment */ error(226,lval3.sym->name); /* self-assignment */
} /* if */ } /* if */
} else { } else {
if (oper){ if (oper) {
rvalue(lval1); rvalue(lval1);
plnge2(oper,hier14,lval1,&lval2); plnge2(oper,hier14,lval1,&lval2);
} else { } else {
@ -936,7 +937,7 @@ static int hier14(value *lval1)
if (hier14(&lval2)) if (hier14(&lval2))
rvalue(&lval2); /* instead of plnge2(). */ rvalue(&lval2); /* instead of plnge2(). */
else if (lval2.ident==iVARIABLE) else if (lval2.ident==iVARIABLE)
lval2.ident=iEXPRESSION;/* mark as "rvalue" if it is not an "lvalue" */ lval2.ident=iEXPRESSION; /* mark as "rvalue" if it is not an "lvalue" */
checkfunction(&lval2); checkfunction(&lval2);
/* check whether lval2 and lval3 (old lval1) refer to the same variable */ /* check whether lval2 and lval3 (old lval1) refer to the same variable */
if (lval2.ident==iVARIABLE && lval3.ident==lval2.ident && lval3.sym==lval2.sym) { if (lval2.ident==iVARIABLE && lval3.ident==lval2.ident && lval3.sym==lval2.sym) {
@ -1001,7 +1002,7 @@ static int hier14(value *lval1)
} /* if */ } /* if */
if (lval3.sym->dim.array.level!=level) if (lval3.sym->dim.array.level!=level)
return error(48); /* array dimensions must match */ return error(48); /* array dimensions must match */
else if (ltlength<val || exactmatch && ltlength>val || val==0) else if (ltlength<val || (exactmatch && ltlength>val) || val==0)
return error(47); /* array sizes must match */ return error(47); /* array sizes must match */
else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE)) 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 */ 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); rvalue(lval);
invert(); /* bitwise NOT */ invert(); /* bitwise NOT */
lval->constval=~lval->constval; lval->constval=~lval->constval;
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
lval->ident=iEXPRESSION;
return FALSE; return FALSE;
case '!': /* ! (logical negate) */ case '!': /* ! (logical negate) */
if (hier2(lval)) if (hier2(lval))
@ -1261,6 +1264,8 @@ static int hier2(value *lval)
lneg(); /* 0 -> 1, !0 -> 0 */ lneg(); /* 0 -> 1, !0 -> 0 */
lval->constval=!lval->constval; lval->constval=!lval->constval;
lval->tag=pc_addtag("bool"); lval->tag=pc_addtag("bool");
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
lval->ident=iEXPRESSION;
} /* if */ } /* if */
return FALSE; return FALSE;
case '-': /* unary - (two's complement) */ case '-': /* unary - (two's complement) */
@ -1289,6 +1294,8 @@ static int hier2(value *lval)
} else { } else {
neg(); /* arithmic negation */ neg(); /* arithmic negation */
lval->constval=-lval->constval; lval->constval=-lval->constval;
if (lval->ident==iVARIABLE || lval->ident==iARRAYCELL)
lval->ident=iEXPRESSION;
} /* if */ } /* if */
return FALSE; return FALSE;
case tLABEL: /* tagname override */ case tLABEL: /* tagname override */
@ -1588,7 +1595,7 @@ restart:
} /* if */ } /* if */
if (close==']') { if (close==']') {
/* normal array index */ /* 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 */ error(32,sym->name); /* array index out of bounds */
if (lval2.constval!=0) { if (lval2.constval!=0) {
/* don't add offsets for zero subscripts */ /* don't add offsets for zero subscripts */
@ -1605,8 +1612,9 @@ restart:
} /* if */ } /* if */
} else { } else {
/* character index */ /* character index */
if (lval2.constval<0 || sym->dim.array.length!=0 if (lval2.constval<0
&& sym->dim.array.length*((8*sizeof(cell))/sCHARBITS)<=(ucell)lval2.constval) || (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 */ error(32,sym->name); /* array index out of bounds */
if (lval2.constval!=0) { if (lval2.constval!=0) {
/* don't add offsets for zero subscripts */ /* don't add offsets for zero subscripts */
@ -2077,7 +2085,14 @@ static int nesting=0;
if (arg[argidx].ident!=0 && arg[argidx].numtags==1) if (arg[argidx].ident!=0 && arg[argidx].numtags==1)
lval.cmptag=arg[argidx].tags[0]; /* set the expected tag, if any */ lval.cmptag=arg[argidx].tags[0]; /* set the expected tag, if any */
lvalue=hier14(&lval); 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) { switch (arg[argidx].ident) {
case 0: case 0:
error(202); /* argument count mismatch */ error(202); /* argument count mismatch */
@ -2190,8 +2205,8 @@ static int nesting=0;
* function argument; a literal string may be smaller than * function argument; a literal string may be smaller than
* the function argument. * the function argument.
*/ */
if (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) || (lval.constval<0 && arg[argidx].dim[0] < -lval.constval))
error(47); /* array sizes must match */ error(47); /* array sizes must match */
} /* if */ } /* if */
} /* if */ } /* if */

View File

@ -249,7 +249,7 @@ SC_FUNC void setline(int chkbounds)
stgwrite("\t; line "); stgwrite("\t; line ");
outval(fline,TRUE); outval(fline,TRUE);
} /* if */ } /* 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 /* generate a "break" (start statement) opcode rather than a "line" opcode
* because earlier versions of Small/Pawn have an incompatible version of the * because earlier versions of Small/Pawn have an incompatible version of the
* line opcode * line opcode
@ -264,12 +264,20 @@ SC_FUNC void setfiledirect(char *name)
{ {
if (sc_status==statFIRST && sc_listing) { if (sc_status==statFIRST && sc_listing) {
assert(name!=NULL); assert(name!=NULL);
pc_writeasm(outf,"#file \""); pc_writeasm(outf,"\n#file \"");
pc_writeasm(outf,name); pc_writeasm(outf,name);
pc_writeasm(outf,"\"\n"); pc_writeasm(outf,"\"\n");
} /* if */ } /* 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) SC_FUNC void setlinedirect(int line)
{ {
if (sc_status==statFIRST && sc_listing) { if (sc_status==statFIRST && sc_listing) {
@ -279,6 +287,15 @@ SC_FUNC void setlinedirect(int line)
} /* if */ } /* if */
} }
SC_FUNC void setlineconst(int line)
{
symbol *sym;
sym=findconst("__line",NULL);
assert(sym!=NULL);
sym->addr=fline;
}
/* setlabel /* setlabel
* *
* Post a code label (specified as a number), on a new line. * 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); stgwrite(sym->name);
} /* if */ } /* if */
if (sc_asmfile 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("\t; ");
stgwrite(symname); stgwrite(symname);

View File

@ -283,7 +283,7 @@ static short lastfile;
} /* if */ } /* if */
va_end(argptr); va_end(argptr);
if (number>=100 && number<200 || errnum>25){ if ((number>=100 && number<200) || errnum>25){
if (strlen(errfname)==0) { if (strlen(errfname)==0) {
va_start(argptr,number); va_start(argptr,number);
pc_error(0,"\nCompilation aborted.\n\n",NULL,0,0,argptr); pc_error(0,"\nCompilation aborted.\n\n",NULL,0,0,argptr);

View File

@ -218,9 +218,9 @@ static char *stripwhitespace(char *str)
if (*str!='\0') { if (*str!='\0') {
size_t len = strlen(str); size_t len = strlen(str);
size_t i; size_t i;
for (i=len-1; i>=0; i--) { for (i=len; i>=1; i--) {
if (!isspace(str[i])) { if (!isspace(str[i-1])) {
str[i+1]='\0'; str[i]='\0';
break; break;
} }
} }
@ -1027,7 +1027,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin)
instr=skipwhitespace(line); instr=skipwhitespace(line);
/* ignore empty lines and labels (labels have a special syntax, so these /* ignore empty lines and labels (labels have a special syntax, so these
* must be parsed separately) */ * must be parsed separately) */
if (*instr=='\0' || tolower(*instr)=='l' && *(instr+1)=='.') if (*instr=='\0' || (tolower(*instr)=='l') && *(instr+1)=='.')
continue; continue;
/* get to the end of the instruction (make use of the '\n' that fgets() /* 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 * added at the end of the line; this way we will *always* drop on a

View File

@ -1642,7 +1642,7 @@ static int matchsequence(char *start,char *end,char *pattern,
assert(*(start+1)=='\0'); assert(*(start+1)=='\0');
start+=2; /* skip '\n' and '\0' */ start+=2; /* skip '\n' and '\0' */
if (*(pattern+1)!='\0') if (*(pattern+1)!='\0')
while (start<end && *start=='\t' || *start==' ') while ((start<end && *start=='\t') || *start==' ')
start++; /* skip leading white space of next instruction */ start++; /* skip leading white space of next instruction */
break; break;
default: default:
@ -1691,8 +1691,10 @@ static char *replacesequence(char *pattern,char symbols[MAX_OPT_VARS][MAX_ALIAS+
} /* while */ } /* while */
/* allocate a buffer to replace the sequence in */ /* allocate a buffer to replace the sequence in */
if ((buffer=(char*)malloc(*repl_length))==NULL) if ((buffer=(char*)malloc(*repl_length))==NULL) {
return (char*)error(103); error(103);
return NULL;
} /* if */
/* replace the pattern into this temporary buffer */ /* replace the pattern into this temporary buffer */
lptr=buffer; lptr=buffer;

View File

@ -339,7 +339,7 @@ SC_FUNC cell get_utf8_char(const unsigned char *string,const unsigned char **end
/* the code positions 0xd800--0xdfff and 0xfffe & 0xffff do not /* the code positions 0xd800--0xdfff and 0xfffe & 0xffff do not
* exist in UCS-4 (and hence, they do not exist in Unicode) * exist in UCS-4 (and hence, they do not exist in Unicode)
*/ */
if (result>=0xd800 && result<=0xdfff || result==0xfffe || result==0xffff) if ((result>=0xd800 && result<=0xdfff) || result==0xfffe || result==0xffff)
return -1; return -1;
} /* if */ } /* if */
break; break;

View File

@ -1,4 +1,5 @@
#define VERSION_MINOR @VERSION_MINOR@ #define VERSION_MINOR @VERSION_MINOR@
#define VERSION_MAJOR @VERSION_MAJOR@ #define VERSION_MAJOR @VERSION_MAJOR@
#define VERSION_BUILD @VERSION_BUILD@
#define VERSION_STR "@VERSION_STR@" #define VERSION_STR "@VERSION_STR@"
#define VERSION_INT @VERSION_INT@ #define VERSION_INT @VERSION_INT@

View File

@ -25,6 +25,10 @@
#define DIRECTORY_SEP_CHAR '/' #define DIRECTORY_SEP_CHAR '/'
#define DIRECTORY_SEP_STR "/" #define DIRECTORY_SEP_STR "/"
#if defined HAVE_ENDIAN_H
# include <endian.h>
#endif
/* /*
* SC assumes that a computer is Little Endian unless told otherwise. It uses * SC assumes that a computer is Little Endian unless told otherwise. It uses
* (and defines) the macros BYTE_ORDER and BIG_ENDIAN. * (and defines) the macros BYTE_ORDER and BIG_ENDIAN.