Merge pull request #116 from Arkshine/update-compiler-safe-fix-feature
Update compiler
This commit is contained in:
commit
1463103cd7
@ -130,6 +130,8 @@ class AMXXConfig(object):
|
||||
'-Wno-uninitialized',
|
||||
'-Wno-unused',
|
||||
'-Wno-switch',
|
||||
'-Wno-format',
|
||||
'-Wno-format-security',
|
||||
'-m32',
|
||||
]
|
||||
cfg.cxxflags += [
|
||||
|
@ -1,9 +1,50 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||
import os.path
|
||||
|
||||
# Build the packing binary garbage.
|
||||
scpack = AMXX.Program(builder, 'scpack')
|
||||
if builder.target_platform == 'windows':
|
||||
scpack.compiler.linkflags.remove('/SUBSYSTEM:WINDOWS')
|
||||
scpack.compiler.linkflags.append('/SUBSYSTEM:CONSOLE')
|
||||
scpack.sources = ['scpack.c']
|
||||
scpack = builder.Add(scpack)
|
||||
|
||||
# Generate pack files.
|
||||
packed_files = ['sc5', 'sc7']
|
||||
packed_includes = []
|
||||
for packed_file in packed_files:
|
||||
# The absolute path to sc5-in.scp etc.
|
||||
in_path = os.path.join(builder.currentSourcePath, '{0}-in.scp'.format(packed_file))
|
||||
|
||||
# The output file relative to the output folder, i.e. sourcepawn/compiler/sc5.scp.
|
||||
out_path = os.path.join(builder.buildFolder, '{0}.scp'.format(packed_file))
|
||||
|
||||
# The absolute path to the build folder, i.e. /Users/.../sourcepawn/compiler.
|
||||
build_folder = os.path.join(builder.buildPath, builder.buildFolder)
|
||||
|
||||
# scpack runs in ./sourcepawn/compiler/scpack/ so we build relative paths
|
||||
# from there.
|
||||
scpack_argv = [
|
||||
os.path.join(builder.buildPath, scpack.binary.path),
|
||||
os.path.relpath(in_path, build_folder),
|
||||
os.path.relpath(os.path.join(builder.buildPath, out_path), build_folder),
|
||||
]
|
||||
|
||||
_, (entry,) = builder.AddCommand(
|
||||
inputs = [scpack.binary, in_path],
|
||||
argv = scpack_argv,
|
||||
outputs = ['{0}.scp'.format(packed_file)],
|
||||
)
|
||||
packed_includes += [entry]
|
||||
|
||||
binary = AMXX.Library(builder, 'amxxpc32')
|
||||
|
||||
binary.compiler.includes += [builder.currentSourcePath]
|
||||
binary.compiler.includes += [
|
||||
builder.currentSourcePath,
|
||||
os.path.join(builder.buildPath, builder.buildFolder),
|
||||
]
|
||||
|
||||
binary.compiler.sourcedeps += packed_includes
|
||||
|
||||
if builder.target_platform in ['mac', 'linux']:
|
||||
binary.compiler.defines += ['ENABLE_BINRELOC']
|
||||
@ -34,6 +75,7 @@ binary.sources = [
|
||||
'libpawnc.c',
|
||||
'prefix.c',
|
||||
'memfile.c',
|
||||
'sp_symhash.c',
|
||||
]
|
||||
|
||||
if builder.target_platform == 'windows':
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sc.h"
|
||||
@ -55,6 +56,10 @@
|
||||
}
|
||||
#endif /* PAWNC_DLL */
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
/* pc_printf()
|
||||
* Called for general purpose "console" output. This function prints general
|
||||
@ -119,6 +124,14 @@ static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct src_file_s {
|
||||
FILE *fp; // Set if writing.
|
||||
char *buffer; // IO buffer.
|
||||
char *pos; // IO position.
|
||||
char *end; // End of buffer.
|
||||
size_t maxlength; // Maximum length of the writable buffer.
|
||||
} src_file_t;
|
||||
|
||||
/* pc_opensrc()
|
||||
* Opens a source file (or include file) for reading. The "file" does not have
|
||||
* to be a physical file, one might compile from memory.
|
||||
@ -133,7 +146,46 @@ static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
*/
|
||||
void *pc_opensrc(char *filename)
|
||||
{
|
||||
return fopen(filename,"rt");
|
||||
FILE *fp = NULL;
|
||||
long length;
|
||||
src_file_t *src = NULL;
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
|
||||
struct stat fileInfo;
|
||||
if (stat(filename, &fileInfo) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (S_ISDIR(fileInfo.st_mode)) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL)
|
||||
return NULL;
|
||||
if (fseek(fp, 0, SEEK_END) == -1)
|
||||
goto err;
|
||||
if ((length = ftell(fp)) == -1)
|
||||
goto err;
|
||||
if (fseek(fp, 0, SEEK_SET) == -1)
|
||||
goto err;
|
||||
|
||||
if ((src = (src_file_t *)calloc(1, sizeof(src_file_t))) == NULL)
|
||||
goto err;
|
||||
if ((src->buffer = (char *)calloc(length, sizeof(char))) == NULL)
|
||||
goto err;
|
||||
if (fread(src->buffer, length, 1, fp) != 1)
|
||||
goto err;
|
||||
|
||||
src->pos = src->buffer;
|
||||
src->end = src->buffer + length;
|
||||
fclose(fp);
|
||||
return src;
|
||||
|
||||
err:
|
||||
pc_closesrc(src);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* pc_createsrc()
|
||||
@ -150,7 +202,23 @@ void *pc_opensrc(char *filename)
|
||||
*/
|
||||
void *pc_createsrc(char *filename)
|
||||
{
|
||||
return fopen(filename,"wt");
|
||||
src_file_t *src = (src_file_t *)calloc(1, sizeof(src_file_t));
|
||||
if (!src)
|
||||
return NULL;
|
||||
if ((src->fp = fopen(filename, "wt")) == NULL) {
|
||||
pc_closesrc(src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src->maxlength = 1024;
|
||||
if ((src->buffer = (char *)calloc(1, src->maxlength)) == NULL) {
|
||||
pc_closesrc(src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src->pos = src->buffer;
|
||||
src->end = src->buffer;
|
||||
return src;
|
||||
}
|
||||
|
||||
/* pc_closesrc()
|
||||
@ -159,8 +227,15 @@ void *pc_createsrc(char *filename)
|
||||
*/
|
||||
void pc_closesrc(void *handle)
|
||||
{
|
||||
assert(handle!=NULL);
|
||||
fclose((FILE*)handle);
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
if (!src)
|
||||
return;
|
||||
if (src->fp) {
|
||||
fwrite(src->buffer, src->pos - src->buffer, 1, src->fp);
|
||||
fclose(src->fp);
|
||||
}
|
||||
free(src->buffer);
|
||||
free(src);
|
||||
}
|
||||
|
||||
/* pc_resetsrc()
|
||||
@ -169,8 +244,12 @@ void pc_closesrc(void *handle)
|
||||
*/
|
||||
void pc_resetsrc(void *handle,void *position)
|
||||
{
|
||||
assert(handle!=NULL);
|
||||
fsetpos((FILE*)handle,(fpos_t *)position);
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
ptrdiff_t pos = (ptrdiff_t)position;
|
||||
|
||||
assert(!src->fp);
|
||||
assert(pos >= 0 && src->buffer + pos <= src->end);
|
||||
src->pos = src->buffer + pos;
|
||||
}
|
||||
|
||||
/* pc_readsrc()
|
||||
@ -179,7 +258,35 @@ void pc_resetsrc(void *handle,void *position)
|
||||
*/
|
||||
char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
|
||||
{
|
||||
return fgets((char*)target,maxchars,(FILE*)handle);
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
char *outptr = (char *)target;
|
||||
char *outend = outptr + maxchars;
|
||||
|
||||
assert(!src->fp);
|
||||
|
||||
if (src->pos == src->end)
|
||||
return NULL;
|
||||
|
||||
while (outptr < outend && src->pos < src->end) {
|
||||
char c = *src->pos++;
|
||||
*outptr++ = c;
|
||||
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c == '\r') {
|
||||
// Handle CRLF.
|
||||
if (src->pos < src->end && *src->pos == '\n') {
|
||||
src->pos++;
|
||||
if (outptr < outend)
|
||||
*outptr++ = '\n';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Caller passes in a buffer of size >= maxchars+1.
|
||||
*outptr = '\0';
|
||||
return (char *)target;
|
||||
}
|
||||
|
||||
/* pc_writesrc()
|
||||
@ -188,20 +295,51 @@ char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
|
||||
*/
|
||||
int pc_writesrc(void *handle,unsigned char *source)
|
||||
{
|
||||
return fputs((char*)source,(FILE*)handle) >= 0;
|
||||
char *str = (char *)source;
|
||||
size_t len = strlen(str);
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
assert(src->fp && src->maxlength);
|
||||
|
||||
if (src->pos + len > src->end) {
|
||||
char *newbuf;
|
||||
size_t newmax = src->maxlength;
|
||||
size_t newlen = (src->pos - src->buffer) + len;
|
||||
while (newmax < newlen) {
|
||||
// Grow by 1.5X
|
||||
newmax += newmax + newmax / 2;
|
||||
if (newmax < src->maxlength)
|
||||
abort();
|
||||
}
|
||||
|
||||
newbuf = (char *)realloc(src->buffer, newmax);
|
||||
if (!newbuf)
|
||||
abort();
|
||||
src->pos = newbuf + (src->pos - src->buffer);
|
||||
src->end = newbuf + newmax;
|
||||
src->buffer = newbuf;
|
||||
src->maxlength = newmax;
|
||||
}
|
||||
|
||||
strcpy(src->pos, str);
|
||||
src->pos += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pc_getpossrc(void *handle)
|
||||
{
|
||||
static fpos_t lastpos; /* may need to have a LIFO stack of such positions */
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
fgetpos((FILE*)handle,&lastpos);
|
||||
return &lastpos;
|
||||
assert(!src->fp);
|
||||
return (void *)(ptrdiff_t)(src->pos - src->buffer);
|
||||
}
|
||||
|
||||
int pc_eofsrc(void *handle)
|
||||
{
|
||||
return feof((FILE*)handle);
|
||||
src_file_t *src = (src_file_t *)handle;
|
||||
|
||||
assert(!src->fp);
|
||||
return src->pos == src->end;
|
||||
}
|
||||
|
||||
/* should return a pointer, which is used as a "magic cookie" to all I/O
|
||||
|
@ -51,7 +51,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPC300_EXPORTS;PAWNC_DLL;PAWN_CELL_SIZE=32;NO_MAIN;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPC300_EXPORTS;PAWNC_DLL;PAWN_CELL_SIZE=32;NO_MAIN;_CRT_SECURE_NO_DEPRECATE;HAVE_STDINT_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>
|
||||
@ -71,7 +71,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPC300_EXPORTS;PAWNC_DLL;PAWN_CELL_SIZE=32;NO_MAIN;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPC300_EXPORTS;PAWNC_DLL;PAWN_CELL_SIZE=32;NO_MAIN;_CRT_SECURE_NO_DEPRECATE;HAVE_STDINT_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>StackFrameRuntimeCheck</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
@ -105,11 +105,13 @@
|
||||
<ClCompile Include="scmemfil.c" />
|
||||
<ClCompile Include="scstate.c" />
|
||||
<ClCompile Include="scvars.c" />
|
||||
<ClCompile Include="sp_symhash.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="amx.h" />
|
||||
<ClInclude Include="memfile.h" />
|
||||
<ClInclude Include="sc.h" />
|
||||
<ClInclude Include="sp_symhash.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="libpawnc.rc" />
|
||||
|
@ -60,6 +60,9 @@
|
||||
<ClCompile Include="scvars.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sp_symhash.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="amx.h">
|
||||
@ -71,6 +74,9 @@
|
||||
<ClInclude Include="sc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sp_symhash.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="libpawnc.rc">
|
||||
|
@ -55,7 +55,7 @@
|
||||
#define sCHARBITS 8 /* size of a packed character */
|
||||
|
||||
#define sDIMEN_MAX 3 /* maximum number of array dimensions */
|
||||
#define sLINEMAX 1023 /* input line length (in characters) */
|
||||
#define sLINEMAX 4095 /* input line length (in characters) */
|
||||
#define sCOMP_STACK 32 /* maximum nesting of #if .. #endif sections */
|
||||
#define sDEF_LITMAX 500 /* initial size of the literal pool, in "cells" */
|
||||
#define sDEF_AMXSTACK 4096 /* default stack size for AMX files */
|
||||
@ -128,6 +128,7 @@ typedef struct s_symbol {
|
||||
char vclass; /* sLOCAL if "addr" refers to a local symbol */
|
||||
char ident; /* see below for possible values */
|
||||
char usage; /* see below for possible values */
|
||||
char flags; /* see below for possible values */
|
||||
int compound; /* compound level (braces nesting level) */
|
||||
int tag; /* tagname id */
|
||||
int fieldtag; /* enumeration fields, where a size is attached to the field */
|
||||
@ -147,6 +148,7 @@ typedef struct s_symbol {
|
||||
} dim; /* for 'dimension', both functions and arrays */
|
||||
constvalue *states; /* list of state function addresses */
|
||||
int fnumber; /* static global variables: file number in which the declaration is visible */
|
||||
int lnumber; /* line number (in the current source file) for the declaration */
|
||||
struct s_symbol **refer; /* referrer list, functions that "use" this symbol */
|
||||
int numrefers; /* number of entries in the referrer list */
|
||||
char *documentation; /* optional documentation string */
|
||||
@ -221,6 +223,8 @@ typedef struct s_symbol {
|
||||
*/
|
||||
#define uRETNONE 0x10
|
||||
|
||||
#define flgDEPRECATED 0x01 /* symbol is deprecated (avoid use) */
|
||||
|
||||
#define uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */
|
||||
#define uSIZEOF 0x80 /* set in the "hasdefault" field of the arginfo struct */
|
||||
|
||||
@ -270,6 +274,8 @@ typedef struct s_stringpair {
|
||||
char *first;
|
||||
char *second;
|
||||
int matchlength;
|
||||
char flags;
|
||||
char *documentation;
|
||||
} stringpair;
|
||||
|
||||
/* macros for code generation */
|
||||
@ -365,6 +371,7 @@ typedef struct s_stringpair {
|
||||
#define tLABEL 331
|
||||
#define tSTRING 332
|
||||
#define tEXPR 333 /* for assigment to "lastst" only */
|
||||
#define tEMPTYBLOCK 334 /* empty blocks for AM bug 4825 */
|
||||
|
||||
/* (reversed) evaluation of staging buffer */
|
||||
#define sSTARTREORDER 0x01
|
||||
@ -400,6 +407,8 @@ typedef struct s_stringpair {
|
||||
#define sFORCESET 1 /* force error flag on */
|
||||
#define sEXPRMARK 2 /* mark start of expression */
|
||||
#define sEXPRRELEASE 3 /* mark end of expression */
|
||||
#define sSETLINE 4 /* set line number for the error */
|
||||
#define sSETFILE 5 /* set file number for the error */
|
||||
|
||||
typedef enum s_regid {
|
||||
sPRI, /* indicates the primary register */
|
||||
@ -508,6 +517,7 @@ SC_FUNC void delete_consttable(constvalue *table);
|
||||
SC_FUNC symbol *add_constant(char *name,cell val,int vclass,int tag);
|
||||
SC_FUNC void exporttag(int tag);
|
||||
SC_FUNC void sc_attachdocumentation(symbol *sym);
|
||||
SC_FUNC int get_actual_compound(symbol *sym);
|
||||
|
||||
/* function prototypes in SC2.C */
|
||||
#define PUSHSTK_P(v) { stkitem s_; s_.pv=(v); pushstk(s_); }
|
||||
@ -535,7 +545,6 @@ SC_FUNC void delete_symbol(symbol *root,symbol *sym);
|
||||
SC_FUNC void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
|
||||
SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom);
|
||||
SC_FUNC void markusage(symbol *sym,int usage);
|
||||
SC_FUNC uint32_t namehash(const char *name);
|
||||
SC_FUNC symbol *findglb(const char *name);
|
||||
SC_FUNC symbol *findloc(const char *name);
|
||||
SC_FUNC symbol *findconst(const char *name);
|
||||
@ -641,7 +650,7 @@ SC_FUNC void outval(cell val,int newline);
|
||||
|
||||
/* function prototypes in SC5.C */
|
||||
SC_FUNC int error(int number,...) INVISIBLE;
|
||||
SC_FUNC void errorset(int code);
|
||||
SC_FUNC void errorset(int code, int line);
|
||||
|
||||
/* function prototypes in SC6.C */
|
||||
SC_FUNC int assemble(FILE *fout,FILE *fin);
|
||||
@ -674,6 +683,9 @@ SC_FUNC void delete_substtable(void);
|
||||
SC_FUNC stringlist *insert_sourcefile(char *string);
|
||||
SC_FUNC char *get_sourcefile(int index);
|
||||
SC_FUNC void delete_sourcefiletable(void);
|
||||
SC_FUNC stringlist *insert_inputfile(char *string);
|
||||
SC_FUNC char *get_inputfile(int index);
|
||||
SC_FUNC void delete_inputfiletable(void);
|
||||
SC_FUNC stringlist *insert_docstring(char *string);
|
||||
SC_FUNC char *get_docstring(int index);
|
||||
SC_FUNC void delete_docstring(int index);
|
||||
@ -728,6 +740,8 @@ SC_FUNC void state_conflict(symbol *root);
|
||||
|
||||
/* external variables (defined in scvars.c) */
|
||||
#if !defined SC_SKIP_VDECL
|
||||
typedef struct HashTable HashTable;
|
||||
SC_VDECL struct HashTable *sp_Globals;
|
||||
SC_VDECL symbol loctab; /* local symbol table */
|
||||
SC_VDECL symbol glbtab; /* global symbol table */
|
||||
SC_VDECL cell *litq; /* the literal queue */
|
||||
@ -770,8 +784,8 @@ SC_VDECL cell sc_stksize; /* stack size */
|
||||
SC_VDECL cell sc_amxlimit; /* abstract machine size limit */
|
||||
SC_VDECL int freading; /* is there an input file ready for reading? */
|
||||
SC_VDECL int fline; /* the line number in the current file */
|
||||
SC_VDECL short fnumber; /* number of files in the file table (debugging) */
|
||||
SC_VDECL short fcurrent; /* current file being processed (debugging) */
|
||||
SC_VDECL short fnumber; /* number of files in the input file table */
|
||||
SC_VDECL short fcurrent; /* current file being processed */
|
||||
SC_VDECL short sc_intest; /* true if inside a test */
|
||||
SC_VDECL int sideeffect; /* true if an expression causes a side-effect */
|
||||
SC_VDECL int stmtindent; /* current indent of the statement */
|
||||
@ -783,6 +797,7 @@ SC_VDECL int sc_rationaltag; /* tag for rational numbers */
|
||||
SC_VDECL int rational_digits; /* number of fractional digits */
|
||||
SC_VDECL int sc_allowproccall;/* allow/detect tagnames in lex() */
|
||||
SC_VDECL short sc_is_utf8; /* is this source file in UTF-8 encoding */
|
||||
SC_VDECL char *pc_deprecate; /* if non-NULL, mark next declaration as deprecated */
|
||||
|
||||
SC_VDECL constvalue sc_automaton_tab; /* automaton table */
|
||||
SC_VDECL constvalue sc_state_tab; /* state table */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#if defined __WIN32__ || defined _WIN32 || defined __MSDOS__
|
||||
#include <conio.h>
|
||||
#include <io.h>
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
@ -64,8 +65,10 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "sc.h"
|
||||
#include "sp_symhash.h"
|
||||
|
||||
#define VERSION_STR "3.0.3367-amxx"
|
||||
#define VERSION_INT 0x300
|
||||
#define VERSION_INT 0x30A
|
||||
|
||||
int pc_anytag;
|
||||
|
||||
@ -102,7 +105,7 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags,
|
||||
int fpublic,int fconst,arginfo *arg);
|
||||
static void make_report(symbol *root,FILE *log,char *sourcefile);
|
||||
static void reduce_referrers(symbol *root);
|
||||
static long max_stacksize(symbol *root);
|
||||
static long max_stacksize(symbol *root, int *recursion);
|
||||
static int testsymbols(symbol *root,int level,int testlabs,int testconst);
|
||||
static void destructsymbols(symbol *root,int level);
|
||||
static constvalue *find_constval_byval(constvalue *table,cell val);
|
||||
@ -113,7 +116,7 @@ static int doexpr(int comma,int chkeffect,int allowarray,int mark_endexpr,
|
||||
static void doassert(void);
|
||||
static void doexit(void);
|
||||
static void test(int label,int parens,int invert);
|
||||
static void doif(void);
|
||||
static int doif(void);
|
||||
static void dowhile(void);
|
||||
static void dodo(void);
|
||||
static void dofor(void);
|
||||
@ -130,6 +133,7 @@ static void addwhile(int *ptr);
|
||||
static void delwhile(void);
|
||||
static int *readwhile(void);
|
||||
static void inst_datetime_defines(void);
|
||||
static void inst_binary_name(char *binfname);
|
||||
|
||||
static int lastst = 0; /* last executed statement type */
|
||||
static int nestlevel = 0; /* number of active (open) compound statements */
|
||||
@ -404,6 +408,38 @@ void inst_datetime_defines()
|
||||
insert_subst("__TIME__", ltime, 8);
|
||||
}
|
||||
|
||||
static void inst_binary_name(char *binfname)
|
||||
{
|
||||
size_t i, len;
|
||||
char *binptr;
|
||||
char newpath[512], newname[512];
|
||||
|
||||
binptr = NULL;
|
||||
len = strlen(binfname);
|
||||
for (i = len - 1; i < len; i--)
|
||||
{
|
||||
if (binfname[i] == '/'
|
||||
#if defined WIN32 || defined _WIN32
|
||||
|| binfname[i] == '\\'
|
||||
#endif
|
||||
)
|
||||
{
|
||||
binptr = &binfname[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (binptr == NULL)
|
||||
{
|
||||
binptr = binfname;
|
||||
}
|
||||
|
||||
snprintf(newpath, sizeof(newpath), "\"%s\"", binfname);
|
||||
snprintf(newname, sizeof(newname), "\"%s\"", binptr);
|
||||
|
||||
insert_subst("__BINARY_PATH__", newpath, 15);
|
||||
insert_subst("__BINARY_NAME__", newname, 15);
|
||||
}
|
||||
|
||||
/* "main" of the compiler
|
||||
*/
|
||||
@ -427,8 +463,8 @@ int pc_compile(int argc, char *argv[])
|
||||
/* set global variables to their initial value */
|
||||
binf=NULL;
|
||||
initglobals();
|
||||
errorset(sRESET);
|
||||
errorset(sEXPRRELEASE);
|
||||
errorset(sRESET,0);
|
||||
errorset(sEXPRRELEASE,0);
|
||||
lexinit();
|
||||
|
||||
/* make sure that we clean up on a fatal error; do this before the first
|
||||
@ -436,6 +472,10 @@ int pc_compile(int argc, char *argv[])
|
||||
if ((jmpcode=setjmp(errbuf))!=0)
|
||||
goto cleanup;
|
||||
|
||||
sp_Globals = NewHashTable();
|
||||
if (!sp_Globals)
|
||||
error(123);
|
||||
|
||||
/* allocate memory for fixed tables */
|
||||
inpfname=(char*)malloc(_MAX_PATH);
|
||||
if (inpfname==NULL)
|
||||
@ -474,7 +514,7 @@ int pc_compile(int argc, char *argv[])
|
||||
if (get_sourcefile(1)!=NULL) {
|
||||
/* there are at least two or more source files */
|
||||
char *tname,*sname;
|
||||
FILE *ftmp,*fsrc;
|
||||
void *ftmp,*fsrc;
|
||||
int fidx;
|
||||
#if defined __WIN32__ || defined _WIN32
|
||||
tname=_tempnam(NULL,"pawn");
|
||||
@ -490,10 +530,10 @@ int pc_compile(int argc, char *argv[])
|
||||
close(mkstemp(buffer));
|
||||
tname=buffer;
|
||||
#endif
|
||||
ftmp=(FILE*)pc_createsrc(tname);
|
||||
ftmp=(void*)pc_createsrc(tname);
|
||||
for (fidx=0; (sname=get_sourcefile(fidx))!=NULL; fidx++) {
|
||||
unsigned char tstring[128];
|
||||
fsrc=(FILE*)pc_opensrc(sname);
|
||||
fsrc=(void*)pc_opensrc(sname);
|
||||
if (fsrc==NULL)
|
||||
error(100,sname);
|
||||
pc_writesrc(ftmp,(unsigned char*)"#file ");
|
||||
@ -511,7 +551,7 @@ int pc_compile(int argc, char *argv[])
|
||||
} else {
|
||||
strcpy(inpfname,get_sourcefile(0));
|
||||
} /* if */
|
||||
inpf_org=(FILE*)pc_opensrc(inpfname);
|
||||
inpf_org=(void*)pc_opensrc(inpfname);
|
||||
if (inpf_org==NULL)
|
||||
error(100,inpfname);
|
||||
freading=TRUE;
|
||||
@ -556,13 +596,14 @@ int pc_compile(int argc, char *argv[])
|
||||
#if !defined NO_DEFINE
|
||||
delete_substtable();
|
||||
inst_datetime_defines();
|
||||
inst_binary_name(binfname);
|
||||
#endif
|
||||
resetglobals();
|
||||
sc_ctrlchar=sc_ctrlchar_org;
|
||||
sc_packstr=lcl_packstr;
|
||||
sc_needsemicolon=lcl_needsemicolon;
|
||||
sc_tabsize=lcl_tabsize;
|
||||
errorset(sRESET);
|
||||
errorset(sRESET,0);
|
||||
/* reset the source file */
|
||||
inpf=inpf_org;
|
||||
freading=TRUE;
|
||||
@ -620,13 +661,14 @@ int pc_compile(int argc, char *argv[])
|
||||
#if !defined NO_DEFINE
|
||||
delete_substtable();
|
||||
inst_datetime_defines();
|
||||
inst_binary_name(binfname);
|
||||
#endif
|
||||
resetglobals();
|
||||
sc_ctrlchar=sc_ctrlchar_org;
|
||||
sc_packstr=lcl_packstr;
|
||||
sc_needsemicolon=lcl_needsemicolon;
|
||||
sc_tabsize=lcl_tabsize;
|
||||
errorset(sRESET);
|
||||
errorset(sRESET,0);
|
||||
/* reset the source file */
|
||||
inpf=inpf_org;
|
||||
freading=TRUE;
|
||||
@ -635,7 +677,8 @@ int pc_compile(int argc, char *argv[])
|
||||
lexinit(); /* clear internal flags of lex() */
|
||||
sc_status=statWRITE; /* allow to write --this variable was reset by resetglobals() */
|
||||
writeleader(&glbtab);
|
||||
insert_dbgfile(inpfname);
|
||||
insert_dbgfile(inpfname); /* attach to debug information */
|
||||
insert_inputfile(inpfname); /* save for the error system */
|
||||
if (strlen(incfname)>0) {
|
||||
if (strcmp(incfname,sDEF_PREFIX)==0)
|
||||
plungefile(incfname,FALSE,TRUE); /* parse "default.inc" (again) */
|
||||
@ -675,7 +718,8 @@ cleanup:
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
if (errnum==0 && strlen(errfname)==0) {
|
||||
long stacksize=max_stacksize(&glbtab);
|
||||
int recursion;
|
||||
long stacksize=max_stacksize(&glbtab,&recursion);
|
||||
int flag_exceed=0;
|
||||
if (sc_amxlimit > 0 && (long)(hdrsize+code_idx+glb_declared*sizeof(cell)+sc_stksize*sizeof(cell)) >= sc_amxlimit)
|
||||
flag_exceed=1;
|
||||
@ -708,6 +752,7 @@ cleanup:
|
||||
delete_symbols(&loctab,0,TRUE,TRUE); /* delete local variables if not yet
|
||||
* done (i.e. on a fatal error) */
|
||||
delete_symbols(&glbtab,0,TRUE,TRUE);
|
||||
DestroyHashTable(sp_Globals);
|
||||
delete_consttable(&tagname_tab);
|
||||
delete_consttable(&libname_tab);
|
||||
delete_consttable(&sc_automaton_tab);
|
||||
@ -716,6 +761,7 @@ cleanup:
|
||||
delete_aliastable();
|
||||
delete_pathtable();
|
||||
delete_sourcefiletable();
|
||||
delete_inputfiletable();
|
||||
delete_dbgstringtable();
|
||||
#if !defined NO_DEFINE
|
||||
delete_substtable();
|
||||
@ -754,7 +800,7 @@ cleanup:
|
||||
#endif
|
||||
int pc_addconstant(char *name,cell value,int tag)
|
||||
{
|
||||
errorset(sFORCESET); /* make sure error engine is silenced */
|
||||
errorset(sFORCESET,0); /* make sure error engine is silenced */
|
||||
sc_status=statIDLE;
|
||||
add_constant(name,value,sGLOBAL,tag);
|
||||
return 1;
|
||||
@ -828,6 +874,7 @@ static void resetglobals(void)
|
||||
pc_addlibtable=TRUE; /* by default, add a "library table" to the output file */
|
||||
sc_alignnext=FALSE;
|
||||
pc_docexpr=FALSE;
|
||||
pc_deprecate = FALSE;
|
||||
}
|
||||
|
||||
static void initglobals(void)
|
||||
@ -1071,7 +1118,11 @@ static void parseoptions(int argc,char **argv,char *oname,char *ename,char *pnam
|
||||
skipinput=atoi(option_value(ptr));
|
||||
break;
|
||||
case 't':
|
||||
sc_tabsize=atoi(option_value(ptr));
|
||||
i=atoi(option_value(ptr));
|
||||
if (i>0)
|
||||
sc_tabsize=i;
|
||||
else
|
||||
about();
|
||||
break;
|
||||
case 'v':
|
||||
verbosity= isdigit(*option_value(ptr)) ? atoi(option_value(ptr)) : 2;
|
||||
@ -1408,6 +1459,7 @@ static void setconstants(void)
|
||||
add_constant("ucharmax",(1 << (sizeof(cell)-1)*8)-1,sGLOBAL,0);
|
||||
|
||||
add_constant("__Pawn",VERSION_INT,sGLOBAL,0);
|
||||
add_constant("__LINE__", 0, sGLOBAL, 0);
|
||||
|
||||
pc_anytag=pc_addtag("any");
|
||||
|
||||
@ -2206,6 +2258,24 @@ static void initials(int ident,int tag,cell *size,int dim[],int numdim,
|
||||
err++;
|
||||
} /* if */
|
||||
} /* for */
|
||||
if (numdim>1 && dim[numdim-1]==0 && !errorfound && err==0) {
|
||||
/* also look whether, by any chance, all "counted" final dimensions are
|
||||
* the same value; if so, we can store this
|
||||
*/
|
||||
constvalue *ld=lastdim.next;
|
||||
int d,match;
|
||||
for (d=0; d<dim[numdim-2]; d++) {
|
||||
assert(ld!=NULL);
|
||||
assert(strtol(ld->name,NULL,16)==d);
|
||||
if (d==0)
|
||||
match=ld->value;
|
||||
else if (match!=ld->value)
|
||||
break;
|
||||
ld=ld->next;
|
||||
} /* for */
|
||||
if (d==dim[numdim-2])
|
||||
dim[numdim-1]=match;
|
||||
} /* if */
|
||||
/* after all arrays have been initalized, we know the (major) dimensions
|
||||
* of the array and we can properly adjust the indirection vectors
|
||||
*/
|
||||
@ -2733,14 +2803,26 @@ SC_FUNC symbol *fetchfunc(char *name,int tag)
|
||||
sym=addsym(name,code_idx,iFUNCTN,sGLOBAL,tag,0);
|
||||
assert(sym!=NULL); /* fatal error 103 must be given on error */
|
||||
/* assume no arguments */
|
||||
sym->dim.arglist=(arginfo*)malloc(1*sizeof(arginfo));
|
||||
sym->dim.arglist[0].ident=0;
|
||||
sym->dim.arglist=(arginfo*)calloc(1, sizeof(arginfo));
|
||||
/* set library ID to NULL (only for native functions) */
|
||||
sym->x.lib=NULL;
|
||||
/* set the required stack size to zero (only for non-native functions) */
|
||||
sym->x.stacksize=1; /* 1 for PROC opcode */
|
||||
} /* if */
|
||||
|
||||
if (pc_deprecate!=NULL) {
|
||||
assert(sym!=NULL);
|
||||
sym->flags |= flgDEPRECATED;
|
||||
if (sc_status==statWRITE) {
|
||||
if (sym->documentation!=NULL) {
|
||||
free(sym->documentation);
|
||||
sym->documentation=NULL;
|
||||
} /* if */
|
||||
sym->documentation=pc_deprecate;
|
||||
} else {
|
||||
free(pc_deprecate);
|
||||
} /* if */
|
||||
pc_deprecate=NULL;
|
||||
}/* if */
|
||||
return sym;
|
||||
}
|
||||
|
||||
@ -2886,8 +2968,10 @@ static int operatoradjust(int opertok,symbol *sym,char *opername,int resulttag)
|
||||
refer_symbol(sym,oldsym->refer[i]);
|
||||
delete_symbol(&glbtab,oldsym);
|
||||
} /* if */
|
||||
RemoveFromHashTable(sp_Globals, sym);
|
||||
strcpy(sym->name,tmpname);
|
||||
sym->hash=namehash(sym->name);/* calculate new hash */
|
||||
sym->hash=NameHash(sym->name);/* calculate new hash */
|
||||
AddToHashTable(sp_Globals, sym);
|
||||
|
||||
/* operators should return a value, except the '~' operator */
|
||||
if (opertok!='~')
|
||||
@ -3244,6 +3328,10 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc
|
||||
cidx=code_idx;
|
||||
glbdecl=glb_declared;
|
||||
} /* if */
|
||||
if ((sym->flags & flgDEPRECATED) != 0 && (sym->usage & uSTOCK) == 0) {
|
||||
char *ptr = (sym->documentation != NULL) ? sym->documentation : "";
|
||||
error(233, symbolname, ptr); /* deprecated (probably a public function) */
|
||||
} /* if */
|
||||
begcseg();
|
||||
sym->usage|=uDEFINE; /* set the definition flag */
|
||||
if (fpublic)
|
||||
@ -3559,7 +3647,7 @@ static int declargs(symbol *sym)
|
||||
} /* for */
|
||||
|
||||
sym->usage|=uPROTOTYPED;
|
||||
errorset(sRESET); /* reset error flag (clear the "panic mode")*/
|
||||
errorset(sRESET,0); /* reset error flag (clear the "panic mode")*/
|
||||
return argcnt;
|
||||
}
|
||||
|
||||
@ -4160,31 +4248,47 @@ static void reduce_referrers(symbol *root)
|
||||
}
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
static long max_stacksize_recurse(symbol *sym,long basesize,int *pubfuncparams)
|
||||
static long max_stacksize_recurse(symbol **sourcesym,symbol *sym,long basesize,int *pubfuncparams,int *recursion)
|
||||
{
|
||||
long size,maxsize;
|
||||
int i;
|
||||
int i,stkpos;
|
||||
|
||||
assert(sourcesym!=NULL);
|
||||
assert(sym!=NULL);
|
||||
assert(sym->ident==iFUNCTN);
|
||||
assert((sym->usage & uNATIVE)==0);
|
||||
/* recursion detection */
|
||||
if (sym->compound==0)
|
||||
return -1; /* this function was processed already -> recursion */
|
||||
sym->compound=0;
|
||||
assert(recursion!=NULL);
|
||||
|
||||
maxsize=sym->x.stacksize;
|
||||
for (i=0; i<sym->numrefers; i++) {
|
||||
if (sym->refer[i]!=NULL) {
|
||||
assert(sym->refer[i]->ident==iFUNCTN);
|
||||
assert((sym->refer[i]->usage & uNATIVE)==0); /* a native function cannot refer to a user-function */
|
||||
size=max_stacksize_recurse(sym->refer[i],sym->x.stacksize,pubfuncparams);
|
||||
if (size<0)
|
||||
return size; /* recursion was detected, quit */
|
||||
if (maxsize<size)
|
||||
maxsize=size;
|
||||
for (stkpos=0; sourcesym[stkpos]!=NULL; stkpos++) {
|
||||
if (sym->refer[i]==sourcesym[stkpos]) { /* recursion detection */
|
||||
if ((sc_debug & sSYMBOLIC)!=0 || verbosity>=2) {
|
||||
char symname[2*sNAMEMAX+16];/* allow space for user defined operators */
|
||||
funcdisplayname(symname,sym->name);
|
||||
errorset(sSETFILE,sym->fnumber);
|
||||
errorset(sSETLINE,sym->lnumber);
|
||||
error(237,symname); /* recursive function */
|
||||
} /* if */
|
||||
*recursion=1;
|
||||
goto break_recursion; /* recursion was detected, quit loop */
|
||||
} /* if */
|
||||
} /* for */
|
||||
/* add this symbol to the stack */
|
||||
sourcesym[stkpos]=sym;
|
||||
sourcesym[stkpos+1]=NULL;
|
||||
/* check size of callee */
|
||||
size=max_stacksize_recurse(sourcesym,sym->refer[i],sym->x.stacksize,pubfuncparams,recursion);
|
||||
if (maxsize<size)
|
||||
maxsize=size;
|
||||
/* remove this symbol from the stack */
|
||||
sourcesym[stkpos]=NULL;
|
||||
} /* if */
|
||||
} /* for */
|
||||
break_recursion:
|
||||
|
||||
if ((sym->usage & uPUBLIC)!=0) {
|
||||
/* Find out how many parameters a public function has, then see if this
|
||||
@ -4202,10 +4306,13 @@ static long max_stacksize_recurse(symbol *sym,long basesize,int *pubfuncparams)
|
||||
*pubfuncparams=count;
|
||||
} /* if */
|
||||
|
||||
errorset(sEXPRRELEASE,0); /* clear error data */
|
||||
errorset(sRESET,0);
|
||||
|
||||
return maxsize+basesize;
|
||||
}
|
||||
|
||||
static long max_stacksize(symbol *root)
|
||||
static long max_stacksize(symbol *root,int *recursion)
|
||||
{
|
||||
/* Loop over all non-native functions. For each function, loop
|
||||
* over all of its referrers, accumulating the stack requirements.
|
||||
@ -4218,39 +4325,44 @@ static long max_stacksize(symbol *root)
|
||||
* stack requirements are thus only an estimate.
|
||||
*/
|
||||
long size,maxsize;
|
||||
int maxparams;
|
||||
int maxparams,numfunctions;
|
||||
symbol *sym;
|
||||
symbol **symstack;
|
||||
|
||||
#if !defined NDEBUG
|
||||
for (sym=root->next; sym!=NULL; sym=sym->next)
|
||||
if (sym->ident==iFUNCTN)
|
||||
assert(root!=NULL);
|
||||
assert(recursion!=NULL);
|
||||
/* count number of functions (for allocating the stack for recursion detection) */
|
||||
numfunctions=0;
|
||||
for (sym=root->next; sym!=NULL; sym=sym->next) {
|
||||
if (sym->ident==iFUNCTN) {
|
||||
assert(sym->compound==0);
|
||||
#endif
|
||||
if ((sym->usage & uNATIVE)==0)
|
||||
numfunctions++;
|
||||
} /* if */
|
||||
} /* if */
|
||||
/* allocate function symbol stack */
|
||||
symstack=(symbol **)malloc((numfunctions+1)*sizeof(symbol*));
|
||||
if (symstack==NULL)
|
||||
error(103); /* insufficient memory (fatal error) */
|
||||
memset(symstack,0,(numfunctions+1)*sizeof(symbol*));
|
||||
|
||||
maxsize=0;
|
||||
maxparams=0;
|
||||
*recursion=0; /* assume no recursion */
|
||||
for (sym=root->next; sym!=NULL; sym=sym->next) {
|
||||
symbol *tmpsym;
|
||||
/* drop out if this is not a user-implemented function */
|
||||
if (sym->ident!=iFUNCTN || (sym->usage & uNATIVE)!=0)
|
||||
continue;
|
||||
/* set a "mark" on all functions */
|
||||
for (tmpsym=root->next; tmpsym!=NULL; tmpsym=tmpsym->next)
|
||||
if (tmpsym->ident==iFUNCTN)
|
||||
tmpsym->compound=1;
|
||||
/* accumulate stack size for this symbol */
|
||||
size=max_stacksize_recurse(sym,0L,&maxparams);
|
||||
if (size<0)
|
||||
return size; /* recursion was detected */
|
||||
symstack[0]=sym;
|
||||
assert(symstack[1]==NULL);
|
||||
size=max_stacksize_recurse(symstack,sym,0L,&maxparams,recursion);
|
||||
assert(size>=0);
|
||||
if (maxsize<size)
|
||||
maxsize=size;
|
||||
} /* for */
|
||||
|
||||
/* clear all marks */
|
||||
for (sym=root->next; sym!=NULL; sym=sym->next)
|
||||
if (sym->ident==iFUNCTN)
|
||||
sym->compound=0;
|
||||
|
||||
free((void*)symstack);
|
||||
maxsize++; /* +1 because a zero cell is always pushed on top
|
||||
* of the stack to catch stack overwrites */
|
||||
return maxsize+(maxparams+1);/* +1 because # of parameters is always pushed on entry */
|
||||
@ -4276,22 +4388,28 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst)
|
||||
int entry=FALSE;
|
||||
|
||||
symbol *sym=root->next;
|
||||
while (sym!=NULL && sym->compound>=level) {
|
||||
while (sym != NULL && get_actual_compound(sym) >= level) {
|
||||
switch (sym->ident) {
|
||||
case iLABEL:
|
||||
if (testlabs) {
|
||||
if ((sym->usage & uDEFINE)==0)
|
||||
if ((sym->usage & uDEFINE)==0) {
|
||||
error(19,sym->name); /* not a label: ... */
|
||||
else if ((sym->usage & uREAD)==0)
|
||||
} else if ((sym->usage & uREAD)==0) {
|
||||
errorset(sSETFILE,sym->fnumber);
|
||||
errorset(sSETLINE,sym->lnumber);
|
||||
error(203,sym->name); /* symbol isn't used: ... */
|
||||
} /* if */
|
||||
} /* if */
|
||||
break;
|
||||
case iFUNCTN:
|
||||
if ((sym->usage & (uDEFINE | uREAD | uNATIVE | uSTOCK))==uDEFINE) {
|
||||
funcdisplayname(symname,sym->name);
|
||||
if (strlen(symname)>0)
|
||||
if (strlen(symname)>0) {
|
||||
errorset(sSETFILE,sym->fnumber);
|
||||
errorset(sSETLINE,sym->lnumber);
|
||||
error(203,symname); /* symbol isn't used ... (and not native/stock) */
|
||||
} /* if */
|
||||
} /* if */
|
||||
if ((sym->usage & uPUBLIC)!=0 || strcmp(sym->name,uMAINFUNC)==0)
|
||||
entry=TRUE; /* there is an entry point */
|
||||
/* also mark the function to the debug information */
|
||||
@ -4299,21 +4417,31 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst)
|
||||
insert_dbgsymbol(sym);
|
||||
break;
|
||||
case iCONSTEXPR:
|
||||
if (testconst && (sym->usage & uREAD)==0)
|
||||
if (testconst && (sym->usage & uREAD)==0) {
|
||||
errorset(sSETFILE,sym->fnumber);
|
||||
errorset(sSETLINE,sym->lnumber);
|
||||
error(203,sym->name); /* symbol isn't used: ... */
|
||||
} /* if */
|
||||
break;
|
||||
default:
|
||||
/* a variable */
|
||||
if (sym->parent!=NULL)
|
||||
break; /* hierarchical data type */
|
||||
if ((sym->usage & (uWRITTEN | uREAD | uSTOCK))==0)
|
||||
error(203,sym->name); /* symbol isn't used (and not stock) */
|
||||
else if ((sym->usage & (uREAD | uSTOCK | uPUBLIC))==0)
|
||||
if ((sym->usage & (uWRITTEN | uREAD | uSTOCK))==0) {
|
||||
errorset(sSETFILE,sym->fnumber);
|
||||
errorset(sSETLINE,sym->lnumber);
|
||||
error(203,sym->name,sym->lnumber); /* symbol isn't used (and not stock) */
|
||||
} else if ((sym->usage & (uREAD | uSTOCK | uPUBLIC))==0) {
|
||||
errorset(sSETFILE,sym->fnumber);
|
||||
errorset(sSETLINE,sym->lnumber);
|
||||
error(204,sym->name); /* value assigned to symbol is never used */
|
||||
#if 0 // ??? not sure whether it is a good idea to force people use "const"
|
||||
else if ((sym->usage & (uWRITTEN | uPUBLIC | uCONST))==0 && sym->ident==iREFARRAY)
|
||||
} else if ((sym->usage & (uWRITTEN | uPUBLIC | uCONST))==0 && sym->ident==iREFARRAY) {
|
||||
errorset(sSETFILE,sym->fnumber);
|
||||
errorset(sSETLINE,sym->lnumber);
|
||||
error(214,sym->name); /* make array argument "const" */
|
||||
#endif
|
||||
} /* if */
|
||||
/* also mark the variable (local or global) to the debug information */
|
||||
if ((sym->usage & (uWRITTEN | uREAD))!=0 && (sym->usage & uNATIVE)==0)
|
||||
insert_dbgsymbol(sym);
|
||||
@ -4321,6 +4449,8 @@ static int testsymbols(symbol *root,int level,int testlabs,int testconst)
|
||||
sym=sym->next;
|
||||
} /* while */
|
||||
|
||||
errorset(sEXPRRELEASE, 0); /* clear error data */
|
||||
errorset(sRESET, 0);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -4407,7 +4537,7 @@ static constvalue *insert_constval(constvalue *prev,constvalue *next,const char
|
||||
error(103); /* insufficient memory (fatal error) */
|
||||
memset(cur,0,sizeof(constvalue));
|
||||
if (name!=NULL) {
|
||||
assert(strlen(name)<sNAMEMAX);
|
||||
assert(strlen(name)<=sNAMEMAX);
|
||||
strcpy(cur->name,name);
|
||||
} /* if */
|
||||
cur->value=val;
|
||||
@ -4531,7 +4661,7 @@ static void statement(int *lastindent,int allow_decl)
|
||||
error(36); /* empty statement */
|
||||
return;
|
||||
} /* if */
|
||||
errorset(sRESET);
|
||||
errorset(sRESET,0);
|
||||
|
||||
tok=lex(&val,&st);
|
||||
if (tok!='{') {
|
||||
@ -4567,16 +4697,19 @@ static void statement(int *lastindent,int allow_decl)
|
||||
break;
|
||||
case '{':
|
||||
tok=fline;
|
||||
if (!matchtoken('}')) /* {} is the empty statement */
|
||||
if (!matchtoken('}')) { /* {} is the empty statement */
|
||||
compound(tok==fline);
|
||||
/* lastst (for "last statement") does not change */
|
||||
} else {
|
||||
lastst = tEMPTYBLOCK;
|
||||
}
|
||||
/* lastst (for "last statement") does not change
|
||||
you're not my father, don't tell me what to do */
|
||||
break;
|
||||
case ';':
|
||||
error(36); /* empty statement */
|
||||
break;
|
||||
case tIF:
|
||||
doif();
|
||||
lastst=tIF;
|
||||
lastst=doif();
|
||||
break;
|
||||
case tWHILE:
|
||||
dowhile();
|
||||
@ -4655,6 +4788,7 @@ static void compound(int stmt_sameline)
|
||||
int indent=-1;
|
||||
cell save_decl=declared;
|
||||
int count_stmt=0;
|
||||
int block_start=fline; /* save line where the compound block started */
|
||||
|
||||
/* if there is more text on this line, we should adjust the statement indent */
|
||||
if (stmt_sameline) {
|
||||
@ -4682,7 +4816,7 @@ static void compound(int stmt_sameline)
|
||||
nestlevel+=1; /* increase compound statement level */
|
||||
while (matchtoken('}')==0){ /* repeat until compound statement is closed */
|
||||
if (!freading){
|
||||
needtoken('}'); /* gives error: "expected token }" */
|
||||
error(30,block_start); /* compound block not closed at end of file */
|
||||
break;
|
||||
} else {
|
||||
if (count_stmt>0 && (lastst==tRETURN || lastst==tBREAK || lastst==tCONTINUE))
|
||||
@ -4720,7 +4854,7 @@ static int doexpr(int comma,int chkeffect,int allowarray,int mark_endexpr,
|
||||
assert(stgidx==0);
|
||||
} /* if */
|
||||
index=stgidx;
|
||||
errorset(sEXPRMARK);
|
||||
errorset(sEXPRMARK,0);
|
||||
do {
|
||||
/* on second round through, mark the end of the previous expression */
|
||||
if (index!=stgidx)
|
||||
@ -4735,7 +4869,7 @@ static int doexpr(int comma,int chkeffect,int allowarray,int mark_endexpr,
|
||||
} while (comma && matchtoken(',')); /* more? */
|
||||
if (mark_endexpr)
|
||||
markexpr(sEXPR,NULL,0); /* optionally, mark the end of the expression */
|
||||
errorset(sEXPRRELEASE);
|
||||
errorset(sEXPRRELEASE,0);
|
||||
if (localstaging) {
|
||||
stgout(index);
|
||||
stgset(FALSE); /* stop staging */
|
||||
@ -4752,7 +4886,7 @@ SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr)
|
||||
|
||||
stgset(TRUE); /* start stage-buffering */
|
||||
stgget(&index,&cidx); /* mark position in code generator */
|
||||
errorset(sEXPRMARK);
|
||||
errorset(sEXPRMARK,0);
|
||||
ident=expression(val,tag,symptr,FALSE);
|
||||
stgdel(index,cidx); /* scratch generated code */
|
||||
stgset(FALSE); /* stop stage-buffering */
|
||||
@ -4765,7 +4899,7 @@ SC_FUNC int constexpr(cell *val,int *tag,symbol **symptr)
|
||||
if (symptr!=NULL)
|
||||
*symptr=NULL;
|
||||
} /* if */
|
||||
errorset(sEXPRRELEASE);
|
||||
errorset(sEXPRRELEASE,0);
|
||||
return (ident==iCONSTEXPR);
|
||||
}
|
||||
|
||||
@ -4846,10 +4980,11 @@ static void test(int label,int parens,int invert)
|
||||
} /* if */
|
||||
}
|
||||
|
||||
static void doif(void)
|
||||
static int doif(void)
|
||||
{
|
||||
int flab1,flab2;
|
||||
int ifindent;
|
||||
int lastst_true;
|
||||
|
||||
ifindent=stmtindent; /* save the indent of the "if" instruction */
|
||||
flab1=getlabel(); /* get label number for false branch */
|
||||
@ -4858,6 +4993,7 @@ static void doif(void)
|
||||
if (matchtoken(tELSE)==0){ /* if...else ? */
|
||||
setlabel(flab1); /* no, simple if..., print false label */
|
||||
} else {
|
||||
lastst_true=lastst;
|
||||
/* to avoid the "dangling else" error, we want a warning if the "else"
|
||||
* has a lower indent than the matching "if" */
|
||||
if (stmtindent<ifindent && sc_tabsize>0)
|
||||
@ -4868,7 +5004,14 @@ static void doif(void)
|
||||
setlabel(flab1); /* print false label */
|
||||
statement(NULL,FALSE); /* do "else" clause */
|
||||
setlabel(flab2); /* print true label */
|
||||
/* if both the "true" branch and the "false" branch ended with the same
|
||||
* kind of statement, set the last statement id to that kind, rather than
|
||||
* to the generic tIF; this allows for better "unreachable code" checking
|
||||
*/
|
||||
if (lastst == lastst_true)
|
||||
return lastst;
|
||||
} /* endif */
|
||||
return tIF;
|
||||
}
|
||||
|
||||
static void dowhile(void)
|
||||
@ -5230,18 +5373,6 @@ static symbol *fetchlab(char *name)
|
||||
return sym;
|
||||
}
|
||||
|
||||
static int is_variadic(symbol *sym)
|
||||
{
|
||||
arginfo *arg;
|
||||
|
||||
assert(sym->ident==iFUNCTN);
|
||||
for (arg = sym->dim.arglist; arg->ident; arg++) {
|
||||
if (arg->ident == iVARARGS)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* doreturn
|
||||
*
|
||||
* Global references: rettype (altered)
|
||||
@ -5258,6 +5389,11 @@ static void doreturn(void)
|
||||
error(78); /* mix "return;" and "return value;" */
|
||||
ident=doexpr(TRUE,FALSE,TRUE,TRUE,&tag,&sym,TRUE);
|
||||
needtoken(tTERM);
|
||||
if (ident == iARRAY && sym == NULL) {
|
||||
/* returning a literal string is not supported (it must be a variable) */
|
||||
error(39);
|
||||
ident = iCONSTEXPR; /* avoid handling an "array" case */
|
||||
} /* if */
|
||||
/* see if this function already has a sub type (an array attached) */
|
||||
sub=finddepend(curfunc);
|
||||
assert(sub==NULL || sub->ident==iREFARRAY);
|
||||
@ -5341,11 +5477,7 @@ static void doreturn(void)
|
||||
* it stays on the heap for the moment, and it is removed -usually- at
|
||||
* the end of the expression/statement, see expression() in SC3.C)
|
||||
*/
|
||||
if (is_variadic(curfunc)) {
|
||||
load_hidden_arg();
|
||||
} else {
|
||||
address(sub,sALT); /* ALT = destination */
|
||||
}
|
||||
arraysize=calc_arraysize(dim,numdim,0);
|
||||
memcopy(arraysize*sizeof(cell)); /* source already in PRI */
|
||||
/* moveto1(); is not necessary, callfunction() does a popreg() */
|
||||
@ -5460,6 +5592,7 @@ static void dostate(void)
|
||||
pc_docexpr=TRUE; /* attach expression as a documentation string */
|
||||
test(flabel,FALSE,FALSE); /* get expression, branch to flabel if false */
|
||||
pc_docexpr=FALSE;
|
||||
pc_deprecate=NULL;
|
||||
needtoken(')');
|
||||
} else {
|
||||
flabel=-1;
|
||||
@ -5607,4 +5740,3 @@ static int *readwhile(void)
|
||||
return (wqptr-wqSIZE);
|
||||
} /* if */
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
#include <sclinux.h>
|
||||
#endif
|
||||
#include "sp_symhash.h"
|
||||
|
||||
#if defined FORTIFY
|
||||
#include "fortify.h"
|
||||
@ -120,18 +121,18 @@ SC_FUNC void clearstk(void)
|
||||
SC_FUNC int plungequalifiedfile(char *name)
|
||||
{
|
||||
static char *extensions[] = { ".inc", ".p", ".pawn" };
|
||||
FILE *fp;
|
||||
void *fp;
|
||||
char *ext;
|
||||
int ext_idx;
|
||||
|
||||
ext_idx=0;
|
||||
do {
|
||||
fp=(FILE*)pc_opensrc(name);
|
||||
fp=(void*)pc_opensrc(name);
|
||||
ext=strchr(name,'\0'); /* save position */
|
||||
if (fp==NULL) {
|
||||
/* try to append an extension */
|
||||
strcpy(ext,extensions[ext_idx]);
|
||||
fp=(FILE*)pc_opensrc(name);
|
||||
fp=(void*)pc_opensrc(name);
|
||||
if (fp==NULL)
|
||||
*ext='\0'; /* on failure, restore filename */
|
||||
} /* if */
|
||||
@ -162,8 +163,10 @@ static char *extensions[] = { ".inc", ".p", ".pawn" };
|
||||
fline=0; /* set current line number to 0 */
|
||||
fcurrent=fnumber;
|
||||
icomment=0; /* not in a comment */
|
||||
insert_dbgfile(inpfname);
|
||||
setfiledirect(inpfname);
|
||||
insert_dbgfile(inpfname); /* attach to debug information */
|
||||
insert_inputfile(inpfname); /* save for the error system */
|
||||
assert(sc_status == statFIRST || strcmp(get_inputfile(fcurrent), inpfname) == 0);
|
||||
setfiledirect(inpfname); /* (optionally) set in the list file */
|
||||
listline=-1; /* force a #line directive when changing the file */
|
||||
sc_is_utf8=(short)scan_utf8(inpf,name);
|
||||
return TRUE;
|
||||
@ -281,6 +284,7 @@ static void readline(unsigned char *line)
|
||||
{
|
||||
int i,num,cont;
|
||||
unsigned char *ptr;
|
||||
symbol *sym;
|
||||
|
||||
if (lptr==term_expr)
|
||||
return;
|
||||
@ -319,6 +323,7 @@ static void readline(unsigned char *line)
|
||||
inpf=(FILE *)POPSTK_P();
|
||||
insert_dbgfile(inpfname);
|
||||
setfiledirect(inpfname);
|
||||
assert(sc_status==statFIRST || strcmp(get_inputfile(fcurrent),inpfname)==0);
|
||||
listline=-1; /* force a #line directive when changing the file */
|
||||
} /* if */
|
||||
|
||||
@ -358,6 +363,9 @@ static void readline(unsigned char *line)
|
||||
line+=strlen((char*)line);
|
||||
} /* if */
|
||||
fline+=1;
|
||||
sym=findconst("__LINE__");
|
||||
assert(sym!=NULL);
|
||||
sym->addr=fline;
|
||||
} while (num>=0 && cont);
|
||||
}
|
||||
|
||||
@ -850,6 +858,7 @@ static int command(void)
|
||||
char *str;
|
||||
int index;
|
||||
cell code_index;
|
||||
size_t len;
|
||||
|
||||
while (*lptr<=' ' && *lptr!='\0')
|
||||
lptr+=1;
|
||||
@ -889,7 +898,7 @@ static int command(void)
|
||||
assert(iflevel>=0);
|
||||
if (iflevel==0) {
|
||||
error(26); /* no matching #if */
|
||||
errorset(sRESET);
|
||||
errorset(sRESET,0);
|
||||
} else {
|
||||
/* check for earlier #else */
|
||||
if ((ifstack[iflevel-1] & HANDLED_ELSE)==HANDLED_ELSE) {
|
||||
@ -897,7 +906,7 @@ static int command(void)
|
||||
error(61); /* #elseif directive may not follow an #else */
|
||||
else
|
||||
error(60); /* multiple #else directives between #if ... #endif */
|
||||
errorset(sRESET);
|
||||
errorset(sRESET,0);
|
||||
} else {
|
||||
assert(iflevel>0);
|
||||
/* if there has been a "parse mode" on this level, set "skip mode",
|
||||
@ -906,11 +915,27 @@ static int command(void)
|
||||
if ((ifstack[iflevel-1] & PARSEMODE)==PARSEMODE) {
|
||||
/* there has been a parse mode already on this level, so skip the rest */
|
||||
ifstack[iflevel-1] |= (char)SKIPMODE;
|
||||
/* if we were already skipping this section, allow expressions with
|
||||
* undefined symbols; otherwise check the expression to catch errors
|
||||
*/
|
||||
if (tok==tpELSEIF) {
|
||||
if (skiplevel==iflevel)
|
||||
preproc_expr(&val,NULL); /* get, but ignore the expression */
|
||||
else
|
||||
lptr=(unsigned char*)strchr((char*)lptr,'\0');
|
||||
} /* if */
|
||||
} else {
|
||||
/* previous conditions were all FALSE */
|
||||
if (tok==tpELSEIF) {
|
||||
/* get new expression */
|
||||
/* if we were already skipping this section, allow expressions with
|
||||
* undefined symbols; otherwise check the expression to catch errors
|
||||
*/
|
||||
if (skiplevel==iflevel) {
|
||||
preproc_expr(&val,NULL); /* get value (or 0 on error) */
|
||||
} else {
|
||||
lptr=(unsigned char*)strchr((char*)lptr,'\0');
|
||||
val=0;
|
||||
} /* if */
|
||||
ifstack[iflevel-1]=(char)(val ? PARSEMODE : SKIPMODE);
|
||||
} else {
|
||||
/* a simple #else, clear skip mode */
|
||||
@ -925,7 +950,7 @@ static int command(void)
|
||||
ret=CMD_IF;
|
||||
if (iflevel==0){
|
||||
error(26); /* no matching "#if" */
|
||||
errorset(sRESET);
|
||||
errorset(sRESET,0);
|
||||
} else {
|
||||
iflevel--;
|
||||
if (iflevel<skiplevel)
|
||||
@ -1003,6 +1028,19 @@ static int command(void)
|
||||
error(27); /* invalid character constant */
|
||||
sc_ctrlchar=(char)val;
|
||||
} /* if */
|
||||
}
|
||||
else if (strcmp(str, "deprecated") == 0) {
|
||||
while (*lptr <= ' ' && *lptr != '\0')
|
||||
lptr++;
|
||||
len = strlen((char*)lptr);
|
||||
pc_deprecate = (char*)malloc(len + 1);
|
||||
if (pc_deprecate != NULL)
|
||||
{
|
||||
strcpy(pc_deprecate, (char*)lptr);
|
||||
if (pc_deprecate[len - 1] == '\n') /* remove extra \n as already appended in .scp file */
|
||||
pc_deprecate[len-1] = '\0';
|
||||
}
|
||||
lptr = (unsigned char*)strchr((char*)lptr, '\0'); /* skip to end (ignore "extra characters on line") */
|
||||
} else if (strcmp(str,"dynamic")==0) {
|
||||
preproc_expr(&sc_stksize,NULL);
|
||||
} else if ( !strcmp(str,"library") ||
|
||||
@ -1117,6 +1155,7 @@ static int command(void)
|
||||
} else if (strcmp(str,"tabsize")==0) {
|
||||
cell val;
|
||||
preproc_expr(&val,NULL);
|
||||
if (val>0)
|
||||
sc_tabsize=(int)val;
|
||||
} else if (strcmp(str,"align")==0) {
|
||||
sc_alignnext=TRUE;
|
||||
@ -1251,7 +1290,7 @@ static int command(void)
|
||||
} /* while */
|
||||
end=lptr;
|
||||
/* check pattern to match */
|
||||
if (!isalpha(*start) && *start!='_') {
|
||||
if (!alpha(*start)) {
|
||||
error(74); /* pattern must start with an alphabetic character */
|
||||
break;
|
||||
} /* if */
|
||||
@ -1302,7 +1341,7 @@ static int command(void)
|
||||
} /* while */
|
||||
substitution[count]='\0';
|
||||
/* check whether the definition already exists */
|
||||
for (prefixlen=0,start=(unsigned char*)pattern; isalpha(*start) || isdigit(*start) || *start=='_'; prefixlen++,start++)
|
||||
for (prefixlen=0,start=(unsigned char*)pattern; alphanum(*start); prefixlen++,start++)
|
||||
/* nothing */;
|
||||
assert(prefixlen>0);
|
||||
if ((def=find_subst(pattern,prefixlen))!=NULL) {
|
||||
@ -1458,7 +1497,7 @@ static int substpattern(unsigned char *line,size_t buffersize,char *pattern,char
|
||||
memset(args,0,sizeof args);
|
||||
|
||||
/* check the length of the prefix */
|
||||
for (prefixlen=0,s=(unsigned char*)pattern; isalpha(*s) || isdigit(*s) || *s=='_'; prefixlen++,s++)
|
||||
for (prefixlen=0,s=(unsigned char*)pattern; alphanum(*s); prefixlen++,s++)
|
||||
/* nothing */;
|
||||
assert(prefixlen>0);
|
||||
assert(strncmp((char*)line,pattern,prefixlen)==0);
|
||||
@ -1618,7 +1657,7 @@ static void substallpatterns(unsigned char *line,int buffersize)
|
||||
/* find the start of a prefix (skip all non-alphabetic characters),
|
||||
* also skip strings
|
||||
*/
|
||||
while (!isalpha(*start) && *start!='_' && *start!='\0') {
|
||||
while (!alpha(*start) && *start!='\0') {
|
||||
/* skip strings */
|
||||
if (is_startstring(start)) {
|
||||
start=(unsigned char *)skipstring(start);
|
||||
@ -1636,7 +1675,7 @@ static void substallpatterns(unsigned char *line,int buffersize)
|
||||
while ((*start<=' ' && *start!='\0') || *start=='(')
|
||||
start++;
|
||||
/* skip the symbol behind it */
|
||||
while (isalpha(*start) || isdigit(*start) || *start=='_')
|
||||
while (alphanum(*start))
|
||||
start++;
|
||||
/* drop back into the main loop */
|
||||
continue;
|
||||
@ -1644,7 +1683,7 @@ static void substallpatterns(unsigned char *line,int buffersize)
|
||||
/* get the prefix (length), look for a matching definition */
|
||||
prefixlen=0;
|
||||
end=start;
|
||||
while (isalpha(*end) || isdigit(*end) || *end=='_') {
|
||||
while (alphanum(*end)) {
|
||||
prefixlen++;
|
||||
end++;
|
||||
} /* while */
|
||||
@ -1688,7 +1727,7 @@ SC_FUNC void preprocess(void)
|
||||
lptr=pline; /* set "line pointer" to start of the parsing buffer */
|
||||
iscommand=command();
|
||||
if (iscommand!=CMD_NONE)
|
||||
errorset(sRESET); /* reset error flag ("panic mode") on empty line or directive */
|
||||
errorset(sRESET,0); /* reset error flag ("panic mode") on empty line or directive */
|
||||
#if !defined NO_DEFINE
|
||||
if (iscommand==CMD_NONE) {
|
||||
assert(lptr!=term_expr);
|
||||
@ -1882,7 +1921,7 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym)
|
||||
while (i<=tLAST) { /* match reserved words and compiler directives */
|
||||
if (*lptr==**tokptr && match(*tokptr,TRUE)) {
|
||||
_lextok=i;
|
||||
errorset(sRESET); /* reset error flag (clear the "panic mode")*/
|
||||
errorset(sRESET,0); /* reset error flag (clear the "panic mode")*/
|
||||
if (pc_docexpr) /* optionally concatenate to documentation string */
|
||||
insert_autolist(*tokptr);
|
||||
return _lextok;
|
||||
@ -1974,7 +2013,7 @@ SC_FUNC int lex(cell *lexvalue,char **lexsym)
|
||||
} else if (*lptr==';') { /* semicolumn resets "error" flag */
|
||||
_lextok=';';
|
||||
lptr+=1;
|
||||
errorset(sRESET); /* reset error flag (clear the "panic mode")*/
|
||||
errorset(sRESET,0); /* reset error flag (clear the "panic mode")*/
|
||||
} else {
|
||||
_lextok=*lptr; /* if every match fails, return the character */
|
||||
lptr+=1; /* increase the "lptr" pointer */
|
||||
@ -2332,6 +2371,7 @@ SC_FUNC int ishex(char c)
|
||||
static symbol *add_symbol(symbol *root,symbol *entry,int sort)
|
||||
{
|
||||
symbol *newsym;
|
||||
int global = root==&glbtab;
|
||||
|
||||
if (sort)
|
||||
while (root->next!=NULL && strcmp(entry->name,root->next->name)>0)
|
||||
@ -2344,6 +2384,8 @@ static symbol *add_symbol(symbol *root,symbol *entry,int sort)
|
||||
memcpy(newsym,entry,sizeof(symbol));
|
||||
newsym->next=root->next;
|
||||
root->next=newsym;
|
||||
if (global)
|
||||
AddToHashTable(sp_Globals, newsym);
|
||||
return newsym;
|
||||
}
|
||||
|
||||
@ -2388,6 +2430,7 @@ static void free_symbol(symbol *sym)
|
||||
|
||||
SC_FUNC void delete_symbol(symbol *root,symbol *sym)
|
||||
{
|
||||
symbol *origRoot = root;
|
||||
/* find the symbol and its predecessor
|
||||
* (this function assumes that you will never delete a symbol that is not
|
||||
* in the table pointed at by "root")
|
||||
@ -2398,13 +2441,27 @@ SC_FUNC void delete_symbol(symbol *root,symbol *sym)
|
||||
assert(root!=NULL);
|
||||
} /* while */
|
||||
|
||||
if (origRoot==&glbtab)
|
||||
RemoveFromHashTable(sp_Globals, sym);
|
||||
|
||||
/* unlink it, then free it */
|
||||
root->next=sym->next;
|
||||
free_symbol(sym);
|
||||
}
|
||||
|
||||
SC_FUNC int get_actual_compound(symbol *sym)
|
||||
{
|
||||
if (sym->ident == iARRAY || sym->ident == iREFARRAY) {
|
||||
while (sym->parent)
|
||||
sym = sym->parent;
|
||||
}
|
||||
|
||||
return sym->compound;
|
||||
}
|
||||
|
||||
SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_functions)
|
||||
{
|
||||
symbol *origRoot=root;
|
||||
symbol *sym,*parent_sym;
|
||||
constvalue *stateptr;
|
||||
int mustdelete=0;
|
||||
@ -2413,7 +2470,7 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_
|
||||
* specified nesting level */
|
||||
while (root->next!=NULL) {
|
||||
sym=root->next;
|
||||
if (sym->compound<level)
|
||||
if (get_actual_compound(sym)<level)
|
||||
break;
|
||||
switch (sym->ident) {
|
||||
case iLABEL:
|
||||
@ -2458,6 +2515,8 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_
|
||||
break;
|
||||
} /* switch */
|
||||
if (mustdelete) {
|
||||
if (origRoot == &glbtab)
|
||||
RemoveFromHashTable(sp_Globals, sym);
|
||||
root->next=sym->next;
|
||||
free_symbol(sym);
|
||||
} else {
|
||||
@ -2475,31 +2534,17 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_
|
||||
/* for user defined operators, also remove the "prototyped" flag, as
|
||||
* user-defined operators *must* be declared before use
|
||||
*/
|
||||
if (sym->ident==iFUNCTN && !isalpha(*sym->name) && *sym->name!='_' && *sym->name!=PUBLIC_CHAR)
|
||||
if (sym->ident==iFUNCTN && !alpha(*sym->name))
|
||||
sym->usage &= ~uPROTOTYPED;
|
||||
root=sym; /* skip the symbol */
|
||||
} /* if */
|
||||
} /* if */
|
||||
}
|
||||
|
||||
/* The purpose of the hash is to reduce the frequency of a "name"
|
||||
* comparison (which is costly). There is little interest in avoiding
|
||||
* clusters in similar names, which is why this function is plain simple.
|
||||
*/
|
||||
SC_FUNC uint32_t namehash(const char *name)
|
||||
{
|
||||
const unsigned char *ptr=(const unsigned char *)name;
|
||||
int len=strlen(name);
|
||||
if (len==0)
|
||||
return 0L;
|
||||
assert(len<256);
|
||||
return (len<<24Lu) + (ptr[0]<<16Lu) + (ptr[len-1]<<8Lu) + (ptr[len>>1Lu]);
|
||||
}
|
||||
|
||||
static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int includechildren)
|
||||
{
|
||||
symbol *ptr=root->next;
|
||||
unsigned long hash=namehash(name);
|
||||
unsigned long hash=NameHash(name);
|
||||
while (ptr!=NULL) {
|
||||
if (hash==ptr->hash && strcmp(name,ptr->name)==0
|
||||
&& (ptr->parent==NULL || includechildren)
|
||||
@ -2569,7 +2614,10 @@ SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom)
|
||||
|
||||
SC_FUNC void markusage(symbol *sym,int usage)
|
||||
{
|
||||
assert(sym!=NULL);
|
||||
sym->usage |= (char)usage;
|
||||
if ((usage & uWRITTEN) != 0)
|
||||
sym->lnumber=fline;
|
||||
/* check if (global) reference must be added to the symbol */
|
||||
if ((usage & (uREAD | uWRITTEN))!=0) {
|
||||
/* only do this for global symbols */
|
||||
@ -2610,7 +2658,7 @@ SC_FUNC symbol *findconst(const char *name)
|
||||
|
||||
sym=find_symbol(&loctab,name,-1,TRUE); /* try local symbols first */
|
||||
if (sym==NULL || sym->ident!=iCONSTEXPR) /* not found, or not a constant */
|
||||
sym=find_symbol(&glbtab,name,fcurrent,TRUE);
|
||||
sym=FindInHashTable(sp_Globals,name,fcurrent);
|
||||
if (sym==NULL || sym->ident!=iCONSTEXPR)
|
||||
return NULL;
|
||||
assert(sym->parent==NULL || (sym->usage & uENUMFIELD)!=0);
|
||||
@ -2651,16 +2699,18 @@ SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,i
|
||||
|
||||
/* first fill in the entry */
|
||||
strcpy(entry.name,name);
|
||||
entry.hash=namehash(name);
|
||||
entry.hash=NameHash(name);
|
||||
entry.addr=addr;
|
||||
entry.codeaddr=code_idx;
|
||||
entry.vclass=(char)vclass;
|
||||
entry.ident=(char)ident;
|
||||
entry.tag=tag;
|
||||
entry.usage=(char)usage;
|
||||
entry.flags=0;
|
||||
entry.compound=0; /* may be overridden later */
|
||||
entry.states=NULL;
|
||||
entry.fnumber=-1; /* assume global visibility (ignored for local symbols) */
|
||||
entry.lnumber=fline;
|
||||
entry.numrefers=1;
|
||||
entry.refer=refer;
|
||||
entry.parent=NULL;
|
||||
@ -2670,7 +2720,6 @@ SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,i
|
||||
/* then insert it in the list */
|
||||
if (vclass==sGLOBAL)
|
||||
return add_symbol(&glbtab,&entry,TRUE);
|
||||
else
|
||||
return add_symbol(&loctab, &entry, FALSE);
|
||||
}
|
||||
|
||||
@ -2685,7 +2734,7 @@ SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int
|
||||
* this special case.
|
||||
*/
|
||||
assert(vclass!=sGLOBAL || (sym=findglb(name))==NULL || (sym->usage & uDEFINE)==0
|
||||
|| sym->ident==iFUNCTN && sym==curfunc);
|
||||
|| (sym->ident==iFUNCTN && sym==curfunc));
|
||||
|
||||
if (ident==iARRAY || ident==iREFARRAY) {
|
||||
symbol *parent=NULL,*top;
|
||||
|
@ -289,7 +289,6 @@ SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
|
||||
*/
|
||||
if (!allowcoerce || formaltag!=0 || (actualtag & FIXEDTAG)!=0)
|
||||
return FALSE;
|
||||
|
||||
} /* if */
|
||||
return TRUE;
|
||||
}
|
||||
@ -488,6 +487,7 @@ static int plnge_rel(int *opstr,int opoff,int (*hier)(value *lval),value *lval)
|
||||
int lvalue,opidx;
|
||||
value lval2 = {0}; /* intialize, to avoid a compiler warning */
|
||||
int count;
|
||||
char boolresult;
|
||||
|
||||
/* this function should only be called for relational operators */
|
||||
assert(op1[opoff]==os_le);
|
||||
@ -504,7 +504,9 @@ static int plnge_rel(int *opstr,int opoff,int (*hier)(value *lval),value *lval)
|
||||
error(212);
|
||||
if (count>0) {
|
||||
relop_prefix();
|
||||
boolresult = lval->boolresult;
|
||||
*lval=lval2; /* copy right hand expression of the previous iteration */
|
||||
lval->boolresult = boolresult;
|
||||
} /* if */
|
||||
opidx+=opoff;
|
||||
plnge2(op1[opidx],hier,lval,&lval2);
|
||||
@ -1126,6 +1128,7 @@ static int hier2(value *lval)
|
||||
symbol *sym=NULL;
|
||||
int saveresult;
|
||||
|
||||
sym = NULL;
|
||||
tok=lex(&val,&st);
|
||||
switch (tok) {
|
||||
case tINC: /* ++lval */
|
||||
@ -1290,7 +1293,7 @@ static int hier2(value *lval)
|
||||
return error(17,st); /* undefined symbol (symbol is in the table, but it is "used" only) */
|
||||
tag=sym->tag;
|
||||
} /* if */
|
||||
if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
|
||||
if (sym!=NULL && (sym->ident==iARRAY || sym->ident==iREFARRAY)) {
|
||||
int level;
|
||||
symbol *idxsym=NULL;
|
||||
for (level=0; matchtoken('['); level++) {
|
||||
@ -1862,6 +1865,11 @@ static int nesting=0;
|
||||
assert(nest_stkusage==0);
|
||||
#endif
|
||||
|
||||
if ((sym->flags & flgDEPRECATED)!=0) {
|
||||
char *ptr= (sym->documentation!=NULL) ? sym->documentation : "";
|
||||
error(233,sym->name,ptr); /* deprecated (probably a native function) */
|
||||
} /* if */
|
||||
|
||||
/* run through the arguments */
|
||||
arg=sym->dim.arglist;
|
||||
assert(arg!=NULL);
|
||||
@ -2039,7 +2047,7 @@ static int nesting=0;
|
||||
error(47); /* array sizes must match */
|
||||
} /* if */
|
||||
} /* if */
|
||||
if (lval.ident!=iARRAYCELL) {
|
||||
if (lval.ident!=iARRAYCELL|| lval.constval>0) {
|
||||
/* save array size, for default values with uSIZEOF flag */
|
||||
cell array_sz=lval.constval;
|
||||
assert(array_sz!=0);/* literal array must have a size */
|
||||
|
@ -829,7 +829,7 @@ SC_FUNC void defstorage(void)
|
||||
stgwrite("dump ");
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Inclrement/decrement stack pointer. Note that this routine does
|
||||
* nothing if the delta is zero.
|
||||
*/
|
||||
|
1
compiler/libpc300/sc5.scp → compiler/libpc300/sc5-in.scp
Executable file → Normal file
1
compiler/libpc300/sc5.scp → compiler/libpc300/sc5-in.scp
Executable file → Normal file
@ -290,6 +290,7 @@ static char *warnmsg[] = {
|
||||
/*230*/ "no implementation for state \"%s\" / function \"%s\", no fall-back\n",
|
||||
/*231*/ "state specification on forward declaration is ignored\n",
|
||||
/*232*/ "output file is written, but with compact encoding disabled\n"
|
||||
/*233*/ "symbol \"%s\" is marked as deprecated: %s\n",
|
||||
#else
|
||||
"\345 \274tr\240\226\233\277 %\206\273\337c\367\305",
|
||||
"\222\323i\231\300\344\224t/\314cr\375\364",
|
@ -41,7 +41,7 @@
|
||||
#pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */
|
||||
#endif
|
||||
|
||||
#include "sc5.scp"
|
||||
#include <sc5.scp>
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(pop)
|
||||
@ -51,7 +51,9 @@
|
||||
static unsigned char warndisable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char */
|
||||
|
||||
static int errflag;
|
||||
static int errfile;
|
||||
static int errstart; /* line number at which the instruction started */
|
||||
static int errline; /* forced line number for the error message */
|
||||
|
||||
/* error
|
||||
*
|
||||
@ -70,7 +72,7 @@ SC_FUNC int error(int number,...)
|
||||
static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||
static int lastline,errorcount;
|
||||
static short lastfile;
|
||||
char *msg,*pre;
|
||||
char *msg,*pre,*filename;
|
||||
va_list argptr;
|
||||
char string[128];
|
||||
|
||||
@ -107,11 +109,22 @@ static short lastfile;
|
||||
|
||||
strexpand(string,(unsigned char *)msg,sizeof string,SCPACK_TABLE);
|
||||
|
||||
assert(errstart<=fline);
|
||||
if (errline>0)
|
||||
errstart=errline; /* forced error position, set single line destination */
|
||||
else
|
||||
errline=fline; /* normal error, errstart may (or may not) have been marked, endpoint is current line */
|
||||
if (errstart>errline)
|
||||
errstart=errline; /* special case: error found at end of included file */
|
||||
if (errfile>=0)
|
||||
filename=get_inputfile(errfile);/* forced filename */
|
||||
else
|
||||
filename=inpfname; /* current file */
|
||||
assert(filename!=NULL);
|
||||
|
||||
va_start(argptr,number);
|
||||
if (strlen(errfname)==0) {
|
||||
int start= (errstart==fline) ? -1 : errstart;
|
||||
if (pc_error(number,string,inpfname,start,fline,argptr)) {
|
||||
int start= (errstart==errline) ? -1 : errstart;
|
||||
if (pc_error((int)number,string,filename,start,errline,argptr)) {
|
||||
if (outf!=NULL) {
|
||||
pc_closeasm(outf,TRUE);
|
||||
outf=NULL;
|
||||
@ -121,10 +134,10 @@ static short lastfile;
|
||||
} else {
|
||||
FILE *fp=fopen(errfname,"a");
|
||||
if (fp!=NULL) {
|
||||
if (errstart>=0 && errstart!=fline)
|
||||
fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,fline,pre,number);
|
||||
if (errstart>=0 && errstart!=errline)
|
||||
fprintf(fp,"%s(%d -- %d) : %s %03d: ",filename,errstart,errline,pre,number);
|
||||
else
|
||||
fprintf(fp,"%s(%d) : %s %03d: ",inpfname,fline,pre,number);
|
||||
fprintf(fp,"%s(%d) : %s %03d: ",filename,errline,pre,number);
|
||||
vfprintf(fp,string,argptr);
|
||||
fclose(fp);
|
||||
} /* if */
|
||||
@ -144,6 +157,8 @@ static short lastfile;
|
||||
longjmp(errbuf,2); /* fatal error, quit */
|
||||
} /* if */
|
||||
|
||||
errline=-1;
|
||||
errfile=-1;
|
||||
/* check whether we are seeing many errors on the same line */
|
||||
if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile)
|
||||
errorcount=0;
|
||||
@ -157,7 +172,7 @@ static short lastfile;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SC_FUNC void errorset(int code)
|
||||
SC_FUNC void errorset(int code,int line)
|
||||
{
|
||||
switch (code) {
|
||||
case sRESET:
|
||||
@ -171,6 +186,15 @@ SC_FUNC void errorset(int code)
|
||||
break;
|
||||
case sEXPRRELEASE:
|
||||
errstart=-1; /* forget start line number */
|
||||
errline=-1;
|
||||
errfile=-1;
|
||||
break;
|
||||
case sSETLINE:
|
||||
errstart=-1; /* force error line number, forget start line */
|
||||
errline=line;
|
||||
break;
|
||||
case sSETFILE:
|
||||
errfile=line;
|
||||
break;
|
||||
} /* switch */
|
||||
}
|
||||
|
0
compiler/libpc300/sc7.scp → compiler/libpc300/sc7-in.scp
Executable file → Normal file
0
compiler/libpc300/sc7.scp → compiler/libpc300/sc7-in.scp
Executable file → Normal file
@ -51,7 +51,7 @@
|
||||
#pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */
|
||||
#endif
|
||||
|
||||
#include "sc7.scp"
|
||||
#include <sc7.scp>
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(pop)
|
||||
|
@ -255,16 +255,16 @@ SC_FUNC void delete_pathtable(void)
|
||||
|
||||
static stringpair substpair = { NULL, NULL, NULL}; /* list of substitution pairs */
|
||||
|
||||
static stringpair *substindex['z'-'A'+1]; /* quick index to first character */
|
||||
static stringpair *substindex['z'-PUBLIC_CHAR+1]; /* quick index to first character */
|
||||
static void adjustindex(char c)
|
||||
{
|
||||
stringpair *cur;
|
||||
assert(c>='A' && c<='Z' || c>='a' && c<='z' || c=='_');
|
||||
assert('A'<'_' && '_'<'z');
|
||||
assert(c>='A' && c<='Z' || c>='a' && c<='z' || c=='_' || c==PUBLIC_CHAR);
|
||||
assert(PUBLIC_CHAR<'A' && 'A'<'_' && '_'<'z');
|
||||
|
||||
for (cur=substpair.next; cur!=NULL && cur->first[0]!=c; cur=cur->next)
|
||||
/* nothing */;
|
||||
substindex[(int)c-'A']=cur;
|
||||
substindex[(int)c-PUBLIC_CHAR]=cur;
|
||||
}
|
||||
|
||||
SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
|
||||
@ -276,6 +276,26 @@ SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
|
||||
if ((cur=insert_stringpair(&substpair,pattern,substitution,prefixlen))==NULL)
|
||||
error(103); /* insufficient memory (fatal error) */
|
||||
adjustindex(*pattern);
|
||||
|
||||
if (pc_deprecate != NULL) {
|
||||
assert(cur != NULL);
|
||||
cur->flags |= flgDEPRECATED;
|
||||
if (sc_status == statWRITE) {
|
||||
if (cur->documentation != NULL) {
|
||||
free(cur->documentation);
|
||||
cur->documentation = NULL;
|
||||
} /* if */
|
||||
cur->documentation = pc_deprecate;
|
||||
}
|
||||
else {
|
||||
free(pc_deprecate);
|
||||
} /* if */
|
||||
pc_deprecate = NULL;
|
||||
}
|
||||
else {
|
||||
cur->flags = 0;
|
||||
cur->documentation = NULL;
|
||||
} /* if */
|
||||
return cur;
|
||||
}
|
||||
|
||||
@ -284,10 +304,26 @@ SC_FUNC stringpair *find_subst(char *name,int length)
|
||||
stringpair *item;
|
||||
assert(name!=NULL);
|
||||
assert(length>0);
|
||||
assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_');
|
||||
item=substindex[(int)*name-'A'];
|
||||
assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
|
||||
item=substindex[(int)*name-PUBLIC_CHAR];
|
||||
if (item!=NULL)
|
||||
item=find_stringpair(item,name,length);
|
||||
|
||||
if (item && (item->flags & flgDEPRECATED) != 0) {
|
||||
static char macro[128];
|
||||
char *rem, *msg = (item->documentation != NULL) ? item->documentation : "";
|
||||
strncpy(macro, item->first, sizeof(macro));
|
||||
macro[sizeof(macro) - 1] = '\0';
|
||||
|
||||
/* If macro contains an opening parentheses and a percent sign, then assume that
|
||||
* it takes arguments and remove them from the warning message.
|
||||
*/
|
||||
if ((rem = strchr(macro, '(')) != NULL && strchr(macro, '%') > rem) {
|
||||
*rem = '\0';
|
||||
}
|
||||
|
||||
error(233, macro, msg); /* deprecated (macro/constant) */
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -296,8 +332,8 @@ SC_FUNC int delete_subst(char *name,int length)
|
||||
stringpair *item;
|
||||
assert(name!=NULL);
|
||||
assert(length>0);
|
||||
assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_');
|
||||
item=substindex[(int)*name-'A'];
|
||||
assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
|
||||
item=substindex[(int)*name-PUBLIC_CHAR];
|
||||
if (item!=NULL)
|
||||
item=find_stringpair(item,name,length);
|
||||
if (item==NULL)
|
||||
@ -318,7 +354,7 @@ SC_FUNC void delete_substtable(void)
|
||||
#endif /* !defined NO_SUBST */
|
||||
|
||||
|
||||
/* ----- input file list ----------------------------------------- */
|
||||
/* ----- input file list (explicit files)------------------------- */
|
||||
static stringlist sourcefiles = {NULL, NULL};
|
||||
|
||||
SC_FUNC stringlist *insert_sourcefile(char *string)
|
||||
@ -338,6 +374,28 @@ SC_FUNC void delete_sourcefiletable(void)
|
||||
}
|
||||
|
||||
|
||||
/* ----- parsed file list (explicit + included files) ------------ */
|
||||
static stringlist inputfiles = {NULL, NULL};
|
||||
|
||||
SC_FUNC stringlist *insert_inputfile(char *string)
|
||||
{
|
||||
if (sc_status!=statFIRST)
|
||||
return insert_string(&inputfiles,string);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SC_FUNC char *get_inputfile(int index)
|
||||
{
|
||||
return get_string(&inputfiles,index);
|
||||
}
|
||||
|
||||
SC_FUNC void delete_inputfiletable(void)
|
||||
{
|
||||
delete_stringtable(&inputfiles);
|
||||
assert(inputfiles.next==NULL);
|
||||
}
|
||||
|
||||
|
||||
/* ----- documentation tags -------------------------------------- */
|
||||
#if !defined SC_LIGHT
|
||||
static stringlist docstrings = {NULL, NULL};
|
||||
|
450
compiler/libpc300/scpack.c
Normal file
450
compiler/libpc300/scpack.c
Normal file
@ -0,0 +1,450 @@
|
||||
/* compress.c -- Byte Pair Encoding compression */
|
||||
/* Copyright 1996 Philip Gage */
|
||||
|
||||
/* This program appeared in the September 1997 issue of
|
||||
* C/C++ Users Journal. The original source code may still
|
||||
* be found at the web site of the magazine (www.cuj.com).
|
||||
*
|
||||
* It has been modified by me (Thiadmer Riemersma) to
|
||||
* compress only a section of the input file and to store
|
||||
* the compressed output along with the input as "C" strings.
|
||||
*
|
||||
* Compiling instructions:
|
||||
* Borland C++ 16-bit (large memory model is required):
|
||||
* bcc -ml scpack.c
|
||||
*
|
||||
* Watcom C/C++ 32-bit:
|
||||
* wcl386 scpack.c
|
||||
*
|
||||
* GNU C (Linux), 32-bit:
|
||||
* gcc scpack.c -o scpack
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if UINT_MAX > 0xFFFFU
|
||||
#define MAXSIZE 1024*1024L
|
||||
#else
|
||||
#define MAXSIZE UINT_MAX /* Input file buffer size */
|
||||
#endif
|
||||
#define HASHSIZE 8192 /* Hash table size, power of 2 */
|
||||
#define THRESHOLD 3 /* Increase for speed, min 3 */
|
||||
|
||||
#define START_TOKEN "#ifdef SCPACK" /* start reading the buffer here */
|
||||
#define NAME_TOKEN "#define SCPACK_TABLE"
|
||||
#define SEP_TOKEN "#define SCPACK_SEPARATOR"
|
||||
#define TERM_TOKEN "#define SCPACK_TERMINATOR"
|
||||
#define TEMPFILE "~SCPACK.TMP"
|
||||
static char tablename[32+1] = "scpack_table";
|
||||
static char separator[16]=",";
|
||||
static char terminator[16]="";
|
||||
|
||||
int compress(unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2])
|
||||
{
|
||||
unsigned char *left, *right, *count;
|
||||
unsigned char a, b, bestcount;
|
||||
unsigned i, j, index, bestindex, code=128;
|
||||
|
||||
/* Dynamically allocate buffers and check for errors */
|
||||
left = (unsigned char *)malloc(HASHSIZE);
|
||||
right = (unsigned char *)malloc(HASHSIZE);
|
||||
count = (unsigned char *)malloc(HASHSIZE);
|
||||
if (left==NULL || right==NULL || count==NULL) {
|
||||
printf("Error allocating memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check for errors */
|
||||
for (i=0; i<buffersize; i++)
|
||||
if (buffer[i] > 127) {
|
||||
printf("This program works only on text files (7-bit ASCII)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(pairtable, 0, 128*2*sizeof(char));
|
||||
|
||||
do { /* Replace frequent pairs with bytes 128..255 */
|
||||
|
||||
/* Enter counts of all byte pairs into hash table */
|
||||
memset(count,0,HASHSIZE);
|
||||
for (i=0; i<buffersize-1; i++) {
|
||||
a = buffer[i];
|
||||
b = buffer[i+1];
|
||||
/* ignore any pair with a '\0' */
|
||||
if (a == 0 || b == 0)
|
||||
continue;
|
||||
index = (a ^ (b << 6)) & (HASHSIZE-1);
|
||||
while ((left[index] != a || right[index] != b) &&
|
||||
count[index] != 0)
|
||||
index = (index + 1) & (HASHSIZE-1);
|
||||
left[index] = a;
|
||||
right[index] = b;
|
||||
if (count[index] < 255)
|
||||
count[index] += (unsigned char)1;
|
||||
}
|
||||
|
||||
/* Search hash table for most frequent pair */
|
||||
bestcount = THRESHOLD - 1;
|
||||
for (i=0; i<HASHSIZE; i++) {
|
||||
if (count[i] > bestcount) {
|
||||
bestcount = count[i];
|
||||
bestindex = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compress if enough occurrences of pair */
|
||||
if (bestcount >= THRESHOLD) {
|
||||
|
||||
/* Add pair to table using code as index */
|
||||
a = pairtable[code-128][0] = left[bestindex];
|
||||
b = pairtable[code-128][1] = right[bestindex];
|
||||
|
||||
/* Replace all pair occurrences with unused byte */
|
||||
for (i=0, j=0; i<buffersize; i++, j++)
|
||||
if (a == buffer[i] && b == buffer[i+1]) {
|
||||
buffer[j] = (unsigned char)code;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
buffer[j] = buffer[i];
|
||||
buffersize = j;
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while (++code < 255);
|
||||
|
||||
/* done */
|
||||
free(left); free(right); free(count);
|
||||
return buffersize; /* return adjusted buffersize */
|
||||
}
|
||||
|
||||
static int strmatch(char *str, char *token, int *indent)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* skip whitespace */
|
||||
while (*str==' ' || *str=='\t') {
|
||||
str++;
|
||||
i++;
|
||||
} /* while */
|
||||
if (strncmp(str,token,strlen(token))!=0)
|
||||
return 0;
|
||||
if (indent != NULL)
|
||||
*indent = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void check_if(char *str,int linenr)
|
||||
{
|
||||
if (strmatch(str,"#if",NULL)) {
|
||||
printf("Error: \"#if...\" preprocessor statement should not be in SCPACK section "
|
||||
"(line %d)\n", linenr);
|
||||
exit(1);
|
||||
} /* if */
|
||||
}
|
||||
|
||||
static int check_tablename(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strmatch(str,NAME_TOKEN,NULL)) {
|
||||
str += strlen(NAME_TOKEN);
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
for (i=0; i<(sizeof tablename - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
|
||||
tablename[i] = *str;
|
||||
tablename[i] = '\0';
|
||||
return 1;
|
||||
} /* if */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_separator(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strmatch(str,SEP_TOKEN,NULL)) {
|
||||
str += strlen(SEP_TOKEN);
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
for (i=0; i<(sizeof separator - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
|
||||
separator[i] = *str;
|
||||
separator[i] = '\0';
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (strmatch(str,TERM_TOKEN,NULL)) {
|
||||
str += strlen(TERM_TOKEN);
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
for (i=0; i<(sizeof terminator - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
|
||||
terminator[i] = *str;
|
||||
terminator[i] = '\0';
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* readbuffer
|
||||
* Reads in the input file and stores all strings in the
|
||||
* section between "#ifdef SCPACK" and "#else" in a buffer.
|
||||
* Only text that is between double quotes is added to the
|
||||
* buffer; the \" escape code is handled. Multiple strings
|
||||
* on one line are handled.
|
||||
*/
|
||||
unsigned readbuffer(FILE *input, unsigned char *buffer)
|
||||
{
|
||||
char str[256];
|
||||
unsigned buffersize;
|
||||
int i,linenr;
|
||||
|
||||
linenr=0;
|
||||
buffersize=0;
|
||||
|
||||
rewind(input);
|
||||
while (!feof(input)) {
|
||||
while (fgets(str,sizeof str,input)!=NULL) {
|
||||
linenr++;
|
||||
check_tablename(str);
|
||||
check_separator(str);
|
||||
if (strmatch(str,START_TOKEN,NULL))
|
||||
break;
|
||||
} /* while */
|
||||
if (!strmatch(str,START_TOKEN,NULL))
|
||||
return buffersize; /* no (more) section found, quit */
|
||||
|
||||
while (fgets(str,sizeof str,input)!=NULL) {
|
||||
linenr++;
|
||||
check_if(str,linenr);
|
||||
if (check_tablename(str))
|
||||
printf("Error: table name definition should not be in SCPACK section (line %d)\n", linenr);
|
||||
check_separator(str);
|
||||
if (strmatch(str,"#else",NULL))
|
||||
break; /* done */
|
||||
/* add to the buffer only what is between double quotes */
|
||||
i=0;
|
||||
do {
|
||||
while (str[i]!='\0' && str[i]!='"')
|
||||
i++;
|
||||
if (str[i]=='"') {
|
||||
/* we are in a string */
|
||||
i++;
|
||||
while (str[i]!='\0' && str[i]!='"') {
|
||||
/* handle escape sequences */
|
||||
if (str[i]=='\\') {
|
||||
i++;
|
||||
switch (str[i]) {
|
||||
case 'a': /* alarm */
|
||||
buffer[buffersize++]='\a';
|
||||
i++;
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
buffer[buffersize++]='\b';
|
||||
i++;
|
||||
break;
|
||||
case 'f': /* form feed */
|
||||
buffer[buffersize++]='\f';
|
||||
i++;
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
buffer[buffersize++]='\n';
|
||||
i++;
|
||||
break;
|
||||
case 'r': /* carriage return */
|
||||
buffer[buffersize++]='\n';
|
||||
i++;
|
||||
break;
|
||||
case 't': /* tab */
|
||||
buffer[buffersize++]='\t';
|
||||
i++;
|
||||
break;
|
||||
case '\'':
|
||||
buffer[buffersize++]='\'';
|
||||
i++;
|
||||
break;
|
||||
case '"':
|
||||
buffer[buffersize++]='"';
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
// ??? octal character code escapes and hexadecimal escapes
|
||||
// not supported
|
||||
printf("Unknown escape sequence '\\%c' on line %d\n",
|
||||
str[i], linenr);
|
||||
} /* switch */
|
||||
} else {
|
||||
buffer[buffersize++]=str[i++];
|
||||
} /* if */
|
||||
} /* while */
|
||||
if (str[i]=='"') {
|
||||
buffer[buffersize++]='\0'; /* terminate each string */
|
||||
i++;
|
||||
} else {
|
||||
printf("Error: unterminated string on line %d\n",linenr);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} while (str[i]!='\0');
|
||||
} /* while - in SCPACK section */
|
||||
/* put in another '\0' to terminate the section */
|
||||
buffer[buffersize++]='\0';
|
||||
} /* while - !feof(input) */
|
||||
return buffersize;
|
||||
}
|
||||
|
||||
static void write_pairtable(FILE *output, unsigned char pairtable[128][2], char *tablename)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* dump the pair table */
|
||||
fprintf(output, "/*-*SCPACK start of pair table, do not change or remove this line */\n");
|
||||
fprintf(output, "unsigned char %s[][2] = {", tablename);
|
||||
for (i=0; i<128 && pairtable[i][0]!=0 && pairtable[i][1]!=0; i++) {
|
||||
if ((i % 16)==0)
|
||||
fprintf(output, "\n ");
|
||||
else
|
||||
fprintf(output, " ");
|
||||
fprintf(output, "{%d,%d}", pairtable[i][0], pairtable[i][1]);
|
||||
/* check if something follows this pair */
|
||||
if (i+1<128 && pairtable[i+1][0]!=0 && pairtable[i+1][1]!=0)
|
||||
fprintf(output, ",");
|
||||
} /* for */
|
||||
fprintf(output, "\n};\n");
|
||||
fprintf(output, "/*-*SCPACK end of pair table, do not change or remove this line */\n");
|
||||
}
|
||||
|
||||
void writefile(FILE *input, FILE *output, unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2])
|
||||
{
|
||||
char str[256];
|
||||
int insection, indent, needseparator;
|
||||
unsigned char *bufptr;
|
||||
|
||||
bufptr = buffer;
|
||||
insection = 0;
|
||||
|
||||
rewind(input);
|
||||
while (!feof(input)) {
|
||||
while (fgets(str,sizeof str,input)!=NULL) {
|
||||
fprintf(output,"%s",str);
|
||||
if (check_tablename(str)) {
|
||||
write_pairtable(output, pairtable, tablename);
|
||||
/* strip an existing pair table from the file */
|
||||
if (fgets(str,sizeof str,input)!=NULL) {
|
||||
if (strmatch(str,"/*-*SCPACK",NULL)) {
|
||||
while (fgets(str,sizeof str,input)!=NULL)
|
||||
if (strmatch(str,"/*-*SCPACK",NULL))
|
||||
break;
|
||||
} else {
|
||||
fprintf(output,"%s",str);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
if (strmatch(str,START_TOKEN,NULL))
|
||||
insection = 1;
|
||||
if (insection && strmatch(str,"#else",NULL))
|
||||
break;
|
||||
} /* while */
|
||||
if (!strmatch(str,"#else",&indent))
|
||||
return; /* no (more) section found, quit */
|
||||
insection=0;
|
||||
|
||||
/* dump the buffer as strings, separated with commas */
|
||||
needseparator = 0;
|
||||
while (*bufptr != '\0') {
|
||||
assert((unsigned)(bufptr-buffer) < buffersize);
|
||||
if (needseparator)
|
||||
fprintf(output, "%s\n",separator);
|
||||
fprintf(output, "%*c\"",indent+2,' ');
|
||||
/* loop over string */
|
||||
while (*bufptr != '\0') {
|
||||
if (*bufptr<' ' || *bufptr >= 128 || *bufptr == '"' || *bufptr == '\\')
|
||||
fprintf(output, "\\%03o", *bufptr);
|
||||
else
|
||||
fprintf(output, "%c", *bufptr);
|
||||
bufptr++;
|
||||
} /* while */
|
||||
fprintf(output, "\"");
|
||||
needseparator = 1;
|
||||
bufptr++; /* skip '\0' */
|
||||
} /* while */
|
||||
fprintf(output, "%s\n",terminator);
|
||||
bufptr++;
|
||||
|
||||
/* skip the input file until the #endif section */
|
||||
while (fgets(str,sizeof str,input)!=NULL) {
|
||||
if (strmatch(str,"#endif",NULL)) {
|
||||
fprintf(output,"%s",str);
|
||||
break; /* done */
|
||||
} /* if */
|
||||
} /* while */
|
||||
} /* while - !feof(input) */
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: scpack <filename> [output file]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *in, *out;
|
||||
unsigned char *buffer;
|
||||
unsigned buffersize, orgbuffersize;
|
||||
unsigned char pairtable[128][2];
|
||||
|
||||
if (argc < 2 || argc > 3)
|
||||
usage();
|
||||
if ((in=fopen(argv[1],"rt"))==NULL) {
|
||||
printf("SCPACK: error opening input %s\n",argv[1]);
|
||||
usage();
|
||||
} /* if */
|
||||
if (argc == 2) {
|
||||
if ((out=fopen(TEMPFILE,"wt"))==NULL) {
|
||||
printf("SCPACK: error opening temporary file %s\n",TEMPFILE);
|
||||
usage();
|
||||
} /* if */
|
||||
} else {
|
||||
if ((out=fopen(argv[2],"wt"))==NULL) {
|
||||
printf("SCPACK: error opening output file %s\n",argv[2]);
|
||||
usage();
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
buffer = (unsigned char *)malloc(MAXSIZE);
|
||||
if (buffer == NULL) {
|
||||
printf("SCPACK: error allocating memory\n");
|
||||
return 1;
|
||||
} /* if */
|
||||
/* 1. read the buffer
|
||||
* 2. compress the buffer
|
||||
* 3. copy the file, insert the compressed buffer
|
||||
*/
|
||||
buffersize = readbuffer(in, buffer);
|
||||
orgbuffersize = buffersize;
|
||||
if (buffersize > 0) {
|
||||
buffersize = compress(buffer, buffersize, pairtable);
|
||||
writefile(in, out, buffer, buffersize, pairtable);
|
||||
printf("SCPACK: compression ratio: %ld%% (%d -> %d)\n",
|
||||
100L-(100L*buffersize)/orgbuffersize, orgbuffersize, buffersize);
|
||||
} else {
|
||||
printf("SCPACK: no SCPACK section found, nothing to do\n");
|
||||
} /* if */
|
||||
fclose(out);
|
||||
fclose(in);
|
||||
/* let the new file replace the old file */
|
||||
if (buffersize == 0) {
|
||||
if (argc == 2)
|
||||
remove(TEMPFILE);
|
||||
else
|
||||
remove(argv[2]);
|
||||
} else if (argc == 2) {
|
||||
remove(argv[1]);
|
||||
rename(TEMPFILE,argv[1]);
|
||||
} /* if */
|
||||
return 0;
|
||||
}
|
@ -24,6 +24,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for _MAX_PATH */
|
||||
#include "sc.h"
|
||||
#include "sp_symhash.h"
|
||||
|
||||
/* global variables
|
||||
*
|
||||
@ -84,6 +85,7 @@ SC_VDEFINE int sc_rationaltag=0; /* tag for rational numbers */
|
||||
SC_VDEFINE int rational_digits=0; /* number of fractional digits */
|
||||
SC_VDEFINE int sc_allowproccall=0; /* allow/detect tagnames in lex() */
|
||||
SC_VDEFINE short sc_is_utf8=FALSE; /* is this source file in UTF-8 encoding */
|
||||
SC_VDEFINE char *pc_deprecate = NULL;/* if non-null, mark next declaration as deprecated */
|
||||
SC_VDEFINE int sc_showincludes=0; /* show include files */
|
||||
|
||||
SC_VDEFINE constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */
|
||||
@ -95,6 +97,8 @@ SC_VDEFINE FILE *outf = NULL; /* (intermediate) text file written to */
|
||||
|
||||
SC_VDEFINE jmp_buf errbuf;
|
||||
|
||||
SC_VDEFINE HashTable *sp_Globals = NULL;
|
||||
|
||||
#if !defined SC_LIGHT
|
||||
SC_VDEFINE int sc_makereport=FALSE; /* generate a cross-reference report */
|
||||
#endif
|
||||
|
229
compiler/libpc300/sp_symhash.c
Normal file
229
compiler/libpc300/sp_symhash.c
Normal file
@ -0,0 +1,229 @@
|
||||
/* vim: set ts=4 sw=4 tw=99 et: */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "sc.h"
|
||||
#include "sp_symhash.h"
|
||||
|
||||
SC_FUNC uint32_t
|
||||
NameHash(const char *str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
const uint8_t *data = (uint8_t *)str;
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
uint32_t hash = len, tmp;
|
||||
int rem;
|
||||
|
||||
if (len <= 0 || data == NULL) return 0;
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += get16bits (data);
|
||||
tmp = (get16bits (data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof (uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += get16bits (data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof (uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += get16bits (data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
|
||||
#undef get16bits
|
||||
}
|
||||
|
||||
SC_FUNC HashTable *NewHashTable()
|
||||
{
|
||||
HashTable *ht = (HashTable*)malloc(sizeof(HashTable));
|
||||
if (!ht)
|
||||
return ht;
|
||||
ht->buckets = (HashEntry **)calloc(32, sizeof(HashEntry *));
|
||||
if (!ht->buckets) {
|
||||
free(ht);
|
||||
return NULL;
|
||||
}
|
||||
ht->nbuckets = 32;
|
||||
ht->nused = 0;
|
||||
ht->bucketmask = 32 - 1;
|
||||
return ht;
|
||||
}
|
||||
|
||||
SC_FUNC void
|
||||
DestroyHashTable(HashTable *ht)
|
||||
{
|
||||
uint32_t i;
|
||||
if (!ht)
|
||||
return;
|
||||
for (i = 0; i < ht->nbuckets; i++) {
|
||||
HashEntry *he = ht->buckets[i];
|
||||
while (he != NULL) {
|
||||
HashEntry *next = he->next;
|
||||
free(he);
|
||||
he = next;
|
||||
}
|
||||
}
|
||||
free(ht->buckets);
|
||||
free(ht);
|
||||
}
|
||||
|
||||
SC_FUNC symbol *
|
||||
FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber,
|
||||
int *cmptag)
|
||||
{
|
||||
int count=0;
|
||||
symbol *firstmatch=NULL;
|
||||
uint32_t hash = NameHash(name);
|
||||
uint32_t bucket = hash & ht->bucketmask;
|
||||
HashEntry *he = ht->buckets[bucket];
|
||||
|
||||
assert(cmptag!=NULL);
|
||||
|
||||
while (he != NULL) {
|
||||
symbol *sym = he->sym;
|
||||
if ((sym->parent==NULL || sym->ident==iCONSTEXPR) &&
|
||||
(sym->fnumber<0 || sym->fnumber==fnumber) &&
|
||||
(strcmp(sym->name, name) == 0))
|
||||
{
|
||||
/* return closest match or first match; count number of matches */
|
||||
if (firstmatch==NULL)
|
||||
firstmatch=sym;
|
||||
if (*cmptag==0)
|
||||
count++;
|
||||
if (*cmptag==sym->tag) {
|
||||
*cmptag=1; /* good match found, set number of matches to 1 */
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
he = he->next;
|
||||
}
|
||||
|
||||
if (firstmatch!=NULL)
|
||||
*cmptag=count;
|
||||
return firstmatch;
|
||||
}
|
||||
|
||||
SC_FUNC symbol *
|
||||
FindInHashTable(HashTable *ht, const char *name, int fnumber)
|
||||
{
|
||||
uint32_t hash = NameHash(name);
|
||||
uint32_t bucket = hash & ht->bucketmask;
|
||||
HashEntry *he = ht->buckets[bucket];
|
||||
|
||||
while (he != NULL) {
|
||||
symbol *sym = he->sym;
|
||||
if ((sym->parent==NULL || sym->ident==iCONSTEXPR) &&
|
||||
(sym->fnumber<0 || sym->fnumber==fnumber) &&
|
||||
(strcmp(sym->name, name) == 0))
|
||||
{
|
||||
return sym;
|
||||
}
|
||||
he = he->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ResizeHashTable(HashTable *ht)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t xnbuckets = ht->nbuckets * 2;
|
||||
uint32_t xbucketmask = xnbuckets - 1;
|
||||
HashEntry **xbuckets = (HashEntry **)calloc(xnbuckets, sizeof(HashEntry*));
|
||||
if (!xbuckets)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ht->nbuckets; i++) {
|
||||
HashEntry *he = ht->buckets[i];
|
||||
while (he != NULL) {
|
||||
HashEntry *next = he->next;
|
||||
uint32_t bucket = he->sym->hash & xbucketmask;
|
||||
he->next = xbuckets[bucket];
|
||||
xbuckets[bucket] = he;
|
||||
he = next;
|
||||
}
|
||||
}
|
||||
free(ht->buckets);
|
||||
ht->buckets = xbuckets;
|
||||
ht->nbuckets = xnbuckets;
|
||||
ht->bucketmask = xbucketmask;
|
||||
}
|
||||
|
||||
SC_FUNC void
|
||||
AddToHashTable(HashTable *ht, symbol *sym)
|
||||
{
|
||||
uint32_t bucket = sym->hash & ht->bucketmask;
|
||||
HashEntry **hep, *he;
|
||||
|
||||
hep = &ht->buckets[bucket];
|
||||
while (*hep) {
|
||||
assert((*hep)->sym != sym);
|
||||
hep = &(*hep)->next;
|
||||
}
|
||||
|
||||
he = (HashEntry *)malloc(sizeof(HashEntry));
|
||||
if (!he)
|
||||
error(163);
|
||||
he->sym = sym;
|
||||
he->next = NULL;
|
||||
*hep = he;
|
||||
ht->nused++;
|
||||
|
||||
if (ht->nused > ht->nbuckets && ht->nbuckets <= INT_MAX / 2)
|
||||
ResizeHashTable(ht);
|
||||
}
|
||||
|
||||
SC_FUNC void
|
||||
RemoveFromHashTable(HashTable *ht, symbol *sym)
|
||||
{
|
||||
uint32_t bucket = sym->hash & ht->bucketmask;
|
||||
HashEntry **hep = &ht->buckets[bucket];
|
||||
HashEntry *he = *hep;
|
||||
|
||||
while (he != NULL) {
|
||||
if (he->sym == sym) {
|
||||
*hep = he->next;
|
||||
free(he);
|
||||
ht->nused--;
|
||||
return;
|
||||
}
|
||||
hep = &he->next;
|
||||
he = *hep;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
28
compiler/libpc300/sp_symhash.h
Normal file
28
compiler/libpc300/sp_symhash.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* vim: set ts=4 sw=4 tw=99 et: */
|
||||
#ifndef _INCLUDE_SPCOMP_SYMHASH_H_
|
||||
#define _INCLUDE_SPCOMP_SYMHASH_H_
|
||||
|
||||
SC_FUNC uint32_t NameHash(const char *str);
|
||||
|
||||
typedef struct HashEntry {
|
||||
symbol *sym;
|
||||
struct HashEntry *next;
|
||||
} HashEntry;
|
||||
|
||||
struct HashTable {
|
||||
uint32_t nbuckets;
|
||||
uint32_t nused;
|
||||
uint32_t bucketmask;
|
||||
HashEntry **buckets;
|
||||
};
|
||||
|
||||
SC_FUNC HashTable *NewHashTable();
|
||||
SC_FUNC void DestroyHashTable(HashTable *ht);
|
||||
SC_FUNC void AddToHashTable(HashTable *ht, symbol *sym);
|
||||
SC_FUNC void RemoveFromHashTable(HashTable *ht, symbol *sym);
|
||||
SC_FUNC symbol *FindInHashTable(HashTable *ht, const char *name, int fnumber);
|
||||
SC_FUNC symbol *FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber,
|
||||
int *cmptag);
|
||||
|
||||
#endif /* _INCLUDE_SPCOMP_SYMHASH_H_ */
|
||||
|
@ -2535,6 +2535,7 @@ native plugin_flags(hdr=0, plid=-1);
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
#pragma deprecated Module dependency is now automatically handled by the compiler. This forward is no longer called.
|
||||
forward plugin_modules();
|
||||
|
||||
/**
|
||||
@ -2545,6 +2546,7 @@ forward plugin_modules();
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
#pragma deprecated Module dependency is now automatically handled by the compiler. This native has no effect.
|
||||
native require_module(const module[]);
|
||||
|
||||
/**
|
||||
@ -2556,6 +2558,7 @@ native require_module(const module[]);
|
||||
*
|
||||
* @return 1 if the server is 64 bit, 0 otherwise
|
||||
*/
|
||||
#pragma deprecated AMXX is not shipping 64bits builds anymore. This native is basically guaranteed to return 0.
|
||||
native is_amd64_server();
|
||||
|
||||
/**
|
||||
|
@ -62,7 +62,7 @@ native bool:geoip_code3_ex(const ip[], result[4]);
|
||||
*
|
||||
* @return 1 on a successful lookup, 0 otherwise.
|
||||
*/
|
||||
//#pragma deprecated Use geoip_code2_ex() instead.
|
||||
#pragma deprecated Use geoip_code2_ex() instead.
|
||||
native geoip_code2(const ip[], ccode[3]);
|
||||
|
||||
/**
|
||||
@ -76,7 +76,7 @@ native geoip_code2(const ip[], ccode[3]);
|
||||
*
|
||||
* @return 1 on a successful lookup, 0 otherwise.
|
||||
*/
|
||||
//#pragma deprecated Use geoip_code3() instead.
|
||||
#pragma deprecated Use geoip_code3() instead.
|
||||
native geoip_code3(const ip[], result[4]);
|
||||
|
||||
/**
|
||||
|
@ -543,6 +543,7 @@ forward client_spawn(id);
|
||||
* @param Damage The amount of damage being done.
|
||||
* @param DamageType The damage type being done (bitmask).
|
||||
*/
|
||||
#pragma deprecated It is suggested to use hamsandwich for this action instead.
|
||||
native ns_takedamage(IDVictim, IDInflictor, IDAttacker, Float:Damage, DamageType);
|
||||
|
||||
/**
|
||||
|
@ -711,7 +711,7 @@ native strncmp(const string1[], const string2[], num, bool:ignorecase=false);
|
||||
* Backwards compatibility stock - use argbreak or argparse.
|
||||
* @deprecated this function does not work properly.
|
||||
*/
|
||||
//#pragma deprecated Use argbreak() instead
|
||||
#pragma deprecated Use argbreak() instead
|
||||
stock strbreak(const text[], Left[], leftLen, Right[], rightLen)
|
||||
{
|
||||
return argbreak(text, Left, leftLen, Right, rightLen);
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <amxmodx>
|
||||
#include <amxmisc>
|
||||
|
||||
#pragma tabsize 0
|
||||
#pragma tabsize 4
|
||||
|
||||
new g_TeamOneAck[12];
|
||||
new g_TeamTwoAck[12];
|
||||
|
Loading…
Reference in New Issue
Block a user