Merge branch 'master' into fix_emit_crash
This commit is contained in:
commit
223838de79
13
.editorconfig
Normal file
13
.editorconfig
Normal 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
|
@ -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()
|
@ -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()
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined __WIN32__ || defined _WIN32 || defined __MSDOS__
|
||||
#include <conio.h>
|
||||
@ -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; idx<numdim; idx++)
|
||||
if (dim[idx]==0)
|
||||
break;
|
||||
/* already reserve space for the indirection tables (for an array with
|
||||
* known dimensions)
|
||||
* (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--)
|
||||
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 */
|
||||
|
@ -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 (commentidx<COMMENT_LIMIT+COMMENT_MARGIN-1) {
|
||||
comment[commentidx++]=(char)((*line!='\n') ? *line : ' ');
|
||||
@ -1314,7 +1311,7 @@ static int command(void)
|
||||
sym=findloc(str);
|
||||
if (sym==NULL)
|
||||
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 */
|
||||
} 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 */
|
||||
|
@ -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; 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 */
|
||||
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; i<sDIMEN_MAX; i++)
|
||||
for (i=0; i<sDIMEN_MAX; i++) {
|
||||
same=same && (lval3.arrayidx[i]==lval2.arrayidx[i]);
|
||||
if (same)
|
||||
error(226,lval3.sym->name); /* self-assignment */
|
||||
} /* 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 (ltlength<val || exactmatch && ltlength>val || val==0)
|
||||
else if (ltlength<val || (exactmatch && ltlength>val) || 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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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<end && *start=='\t' || *start==' ')
|
||||
while ((start<end && *start=='\t') || *start==' ')
|
||||
start++; /* skip leading white space of next instruction */
|
||||
break;
|
||||
default:
|
||||
@ -1691,8 +1691,10 @@ static char *replacesequence(char *pattern,char symbols[MAX_OPT_VARS][MAX_ALIAS+
|
||||
} /* while */
|
||||
|
||||
/* allocate a buffer to replace the sequence in */
|
||||
if ((buffer=(char*)malloc(*repl_length))==NULL)
|
||||
return (char*)error(103);
|
||||
if ((buffer=(char*)malloc(*repl_length))==NULL) {
|
||||
error(103);
|
||||
return NULL;
|
||||
} /* if */
|
||||
|
||||
/* replace the pattern into this temporary buffer */
|
||||
lptr=buffer;
|
||||
|
@ -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
|
||||
* 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;
|
||||
} /* if */
|
||||
break;
|
||||
|
@ -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@
|
||||
|
@ -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 <endian.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SC assumes that a computer is Little Endian unless told otherwise. It uses
|
||||
* (and defines) the macros BYTE_ORDER and BIG_ENDIAN.
|
||||
|
Loading…
x
Reference in New Issue
Block a user