Use upstream SourcePawn as a submodule.

This commit is contained in:
David Anderson 2015-03-08 12:37:10 -07:00
parent 7f24f137d6
commit 2ab3498ab0
276 changed files with 29 additions and 52221 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "public/amtl"]
path = public/amtl
url = https://github.com/alliedmodders/amtl
[submodule "sourcepawn"]
path = sourcepawn
url = https://github.com/alliedmodders/sourcepawn

View File

@ -226,7 +226,6 @@ class SMConfig(object):
]
cxx.linkflags += [
'/MACHINE:X86',
'/SUBSYSTEM:WINDOWS',
'kernel32.lib',
'user32.lib',
'gdi32.lib',
@ -286,10 +285,15 @@ class SMConfig(object):
'SOURCEMOD_BUILD',
'SM_USE_VERSIONLIB',
]
cxx.includes += [
os.path.join(builder.sourcePath, 'public'),
]
if self.use_auto_versioning():
cxx.defines += ['SM_GENERATED_BUILD']
cxx.includes += [os.path.join(builder.buildPath, 'includes')]
cxx.includes += [os.path.join(builder.sourcePath, 'versionlib')]
cxx.includes += [
os.path.join(builder.buildPath, 'includes'),
os.path.join(builder.sourcePath, 'versionlib'),
]
def AddVersioning(self, binary):
if builder.target_platform == 'windows':
@ -313,17 +317,20 @@ class SMConfig(object):
def Library(self, context, name):
binary = context.compiler.Library(name)
if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
return self.AddVersioning(binary)
def Program(self, context, name):
binary = context.compiler.Program(name)
if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE']
return self.AddVersioning(binary)
def ConfigureForExtension(self, context, compiler):
compiler.cxxincludes += [
os.path.join(context.currentSourcePath),
os.path.join(context.currentSourcePath, 'sdk'),
os.path.join(builder.sourcePath, 'public'),
os.path.join(builder.sourcePath, 'public', 'extensions'),
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
os.path.join(builder.sourcePath, 'public', 'amtl', 'include'),
@ -491,6 +498,19 @@ if SM.use_auto_versioning():
{ 'SM': SM }
)
# Build SourcePawn externally.
with builder.Context('sourcepawn') as context:
SourcePawn = builder.RunScript('sourcepawn/AMBuildScript', {})
SP = SourcePawn(
root = SM,
amtl = os.path.join(builder.sourcePath, 'public', 'amtl'),
)
SP.BuildCore()
SM.spcomp = SP.spcomp
SM.binaries += [
SP.libsourcepawn
]
BuildScripts = [
'loader/AMBuilder',
'core/AMBuilder',
@ -508,8 +528,6 @@ BuildScripts = [
'extensions/tf2/AMBuilder',
'extensions/topmenus/AMBuilder',
'extensions/updater/AMBuilder',
'sourcepawn/compiler/AMBuilder',
'sourcepawn/vm/AMBuilder',
]
if builder.backend == 'amb2':

1
sourcepawn Submodule

@ -0,0 +1 @@
Subproject commit 1b3062875df9121a3fd553673b1a6c6c412d9b08

View File

@ -1,79 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
binary = SM.Program(builder, 'spcomp')
compiler = binary.compiler
compiler.includes += [
os.path.join(builder.sourcePath, 'public'),
os.path.join(builder.sourcePath, 'public', 'amtl', 'include'),
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
os.path.join(builder.currentSourcePath, '..', 'include'),
os.path.join(builder.currentSourcePath, '..', 'third_party'),
os.path.join(builder.buildPath, 'includes'),
os.path.join(builder.buildPath, builder.buildFolder),
]
if compiler.cc.behavior == 'gcc':
compiler.cflags += ['-Wno-format']
compiler.c_only_flags += ['-std=c99']
if builder.target_platform == 'linux':
compiler.postlink += ['-lm']
compiler.postlink += ['-lstdc++']
elif compiler.cc.behavior == 'msvc':
compiler.linkflags.remove('/SUBSYSTEM:WINDOWS')
compiler.linkflags.append('/SUBSYSTEM:CONSOLE')
compiler.cxxflags.remove('/TP')
compiler.defines += ['HAVE_STDINT_H']
if builder.target_platform == 'linux':
compiler.defines += [
'LINUX',
'AMX_ANSIONLY',
'ENABLE_BINRELOC',
'_GNU_SOURCE'
]
elif builder.target_platform == 'mac':
compiler.defines += [
'DARWIN',
'AMX_ANSIONLY',
'ENABLE_BINRELOC',
'HAVE_SAFESTR'
]
binary.sources += [
'libpawnc.cpp',
'lstring.cpp',
'memfile.cpp',
'pawncc.cpp',
'sc1.cpp',
'sc2.cpp',
'sc3.cpp',
'sc4.cpp',
'sc5.cpp',
'sc6.cpp',
'sc7.cpp',
'sci18n.cpp',
'sclist.cpp',
'scmemfil.cpp',
'scstate.cpp',
'sctracker.cpp',
'scvars.cpp',
'smx-builder.cpp',
'sp_symhash.cpp',
'../third_party/zlib/adler32.c',
'../third_party/zlib/compress.c',
'../third_party/zlib/crc32.c',
'../third_party/zlib/deflate.c',
'../third_party/zlib/gzio.c',
'../third_party/zlib/infback.c',
'../third_party/zlib/inffast.c',
'../third_party/zlib/inflate.c',
'../third_party/zlib/inftrees.c',
'../third_party/zlib/trees.c',
'../third_party/zlib/uncompr.c',
'../third_party/zlib/zutil.c',
]
if builder.target_platform != 'windows':
binary.sources.append('binreloc.c')
SM.spcomp = builder.Add(binary)

View File

@ -1,74 +0,0 @@
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
SMSDK = ../..
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
BINARY = spcomp
OBJECTS = binreloc.c libpawnc.c lstring.c memfile.c pawncc.c sc1.c sc2.c sc3.c sc4.c \
sc5.c sc6.c sc7.c scexpand.c sci18n.c sclist.c scmemfil.c scstate.c sctracker.c \
scvars.c sp_file.c sp_symhash.c
OBJECTS += zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/deflate.c zlib/gzio.c \
zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \
zlib/uncompr.c zlib/zutil.c
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing -fomit-frame-pointer
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc
LINK = -lgcc -static-libgcc
INCLUDE = -I. -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
CFLAGS += -D_GNU_SOURCE -Wall -Werror -Wno-uninitialized -Wno-unused-result -Wno-unused -Wno-switch -Wno-parentheses -Wno-format -DLINUX -DHAVE_STDINT_H -DAMX_ANSIONLY -DENABLE_BINRELOC -Dstricmp=strcasecmp -m32
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS += $(C_OPT_FLAGS)
endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
OBJ_LINUX := $(OBJECTS:%.c=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)/zlib
$(MAKE) -f Makefile compiler
compiler: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -ldl -lm -o $(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f Makefile all DEBUG=true
default: all
clean:
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/zlib/*.o
rm -rf $(BIN_DIR)/$(BINARY)

View File

@ -1,634 +0,0 @@
/* Pawn Abstract Machine (for the Pawn language)
*
* Copyright (c) ITB CompuPhase, 1997-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#ifndef AMX_H_INCLUDED
#define AMX_H_INCLUDED
#include <stdlib.h> /* for size_t */
#include <limits.h>
#if defined FREEBSD && !defined __FreeBSD__
#define __FreeBSD__
#endif
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
#include "sclinux.h"
#endif
#if defined HAVE_STDINT_H
# include <stddef.h>
# include <stdint.h>
#endif
#if defined __GNUC__
#if !defined HAVE_STDINT_H
#define HAVE_STDINT_H
#endif
#elif !defined HAVE_STDINT_H
#if defined __LCC__ || defined __DMC__ || defined LINUX || (defined __WATCOMC__ && __WATCOMC__ >= 1200)
#if defined HAVE_INTTYPES_H
#include <inttypes.h>
#else
#include <stdint.h>
#endif
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
/* The ISO C99 defines the int16_t and int_32t types. If the compiler got
* here, these types are probably undefined.
*/
#if defined __MACH__
#include <ppc/types.h>
typedef unsigned short int uint16_t;
typedef unsigned long int uint32_t;
#elif defined __FreeBSD__
#include <inttypes.h>
#else
typedef short int int16_t;
typedef unsigned short int uint16_t;
#if defined SN_TARGET_PS2
typedef int int32_t;
typedef unsigned int uint32_t;
#else
typedef long int int32_t;
typedef unsigned long int uint32_t;
#endif
#if defined __WIN32__ || defined _WIN32 || defined WIN32
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define HAVE_I64
#elif defined __GNUC__
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define HAVE_I64
#endif
#endif
#endif
#define HAVE_STDINT_H
#endif
#if defined _LP64 || defined WIN64 || defined _WIN64
#if !defined __64BIT__
#define __64BIT__
#endif
#endif
#if HAVE_ALLOCA_H
#include <alloca.h>
#endif
#if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */
#if !defined alloca
#define alloca(n) _alloca(n)
#endif
#endif
#if !defined arraysize
#define arraysize(array) (sizeof(array) / sizeof((array)[0]))
#endif
#if !defined assert_static
/* see "Compile-Time Assertions" by Ralf Holly,
* C/C++ Users Journal, November 2004
*/
#define assert_static(e) \
do { \
enum { assert_static__ = 1/(e) }; \
} while (0)
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined PAWN_DLL
#if !defined AMX_NATIVE_CALL
#define AMX_NATIVE_CALL __stdcall
#endif
#if !defined AMXAPI
#define AMXAPI __stdcall
#endif
#endif
/* calling convention for native functions */
#if !defined AMX_NATIVE_CALL
#define AMX_NATIVE_CALL
#endif
/* calling convention for all interface functions and callback functions */
#if !defined AMXAPI
#if defined STDECL
#define AMXAPI __stdcall
#elif defined CDECL
#define AMXAPI __cdecl
#elif defined GCC_HASCLASSVISIBILITY
#define AMXAPI __attribute__ ((visibility("default")))
#else
#define AMXAPI
#endif
#endif
#if !defined AMXEXPORT
#define AMXEXPORT
#endif
/* File format version (in CUR_FILE_VERSION)
* 0 (original version)
* 1 (opcodes JUMP.pri, SWITCH and CASETBL)
* 2 (compressed files)
* 3 (public variables)
* 4 (opcodes SWAP.pri/alt and PUSHADDR)
* 5 (tagnames table)
* 6 (reformatted header)
* 7 (name table, opcodes SYMTAG & SYSREQ.D)
* 8 (opcode STMT, renewed debug interface)
* 9 (macro opcodes)
* MIN_FILE_VERSION is the lowest file version number that the current AMX
* implementation supports. If the AMX file header gets new fields, this number
* often needs to be incremented. MAX_AMX_VERSION is the lowest AMX version that
* is needed to support the current file version. When there are new opcodes,
* this number needs to be incremented.
* The file version supported by the JIT may run behind MIN_AMX_VERSION. So
* there is an extra constant for it: MAX_FILE_VER_JIT.
*/
#define CUR_FILE_VERSION 9 /* current file version; also the current AMX version */
#define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */
#define MIN_AMX_VERSION 9 /* minimum AMX version needed to support the current file format */
#define MAX_FILE_VER_JIT 8 /* file version supported by the JIT */
#define MIN_AMX_VER_JIT 8 /* AMX version supported by the JIT */
#if !defined PAWN_CELL_SIZE
#define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */
#endif
#if PAWN_CELL_SIZE==16
typedef uint16_t ucell;
typedef int16_t cell;
#elif PAWN_CELL_SIZE==32
typedef uint32_t ucell;
typedef int32_t cell;
#elif PAWN_CELL_SIZE==64
typedef uint64_t ucell;
typedef int64_t cell;
#else
#error Unsupported cell size (PAWN_CELL_SIZE)
#endif
#define UNPACKEDMAX (((cell)1 << (sizeof(cell)-1)*8) - 1)
#define UNLIMITED (~1u >> 1)
struct tagAMX;
typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
cell *result, cell *params);
typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX *, cell *, int));
#if !defined _FAR
#define _FAR
#endif
#if defined _MSC_VER
#pragma warning(disable:4103) /* disable warning message 4103 that complains
* about pragma pack in a header file */
#pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */
#endif
/* Some compilers do not support the #pragma align, which should be fine. Some
* compilers give a warning on unknown #pragmas, which is not so fine...
*/
#if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN
#define AMX_NO_ALIGN
#endif
#if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */
#elif defined MACOS && defined __MWERKS__
#pragma options align=mac68k
#else
#pragma pack(push)
#pragma pack(1) /* structures must be packed (byte-aligned) */
#if defined __TURBOC__
#pragma option -a- /* "pack" pragma for older Borland compilers */
#endif
#endif
#endif
typedef struct tagAMX_NATIVE_INFO {
const char _FAR *name;
AMX_NATIVE func;
} AMX_NATIVE_INFO;
#define AMX_USERNUM 4
#define sEXPMAX 19 /* maximum name length for file version <= 6 */
#define sNAMEMAX 63 /* maximum name length of symbol name */
typedef struct tagAMX_FUNCSTUB {
ucell address;
char name[sEXPMAX+1];
} AMX_FUNCSTUB;
typedef struct tagFUNCSTUBNT {
ucell address;
uint32_t nameofs;
} AMX_FUNCSTUBNT;
/* The AMX structure is the internal structure for many functions. Not all
* fields are valid at all times; many fields are cached in local variables.
*/
typedef struct tagAMX {
unsigned char _FAR *base; /* points to the AMX header plus the code, optionally also the data */
unsigned char _FAR *data; /* points to separate data+stack+heap, may be NULL */
AMX_CALLBACK callback;
AMX_DEBUG debug ; /* debug callback */
/* for external functions a few registers must be accessible from the outside */
cell cip ; /* instruction pointer: relative to base + amxhdr->cod */
cell frm ; /* stack frame base: relative to base + amxhdr->dat */
cell hea ; /* top of the heap: relative to base + amxhdr->dat */
cell hlw ; /* bottom of the heap: relative to base + amxhdr->dat */
cell stk ; /* stack pointer: relative to base + amxhdr->dat */
cell stp ; /* top of the stack: relative to base + amxhdr->dat */
int flags ; /* current status, see amx_Flags() */
/* user data */
long usertags[AMX_USERNUM] ;
void _FAR *userdata[AMX_USERNUM] ;
/* native functions can raise an error */
int error ;
/* passing parameters requires a "count" field */
int paramcount;
/* the sleep opcode needs to store the full AMX status */
cell pri ;
cell alt ;
cell reset_stk ;
cell reset_hea ;
/* extra fields for increased performance */
cell sysreq_d ; /* relocated address/value for the SYSREQ.D opcode */
#if defined JIT
/* support variables for the JIT */
int reloc_size ; /* required temporary buffer for relocations */
long code_size ; /* estimated memory footprint of the native code */
#endif
} AMX;
/* The AMX_HEADER structure is both the memory format as the file format. The
* structure is used internaly.
*/
typedef struct tagAMX_HEADER {
int32_t size ; /* size of the "file" */
uint16_t magic ; /* signature */
char file_version ; /* file format version */
char amx_version ; /* required version of the AMX */
int16_t flags ;
int16_t defsize ; /* size of a definition record */
int32_t cod ; /* initial value of COD - code block */
int32_t dat ; /* initial value of DAT - data block */
int32_t hea ; /* initial value of HEA - start of the heap */
int32_t stp ; /* initial value of STP - stack top */
int32_t cip ; /* initial value of CIP - the instruction pointer */
int32_t publics ; /* offset to the "public functions" table */
int32_t natives ; /* offset to the "native functions" table */
int32_t libraries ; /* offset to the table of libraries */
int32_t pubvars ; /* the "public variables" table */
int32_t tags ; /* the "public tagnames" table */
int32_t nametable ; /* name table */
} AMX_HEADER;
#if PAWN_CELL_SIZE==16
#define AMX_MAGIC 0xf1e2
#elif PAWN_CELL_SIZE==32
#define AMX_MAGIC 0xf1e0
#elif PAWN_CELL_SIZE==64
#define AMX_MAGIC 0xf1e1
#endif
enum {
AMX_ERR_NONE,
/* reserve the first 15 error codes for exit codes of the abstract machine */
AMX_ERR_EXIT, /* forced exit */
AMX_ERR_ASSERT, /* assertion failed */
AMX_ERR_STACKERR, /* stack/heap collision */
AMX_ERR_BOUNDS, /* index out of bounds */
AMX_ERR_MEMACCESS, /* invalid memory access */
AMX_ERR_INVINSTR, /* invalid instruction */
AMX_ERR_STACKLOW, /* stack underflow */
AMX_ERR_HEAPLOW, /* heap underflow */
AMX_ERR_CALLBACK, /* no callback, or invalid callback */
AMX_ERR_NATIVE, /* native function failed */
AMX_ERR_DIVIDE, /* divide by zero */
AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */
AMX_ERR_INVSTATE, /* invalid state for this access */
AMX_ERR_MEMORY = 16, /* out of memory */
AMX_ERR_FORMAT, /* invalid file format */
AMX_ERR_VERSION, /* file is for a newer version of the AMX */
AMX_ERR_NOTFOUND, /* function not found */
AMX_ERR_INDEX, /* invalid index parameter (bad entry point) */
AMX_ERR_DEBUG, /* debugger cannot run */
AMX_ERR_INIT, /* AMX not initialized (or doubly initialized) */
AMX_ERR_USERDATA, /* unable to set user data field (table full) */
AMX_ERR_INIT_JIT, /* cannot initialize the JIT */
AMX_ERR_PARAMS, /* parameter error */
AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */
AMX_ERR_GENERAL, /* general error (unknown or unspecific error) */
};
/* AMX_FLAG_CHAR16 0x01 no longer used */
#define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */
#define AMX_FLAG_COMPACT 0x04 /* compact encoding */
#define AMX_FLAG_SLEEP 0x08 /* script uses the sleep instruction (possible re-entry or power-down mode) */
#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no BREAK opcodes */
#define AMX_FLAG_SYSREQN 0x800 /* script new (optimized) version of SYSREQ opcode */
#define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */
#define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */
#define AMX_FLAG_BROWSE 0x4000 /* busy browsing */
#define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */
#define AMX_EXEC_MAIN (-1) /* start at program entry point */
#define AMX_EXEC_CONT (-2) /* continue from last address */
#define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24))
#if !defined AMX_COMPACTMARGIN
#define AMX_COMPACTMARGIN 64
#endif
/* for native functions that use floating point parameters, the following
* two macros are convenient for casting a "cell" into a "float" type _without_
* changing the bit pattern
*/
#if PAWN_CELL_SIZE==32
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
#define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */
#elif PAWN_CELL_SIZE==64
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
#define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */
#else
#error Unsupported cell size
#endif
#define amx_StrParam(amx,param,result) \
do { \
cell *amx_cstr_; int amx_length_; \
amx_GetAddr((amx), (param), &amx_cstr_); \
amx_StrLen(amx_cstr_, &amx_length_); \
if (amx_length_ > 0 && \
((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \
amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_ + 1); \
else (result) = NULL; \
} while (0)
uint16_t * AMXAPI amx_Align16(uint16_t *v);
uint32_t * AMXAPI amx_Align32(uint32_t *v);
#if defined _I64_MAX || defined HAVE_I64
uint64_t * AMXAPI amx_Align64(uint64_t *v);
#endif
int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr);
int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
int AMXAPI amx_Cleanup(AMX *amx);
int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index);
int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index);
int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr);
int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname);
int AMXAPI amx_Flags(AMX *amx,uint16_t *flags);
int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr);
int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname);
int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname);
int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr);
int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size);
int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id);
int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr);
int AMXAPI amx_Init(AMX *amx, void *program);
int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code);
int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap);
int AMXAPI amx_NameLength(AMX *amx, int *length);
AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func);
int AMXAPI amx_NumNatives(AMX *amx, int *number);
int AMXAPI amx_NumPublics(AMX *amx, int *number);
int AMXAPI amx_NumPubVars(AMX *amx, int *number);
int AMXAPI amx_NumTags(AMX *amx, int *number);
int AMXAPI amx_Push(AMX *amx, cell value);
int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells);
int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar);
int AMXAPI amx_RaiseError(AMX *amx, int error);
int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
int AMXAPI amx_Release(AMX *amx, cell amx_addr);
int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug);
int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size);
int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr);
int AMXAPI amx_StrLen(const cell *cstring, int *length);
int AMXAPI amx_UTF8Check(const char *string, int *length);
int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value);
int AMXAPI amx_UTF8Len(const cell *cstr, int *length);
int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value);
#if PAWN_CELL_SIZE==16
#define amx_AlignCell(v) amx_Align16(v)
#elif PAWN_CELL_SIZE==32
#define amx_AlignCell(v) amx_Align32(v)
#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64)
#define amx_AlignCell(v) amx_Align64(v)
#else
#error Unsupported cell size
#endif
#define amx_RegisterFunc(amx, name, func) \
amx_Register((amx), amx_NativeInfo((name),(func)), 1);
#if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__
#pragma pack() /* reset default packing */
#elif defined MACOS && defined __MWERKS__
#pragma options align=reset
#else
#pragma pack(pop) /* reset previous packing */
#endif
#endif
#ifdef __cplusplus
}
#endif
typedef enum {
OP_NONE, /* invalid opcode */
OP_LOAD_PRI,
OP_LOAD_ALT,
OP_LOAD_S_PRI,
OP_LOAD_S_ALT,
OP_LREF_PRI,
OP_LREF_ALT,
OP_LREF_S_PRI,
OP_LREF_S_ALT,
OP_LOAD_I,
OP_LODB_I,
OP_CONST_PRI,
OP_CONST_ALT,
OP_ADDR_PRI,
OP_ADDR_ALT,
OP_STOR_PRI,
OP_STOR_ALT,
OP_STOR_S_PRI,
OP_STOR_S_ALT,
OP_SREF_PRI,
OP_SREF_ALT,
OP_SREF_S_PRI,
OP_SREF_S_ALT,
OP_STOR_I,
OP_STRB_I,
OP_LIDX,
OP_LIDX_B,
OP_IDXADDR,
OP_IDXADDR_B,
OP_ALIGN_PRI,
OP_ALIGN_ALT,
OP_LCTRL,
OP_SCTRL,
OP_MOVE_PRI,
OP_MOVE_ALT,
OP_XCHG,
OP_PUSH_PRI,
OP_PUSH_ALT,
OP_PUSH_R,
OP_PUSH_C,
OP_PUSH,
OP_PUSH_S,
OP_POP_PRI,
OP_POP_ALT,
OP_STACK,
OP_HEAP,
OP_PROC,
OP_RET,
OP_RETN,
OP_CALL,
OP_CALL_PRI,
OP_JUMP,
OP_JREL,
OP_JZER,
OP_JNZ,
OP_JEQ,
OP_JNEQ,
OP_JLESS,
OP_JLEQ,
OP_JGRTR,
OP_JGEQ,
OP_JSLESS,
OP_JSLEQ,
OP_JSGRTR,
OP_JSGEQ,
OP_SHL,
OP_SHR,
OP_SSHR,
OP_SHL_C_PRI,
OP_SHL_C_ALT,
OP_SHR_C_PRI,
OP_SHR_C_ALT,
OP_SMUL,
OP_SDIV,
OP_SDIV_ALT,
OP_UMUL,
OP_UDIV,
OP_UDIV_ALT,
OP_ADD,
OP_SUB,
OP_SUB_ALT,
OP_AND,
OP_OR,
OP_XOR,
OP_NOT,
OP_NEG,
OP_INVERT,
OP_ADD_C,
OP_SMUL_C,
OP_ZERO_PRI,
OP_ZERO_ALT,
OP_ZERO,
OP_ZERO_S,
OP_SIGN_PRI,
OP_SIGN_ALT,
OP_EQ,
OP_NEQ,
OP_LESS,
OP_LEQ,
OP_GRTR,
OP_GEQ,
OP_SLESS,
OP_SLEQ,
OP_SGRTR,
OP_SGEQ,
OP_EQ_C_PRI,
OP_EQ_C_ALT,
OP_INC_PRI,
OP_INC_ALT,
OP_INC,
OP_INC_S,
OP_INC_I,
OP_DEC_PRI,
OP_DEC_ALT,
OP_DEC,
OP_DEC_S,
OP_DEC_I,
OP_MOVS,
OP_CMPS,
OP_FILL,
OP_HALT,
OP_BOUNDS,
OP_SYSREQ_PRI,
OP_SYSREQ_C,
OP_FILE, /* obsolete */
OP_LINE, /* obsolete */
OP_SYMBOL, /* obsolete */
OP_SRANGE, /* obsolete */
OP_JUMP_PRI,
OP_SWITCH,
OP_CASETBL,
OP_SWAP_PRI,
OP_SWAP_ALT,
OP_PUSH_ADR,
OP_NOP,
OP_SYSREQ_N,
OP_SYMTAG, /* obsolete */
OP_BREAK,
OP_PUSH2_C,
OP_PUSH2,
OP_PUSH2_S,
OP_PUSH2_ADR,
OP_PUSH3_C,
OP_PUSH3,
OP_PUSH3_S,
OP_PUSH3_ADR,
OP_PUSH4_C,
OP_PUSH4,
OP_PUSH4_S,
OP_PUSH4_ADR,
OP_PUSH5_C,
OP_PUSH5,
OP_PUSH5_S,
OP_PUSH5_ADR,
OP_LOAD_BOTH,
OP_LOAD_S_BOTH,
OP_CONST,
OP_CONST_S,
/* ----- */
OP_SYSREQ_D,
OP_SYSREQ_ND,
/* ----- */
OP_HEAP_I,
OP_PUSH_H_C,
OP_GENARRAY,
OP_NUM_OPCODES
} OPCODE;
#endif /* AMX_H_INCLUDED */

View File

@ -1,173 +0,0 @@
/* Abstract Machine for the Pawn compiler, debugger support
*
* This file contains extra definitions that are convenient for debugger
* support.
*
* Copyright (c) ITB CompuPhase, 2005
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#ifndef AMXDBG_H_INCLUDED
#define AMXDBG_H_INCLUDED
#ifndef AMX_H_INCLUDED
#include "amx.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Some compilers do not support the #pragma align, which should be fine. Some
* compilers give a warning on unknown #pragmas, which is not so fine...
*/
#if defined SN_TARGET_PS2 || defined __GNUC__
#define AMX_NO_ALIGN
#endif
#if defined __GNUC__
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
#if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */
#elif defined MACOS && defined __MWERKS__
#pragma options align=mac68k
#else
#pragma pack(push)
#pragma pack(1) /* structures must be packed (byte-aligned) */
#if defined __TURBOC__
#pragma option -a- /* "pack" pragma for older Borland compilers */
#endif
#endif
#endif
typedef struct tagAMX_DBG_HDR {
int32_t size PACKED; /* size of the debug information chunk */
uint16_t magic PACKED; /* signature, must be 0xf1ef */
char file_version; /* file format version */
char amx_version; /* required version of the AMX */
int16_t flags PACKED; /* currently unused */
int16_t files PACKED; /* number of entries in the "file" table */
int32_t lines PACKED; /* number of entries in the "line" table */
int32_t symbols PACKED; /* number of entries in the "symbol" table */
int16_t tags PACKED; /* number of entries in the "tag" table */
int16_t automatons PACKED; /* number of entries in the "automaton" table */
int16_t states PACKED; /* number of entries in the "state" table */
} PACKED AMX_DBG_HDR;
#define AMX_DBG_MAGIC 0xf1ef
typedef struct tagAMX_DBG_FILE {
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */
char name[1]; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_FILE;
typedef struct tagAMX_DBG_LINE {
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */
int32_t line PACKED; /* line number */
} PACKED AMX_DBG_LINE;
typedef struct tagAMX_DBG_SYMBOL {
ucell address PACKED; /* address in the data segment or relative to the frame */
int16_t tag PACKED; /* tag for the symbol */
ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */
ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */
char ident; /* kind of symbol (function/variable) */
char vclass; /* class of symbol (global/local) */
int16_t dim PACKED; /* number of dimensions */
char name[1]; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_SYMBOL;
typedef struct tagAMX_DBG_SYMDIM {
int16_t tag PACKED; /* tag for the array dimension */
ucell size PACKED; /* size of the array dimension */
} PACKED AMX_DBG_SYMDIM;
typedef struct tagAMX_DBG_TAG {
int16_t tag PACKED; /* tag id */
char name[1]; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_TAG;
typedef struct tagAMX_DBG_MACHINE {
int16_t automaton PACKED; /* automaton id */
ucell address PACKED; /* address of state variable */
char name[1]; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_MACHINE;
typedef struct tagAMX_DBG_STATE {
int16_t state PACKED; /* state id */
int16_t automaton PACKED; /* automaton id */
char name[1]; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_STATE;
typedef struct tagAMX_DBG {
AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */
AMX_DBG_FILE _FAR **filetbl PACKED;
AMX_DBG_LINE _FAR *linetbl PACKED;
AMX_DBG_SYMBOL _FAR **symboltbl PACKED;
AMX_DBG_TAG _FAR **tagtbl PACKED;
AMX_DBG_MACHINE _FAR **automatontbl PACKED;
AMX_DBG_STATE _FAR **statetbl PACKED;
} PACKED AMX_DBG;
#if !defined iVARIABLE
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
#define iARRAY 3
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
#define iFUNCTN 9
#endif
int AMXAPI dbg_FreeInfo(AMX_DBG *amxdbg);
int AMXAPI dbg_LoadInfo(AMX_DBG *amxdbg, void *dbg_addr);
int AMXAPI dbg_LookupFile(AMX_DBG *amxdbg, ucell address, const char **filename);
int AMXAPI dbg_LookupFunction(AMX_DBG *amxdbg, ucell address, const char **funcname);
int AMXAPI dbg_LookupLine(AMX_DBG *amxdbg, ucell address, long *line);
int AMXAPI dbg_GetFunctionAddress(AMX_DBG *amxdbg, const char *funcname, const char *filename, ucell *address);
int AMXAPI dbg_GetLineAddress(AMX_DBG *amxdbg, long line, const char *filename, ucell *address);
int AMXAPI dbg_GetAutomatonName(AMX_DBG *amxdbg, int automaton, const char **name);
int AMXAPI dbg_GetStateName(AMX_DBG *amxdbg, int state, const char **name);
int AMXAPI dbg_GetTagName(AMX_DBG *amxdbg, int tag, const char **name);
int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr, const AMX_DBG_SYMBOL **sym);
int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX_DBG_SYMDIM **symdim);
#if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__
#pragma pack() /* reset default packing */
#elif defined MACOS && defined __MWERKS__
#pragma options align=reset
#else
#pragma pack(pop) /* reset previous packing */
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* AMXDBG_H_INCLUDED */

View File

@ -1,766 +0,0 @@
/*
* BinReloc - a library for creating relocatable executables
* Written by: Hongli Lai <h.lai@chello.nl>
* http://autopackage.org/
*
* This source code is public domain. You can relicense this code
* under whatever license you want.
*
* See http://autopackage.org/docs/binreloc/ for
* more information and how to use this.
*/
#ifndef __BINRELOC_C__
#define __BINRELOC_C__
#ifdef ENABLE_BINRELOC
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif /* ENABLE_BINRELOC */
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include "binreloc.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** @internal
* Find the canonical filename of the executable. Returns the filename
* (which must be freed) or NULL on error. If the parameter 'error' is
* not NULL, the error code will be stored there, if an error occured.
*/
static char *
_br_find_exe (BrInitError *error)
{
#ifndef ENABLE_BINRELOC
if (error)
*error = BR_INIT_ERROR_DISABLED;
return NULL;
#else
char *path, *path2, *line, *result;
size_t buf_size;
ssize_t size;
struct stat stat_buf;
FILE *f;
/* Read from /proc/self/exe (symlink) */
if (sizeof (path) > SSIZE_MAX)
buf_size = SSIZE_MAX - 1;
else
buf_size = PATH_MAX - 1;
path = (char *) malloc (buf_size);
if (path == NULL) {
/* Cannot allocate memory. */
if (error)
*error = BR_INIT_ERROR_NOMEM;
return NULL;
}
path2 = (char *) malloc (buf_size);
if (path2 == NULL) {
/* Cannot allocate memory. */
if (error)
*error = BR_INIT_ERROR_NOMEM;
free (path);
return NULL;
}
strncpy (path2, "/proc/self/exe", buf_size - 1);
while (1) {
int i;
size = readlink (path2, path, buf_size - 1);
if (size == -1) {
/* Error. */
free (path2);
break;
}
/* readlink() success. */
path[size] = '\0';
/* Check whether the symlink's target is also a symlink.
* We want to get the final target. */
i = stat (path, &stat_buf);
if (i == -1) {
/* Error. */
free (path2);
break;
}
/* stat() success. */
if (!S_ISLNK (stat_buf.st_mode)) {
/* path is not a symlink. Done. */
free (path2);
return path;
}
/* path is a symlink. Continue loop and resolve this. */
strncpy (path, path2, buf_size - 1);
}
/* readlink() or stat() failed; this can happen when the program is
* running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
buf_size = PATH_MAX + 128;
line = (char *) realloc (path, buf_size);
if (line == NULL) {
/* Cannot allocate memory. */
free (path);
if (error)
*error = BR_INIT_ERROR_NOMEM;
return NULL;
}
f = fopen ("/proc/self/maps", "r");
if (f == NULL) {
free (line);
if (error)
*error = BR_INIT_ERROR_OPEN_MAPS;
return NULL;
}
/* The first entry should be the executable name. */
result = fgets (line, (int) buf_size, f);
if (result == NULL) {
fclose (f);
free (line);
if (error)
*error = BR_INIT_ERROR_READ_MAPS;
return NULL;
}
/* Get rid of newline character. */
buf_size = strlen (line);
if (buf_size <= 0) {
/* Huh? An empty string? */
fclose (f);
free (line);
if (error)
*error = BR_INIT_ERROR_INVALID_MAPS;
return NULL;
}
if (line[buf_size - 1] == 10)
line[buf_size - 1] = 0;
/* Extract the filename; it is always an absolute path. */
path = strchr (line, '/');
/* Sanity check. */
if (strstr (line, " r-xp ") == NULL || path == NULL) {
fclose (f);
free (line);
if (error)
*error = BR_INIT_ERROR_INVALID_MAPS;
return NULL;
}
path = strdup (path);
free (line);
fclose (f);
return path;
#endif /* ENABLE_BINRELOC */
}
/** @internal
* Find the canonical filename of the executable which owns symbol.
* Returns a filename which must be freed, or NULL on error.
*/
static char *
_br_find_exe_for_symbol (const void *symbol, BrInitError *error)
{
#ifndef ENABLE_BINRELOC
if (error)
*error = BR_INIT_ERROR_DISABLED;
return (char *) NULL;
#else
#define SIZE PATH_MAX + 100
FILE *f;
size_t address_string_len;
char *address_string, line[SIZE], *found;
if (symbol == NULL)
return (char *) NULL;
f = fopen ("/proc/self/maps", "r");
if (f == NULL)
return (char *) NULL;
address_string_len = 4;
address_string = (char *) malloc (address_string_len);
found = (char *) NULL;
while (!feof (f)) {
char *start_addr, *end_addr, *end_addr_end, *file;
void *start_addr_p, *end_addr_p;
size_t len;
if (fgets (line, SIZE, f) == NULL)
break;
/* Sanity check. */
if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
continue;
/* Parse line. */
start_addr = line;
end_addr = strchr (line, '-');
file = strchr (line, '/');
/* More sanity check. */
if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
continue;
end_addr[0] = '\0';
end_addr++;
end_addr_end = strchr (end_addr, ' ');
if (end_addr_end == NULL)
continue;
end_addr_end[0] = '\0';
len = strlen (file);
if (len == 0)
continue;
if (file[len - 1] == '\n')
file[len - 1] = '\0';
/* Get rid of "(deleted)" from the filename. */
len = strlen (file);
if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
file[len - 10] = '\0';
/* I don't know whether this can happen but better safe than sorry. */
len = strlen (start_addr);
if (len != strlen (end_addr))
continue;
/* Transform the addresses into a string in the form of 0xdeadbeef,
* then transform that into a pointer. */
if (address_string_len < len + 3) {
address_string_len = len + 3;
address_string = (char *) realloc (address_string, address_string_len);
}
memcpy (address_string, "0x", 2);
memcpy (address_string + 2, start_addr, len);
address_string[2 + len] = '\0';
sscanf (address_string, "%p", &start_addr_p);
memcpy (address_string, "0x", 2);
memcpy (address_string + 2, end_addr, len);
address_string[2 + len] = '\0';
sscanf (address_string, "%p", &end_addr_p);
if (symbol >= start_addr_p && symbol < end_addr_p) {
found = file;
break;
}
}
free (address_string);
fclose (f);
if (found == NULL)
return (char *) NULL;
else
return strdup (found);
#endif /* ENABLE_BINRELOC */
}
#ifndef BINRELOC_RUNNING_DOXYGEN
#undef NULL
#define NULL ((void *) 0) /* typecasted as char* for C++ type safeness */
#endif
static char *exe = (char *) NULL;
/** Initialize the BinReloc library (for applications).
*
* This function must be called before using any other BinReloc functions.
* It attempts to locate the application's canonical filename.
*
* @note If you want to use BinReloc for a library, then you should call
* br_init_lib() instead.
*
* @param error If BinReloc failed to initialize, then the error code will
* be stored in this variable. Set to NULL if you want to
* ignore this. See #BrInitError for a list of error codes.
*
* @returns 1 on success, 0 if BinReloc failed to initialize.
*/
int
br_init (BrInitError *error)
{
exe = _br_find_exe (error);
return exe != NULL;
}
/** Initialize the BinReloc library (for libraries).
*
* This function must be called before using any other BinReloc functions.
* It attempts to locate the calling library's canonical filename.
*
* @note The BinReloc source code MUST be included in your library, or this
* function won't work correctly.
*
* @param error If BinReloc failed to initialize, then the error code will
* be stored in this variable. Set to NULL if you want to
* ignore this. See #BrInitError for a list of error codes.
*
* @returns 1 on success, 0 if a filename cannot be found.
*/
int
br_init_lib (BrInitError *error)
{
exe = _br_find_exe_for_symbol ((const void *) "", error);
return exe != NULL;
}
/** Find the canonical filename of the current application.
*
* @param default_exe A default filename which will be used as fallback.
* @returns A string containing the application's canonical filename,
* which must be freed when no longer necessary. If BinReloc is
* not initialized, or if br_init() failed, then a copy of
* default_exe will be returned. If default_exe is NULL, then
* NULL will be returned.
*/
char *
br_find_exe (const char *default_exe)
{
if (exe == (char *) NULL) {
/* BinReloc is not initialized. */
if (default_exe != (const char *) NULL)
return strdup (default_exe);
else
return (char *) NULL;
}
return strdup (exe);
}
/** Locate the directory in which the current application is installed.
*
* The prefix is generated by the following pseudo-code evaluation:
* \code
* dirname(exename)
* \endcode
*
* @param default_dir A default directory which will used as fallback.
* @return A string containing the directory, which must be freed when no
* longer necessary. If BinReloc is not initialized, or if the
* initialization function failed, then a copy of default_dir
* will be returned. If default_dir is NULL, then NULL will be
* returned.
*/
char *
br_find_exe_dir (const char *default_dir)
{
if (exe == NULL) {
/* BinReloc not initialized. */
if (default_dir != NULL)
return strdup (default_dir);
else
return NULL;
}
return br_dirname (exe);
}
/** Locate the prefix in which the current application is installed.
*
* The prefix is generated by the following pseudo-code evaluation:
* \code
* dirname(dirname(exename))
* \endcode
*
* @param default_prefix A default prefix which will used as fallback.
* @return A string containing the prefix, which must be freed when no
* longer necessary. If BinReloc is not initialized, or if
* the initialization function failed, then a copy of default_prefix
* will be returned. If default_prefix is NULL, then NULL will be returned.
*/
char *
br_find_prefix (const char *default_prefix)
{
char *dir1, *dir2;
if (exe == (char *) NULL) {
/* BinReloc not initialized. */
if (default_prefix != (const char *) NULL)
return strdup (default_prefix);
else
return (char *) NULL;
}
dir1 = br_dirname (exe);
dir2 = br_dirname (dir1);
free (dir1);
return dir2;
}
/** Locate the application's binary folder.
*
* The path is generated by the following pseudo-code evaluation:
* \code
* prefix + "/bin"
* \endcode
*
* @param default_bin_dir A default path which will used as fallback.
* @return A string containing the bin folder's path, which must be freed when
* no longer necessary. If BinReloc is not initialized, or if
* the initialization function failed, then a copy of default_bin_dir will
* be returned. If default_bin_dir is NULL, then NULL will be returned.
*/
char *
br_find_bin_dir (const char *default_bin_dir)
{
char *prefix, *dir;
prefix = br_find_prefix ((const char *) NULL);
if (prefix == (char *) NULL) {
/* BinReloc not initialized. */
if (default_bin_dir != (const char *) NULL)
return strdup (default_bin_dir);
else
return (char *) NULL;
}
dir = br_build_path (prefix, "bin");
free (prefix);
return dir;
}
/** Locate the application's superuser binary folder.
*
* The path is generated by the following pseudo-code evaluation:
* \code
* prefix + "/sbin"
* \endcode
*
* @param default_sbin_dir A default path which will used as fallback.
* @return A string containing the sbin folder's path, which must be freed when
* no longer necessary. If BinReloc is not initialized, or if the
* initialization function failed, then a copy of default_sbin_dir will
* be returned. If default_bin_dir is NULL, then NULL will be returned.
*/
char *
br_find_sbin_dir (const char *default_sbin_dir)
{
char *prefix, *dir;
prefix = br_find_prefix ((const char *) NULL);
if (prefix == (char *) NULL) {
/* BinReloc not initialized. */
if (default_sbin_dir != (const char *) NULL)
return strdup (default_sbin_dir);
else
return (char *) NULL;
}
dir = br_build_path (prefix, "sbin");
free (prefix);
return dir;
}
/** Locate the application's data folder.
*
* The path is generated by the following pseudo-code evaluation:
* \code
* prefix + "/share"
* \endcode
*
* @param default_data_dir A default path which will used as fallback.
* @return A string containing the data folder's path, which must be freed when
* no longer necessary. If BinReloc is not initialized, or if the
* initialization function failed, then a copy of default_data_dir
* will be returned. If default_data_dir is NULL, then NULL will be
* returned.
*/
char *
br_find_data_dir (const char *default_data_dir)
{
char *prefix, *dir;
prefix = br_find_prefix ((const char *) NULL);
if (prefix == (char *) NULL) {
/* BinReloc not initialized. */
if (default_data_dir != (const char *) NULL)
return strdup (default_data_dir);
else
return (char *) NULL;
}
dir = br_build_path (prefix, "share");
free (prefix);
return dir;
}
/** Locate the application's localization folder.
*
* The path is generated by the following pseudo-code evaluation:
* \code
* prefix + "/share/locale"
* \endcode
*
* @param default_locale_dir A default path which will used as fallback.
* @return A string containing the localization folder's path, which must be freed when
* no longer necessary. If BinReloc is not initialized, or if the
* initialization function failed, then a copy of default_locale_dir will be returned.
* If default_locale_dir is NULL, then NULL will be returned.
*/
char *
br_find_locale_dir (const char *default_locale_dir)
{
char *data_dir, *dir;
data_dir = br_find_data_dir ((const char *) NULL);
if (data_dir == (char *) NULL) {
/* BinReloc not initialized. */
if (default_locale_dir != (const char *) NULL)
return strdup (default_locale_dir);
else
return (char *) NULL;
}
dir = br_build_path (data_dir, "locale");
free (data_dir);
return dir;
}
/** Locate the application's library folder.
*
* The path is generated by the following pseudo-code evaluation:
* \code
* prefix + "/lib"
* \endcode
*
* @param default_lib_dir A default path which will used as fallback.
* @return A string containing the library folder's path, which must be freed when
* no longer necessary. If BinReloc is not initialized, or if the initialization
* function failed, then a copy of default_lib_dir will be returned.
* If default_lib_dir is NULL, then NULL will be returned.
*/
char *
br_find_lib_dir (const char *default_lib_dir)
{
char *prefix, *dir;
prefix = br_find_prefix ((const char *) NULL);
if (prefix == (char *) NULL) {
/* BinReloc not initialized. */
if (default_lib_dir != (const char *) NULL)
return strdup (default_lib_dir);
else
return (char *) NULL;
}
dir = br_build_path (prefix, "lib");
free (prefix);
return dir;
}
/** Locate the application's libexec folder.
*
* The path is generated by the following pseudo-code evaluation:
* \code
* prefix + "/libexec"
* \endcode
*
* @param default_libexec_dir A default path which will used as fallback.
* @return A string containing the libexec folder's path, which must be freed when
* no longer necessary. If BinReloc is not initialized, or if the initialization
* function failed, then a copy of default_libexec_dir will be returned.
* If default_libexec_dir is NULL, then NULL will be returned.
*/
char *
br_find_libexec_dir (const char *default_libexec_dir)
{
char *prefix, *dir;
prefix = br_find_prefix ((const char *) NULL);
if (prefix == (char *) NULL) {
/* BinReloc not initialized. */
if (default_libexec_dir != (const char *) NULL)
return strdup (default_libexec_dir);
else
return (char *) NULL;
}
dir = br_build_path (prefix, "libexec");
free (prefix);
return dir;
}
/** Locate the application's configuration files folder.
*
* The path is generated by the following pseudo-code evaluation:
* \code
* prefix + "/etc"
* \endcode
*
* @param default_etc_dir A default path which will used as fallback.
* @return A string containing the etc folder's path, which must be freed when
* no longer necessary. If BinReloc is not initialized, or if the initialization
* function failed, then a copy of default_etc_dir will be returned.
* If default_etc_dir is NULL, then NULL will be returned.
*/
char *
br_find_etc_dir (const char *default_etc_dir)
{
char *prefix, *dir;
prefix = br_find_prefix ((const char *) NULL);
if (prefix == (char *) NULL) {
/* BinReloc not initialized. */
if (default_etc_dir != (const char *) NULL)
return strdup (default_etc_dir);
else
return (char *) NULL;
}
dir = br_build_path (prefix, "etc");
free (prefix);
return dir;
}
/***********************
* Utility functions
***********************/
/** Concatenate str1 and str2 to a newly allocated string.
*
* @param str1 A string.
* @param str2 Another string.
* @returns A newly-allocated string. This string should be freed when no longer needed.
*/
char *
br_strcat (const char *str1, const char *str2)
{
char *result;
size_t len1, len2;
if (str1 == NULL)
str1 = "";
if (str2 == NULL)
str2 = "";
len1 = strlen (str1);
len2 = strlen (str2);
result = (char *) malloc (len1 + len2 + 1);
memcpy (result, str1, len1);
memcpy (result + len1, str2, len2);
result[len1 + len2] = '\0';
return result;
}
char *
br_build_path (const char *dir, const char *file)
{
char *dir2, *result;
size_t len;
int must_free = 0;
len = strlen (dir);
if (len > 0 && dir[len - 1] != '/') {
dir2 = br_strcat (dir, "/");
must_free = 1;
} else
dir2 = (char *) dir;
result = br_strcat (dir2, file);
if (must_free)
free (dir2);
return result;
}
/* Emulates glibc's strndup() */
static char *
br_strndup (const char *str, size_t size)
{
char *result = (char *) NULL;
size_t len;
if (str == (const char *) NULL)
return (char *) NULL;
len = strlen (str);
if (len == 0)
return strdup ("");
if (size > len)
size = len;
result = (char *) malloc (len + 1);
memcpy (result, str, size);
result[size] = '\0';
return result;
}
/** Extracts the directory component of a path.
*
* Similar to g_dirname() or the dirname commandline application.
*
* Example:
* \code
* br_dirname ("/usr/local/foobar"); --> Returns: "/usr/local"
* \endcode
*
* @param path A path.
* @returns A directory name. This string should be freed when no longer needed.
*/
char *
br_dirname (const char *path)
{
char *end, *result;
if (path == (const char *) NULL)
return (char *) NULL;
end = strrchr (path, '/');
if (end == (const char *) NULL)
return strdup (".");
while (end > path && *end == '/')
end--;
result = br_strndup (path, end - path + 1);
if (result[0] == 0) {
free (result);
return strdup ("/");
} else
return result;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __BINRELOC_C__ */

View File

@ -1,80 +0,0 @@
/*
* BinReloc - a library for creating relocatable executables
* Written by: Hongli Lai <h.lai@chello.nl>
* http://autopackage.org/
*
* This source code is public domain. You can relicense this code
* under whatever license you want.
*
* See http://autopackage.org/docs/binreloc/ for
* more information and how to use this.
*/
#ifndef __BINRELOC_H__
#define __BINRELOC_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** These error codes can be returned by br_init(), br_init_lib(), gbr_init() or gbr_init_lib(). */
typedef enum {
/** Cannot allocate memory. */
BR_INIT_ERROR_NOMEM,
/** Unable to open /proc/self/maps; see errno for details. */
BR_INIT_ERROR_OPEN_MAPS,
/** Unable to read from /proc/self/maps; see errno for details. */
BR_INIT_ERROR_READ_MAPS,
/** The file format of /proc/self/maps is invalid; kernel bug? */
BR_INIT_ERROR_INVALID_MAPS,
/** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */
BR_INIT_ERROR_DISABLED
} BrInitError;
#ifndef BINRELOC_RUNNING_DOXYGEN
/* Mangle symbol names to avoid symbol collisions with other ELF objects. */
#define br_init SbCJ22537442193159_br_init
#define br_init_lib SbCJ22537442193159_br_init_lib
#define br_find_exe SbCJ22537442193159_br_find_exe
#define br_find_exe_dir SbCJ22537442193159_br_find_exe_dir
#define br_find_prefix SbCJ22537442193159_br_find_prefix
#define br_find_bin_dir SbCJ22537442193159_br_find_bin_dir
#define br_find_sbin_dir SbCJ22537442193159_br_find_sbin_dir
#define br_find_data_dir SbCJ22537442193159_br_find_data_dir
#define br_find_locale_dir SbCJ22537442193159_br_find_locale_dir
#define br_find_lib_dir SbCJ22537442193159_br_find_lib_dir
#define br_find_libexec_dir SbCJ22537442193159_br_find_libexec_dir
#define br_find_etc_dir SbCJ22537442193159_br_find_etc_dir
#define br_strcat SbCJ22537442193159_br_strcat
#define br_build_path SbCJ22537442193159_br_build_path
#define br_dirname SbCJ22537442193159_br_dirname
#endif
int br_init (BrInitError *error);
int br_init_lib (BrInitError *error);
char *br_find_exe (const char *default_exe);
char *br_find_exe_dir (const char *default_dir);
char *br_find_prefix (const char *default_prefix);
char *br_find_bin_dir (const char *default_bin_dir);
char *br_find_sbin_dir (const char *default_sbin_dir);
char *br_find_data_dir (const char *default_data_dir);
char *br_find_locale_dir (const char *default_locale_dir);
char *br_find_lib_dir (const char *default_lib_dir);
char *br_find_libexec_dir (const char *default_libexec_dir);
char *br_find_etc_dir (const char *default_etc_dir);
/* Utility functions */
char *br_strcat (const char *str1, const char *str2);
char *br_build_path (const char *dir, const char *file);
char *br_dirname (const char *path);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __BINRELOC_H__ */

View File

@ -1,15 +0,0 @@
/* Extremely inefficient but portable POSIX getch(), see getch.c */
#ifndef GETCH_H
#define GETCH_H
#if defined __cplusplus
extern "C" {
#endif
int getch(void);
int kbhit(void);
#if defined __cplusplus
}
#endif
#endif /* GETCH_H */

View File

@ -1,346 +0,0 @@
// vim: set sts=8 ts=2 sw=2 tw=99 noet:
/* LIBPAWNC.C
*
* A "glue file" for building the Pawn compiler as a DLL or shared library.
*
* Copyright (c) ITB CompuPhase, 2000-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "sc.h"
#include "memfile.h"
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
#include <sys/types.h>
#include <sys/stat.h>
#endif
/* pc_printf()
* Called for general purpose "console" output. This function prints general
* purpose messages; errors go through pc_error(). The function is modelled
* after printf().
*/
int pc_printf(const char *message,...)
{
int ret;
va_list argptr;
va_start(argptr,message);
ret=vprintf(message,argptr);
va_end(argptr);
return ret;
}
/* pc_error()
* Called for producing error output.
* number the error number (as documented in the manual)
* message a string describing the error with embedded %d and %s tokens
* filename the name of the file currently being parsed
* firstline the line number at which the expression started on which
* the error was found, or -1 if there is no "starting line"
* lastline the line number at which the error was detected
* argptr a pointer to the first of a series of arguments (for macro
* "va_arg")
* Return:
* If the function returns 0, the parser attempts to continue compilation.
* On a non-zero return value, the parser aborts.
*/
int pc_error(int number,const char *message,const char *filename,int firstline,int lastline,va_list argptr)
{
static const char *prefix[3]={ "error", "fatal error", "warning" };
if (number!=0) {
int idx;
if (number < FIRST_FATAL_ERROR || (number >= 200 && sc_warnings_are_errors))
idx = 0;
else if (number < 200)
idx = 1;
else
idx = 2;
const char *pre=prefix[idx];
if (firstline>=0)
fprintf(stdout,"%s(%d -- %d) : %s %03d: ",filename,firstline,lastline,pre,number);
else
fprintf(stdout,"%s(%d) : %s %03d: ",filename,lastline,pre,number);
} /* if */
vfprintf(stdout,message,argptr);
fflush(stdout);
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.
* filename the name of the "file" to read from
* Return:
* The function must return a pointer, which is used as a "magic cookie" to
* all I/O functions. When failing to open the file for reading, the
* function must return NULL.
* Note:
* Several "source files" may be open at the same time. Specifically, one
* file can be open for reading and another for writing.
*/
void *pc_opensrc(char *filename)
{
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()
* Creates/overwrites a source file for writing. The "file" does not have
* to be a physical file, one might compile from memory.
* filename the name of the "file" to create
* Return:
* The function must return a pointer which is used as a "magic cookie" to
* all I/O functions. When failing to open the file for reading, the
* function must return NULL.
* Note:
* Several "source files" may be open at the same time. Specifically, one
* file can be open for reading and another for writing.
*/
void *pc_createsrc(char *filename)
{
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 + src->maxlength;
return src;
}
/* pc_closesrc()
* Closes a source file (or include file). The "handle" parameter has the
* value that pc_opensrc() returned in an earlier call.
*/
void pc_closesrc(void *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_readsrc()
* Reads a single line from the source file (or up to a maximum number of
* characters if the line in the input file is too long).
*/
char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
{
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';
} else {
// Replace with \n.
*(outptr - 1) = '\n';
}
break;
}
}
// Caller passes in a buffer of size >= maxchars+1.
*outptr = '\0';
return (char *)target;
}
/* pc_writesrc()
* Writes to to the source file. There is no automatic line ending; to end a
* line, write a "\n".
*/
int pc_writesrc(void *handle,unsigned char *source)
{
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,void *position)
{
src_file_t *src = (src_file_t *)handle;
assert(!src->fp);
return (void *)(ptrdiff_t)(src->pos - src->buffer);
}
/* pc_resetsrc()
* "position" may only hold a pointer that was previously obtained from
* pc_getpossrc()
*/
void pc_resetsrc(void *handle,void *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;
}
int pc_eofsrc(void *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
* functions; return NULL for failure
*/
void *pc_openasm(char *filename)
{
return mfcreate(filename);
}
void pc_closeasm(void *handle, int deletefile)
{
if (handle!=NULL) {
if (!deletefile)
mfdump((MEMFILE*)handle);
mfclose((MEMFILE*)handle);
} /* if */
}
void pc_resetasm(void *handle)
{
mfseek((MEMFILE*)handle,0,SEEK_SET);
}
int pc_writeasm(void *handle,const char *string)
{
return mfputs((MEMFILE*)handle,string);
}
char *pc_readasm(void *handle, char *string, int maxchars)
{
return mfgets((MEMFILE*)handle,string,maxchars);
}

View File

@ -1,124 +0,0 @@
/* Safe string copying and concatenation
* These routines are originally distributed in two separate files. I have
* copied the files verbatim in this single source file, including all comments.
* The only change is that the second set of include files is commented out
* (there is no need to include the same files twice).
*/
#include "lstring.h"
#if !defined HAVE_SAFESTR
/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
#include <sys/types.h> already included through lstring.h
*/
#include <string.h> /* for strlen() */
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
extern "C" size_t
strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
#include <sys/types.h> already included
#include <string.h> already included
*/
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
extern "C" size_t
strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
#endif /* #if !defined HAVE_SAFESTR */

View File

@ -1,26 +0,0 @@
/* prototypes for strlcpy() and strlcat() */
#include <stddef.h>
#if defined __WATCOMC__ && __WATCOMC__ >= 1240
/* OpenWatcom introduced BSD "safe string functions" with version 1.4 */
#define HAVE_SAFESTR
#endif
#if !defined HAVE_SAFESTR
#if defined(__cplusplus)
# define EXPORT extern "C"
#else
# define EXPORT
#endif
EXPORT size_t
strlcpy(char *dst, const char *src, size_t siz);
EXPORT size_t
strlcat(char *dst, const char *src, size_t siz);
#undef EXPORT
#endif

View File

@ -1,116 +0,0 @@
#include "memfile.h"
#include <string.h>
#include "osdefs.h"
memfile_t *memfile_creat(const char *name, size_t init)
{
memfile_t mf;
memfile_t *pmf;
mf.size = init;
mf.base = (char *)malloc(init);
mf.usedoffs = 0;
if (!mf.base)
{
return NULL;
}
mf.offs = 0;
mf._static = 0;
pmf = (memfile_t *)malloc(sizeof(memfile_t));
memcpy(pmf, &mf, sizeof(memfile_t));
pmf->name = strdup(name);
return pmf;
}
void memfile_destroy(memfile_t *mf)
{
if (!mf)
{
return;
}
if (!mf->_static)
{
free(mf->name);
free(mf->base);
free(mf);
}
}
void memfile_seek(memfile_t *mf, long seek)
{
mf->offs = seek;
}
long memfile_tell(memfile_t *mf)
{
return mf->offs;
}
size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize)
{
if (!maxsize || mf->offs >= mf->usedoffs)
{
return 0;
}
if (mf->usedoffs - mf->offs < (long)maxsize)
{
maxsize = mf->usedoffs - mf->offs;
if (!maxsize)
{
return 0;
}
}
memcpy(buffer, mf->base + mf->offs, maxsize);
mf->offs += maxsize;
return maxsize;
}
int memfile_write(memfile_t *mf, const void *buffer, size_t size)
{
if (mf->offs + size > mf->size)
{
size_t newsize = (mf->size + size) * 2;
if (mf->_static)
{
char *oldbase = mf->base;
mf->base = (char *)malloc(newsize);
if (!mf->base)
{
return 0;
}
memcpy(mf->base, oldbase, mf->size);
} else {
mf->base = (char *)realloc(mf->base, newsize);
if (!mf->base)
{
return 0;
}
}
mf->_static = 0;
mf->size = newsize;
}
memcpy(mf->base + mf->offs, buffer, size);
mf->offs += size;
if (mf->offs > mf->usedoffs)
{
mf->usedoffs = mf->offs;
}
return 1;
}
void memfile_reset(memfile_t *mf)
{
mf->usedoffs = 0;
mf->offs = 0;
}

View File

@ -1,66 +0,0 @@
#ifndef _INCLUDE_MEMFILE_H
#define _INCLUDE_MEMFILE_H
#include <stdlib.h>
typedef struct memfile_s
{
char *name;
char *base;
long offs;
long usedoffs;
size_t size;
int _static;
} memfile_t;
/**
* Creates a new memory file
* init is the initial size in bytes
*/
memfile_t *memfile_creat(const char *name, size_t init);
/**
* Frees the memory associated.
*/
void memfile_destroy(memfile_t *mf);
/**
* Seeks to a given offset (always from start)
*/
void memfile_seek(memfile_t *mf, long seek);
/**
* Writes to a memory buffer (expands as necessary).
* Returns 1 on success, 0 on failure.
*/
int memfile_write(memfile_t *mf, const void *buffer, size_t size);
/**
* Reads a number of bytes from a memory buffer.
* Returns the number of bytes read until the end was hit.
*/
size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize);
/**
* Returns the current position from the start.
*/
long memfile_tell(memfile_t *mf);
/**
* Resets all the states of the memory buffer.
* (does not actually free or zero memory)
*/
void memfile_reset(memfile_t *mf);
typedef memfile_t MEMFILE;
MEMFILE *mfcreate(const char *filename);
void mfclose(MEMFILE *mf);
int mfdump(MEMFILE *mf);
long mflength(const MEMFILE *mf);
long mfseek(MEMFILE *mf,long offset,int whence);
unsigned int mfwrite(MEMFILE *mf,const unsigned char *buffer,unsigned int size);
unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size);
char *mfgets(MEMFILE *mf,char *string,unsigned int size);
int mfputs(MEMFILE *mf,const char *string);
#endif //_INCLUDE_MEMFILE_H

View File

@ -1,103 +0,0 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2012-2014 AlliedModders LLC, David Anderson
//
// This file is part of SourcePawn.
//
// SourcePawn is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
#ifndef _include_sp_memory_buffer_h_
#define _include_sp_memory_buffer_h_
#include <stdio.h>
#include <am-utility.h>
#include "smx-builder.h"
// Interface for SmxBuilder to blit bytes.
class ISmxBuffer
{
public:
virtual bool write(const void *bytes, size_t len) = 0;
virtual size_t pos() const = 0;
};
// An in-memory buffer for SmxBuilder.
class MemoryBuffer : public ISmxBuffer
{
static const size_t kDefaultSize = 4096;
public:
MemoryBuffer() {
buffer_ = (uint8_t *)calloc(kDefaultSize, 1);
pos_ = buffer_;
end_ = buffer_ + kDefaultSize;
}
~MemoryBuffer() {
free(buffer_);
}
bool write(const void *bytes, size_t len) KE_OVERRIDE {
if (pos_ + len > end_)
grow(len);
memcpy(pos_, bytes, len);
pos_ += len;
return true;
}
size_t pos() const KE_OVERRIDE {
return pos_ - buffer_;
}
uint8_t *bytes() const {
return buffer_;
}
size_t size() const {
return pos();
}
void rewind(size_t newpos) {
assert(newpos < pos());
pos_ = buffer_ + newpos;
}
private:
void grow(size_t len) {
if (!ke::IsUintPtrAddSafe(pos(), len)) {
fprintf(stderr, "Allocation overflow!\n");
abort();
}
size_t new_maxsize = end_ - buffer_;
while (pos() + len > new_maxsize) {
if (!ke::IsUintPtrMultiplySafe(new_maxsize, 2)) {
fprintf(stderr, "Allocation overflow!\n");
abort();
}
new_maxsize *= 2;
}
uint8_t *newbuffer = (uint8_t *)realloc(buffer_, new_maxsize);
if (!newbuffer) {
fprintf(stderr, "Out of memory!\n");
abort();
}
pos_ = newbuffer + (pos_ - buffer_);
end_ = newbuffer + new_maxsize;
buffer_ = newbuffer;
}
private:
uint8_t *buffer_;
uint8_t *pos_;
uint8_t *end_;
};
#endif // _include_sp_memory_buffer_h_

View File

@ -1,111 +0,0 @@
/* __MSDOS__ set when compiling for DOS (not Windows)
* _Windows set when compiling for any version of Microsoft Windows
* __WIN32__ set when compiling for Windows95 or WindowsNT (32 bit mode)
* __32BIT__ set when compiling in 32-bit "flat" mode (DOS or Windows)
*
* Copyright 1998-2005, ITB CompuPhase, The Netherlands.
* info@compuphase.com.
*/
#ifndef _OSDEFS_H
#define _OSDEFS_H
/* Every compiler uses different "default" macros to indicate the mode
* it is in. Throughout the source, we use the Borland C++ macros, so
* the macros of Watcom C/C++ and Microsoft Visual C/C++ are mapped to
* those of Borland C++.
*/
#if defined(__WATCOMC__)
# if defined(__WINDOWS__) || defined(__NT__)
# define _Windows 1
# endif
# ifdef __386__
# define __32BIT__ 1
# endif
# if defined(_Windows) && defined(__32BIT__)
# define __WIN32__ 1
# endif
#elif defined(_MSC_VER)
# if defined(_WINDOWS) || defined(_WIN32)
# define _Windows 1
# endif
# ifdef _WIN32
# define __WIN32__ 1
# define __32BIT__ 1
# endif
# if _MSC_VER >= 1400
# if !defined _CRT_SECURE_NO_DEPRECATE
# define _CRT_SECURE_NO_DEPRECATE
# endif
# define strdup _strdup
# define stricmp _stricmp
# define access _access
# define chdir _chdir
# define strdup _strdup
# define unlink _unlink
# endif
#endif
#if defined __FreeBSD__
#include <sys/endian.h>
#elif defined __APPLE__
#include <machine/endian.h>
#elif defined LINUX
#include <endian.h>
#endif
/* Linux NOW has these */
#if !defined BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
#if !defined LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
/* educated guess, BYTE_ORDER is undefined, i386 is common => little endian */
#if !defined BYTE_ORDER
#if defined UCLINUX
#define BYTE_ORDER BIG_ENDIAN
#else
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#endif
#if defined __MSDOS__ || defined __WIN32__ || defined _Windows
#define DIRSEP_CHAR '\\'
#elif defined macintosh
#define DIRSEP_CHAR ':'
#else
#define DIRSEP_CHAR '/' /* directory separator character */
#endif
/* _MAX_PATH is sometimes called differently and it may be in limits.h or
* stdlib.h instead of stdio.h.
*/
#if !defined _MAX_PATH
/* not defined, perhaps stdio.h was not included */
#if !defined PATH_MAX
#include <stdio.h>
#endif
#if !defined _MAX_PATH && !defined PATH_MAX
/* no _MAX_PATH and no MAX_PATH, perhaps it is in limits.h */
#include <limits.h>
#endif
#if !defined _MAX_PATH && !defined PATH_MAX
/* no _MAX_PATH and no MAX_PATH, perhaps it is in stdlib.h */
#include <stdlib.h>
#endif
/* if _MAX_PATH is undefined, try common alternative names */
#if !defined _MAX_PATH
#if defined MAX_PATH
#define _MAX_PATH MAX_PATH
#elif defined _POSIX_PATH_MAX
#define _MAX_PATH _POSIX_PATH_MAX
#else
/* everything failed, actually we have a problem here... */
#define _MAX_PATH 1024
#endif
#endif
#endif
#endif /* _OSDEFS_H */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -1,43 +0,0 @@
#include <stdio.h>
#include <setjmp.h>
#include <assert.h>
#include <string.h>
#include "memfile.h"
#include "osdefs.h"
#if defined LINUX || defined DARWIN
#include <unistd.h>
#elif defined WIN32
#include <io.h>
#endif
#include "sc.h"
int main(int argc, char *argv[])
{
return pc_compile(argc,argv);
}
#if defined __linux__ || defined __APPLE__
extern "C" void __cxa_pure_virtual(void)
{
}
void *operator new(size_t size)
{
return malloc(size);
}
void *operator new[](size_t size)
{
return malloc(size);
}
void operator delete(void *ptr)
{
free(ptr);
}
void operator delete[](void * ptr)
{
free(ptr);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,272 +0,0 @@
/* Pawn compiler - Error message strings (plain and compressed formats)
*
* Copyright (c) ITB CompuPhase, 2000-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
static const char *errmsg[] = {
/*001*/ "expected token: \"%s\", but found \"%s\"\n",
/*002*/ "only a single statement (or expression) can follow each \"case\"\n",
/*003*/ "declaration of a local variable must appear in a compound block\n",
/*004*/ "function \"%s\" is not implemented\n",
/*005*/ "function may not have arguments\n",
/*006*/ "must be assigned to an array\n",
/*007*/ "operator cannot be redefined\n",
/*008*/ "must be a constant expression; assumed zero\n",
/*009*/ "invalid array size (negative, zero or out of bounds)\n",
/*010*/ "invalid function or declaration\n",
/*011*/ "invalid outside functions\n",
/*012*/ "invalid function call, not a valid address\n",
/*013*/ "no entry point (no public functions)\n",
/*014*/ "invalid statement; not in switch\n",
/*015*/ "\"default\" case must be the last case in switch statement\n",
/*016*/ "multiple defaults in \"switch\"\n",
/*017*/ "undefined symbol \"%s\"\n",
/*018*/ "initialization data exceeds declared size\n",
/*019*/ "not a label: \"%s\"\n",
/*020*/ "invalid symbol name \"%s\"\n",
/*021*/ "symbol already defined: \"%s\"\n",
/*022*/ "must be lvalue (non-constant)\n",
/*023*/ "array assignment must be simple assignment\n",
/*024*/ "\"break\" or \"continue\" is out of context\n",
/*025*/ "function heading differs from prototype\n",
/*026*/ "no matching \"#if...\"\n",
/*027*/ "invalid character constant\n",
/*028*/ "invalid subscript (not an array or too many subscripts): \"%s\"\n",
/*029*/ "invalid expression, assumed zero\n",
/*030*/ "compound statement not closed at the end of file (started at line %d)\n",
/*031*/ "unknown directive\n",
/*032*/ "array index out of bounds (variable \"%s\")\n",
/*033*/ "array must be indexed (variable \"%s\")\n",
/*034*/ "argument does not have a default value (argument %d)\n",
/*035*/ "argument type mismatch (argument %d)\n",
/*036*/ "empty statement\n",
/*037*/ "invalid string (possibly non-terminated string)\n",
/*038*/ "extra characters on line\n",
/*039*/ "constant symbol has no size\n",
/*040*/ "duplicate \"case\" label (value %d)\n",
/*041*/ "invalid ellipsis, array size is not known\n",
/*042*/ "invalid combination of class specifiers\n",
/*043*/ "character constant exceeds range for packed string\n",
/*044*/ "positional parameters must precede all named parameters\n",
/*045*/ "too many function arguments\n",
/*046*/ "unknown array size (variable \"%s\")\n",
/*047*/ "array sizes do not match, or destination array is too small\n",
/*048*/ "array (s do not match\n",
/*049*/ "invalid line continuation\n",
/*050*/ "invalid range\n",
/*051*/ "invalid subscript, use \"[ ]\" operators on major dimensions\n",
/*052*/ "multi-dimensional arrays must be fully initialized\n",
/*053*/ "exceeding maximum number of dimensions\n",
/*054*/ "unmatched closing brace (\"}\")\n",
/*055*/ "start of function body without function header\n",
/*056*/ "arrays, local variables and function arguments cannot be public (variable \"%s\")\n",
/*057*/ "unfinished expression before compiler directive\n",
/*058*/ "duplicate argument; same argument is passed twice\n",
/*059*/ "function argument may not have a default value (variable \"%s\")\n",
/*060*/ "multiple \"#else\" directives between \"#if ... #endif\"\n",
/*061*/ "\"#elseif\" directive follows an \"#else\" directive\n",
/*062*/ "number of operands does not fit the operator\n",
/*063*/ "function result tag of operator \"%s\" must be \"%s\"\n",
/*064*/ "cannot change predefined operators\n",
/*065*/ "function argument may only have a single tag (argument %d)\n",
/*066*/ "function argument may not be a reference argument or an array (argument \"%s\")\n",
/*067*/ "variable cannot be both a reference and an array (variable \"%s\")\n",
/*068*/ "invalid rational number precision in #pragma\n",
/*069*/ "rational number format already defined\n",
/*070*/ "rational number support was not enabled\n",
/*071*/ "user-defined operator must be declared before use (function \"%s\")\n",
/*072*/ "\"sizeof\" operator is invalid on \"function\" symbols\n",
/*073*/ "function argument must be an array (argument \"%s\")\n",
/*074*/ "#define pattern must start with an alphabetic character\n",
/*075*/ "input line too long (after substitutions)\n",
/*076*/ "syntax error in the expression, or invalid function call\n",
/*077*/ "malformed UTF-8 encoding, or corrupted file: %s\n",
/*078*/ "function uses both \"return\" and \"return <value>\"\n",
/*079*/ "inconsistent return types (array & non-array)\n",
/*080*/ "unknown symbol, or not a constant symbol (symbol \"%s\")\n",
/*081*/ "cannot take a tag as a default value for an indexed array parameter (symbol \"%s\")\n",
/*082*/ "user-defined operators and native functions may not have states\n",
/*083*/ "a function or variable may only belong to a single automaton (symbol \"%s\")\n",
/*084*/ "state conflict: one of the states is already assigned to another implementation (symbol \"%s\")\n",
/*085*/ "no states are defined for symbol \"%s\"\n",
/*086*/ "unknown automaton \"%s\"\n",
/*087*/ "unknown state \"%s\" for automaton \"%s\"\n",
/*088*/ "public variables and local variables may not have states (symbol \"%s\")\n",
/*089*/ "state variables may not be initialized (symbol \"%s\")\n",
/*090*/ "public functions may not return arrays (symbol \"%s\")\n",
/*091*/ "ambiguous constant; tag override is required (symbol \"%s\")\n",
/*092*/ "number of arguments does not match definition\n",
/*093*/ "expected tag name identifier\n",
/*094*/ "function enumeration requires unique tag\n",
/*095*/ "cannot have required parameters after optional parameters\n",
/*096*/ "could not find member \"%s\" in struct \"%s\"\n",
/*097*/ "symbol \"%s\" does not have a matching type\n",
/*098*/ "type \"%s\" should be \"%s\" in new-style declarations\n",
/*099*/ "%s should not have an explicit return type\n",
/*100*/ "function prototypes do not match\n",
/*101*/ "specify either all dimensions or only the last dimension\n",
/*102*/ "cannot find %s %s\n",
/*103*/ "%s was already defined on this %s\n",
/*104*/ "cannot find any methods for %s\n",
/*105*/ "cannot find method or property %s.%s\n",
/*106*/ "cannot call methods on an array\n",
/*107*/ "cannot call methods on a function\n",
/*108*/ "method must have a first argument compatible with the %s type (%s)\n",
/*109*/ "%s name must start with an uppercase letter\n",
/*110*/ "%s has already been defined (previously seen as %s)\n",
/*111*/ "expected identifier - did you forget a type?\n",
/*112*/ "constructor function must return tag %s\n",
/*113*/ "constructor for \"%s\" already exists\n",
/*114*/ "missing type, or %s must have the same name as %s \"%s\"\n",
/*115*/ "cannot use delete, %s %s has no destructor\n",
/*116*/ "no methodmap or class was found for %s\n",
/*117*/ "no destructor was found for %s %s\n",
/*118*/ "destructors must be native functions\n",
/*119*/ "destructors cannot have extra arguments\n",
/*120*/ "methodmap and class signatures must use new-style type declarations\n",
/*121*/ "cannot specify array dimensions on both type and name\n",
/*122*/ "expected type expression\n",
/*123*/ "fully-qualified name \"%s\" is too long, would be truncated to \"%s\"\n",
/*124*/ "unexpected token, expected method or property\n",
/*125*/ "expected \"native\", \"get\", or \"set\"\n",
/*126*/ "%s for %s already exists\n",
/*127*/ "property getters cannot accept extra arguments\n",
/*128*/ "%s must have the same return type as property %s (%s)\n",
/*129*/ "cannot mix methodmaps and classes with inheritance\n",
/*130*/ "cannot coerce functions to values\n",
/*131*/ "cannot coerce object type %s to non-object type %s\n",
/*132*/ "cannot coerce non-object type %s to object type %s\n",
/*133*/ "cannot coerce unrelated object types %s and %s\n",
/*134*/ "type mismatch (%s and %s)\n",
/*135*/ "cannot use an object in a multi-tag selector\n",
/*136*/ "arrays are not supported as return types\n",
/*137*/ "cannot mix reference and array types\n",
/*138*/ "const was specified twice\n",
/*139*/ "could not find type \"%s\"\n",
/*140*/ "new-style array types cannot specify dimension sizes as part of their type\n",
/*141*/ "natives, forwards, and public functions cannot return arrays\n",
/*142*/ "invalid type declaration\n",
/*143*/ "new-style declarations should not have \"new\"\n",
/*144*/ "void cannot be used as a variable type\n",
/*145*/ "invalid type expression\n",
/*146*/ "#pragma newdecls must be required or optional\n",
/*147*/ "new-style declarations are required\n",
/*148*/ "cannot assign null to a non-nullable type\n",
/*149*/ "no getter found for property %s\n",
/*150*/ "setter must take exactly one extra argument with type %s\n",
/*151*/ "setter must return void\n",
/*152*/ "no setter found for property %s\n",
/*153*/ "cannot use non-public functions as callbacks\n",
/*154*/ "cannot assign INVALID_FUNCTION to a non-function type\n",
/*155*/ "expected newline, but found '%s'\n",
/*156*/ "unused156\n",
/*157*/ "'%s' is a reserved keyword\n",
/*158*/ "multi-tags are no longer supported\n",
/*159*/ "brackets after variable name indicate a fixed-size array, but size could not be determined - either specify sizes, an array initializer, or use dynamic syntax (such as 'char[] x')\n",
/*160*/ "brackets in between type and variable name indicate a dynamic-size array, but a fixed-size initializer was given\n",
/*161*/ "brackets after variable name indicate a fixed-size array, but a dynamic size was given - did you mean to use 'new %s[size]' syntax?\n",
/*162*/ "cannot create dynamic arrays in global scope - did you mean to create a fixed-length array with brackets after the variable name?\n",
/*163*/ "indeterminate array size in \"sizeof\" expression (symbol \"%s\")\n",
/*164*/ "allocated array type '%s' doesn't match original type '%s'\n",
/*165*/ "cannot create dynamic arrays in static scope - did you mean to create a fixed-length array with brackets after the variable name?\n",
/*166*/ "cannot use 'this' outside of a methodmap method or property\n",
/*167*/ "cannot use delete, %s do not have destructors\n",
/*168*/ "re-tagging enums is no longer supported\n",
/*169*/ "cannot tag an enum as implicit-int\n",
/*170*/ "creating new object '%s' requires using 'new' before its constructor\n",
/*171*/ "cannot use 'new' with non-object-like methodmap '%s'\n",
/*172*/ "methodmap '%s' does not have a constructor\n",
/*173*/ "'%s' is a newly reserved keyword that may be used in the future; use a different name as an identifier\n",
/*174*/ "symbol '%s' is a type and cannot be used as a value\n",
/*175*/ "constructors cannot be static\n",
/*176*/ "non-static method or property '%s' must be called with a value of type '%s'\n",
/*177*/ "static method '%s' must be invoked via its type (try '%s.%s')\n",
/*178*/ "cannot coerce %s[] to %s[]; storage classes differ\n",
/*179*/ "cannot assign %s[] to %s[], storage classes differ\n",
/*180*/ "function return type differs from prototype. expected '%s', but got '%s'\n",
/*181*/ "function argument named '%s' differs from prototype\n",
/*182*/ "functions that return arrays cannot be used as callbacks\n",
};
static const char *fatalmsg[] = {
/*182*/ "cannot read from file: \"%s\"\n",
/*183*/ "cannot write to file: \"%s\"\n",
/*184*/ "table overflow: \"%s\"\n",
/* table can be: loop table
* literal table
* staging buffer
* option table (response file)
* peephole optimizer table
*/
/*185*/ "insufficient memory\n",
/*186*/ "invalid assembler instruction \"%s\"\n",
/*187*/ "numeric overflow, exceeding capacity\n",
/*188*/ "compiled script exceeds the maximum memory size (%ld bytes)\n",
/*189*/ "too many error messages on one line\n",
/*190*/ "codepage mapping file not found\n",
/*191*/ "invalid path: \"%s\"\n",
/*192*/ "assertion failed: %s\n",
/*193*/ "user error: %s\n",
};
static const char *warnmsg[] = {
/*200*/ "symbol \"%s\" is truncated to %d characters\n",
/*201*/ "redefinition of constant/macro (symbol \"%s\")\n",
/*202*/ "number of arguments does not match definition\n",
/*203*/ "symbol is never used: \"%s\"\n",
/*204*/ "symbol is assigned a value that is never used: \"%s\"\n",
/*205*/ "redundant code: constant expression is zero\n",
/*206*/ "redundant test: constant expression is non-zero\n",
/*207*/ "unknown #pragma\n",
/*208*/ "function with tag result used before definition, forcing reparse\n",
/*209*/ "function \"%s\" should return a value\n",
/*210*/ "possible use of symbol before initialization: \"%s\"\n",
/*211*/ "possibly unintended assignment\n",
/*212*/ "possibly unintended bitwise operation\n",
/*213*/ "tag mismatch\n",
/*214*/ "possibly a \"const\" array argument was intended: \"%s\"\n",
/*215*/ "expression has no effect\n",
/*216*/ "nested comment\n",
/*217*/ "loose indentation\n",
/*218*/ "old style prototypes used with optional semicolumns\n",
/*219*/ "local variable \"%s\" shadows a variable at a preceding level\n",
/*220*/ "expression with tag override must appear between parentheses\n",
/*221*/ "label name \"%s\" shadows tag name\n",
/*222*/ "number of digits exceeds rational number precision\n",
/*223*/ "redundant \"sizeof\": argument size is always 1 (symbol \"%s\")\n",
/*224*/ "unused\n",
/*225*/ "unreachable code\n",
/*226*/ "a variable is assigned to itself (symbol \"%s\")\n",
/*227*/ "more initializers than enum fields\n",
/*228*/ "length of initializer exceeds size of the enum field\n",
/*229*/ "index tag mismatch (symbol \"%s\")\n",
/*230*/ "no implementation for state \"%s\" in function \"%s\", no fall-back\n",
/*231*/ "state specification on forward declaration is ignored\n",
/*232*/ "output file is written, but with compact encoding disabled\n",
/*233*/ "state variable \"%s\" shadows a global variable\n",
/*234*/ "symbol \"%s\" is marked as deprecated: %s\n",
/*235*/ "public function lacks forward declaration (symbol \"%s\")\n",
/*236*/ "unknown parameter in substitution (incorrect #define pattern)\n",
/*237*/ "coercing functions to and from primitives is unsupported and will be removed in the future\n",
/*238*/ "'%s:' is an illegal cast; use view_as<%s>(expression)\n",
/*239*/ "'%s' is an illegal tag; use %s as a type\n",
/*240*/ "'%s:' is an old-style tag operation; use view_as<%s>(expression) instead\n",
};

View File

@ -1,243 +0,0 @@
// vim: set ts=8 sts=2 sw=2 tw=99 et:
/* Pawn compiler - Error message system
* In fact a very simple system, using only 'panic mode'.
*
* Copyright (c) ITB CompuPhase, 1997-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#if defined __WIN32__ || defined _WIN32 || defined __MSDOS__
#include <io.h>
#endif
#if defined LINUX || defined __GNUC__
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h> /* ANSI standardized variable argument list functions */
#include <string.h>
#if defined FORTIFY
#include <alloc/fortify.h>
#endif
#include "sc.h"
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */
#endif
#include "sc5-in.scp"
#if defined _MSC_VER
#pragma warning(pop)
#endif
#define NUM_WARNINGS (int)(sizeof warnmsg / sizeof warnmsg[0])
static unsigned char warndisable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char */
static int errflag;
static int errstart; /* line number at which the instruction started */
static int sErrLine; /* forced line number for the error message */
/* error
*
* Outputs an error message (note: msg is passed optionally).
* If an error is found, the variable "errflag" is set and subsequent
* errors are ignored until lex() finds a semicolumn or a keyword
* (lex() resets "errflag" in that case).
*
* Global references: inpfname (reffered to only)
* fline (reffered to only)
* fcurrent (reffered to only)
* errflag (altered)
*/
int error(int number,...)
{
static const char *prefix[3]={ "error", "fatal error", "warning" };
static int lastline,errorcount;
static short lastfile;
const char *msg,*pre;
va_list argptr;
// sErrLine is used to temporarily change the line number of reported errors.
// Pawn has an upstream bug where this is not reset on early-return, which
// can lead to broken line numbers in error messages.
int errline = sErrLine;
sErrLine = -1;
bool is_warning = (number >= 200 && !sc_warnings_are_errors);
/* errflag is reset on each semicolon.
* In a two-pass compiler, an error should not be reported twice. Therefore
* the error reporting is enabled only in the second pass (and only when
* actually producing output). Fatal errors may never be ignored.
*/
int not_fatal = (number < FIRST_FATAL_ERROR || number >= 200);
if (errflag && not_fatal)
return 0;
if (sc_status != statWRITE && not_fatal) {
if (!sc_err_status)
return 0;
}
/* also check for disabled warnings */
if (number>=200) {
int index=(number-200)/8;
int mask=1 << ((number-200)%8);
if ((warndisable[index] & mask)!=0)
return 0;
} /* if */
if (number<FIRST_FATAL_ERROR) {
msg=errmsg[number-1];
pre=prefix[0];
errflag=TRUE; /* set errflag (skip rest of erroneous expression) */
errnum++;
} else if (number<200){
msg=fatalmsg[number-FIRST_FATAL_ERROR];
pre=prefix[1];
errnum++; /* a fatal error also counts as an error */
} else {
msg=warnmsg[number-200];
if (sc_warnings_are_errors) {
pre=prefix[0];
errnum++;
} else {
pre=prefix[2];
warnnum++;
}
} /* if */
assert(errstart<=fline);
if (errline>0)
errstart=errline;
else
errline=fline;
assert(errstart<=errline);
va_start(argptr,number);
if (strlen(errfname)==0) {
int start= (errstart==errline) ? -1 : errstart;
if (pc_error(number,msg,inpfname,start,errline,argptr)) {
if (outf!=NULL) {
pc_closeasm(outf,TRUE);
outf=NULL;
} /* if */
longjmp(errbuf,3); /* user abort */
} /* if */
} else {
FILE *fp=fopen(errfname,"a");
if (fp!=NULL) {
if (errstart>=0 && errstart!=errline)
fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,number);
else
fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,number);
vfprintf(fp,msg,argptr);
fclose(fp);
} /* if */
} /* if */
va_end(argptr);
if ((number>=FIRST_FATAL_ERROR && number<200) || errnum>25){
if (strlen(errfname)==0) {
va_start(argptr,number);
pc_error(0,"\nCompilation aborted.",NULL,0,0,argptr);
va_end(argptr);
} /* if */
if (outf!=NULL) {
pc_closeasm(outf,TRUE);
outf=NULL;
} /* if */
longjmp(errbuf,2); /* fatal error, quit */
} /* if */
/* check whether we are seeing many errors on the same line */
if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile)
errorcount=0;
lastline=fline;
lastfile=fcurrent;
if (!is_warning)
errorcount++;
if (errorcount>=3)
error(FATAL_ERROR_OVERWHELMED_BY_BAD);
return 0;
}
void errorset(int code,int line)
{
switch (code) {
case sRESET:
errflag=FALSE; /* start reporting errors */
break;
case sFORCESET:
errflag=TRUE; /* stop reporting errors */
break;
case sEXPRMARK:
errstart=fline; /* save start line number */
break;
case sEXPRRELEASE:
errstart=-1; /* forget start line number */
sErrLine=-1;
break;
case sSETPOS:
sErrLine=line;
break;
} /* switch */
}
/* sc_enablewarning()
* Enables or disables a warning (errors cannot be disabled).
* Initially all warnings are enabled. The compiler does this by setting bits
* for the *disabled* warnings and relying on the array to be zero-initialized.
*
* Parameter enable can be:
* o 0 for disable
* o 1 for enable
* o 2 for toggle
*/
int pc_enablewarning(int number,int enable)
{
int index;
unsigned char mask;
if (number<200)
return FALSE; /* errors and fatal errors cannot be disabled */
number -= 200;
if (number>=NUM_WARNINGS)
return FALSE;
index=number/8;
mask=(unsigned char)(1 << (number%8));
switch (enable) {
case 0:
warndisable[index] |= mask;
break;
case 1:
warndisable[index] &= (unsigned char)~mask;
break;
case 2:
warndisable[index] ^= mask;
break;
} /* switch */
return TRUE;
}
#undef SCPACK_TABLE

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,653 +0,0 @@
/* Pawn compiler - Staging buffer and optimizer
*
* The staging buffer
* ------------------
* The staging buffer allows buffered output of generated code, deletion
* of redundant code, optimization by a tinkering process and reversing
* the ouput of evaluated expressions (which is used for the reversed
* evaluation of arguments in functions).
* Initially, stgwrite() writes to the file directly, but after a call to
* stgset(TRUE), output is redirected to the buffer. After a call to
* stgset(FALSE), stgwrite()'s output is directed to the file again. Thus
* only one routine is used for writing to the output, which can be
* buffered output or direct output.
*
* staging buffer variables: stgbuf - the buffer
* stgidx - current index in the staging buffer
* staging - if true, write to the staging buffer;
* if false, write to file directly.
*
* The peephole optimizer uses a dual "pipeline". The staging buffer (described
* above) gets optimized for each expression or sub-expression in a function
* call. The peephole optimizer is recursive, but it does not span multiple
* sub-expressions. However, the data gets written to a second buffer that
* behaves much like the staging buffer. This second buffer gathers all
* optimized strings from the staging buffer for a complete expression. The
* peephole optmizer then runs over this second buffer to find optimzations
* across function parameter boundaries.
*
*
* Copyright (c) ITB CompuPhase, 1997-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h> /* for atoi() */
#include <string.h>
#include <ctype.h>
#if defined FORTIFY
#include <alloc/fortify.h>
#endif
#include "sc.h"
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */
#endif
#include "sc7-in.scp"
#if defined _MSC_VER
#pragma warning(pop)
#endif
static int stgstring(char *start,char *end);
static void stgopt(char *start,char *end,int (*outputfunc)(char *str));
#define sSTG_GROW 512
#define sSTG_MAX 20480
static char *stgbuf=NULL;
static int stgmax=0; /* current size of the staging buffer */
static char *stgpipe=NULL;
static int pipemax=0; /* current size of the stage pipe, a second staging buffer */
static int pipeidx=0;
#define CHECK_STGBUFFER(index) if ((int)(index)>=stgmax) grow_stgbuffer(&stgbuf, &stgmax, (index)+1)
#define CHECK_STGPIPE(index) if ((int)(index)>=pipemax) grow_stgbuffer(&stgpipe, &pipemax, (index)+1)
static void grow_stgbuffer(char **buffer, int *curmax, int requiredsize)
{
char *p;
int clear= (*buffer==NULL); /* if previously none, empty buffer explicitly */
assert(*curmax<requiredsize);
/* if the staging buffer (holding intermediate code for one line) grows
* over a few kBytes, there is probably a run-away expression
*/
if (requiredsize>sSTG_MAX)
error(FATAL_ERROR_OOM);
*curmax=requiredsize+sSTG_GROW;
if (*buffer!=NULL)
p=(char *)realloc(*buffer,*curmax*sizeof(char));
else
p=(char *)malloc(*curmax*sizeof(char));
if (p==NULL)
error(FATAL_ERROR_OOM);
*buffer=p;
if (clear)
**buffer='\0';
}
void stgbuffer_cleanup(void)
{
if (stgbuf!=NULL) {
free(stgbuf);
stgbuf=NULL;
stgmax=0;
} /* if */
if (stgpipe!=NULL) {
free(stgpipe);
stgpipe=NULL;
pipemax=0;
pipeidx=0;
} /* if */
}
/* the variables "stgidx" and "staging" are declared in "scvars.c" */
/* stgmark
*
* Copies a mark into the staging buffer. At this moment there are three
* possible marks:
* sSTARTREORDER identifies the beginning of a series of expression
* strings that must be written to the output file in
* reordered order
* sENDREORDER identifies the end of 'reverse evaluation'
* sEXPRSTART + idx only valid within a block that is evaluated in
* reordered order, it identifies the start of an
* expression; the "idx" value is the argument position
*
* Global references: stgidx (altered)
* stgbuf (altered)
* staging (referred to only)
*/
void stgmark(char mark)
{
if (staging) {
CHECK_STGBUFFER(stgidx);
stgbuf[stgidx++]=mark;
} /* if */
}
static int rebuffer(char *str)
{
if (sc_status==statWRITE) {
if (pipeidx>=2 && stgpipe[pipeidx-1]=='\0' && stgpipe[pipeidx-2]!='\n')
pipeidx-=1; /* overwrite last '\0' */
while (*str!='\0') { /* copy to staging buffer */
CHECK_STGPIPE(pipeidx);
stgpipe[pipeidx++]=*str++;
} /* while */
CHECK_STGPIPE(pipeidx);
stgpipe[pipeidx++]='\0';
} /* if */
return TRUE;
}
static int filewrite(char *str)
{
if (sc_status==statWRITE)
return pc_writeasm(outf,str);
return TRUE;
}
/* stgwrite
*
* Writes the string "st" to the staging buffer or to the output file. In the
* case of writing to the staging buffer, the terminating byte of zero is
* copied too, but... the optimizer can only work on complete lines (not on
* fractions of it. Therefore if the string is staged, if the last character
* written to the buffer is a '\0' and the previous-to-last is not a '\n',
* the string is concatenated to the last string in the buffer (the '\0' is
* overwritten). This also means an '\n' used in the middle of a string isn't
* recognized and could give wrong results with the optimizer.
* Even when writing to the output file directly, all strings are buffered
* until a whole line is complete.
*
* Global references: stgidx (altered)
* stgbuf (altered)
* staging (referred to only)
*/
void stgwrite(const char *st)
{
int len;
if (staging) {
assert(stgidx==0 || stgbuf!=NULL); /* staging buffer must be valid if there is (apparently) something in it */
if (stgidx>=2 && stgbuf[stgidx-1]=='\0' && stgbuf[stgidx-2]!='\n')
stgidx-=1; /* overwrite last '\0' */
while (*st!='\0') { /* copy to staging buffer */
CHECK_STGBUFFER(stgidx);
stgbuf[stgidx++]=*st++;
} /* while */
CHECK_STGBUFFER(stgidx);
stgbuf[stgidx++]='\0';
} else {
len=(stgbuf!=NULL) ? strlen(stgbuf) : 0;
CHECK_STGBUFFER(len+strlen(st)+1);
strcat(stgbuf,st);
len=strlen(stgbuf);
if (len>0 && stgbuf[len-1]=='\n') {
filewrite(stgbuf);
stgbuf[0]='\0';
} /* if */
} /* if */
}
/* stgout
*
* Writes the staging buffer to the output file via stgstring() (for
* reversing expressions in the buffer) and stgopt() (for optimizing). It
* resets "stgidx".
*
* Global references: stgidx (altered)
* stgbuf (referred to only)
* staging (referred to only)
*/
void stgout(int index)
{
int reordered=0;
int idx;
if (!staging)
return;
assert(pipeidx==0);
/* first pass: sub-expressions */
if (sc_status==statWRITE)
reordered=stgstring(&stgbuf[index],&stgbuf[stgidx]);
stgidx=index;
/* second pass: optimize the buffer created in the first pass */
if (sc_status==statWRITE) {
if (reordered) {
stgopt(stgpipe,stgpipe+pipeidx,filewrite);
} else {
/* there is no sense in re-optimizing if the order of the sub-expressions
* did not change; so output directly
*/
for (idx=0; idx<pipeidx; idx+=strlen(stgpipe+idx)+1)
filewrite(stgpipe+idx);
} /* if */
} /* if */
pipeidx=0; /* reset second pipe */
}
typedef struct {
char *start,*end;
} argstack;
/* stgstring
*
* Analyses whether code strings should be output to the file as they appear
* in the staging buffer or whether portions of it should be re-ordered.
* Re-ordering takes place in function argument lists; Pawn passes arguments
* to functions from right to left. When arguments are "named" rather than
* positional, the order in the source stream is indeterminate.
* This function calls itself recursively in case it needs to re-order code
* strings, and it uses a private stack (or list) to mark the start and the
* end of expressions in their correct (reversed) order.
* In any case, stgstring() sends a block as large as possible to the
* optimizer stgopt().
*
* In "reorder" mode, each set of code strings must start with the token
* sEXPRSTART, even the first. If the token sSTARTREORDER is represented
* by '[', sENDREORDER by ']' and sEXPRSTART by '|' the following applies:
* '[]...' valid, but useless; no output
* '[|...] valid, but useless; only one string
* '[|...|...] valid and usefull
* '[...|...] invalid, first string doesn't start with '|'
* '[|...|] invalid
*/
static int stgstring(char *start,char *end)
{
char *ptr;
int nest,argc,arg;
argstack *stack;
int reordered=0;
while (start<end) {
if (*start==sSTARTREORDER) {
start+=1; /* skip token */
/* allocate a argstack with sMAXARGS items */
stack=(argstack *)malloc(sMAXARGS*sizeof(argstack));
if (stack==NULL)
error(103); /* insufficient memory */
reordered=1; /* mark that the expression is reordered */
nest=1; /* nesting counter */
argc=0; /* argument counter */
arg=-1; /* argument index; no valid argument yet */
do {
switch (*start) {
case sSTARTREORDER:
nest++;
start++;
break;
case sENDREORDER:
nest--;
start++;
break;
default:
if ((*start & sEXPRSTART)==sEXPRSTART) {
if (nest==1) {
if (arg>=0)
stack[arg].end=start-1; /* finish previous argument */
arg=(unsigned char)*start - sEXPRSTART;
stack[arg].start=start+1;
if (arg>=argc)
argc=arg+1;
} /* if */
start++;
} else {
start+=strlen(start)+1;
} /* if */
} /* switch */
} while (nest); /* enddo */
if (arg>=0)
stack[arg].end=start-1; /* finish previous argument */
while (argc>0) {
argc--;
stgstring(stack[argc].start,stack[argc].end);
} /* while */
free(stack);
} else {
ptr=start;
while (ptr<end && *ptr!=sSTARTREORDER)
ptr+=strlen(ptr)+1;
stgopt(start,ptr,rebuffer);
start=ptr;
} /* if */
} /* while */
return reordered;
}
/* stgdel
*
* Scraps code from the staging buffer by resetting "stgidx" to "index".
*
* Global references: stgidx (altered)
* staging (reffered to only)
*/
void stgdel(int index,cell code_index)
{
if (staging) {
stgidx=index;
code_idx=code_index;
} /* if */
}
int stgget(int *index,cell *code_index)
{
if (staging) {
*index=stgidx;
*code_index=code_idx;
} /* if */
return staging;
}
/* stgset
*
* Sets staging on or off. If it's turned off, the staging buffer must be
* initialized to an empty string. If it's turned on, the routine makes sure
* the index ("stgidx") is set to 0 (it should already be 0).
*
* Global references: staging (altered)
* stgidx (altered)
* stgbuf (contents altered)
*/
void stgset(int onoff)
{
staging=onoff;
if (staging){
assert(stgidx==0);
stgidx=0;
CHECK_STGBUFFER(stgidx);
/* write any contents that may be put in the buffer by stgwrite()
* when "staging" was 0
*/
if (strlen(stgbuf)>0)
filewrite(stgbuf);
} /* if */
stgbuf[0]='\0';
}
/* phopt_init
* Initialize all sequence strings of the peehole optimizer. The strings
* are embedded in the .EXE file in compressed format, here we expand
* them (and allocate memory for the sequences).
*/
static SEQUENCE *sequences = sequences_cmp;
int phopt_init(void)
{
return TRUE;
}
int phopt_cleanup(void)
{
return FALSE;
}
#define MAX_OPT_VARS 5
#define MAX_OPT_CAT 5 /* max. values that are concatenated */
#if sNAMEMAX > (PAWN_CELL_SIZE/4) * MAX_OPT_CAT
#define MAX_ALIAS sNAMEMAX
#else
#define MAX_ALIAS (PAWN_CELL_SIZE/4) * MAX_OPT_CAT
#endif
static int matchsequence(const char *start,const char *end,const char *pattern,
char symbols[MAX_OPT_VARS][MAX_ALIAS+1],
int *match_length)
{
int var,i;
char str[MAX_ALIAS+1];
const char *start_org=start;
cell value;
char *ptr;
*match_length=0;
for (var=0; var<MAX_OPT_VARS; var++)
symbols[var][0]='\0';
while (*start=='\t' || *start==' ')
start++;
while (*pattern) {
if (start>=end)
return FALSE;
switch (*pattern) {
case '%': /* new "symbol" */
pattern++;
assert(isdigit(*pattern));
var=atoi(pattern) - 1;
assert(var>=0 && var<MAX_OPT_VARS);
assert(*start=='-' || alphanum(*start));
for (i=0; start<end && (*start=='-' || *start=='+' || alphanum(*start)); i++,start++) {
assert(i<=MAX_ALIAS);
str[i]=*start;
} /* for */
str[i]='\0';
if (symbols[var][0]!='\0') {
if (strcmp(symbols[var],str)!=0)
return FALSE; /* symbols should be identical */
} else {
strcpy(symbols[var],str);
} /* if */
break;
case '-':
value=-strtol(pattern+1,(char **)&pattern,16);
ptr=itoh((ucell)value);
while (*ptr!='\0') {
if (tolower(*start) != tolower(*ptr))
return FALSE;
start++;
ptr++;
} /* while */
pattern--; /* there is an increment following at the end of the loop */
break;
case ' ':
if (*start!='\t' && *start!=' ')
return FALSE;
while (start<end && (*start=='\t' || *start==' '))
start++;
break;
case '!':
while (start<end && (*start=='\t' || *start==' '))
start++; /* skip trailing white space */
if (*start==';')
while (start<end && *start!='\n')
start++; /* skip trailing comment */
if (*start!='\n')
return FALSE;
assert(*(start+1)=='\0');
start+=2; /* skip '\n' and '\0' */
if (*(pattern+1)!='\0')
while ((start<end && *start=='\t') || *start==' ')
start++; /* skip leading white space of next instruction */
break;
default:
if (tolower(*start) != tolower(*pattern))
return FALSE;
start++;
} /* switch */
pattern++;
} /* while */
*match_length=(int)(start-start_org);
return TRUE;
}
static char *replacesequence(const char *pattern,char symbols[MAX_OPT_VARS][MAX_ALIAS+1],int *repl_length)
{
const char *lptr;
int var;
char *buffer;
/* calculate the length of the new buffer
* this is the length of the pattern plus the length of all symbols (note
* that the same symbol may occur multiple times in the pattern) plus
* line endings and startings ('\t' to start a line and '\n\0' to end one)
*/
assert(repl_length!=NULL);
*repl_length=0;
lptr=pattern;
while (*lptr) {
switch (*lptr) {
case '%':
lptr++; /* skip '%' */
assert(isdigit(*lptr));
var=atoi(lptr) - 1;
assert(var>=0 && var<MAX_OPT_VARS);
assert(symbols[var][0]!='\0'); /* variable should be defined */
*repl_length+=strlen(symbols[var]);
break;
case '!':
*repl_length+=3; /* '\t', '\n' & '\0' */
break;
default:
*repl_length+=1;
} /* switch */
lptr++;
} /* while */
/* allocate a buffer to replace the sequence in */
if ((buffer=(char*)malloc(*repl_length))==NULL)
return (char*)error(103);
/* replace the pattern into this temporary buffer */
char *ptr=buffer;
*ptr++='\t'; /* the "replace" patterns do not have tabs */
while (*pattern) {
assert((int)(ptr-buffer)<*repl_length);
switch (*pattern) {
case '%':
/* write out the symbol */
pattern++;
assert(isdigit(*pattern));
var=atoi(pattern) - 1;
assert(var>=0 && var<MAX_OPT_VARS);
assert(symbols[var][0]!='\0'); /* variable should be defined */
strcpy(ptr,symbols[var]);
ptr+=strlen(symbols[var]);
break;
case '!':
/* finish the line, optionally start the next line with an indent */
*ptr++='\n';
*ptr++='\0';
if (*(pattern+1)!='\0')
*ptr++='\t';
break;
default:
*ptr++=*pattern;
} /* switch */
pattern++;
} /* while */
assert((int)(ptr-buffer)==*repl_length);
return buffer;
}
static void strreplace(char *dest,char *replace,int sub_length,int repl_length,int dest_length)
{
int offset=sub_length-repl_length;
if (offset>0) { /* delete a section */
memmove(dest,dest+offset,dest_length-offset);
memset(dest+dest_length-offset,0xcc,offset); /* not needed, but for cleanlyness */
} else if (offset<0) { /* insert a section */
memmove(dest-offset, dest, dest_length);
} /* if */
memcpy(dest, replace, repl_length);
}
/* stgopt
*
* Optimizes the staging buffer by checking for series of instructions that
* can be coded more compact. The routine expects the lines in the staging
* buffer to be separated with '\n' and '\0' characters.
*
* The longest sequences should probably be checked first.
*/
static void stgopt(char *start,char *end,int (*outputfunc)(char *str))
{
char symbols[MAX_OPT_VARS][MAX_ALIAS+1];
int seq,match_length,repl_length;
int matches;
char *debut=start; /* save original start of the buffer */
assert(sequences!=NULL);
/* do not match anything if debug-level is maximum */
if (pc_optimize>sOPTIMIZE_NONE && sc_status==statWRITE) {
do {
matches=0;
start=debut;
while (start<end) {
seq=0;
while (sequences[seq].find!=NULL) {
assert(seq>=0);
if (*sequences[seq].find=='\0') {
if (pc_optimize==sOPTIMIZE_NOMACRO) {
break; /* don't look further */
} else {
seq++; /* continue with next string */
continue;
} /* if */
} /* if */
if (matchsequence(start,end,sequences[seq].find,symbols,&match_length)) {
char *replace=replacesequence(sequences[seq].replace,symbols,&repl_length);
/* If the replacement is bigger than the original section, we may need
* to "grow" the staging buffer. This is quite complex, due to the
* re-ordering of expressions that can also happen in the staging
* buffer. In addition, it should not happen: the peephole optimizer
* must replace sequences with *shorter* sequences, not longer ones.
* So, I simply forbid sequences that are longer than the ones they
* are meant to replace.
*/
assert(match_length>=repl_length);
if (match_length>=repl_length) {
strreplace(start,replace,match_length,repl_length,(int)(end-start));
end-=match_length-repl_length;
free(replace);
code_idx-=sequences[seq].savesize;
seq=0; /* restart search for matches */
matches++;
} else {
/* actually, we should never get here (match_length<repl_length) */
assert(0);
seq++;
} /* if */
} else {
seq++;
} /* if */
} /* while */
assert(sequences[seq].find==NULL || (*sequences[seq].find=='\0' && pc_optimize==sOPTIMIZE_NOMACRO));
start += strlen(start) + 1; /* to next string */
} /* while (start<end) */
} while (matches>0);
} /* if (pc_optimize>sOPTIMIZE_NONE && sc_status==statWRITE) */
for (start=debut; start<end; start+=strlen(start)+1)
outputfunc(start);
}
#undef SCPACK_TABLE

View File

@ -1,429 +0,0 @@
/* Codepage translation to Unicode, and UTF-8 support
*
* The translation is based on codepage mapping files that are distributed
* by the Unicode consortium, see ftp://ftp.unicode.org/Public/MAPPINGS/.
*
* Character sets with a maximum of 256 codes are translated via a lookup
* table (these are Single-Byte Character Sets). Character sets like Shift-JIS
* with single-byte characters and multi-byte characters (introduced by a
* leader byte) are split into two tables: the 256-entry lookup table for
* the single-byte characters and an extended table for the multi-byte
* characters. The extended table is allocated dynamically; the lookup table
* is allocated statically, so loading SBCS tables cannot fail (if the tables
* themselves are valid, of course).
*
* Copyright (c) ITB CompuPhase, 2004-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "sc.h"
#if !defined TRUE
#define FALSE 0
#define TRUE 1
#endif
#if !defined _MAX_PATH
#define _MAX_PATH 250
#endif
#if !defined DIRSEP_CHAR
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
#define DIRSEP_CHAR '/'
#elif defined macintosh
#define DIRSEP_CHAR ':'
#else
#define DIRSEP_CHAR '\\'
#endif
#endif
#if !defined ELEMENTS
#define ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
#endif
#if !defined NO_CODEPAGE
#if !defined MAXCODEPAGE
#define MAXCODEPAGE 12 /* typically "cp" + 4 digits + ".txt" */
#endif
#define INVALID 0xffffu /* 0xffff and 0xfffe are invalid Unicode characters */
#define LEADBYTE 0xfffeu
struct wordpair {
unsigned short index;
wchar_t code;
};
static char cprootpath[_MAX_PATH] = { DIRSEP_CHAR, '\0' };
static wchar_t bytetable[256];
static struct wordpair *wordtable = NULL;
static unsigned wordtablesize = 0;
static unsigned wordtabletop = 0;
/* read in a line delimited by '\r' or '\n'; do NOT store the '\r' or '\n' into
* the string and ignore empty lines
* returns 1 for success and 0 for failure
*/
static int cp_readline(FILE *fp,char *string,size_t size)
{
size_t count=0;
int c;
assert(size>1);
while ((c=fgetc(fp))!=EOF && count<size-1) {
if (c=='\r' || c=='\n') {
if (count>0) /* '\r' or '\n' ends a string */
break;
/* if count==0, the line started with a '\r' or '\n', or perhaps line
* ends in the file are '\r\n' and we read and stopped on the '\r' of
* the preceding line
*/
} else {
string[count++]=(char)c;
} /* if */
} /* while */
string[count]='\0';
return count>0;
}
/* cp_path() sets the directory where all codepage files must be found (if
* the parameter to cp_set() specifies a full path, that is used instead).
* The path is specified into two parts: root and directory; the full path
* for the codepage direcory is just the concatenation of the two, with a
* directory separator in between. The directory is given in two parts,
* because often a program already retrieves its "home" directory and the
* codepages are most conveniently stored in a subdirectory of this home
* directory.
*/
int cp_path(const char *root, const char *directory)
{
size_t len1,len2;
int add_slash1,add_slash2;
len1= (root!=NULL) ? strlen(root) : 0;
add_slash1= (len1==0 || root[len1-1]!=DIRSEP_CHAR);
len2= (directory!=NULL) ? strlen(directory) : 0;
add_slash2= (len2>0 && root[len2-1]!=DIRSEP_CHAR);
if (len1+add_slash1+len2+add_slash2>=(_MAX_PATH-MAXCODEPAGE))
return FALSE; /* full filename may not fit */
if (root!=NULL)
strcpy(cprootpath,root);
if (add_slash1) {
assert(len1==0 || cprootpath[len1]=='\0');
cprootpath[len1]=DIRSEP_CHAR;
cprootpath[len1+1]='\0';
} /* if */
if (directory!=NULL)
strcat(cprootpath,directory);
if (add_slash2) {
assert(cprootpath[len1+add_slash1+len2]=='\0');
cprootpath[len1+add_slash1+len2]=DIRSEP_CHAR;
cprootpath[len1+add_slash1+len2+1]='\0';
} /* if */
cp_set(NULL); /* start with a "linear" table (no translation) */
return TRUE;
}
/* cp_set() loads a codepage from a file. The name parameter may be a
* filename (including a full path) or it may be a partial codepage name.
* If the name parameter is NULL, the codepage is cleared to be a "linear"
* table (no translation).
* The following files are attempted to open (where <name> specifies the
* value of the parameter):
* <name>
* <cprootpath>/<name>
* <cprootpath>/<name>.txt
* <cprootpath>/cp<name>
* <cprootpath>/cp<name>.txt
*/
int cp_set(const char *name)
{
char filename[_MAX_PATH];
FILE *fp=NULL;
unsigned index;
/* for name==NULL, set up an identity table */
if (name==NULL || *name=='\0') {
if (wordtable!=NULL) {
free(wordtable);
wordtable=NULL;
wordtablesize=0;
wordtabletop=0;
} /* if */
for (index=0; index<ELEMENTS(bytetable); index++)
bytetable[index]=(wchar_t)index;
return TRUE;
} /* if */
/* try to open the file as-is */
if (strchr(name,DIRSEP_CHAR)!=NULL)
fp=fopen(name,"rt");
if (fp==NULL) {
/* try opening the file in the "root path" for codepages */
if (strlen(name)>MAXCODEPAGE)
return 0;
assert(strlen(name)+strlen(cprootpath)<_MAX_PATH);
strcpy(filename,cprootpath);
strcat(filename,name);
fp=fopen(filename,"rt");
} /* if */
if (fp==NULL) {
/* try opening the file in the "root path" for codepages, with a ".txt" extension */
if (strlen(name)+4>=MAXCODEPAGE)
return 0;
assert(strlen(filename)+4<_MAX_PATH);
strcat(filename,".txt");
fp=fopen(filename,"rt");
} /* if */
if (fp==NULL) {
/* try opening the file in the "root path" for codepages, with "cp" prefixed before the name */
if (strlen(name)+2>MAXCODEPAGE)
return 0;
assert(2+strlen(name)+strlen(cprootpath)<_MAX_PATH);
strcpy(filename,cprootpath);
strcat(filename,"cp");
strcat(filename,name);
fp=fopen(filename,"rt");
} /* if */
if (fp==NULL) {
/* try opening the file in the "root path" for codepages, with "cp" prefixed an ".txt" appended */
if (strlen(name)+2+4>MAXCODEPAGE)
return 0;
assert(strlen(filename)+4<_MAX_PATH);
strcat(filename,".txt");
fp=fopen(filename,"rt");
} /* if */
if (fp==NULL)
return FALSE; /* all failed */
/* clear the tables */
for (index=0; index<ELEMENTS(bytetable); index++)
bytetable[index]=INVALID; /* special code meaning "not found" */
assert((wordtablesize==0 && wordtabletop==0 && wordtable==NULL)
|| (wordtablesize>0 && wordtable!=NULL));
if (wordtable!=NULL) {
free(wordtable);
wordtable=NULL;
wordtablesize=0;
wordtabletop=0;
} /* if */
/* read in the table */
while (cp_readline(fp,filename,sizeof filename)) {
char *ptr;
if ((ptr=strchr(filename,'#'))!=NULL)
*ptr='\0'; /* strip of comment */
for (ptr=filename; *ptr>0 && *ptr<' '; ptr++)
/* nothing */; /* skip leading whitespace */
if (*ptr!='\0') {
/* content on line */
unsigned code=LEADBYTE;
int num=sscanf(ptr,"%i %i",&index,&code);
/* if sscanf() returns 1 and the index is in range 0..255, then the
* code is a DBCS lead byte; if sscanf() returns 2 and index>=256, this
* is a double byte pair (lead byte + follower)
*/
if (num>=1 && index<256) {
bytetable[index]=(wchar_t)code;
} else if (num==2 && index>=256 && index<LEADBYTE) {
/* store the DBCS character in wordtable */
if (wordtabletop>=wordtablesize) {
/* grow the list */
int newsize;
struct wordpair *newblock;
newsize= (wordtablesize==0) ? 128 : 2*wordtablesize;
newblock=(struct wordpair *)malloc(newsize*sizeof(*wordtable));
if (newblock!=NULL) {
memcpy(newblock,wordtable,wordtabletop*sizeof(*wordtable));
free(wordtable);
wordtable=newblock;
wordtablesize=newsize;
} /* if */
} /* if */
if (wordtabletop<wordtablesize) {
/* insert at sorted position */
int pos=wordtabletop;
assert(wordtable!=NULL);
while (pos>0 && (unsigned)wordtable[pos-1].index>index) {
wordtable[pos]=wordtable[pos-1];
pos--;
} /* while */
wordtable[pos].index=(unsigned short)index;
wordtable[pos].code=(wchar_t)code;
} /* if */
} /* if */
} /* if */
} /* while */
fclose(fp);
return TRUE;
}
cell cp_translate(const unsigned char *string,const unsigned char **endptr)
{
wchar_t result;
result=bytetable[*string++];
/* check whether this is a leader code */
if ((unsigned)result==LEADBYTE && wordtable!=NULL) {
/* look up the code via binary search */
int low,high,mid;
unsigned short index=(unsigned short)(((*(string-1)) << 8) | *string);
string++;
assert(wordtabletop>0);
low=0;
high=wordtabletop-1;
while (low<high) {
mid=(low+high)/2;
assert(low<=mid && mid<high);
if (index>wordtable[mid].index)
low=mid+1;
else
high=mid;
} /* while */
assert(low==high);
if (wordtable[low].index==index)
result=wordtable[low].code;
} /* if */
if (endptr!=NULL)
*endptr=string;
return (cell)result;
}
#endif /* NO_CODEPAGE */
#if !defined NO_UTF8
cell get_utf8_char(const unsigned char *string,const unsigned char **endptr)
{
int follow=0;
long lowmark=0;
unsigned char ch;
cell result=0;
if (endptr!=NULL)
*endptr=string;
for ( ;; ) {
ch=*string++;
if (follow>0 && (ch & 0xc0)==0x80) {
/* leader code is active, combine with earlier code */
result=(result << 6) | (ch & 0x3f);
if (--follow==0) {
/* encoding a character in more bytes than is strictly needed,
* is not really valid UTF-8; we are strict here to increase
* the chance of heuristic dectection of non-UTF-8 text
* (JAVA writes zero bytes as a 2-byte code UTF-8, which is invalid)
*/
if (result<lowmark)
return -1;
/* the code positions 0xd800--0xdfff and 0xfffe & 0xffff do not
* exist in UCS-4 (and hence, they do not exist in Unicode)
*/
if ((result>=0xd800 && result<=0xdfff) || result==0xfffe || result==0xffff)
return -1;
} /* if */
break;
} else if (follow==0 && (ch & 0x80)==0x80) {
/* UTF-8 leader code */
if ((ch & 0xe0)==0xc0) {
/* 110xxxxx 10xxxxxx */
follow=1;
lowmark=0x80L;
result=ch & 0x1f;
} else if ((ch & 0xf0)==0xe0) {
/* 1110xxxx 10xxxxxx 10xxxxxx (16 bits, BMP plane) */
follow=2;
lowmark=0x800L;
result=ch & 0x0f;
} else if ((ch & 0xf8)==0xf0) {
/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
follow=3;
lowmark=0x10000L;
result=ch & 0x07;
} else if ((ch & 0xfc)==0xf8) {
/* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
follow=4;
lowmark=0x200000L;
result=ch & 0x03;
} else if ((ch & 0xfe)==0xfc) {
/* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (32 bits) */
follow=5;
lowmark=0x4000000L;
result=ch & 0x01;
} else {
/* this is invalid UTF-8 */
return -1;
} /* if */
} else if (follow==0 && (ch & 0x80)==0x00) {
/* 0xxxxxxx (US-ASCII) */
result=ch;
break;
} else {
/* this is invalid UTF-8 */
return -1;
} /* if */
} /* for */
if (endptr!=NULL)
*endptr=string;
return result;
}
#endif
int scan_utf8(void *fp,const char *filename)
{
#if defined NO_UTF8
return 0;
#else
static void *resetpos=NULL;
int utf8=TRUE;
int firstchar=TRUE,bom_found=FALSE;
const unsigned char *ptr;
resetpos=pc_getpossrc(fp,resetpos);
while (utf8 && pc_readsrc(fp,pline,sLINEMAX)!=NULL) {
ptr=pline;
if (firstchar) {
/* check whether the very first character on the very first line
* starts with a BYTE order mark
*/
cell c=get_utf8_char(ptr,&ptr);
bom_found= (c==0xfeff);
utf8= (c>=0);
firstchar=FALSE;
} /* if */
while (utf8 && *ptr!='\0')
utf8= (get_utf8_char(ptr,&ptr)>=0);
} /* while */
pc_resetsrc(fp,resetpos);
if (bom_found) {
unsigned char bom[3];
if (!utf8)
error(77,filename); /* malformed UTF-8 encoding */
pc_readsrc(fp,bom,3);
assert(bom[0]==0xef && bom[1]==0xbb && bom[2]==0xbf);
} /* if */
return utf8;
#endif /* NO_UTF8 */
}

View File

@ -1,48 +0,0 @@
/*
* Things needed to compile under linux.
*
* Should be reworked totally to use GNU's 'configure'
*/
#ifndef SCLINUX_H
#define SCLINUX_H
/* getchar() is not a 'cool' replacement for MSDOS getch: Linux/unix depends on the features activated or not about the
* controlling terminal's tty. This means that ioctl(2) calls must be performed, for instance to have the controlling
* terminal tty's in 'raw' mode, if we want to be able to fetch a single character. This also means that everything must
* be put back correctly when the function ends. See GETCH.C for an implementation.
*
* For interactive use of SRUN/SDBG if would be much better to use GNU's readline package: the user would be able to
* have a complete emacs/vi like line editing system.
*/
#include "getch.h"
/*
* WinWorld wants '\'. Unices do not.
*/
#define DIRECTORY_SEP_CHAR '/'
#define DIRECTORY_SEP_STR "/"
/*
* SC assumes that a computer is Little Endian unless told otherwise. It uses
* (and defines) the macros BYTE_ORDER and BIG_ENDIAN.
* For Linux, we must overrule these settings with those defined in glibc.
*/
#if !defined __BYTE_ORDER
# if defined EMSCRIPTEN
# include <endian.h>
# else
# include <stdlib.h>
# endif
#endif
#if defined __OpenBSD__ || defined __FreeBSD__ || defined __APPLE__
# define __BYTE_ORDER BYTE_ORDER
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __BIG_ENDIAN BIG_ENDIAN
#endif
#if !defined __BYTE_ORDER
# error "Can't figure computer byte order (__BYTE_ORDER macro not found)"
#endif
#endif /* SCLINUX_H */

View File

@ -1,539 +0,0 @@
/* Pawn compiler - maintenance of various lists
*
* o Name list (aliases)
* o Include path list
* o Macro definitions (text substitutions)
* o Documentation tags and automatic listings
* o Debug strings
*
* Copyright (c) ITB CompuPhase, 2001-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "sc.h"
#include "lstring.h"
#if defined FORTIFY
#include <alloc/fortify.h>
#endif
/* a "private" implementation of strdup(), so that porting
* to other memory allocators becomes easier.
* By Søren Hannibal.
*/
char* duplicatestring(const char* sourcestring)
{
char* result=(char*)malloc(strlen(sourcestring)+1);
strcpy(result,sourcestring);
return result;
}
static stringpair *insert_stringpair(stringpair *root,const char *first,const char *second,int matchlength)
{
stringpair *cur,*pred;
assert(root!=NULL);
assert(first!=NULL);
assert(second!=NULL);
/* create a new node, and check whether all is okay */
if ((cur=(stringpair*)malloc(sizeof(stringpair)))==NULL)
return NULL;
cur->first=duplicatestring(first);
cur->second=duplicatestring(second);
cur->matchlength=matchlength;
cur->documentation=NULL;
if (cur->first==NULL || cur->second==NULL) {
if (cur->first!=NULL)
free(cur->first);
if (cur->second!=NULL)
free(cur->second);
free(cur);
return NULL;
} /* if */
/* link the node to the tree, find the position */
for (pred=root; pred->next!=NULL && strcmp(pred->next->first,first)<0; pred=pred->next)
/* nothing */;
cur->next=pred->next;
pred->next=cur;
return cur;
}
static void delete_stringpairtable(stringpair *root)
{
stringpair *cur, *next;
assert(root!=NULL);
cur=root->next;
while (cur!=NULL) {
next=cur->next;
assert(cur->first!=NULL);
assert(cur->second!=NULL);
free(cur->first);
free(cur->second);
free(cur);
cur=next;
} /* while */
memset(root,0,sizeof(stringpair));
}
static stringpair *find_stringpair(stringpair *cur,char *first,int matchlength)
{
int result=0;
assert(matchlength>0); /* the function cannot handle zero-length comparison */
assert(first!=NULL);
while (cur!=NULL && result<=0) {
result=(int)*cur->first - (int)*first;
if (result==0 && matchlength==cur->matchlength) {
result=strncmp(cur->first,first,matchlength);
if (result==0)
return cur;
} /* if */
cur=cur->next;
} /* while */
return NULL;
}
static int delete_stringpair(stringpair *root,stringpair *item)
{
stringpair *cur;
assert(root!=NULL);
cur=root;
while (cur->next!=NULL) {
if (cur->next==item) {
cur->next=item->next; /* unlink from list */
assert(item->first!=NULL);
assert(item->second!=NULL);
free(item->first);
free(item->second);
free(item);
return TRUE;
} /* if */
cur=cur->next;
} /* while */
return FALSE;
}
/* ----- string list functions ----------------------------------- */
static stringlist *insert_string(stringlist *root,const char *string)
{
stringlist *cur;
assert(string!=NULL);
if ((cur=(stringlist*)malloc(sizeof(stringlist)))==NULL)
error(103); /* insufficient memory (fatal error) */
if ((cur->line=duplicatestring(string))==NULL)
error(103); /* insufficient memory (fatal error) */
cur->next=NULL;
if (root->tail)
root->tail->next=cur;
else
root->next=cur;
root->tail=cur;
return cur;
}
static char *get_string(stringlist *root,int index)
{
stringlist *cur;
assert(root!=NULL);
cur=root->next;
while (cur!=NULL && index-->0)
cur=cur->next;
if (cur!=NULL) {
assert(cur->line!=NULL);
return cur->line;
} /* if */
return NULL;
}
static int delete_string(stringlist *root,int index)
{
stringlist *cur,*item;
assert(root!=NULL);
for (cur=root; cur->next!=NULL && index>0; cur=cur->next,index--)
/* nothing */;
if (cur->next!=NULL) {
item=cur->next;
if (root->tail == cur->next)
root->tail = cur;
cur->next=item->next; /* unlink from list */
assert(item->line!=NULL);
free(item->line);
free(item);
return TRUE;
} /* if */
return FALSE;
}
void delete_stringtable(stringlist *root)
{
stringlist *cur,*next;
assert(root!=NULL);
cur=root->next;
while (cur!=NULL) {
next=cur->next;
assert(cur->line!=NULL);
free(cur->line);
free(cur);
cur=next;
} /* while */
memset(root,0,sizeof(stringlist));
}
/* ----- alias table --------------------------------------------- */
static stringpair alias_tab = {NULL, NULL, NULL}; /* alias table */
stringpair *insert_alias(char *name,char *alias)
{
stringpair *cur;
assert(name!=NULL);
assert(strlen(name)<=sNAMEMAX);
assert(alias!=NULL);
assert(strlen(alias)<=sNAMEMAX);
if ((cur=insert_stringpair(&alias_tab,name,alias,strlen(name)))==NULL)
error(103); /* insufficient memory (fatal error) */
return cur;
}
int lookup_alias(char *target,char *name)
{
stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name));
if (cur!=NULL) {
assert(strlen(cur->second)<=sNAMEMAX);
strcpy(target,cur->second);
} /* if */
return cur!=NULL;
}
void delete_aliastable(void)
{
delete_stringpairtable(&alias_tab);
}
/* ----- include paths list -------------------------------------- */
static stringlist includepaths; /* directory list for include files */
stringlist *insert_path(char *path)
{
return insert_string(&includepaths,path);
}
char *get_path(int index)
{
return get_string(&includepaths,index);
}
void delete_pathtable(void)
{
delete_stringtable(&includepaths);
assert(includepaths.next==NULL);
}
/* ----- text substitution patterns ------------------------------ */
#if !defined NO_DEFINE
static stringpair substpair = { NULL, NULL, NULL}; /* list of substitution pairs */
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=='_' || 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-PUBLIC_CHAR]=cur;
}
stringpair *insert_subst(const char *pattern,const char *substitution,int prefixlen)
{
stringpair *cur;
assert(pattern!=NULL);
assert(substitution!=NULL);
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;
}
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=='_' || *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];
const char *msg = (item->documentation != NULL) ? item->documentation : "";
strlcpy(macro, item->first, sizeof(macro));
/* If macro contains an opening parentheses and a percent sign, then assume that
* it takes arguments and remove them from the warning message.
*/
char *rem;
if ((rem = strchr(macro, '(')) != NULL && strchr(macro, '%') > rem)
{
*rem = '\0';
}
error(234, macro, msg); /* deprecated (macro/constant) */
}
return item;
}
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=='_' || *name==PUBLIC_CHAR);
item=substindex[(int)*name-PUBLIC_CHAR];
if (item!=NULL)
item=find_stringpair(item,name,length);
if (item==NULL)
return FALSE;
if (item->documentation)
{
free(item->documentation);
item->documentation=NULL;
}
delete_stringpair(&substpair,item);
adjustindex(*name);
return TRUE;
}
void delete_substtable(void)
{
size_t i;
delete_stringpairtable(&substpair);
for (i=0; i<sizeof substindex/sizeof substindex[0]; i++)
substindex[i]=NULL;
}
#endif /* !defined NO_SUBST */
/* ----- input file list ----------------------------------------- */
static stringlist sourcefiles;
stringlist *insert_sourcefile(char *string)
{
return insert_string(&sourcefiles,string);
}
char *get_sourcefile(int index)
{
return get_string(&sourcefiles,index);
}
void delete_sourcefiletable(void)
{
delete_stringtable(&sourcefiles);
assert(sourcefiles.next==NULL);
}
/* ----- documentation tags -------------------------------------- */
#if !defined SC_LIGHT
static stringlist docstrings;
stringlist *insert_docstring(char *string)
{
return insert_string(&docstrings,string);
}
char *get_docstring(int index)
{
return get_string(&docstrings,index);
}
void delete_docstring(int index)
{
delete_string(&docstrings,index);
}
void delete_docstringtable(void)
{
delete_stringtable(&docstrings);
assert(docstrings.next==NULL);
}
#endif /* !defined SC_LIGHT */
/* ----- autolisting --------------------------------------------- */
static stringlist autolist;
stringlist *insert_autolist(const char *string)
{
return insert_string(&autolist,string);
}
char *get_autolist(int index)
{
return get_string(&autolist,index);
}
void delete_autolisttable(void)
{
delete_stringtable(&autolist);
assert(autolist.next==NULL);
}
/* ----- debug information --------------------------------------- */
/* These macros are adapted from LibDGG libdgg-int64.h, see
* http://www.dennougedougakkai-ndd.org/pub/libdgg/
*/
#if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
#define __STDC_FORMAT_MACROS
#define __STDC_CONSTANT_MACROS
#include <inttypes.h> /* automatically includes stdint.h */
#elif (defined _MSC_VER || defined __BORLANDC__) && (defined _I64_MAX || defined HAVE_I64)
#define PRId64 "I64d"
#define PRIx64 "I64x"
#else
#define PRId64 "lld"
#define PRIx64 "llx"
#endif
#if PAWN_CELL_SIZE==64
#define PRIdC PRId64
#define PRIxC PRIx64
#elif PAWN_CELL_SIZE==32
#define PRIdC "ld"
#define PRIxC "lx"
#else
#define PRIdC "d"
#define PRIxC "x"
#endif
static stringlist dbgstrings;
stringlist *insert_dbgfile(const char *filename)
{
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
char string[_MAX_PATH+40];
assert(filename!=NULL);
assert(strlen(filename)+40<sizeof string);
sprintf(string,"F:%" PRIxC " %s",code_idx,filename);
return insert_string(&dbgstrings,string);
} /* if */
return NULL;
}
stringlist *insert_dbgline(int linenr)
{
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
char string[40];
if (linenr>0)
linenr--; /* line numbers are zero-based in the debug information */
sprintf(string,"L:%" PRIxC " %x",code_idx,linenr);
return insert_string(&dbgstrings,string);
} /* if */
return NULL;
}
stringlist *insert_dbgsymbol(symbol *sym)
{
if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
char string[2*sNAMEMAX+128];
char symname[2*sNAMEMAX+16];
funcdisplayname(symname,sym->name);
/* address tag:name codestart codeend ident vclass [tag:dim ...] */
if (sym->ident==iFUNCTN) {
sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
sym->addr,sym->tag,symname,sym->addr,sym->codeaddr,sym->ident,sym->vclass);
} else {
sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
sym->addr,sym->tag,symname,sym->codeaddr,code_idx,sym->ident,sym->vclass);
} /* if */
if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
#if !defined NDEBUG
int count=sym->dim.array.level;
#endif
symbol *sub;
strcat(string," [ ");
for (sub=sym; sub!=NULL; sub=finddepend(sub)) {
assert(sub->dim.array.level==count--);
sprintf(string+strlen(string),"%x:%x ",sub->x.tags.index,sub->dim.array.length);
} /* for */
strcat(string,"]");
} /* if */
return insert_string(&dbgstrings,string);
} /* if */
return NULL;
}
stringlist *get_dbgstrings()
{
return &dbgstrings;
}
char *get_dbgstring(int index)
{
return get_string(&dbgstrings,index);
}
void delete_dbgstringtable(void)
{
delete_stringtable(&dbgstrings);
assert(dbgstrings.next==NULL);
}

View File

@ -1,165 +0,0 @@
/* Pawn compiler
*
* Routines to maintain a "text file" in memory.
*
* Copyright (c) ITB CompuPhase, 2003-2006
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memfile.h"
#if defined FORTIFY
#include <alloc/fortify.h>
#endif
#include "sc.h"
MEMFILE *mfcreate(const char *filename)
{
return memfile_creat(filename, 4096);
}
void mfclose(MEMFILE *mf)
{
memfile_destroy(mf);
}
int mfdump(MEMFILE *mf)
{
FILE *fp;
int okay;
assert(mf!=NULL);
/* create the file */
fp=fopen(mf->name, "wb");
if (fp==NULL)
return 0;
okay=1;
okay = okay & (fwrite(mf->base, mf->usedoffs, 1, fp)==(size_t)mf->usedoffs);
fclose(fp);
return okay;
}
long mflength(const MEMFILE *mf)
{
return mf->usedoffs;
}
long mfseek(MEMFILE *mf,long offset,int whence)
{
long length;
assert(mf!=NULL);
if (mf->usedoffs == 0)
return 0L; /* early exit: not a single byte in the file */
/* find the size of the memory file */
length=mflength(mf);
/* convert the offset to an absolute position */
switch (whence) {
case SEEK_SET:
break;
case SEEK_CUR:
offset+=mf->offs;
break;
case SEEK_END:
assert(offset<=0);
offset+=length;
break;
} /* switch */
/* clamp to the file length limit */
if (offset<0)
offset=0;
else if (offset>length)
offset=length;
/* set new position and return it */
memfile_seek(mf, offset);
return offset;
}
unsigned int mfwrite(MEMFILE *mf,const unsigned char *buffer,unsigned int size)
{
return (memfile_write(mf, buffer, size) ? size : 0);
}
unsigned int mfread(MEMFILE *mf,unsigned char *buffer,unsigned int size)
{
return memfile_read(mf, buffer, size);
}
char *mfgets(MEMFILE *mf,char *string,unsigned int size)
{
char *ptr;
unsigned int read;
long seek;
assert(mf!=NULL);
read=mfread(mf,(unsigned char *)string,size);
if (read==0)
return NULL;
seek=0L;
/* make sure that the string is zero-terminated */
assert(read<=size);
if (read<size) {
string[read]='\0';
} else {
string[size-1]='\0';
seek=-1; /* undo reading the character that gets overwritten */
} /* if */
/* find the first '\n' */
ptr=strchr(string,'\n');
if (ptr!=NULL) {
*(ptr+1)='\0';
seek=(long)(ptr-string)+1-(long)read;
} /* if */
/* undo over-read */
assert(seek<=0); /* should seek backward only */
if (seek!=0)
mfseek(mf,seek,SEEK_CUR);
return string;
}
int mfputs(MEMFILE *mf,const char *string)
{
unsigned int written,length;
assert(mf!=NULL);
length=strlen(string);
written=mfwrite(mf,(unsigned char *)string,length);
return written==length;
}

View File

@ -1,375 +0,0 @@
/* Pawn compiler
*
* Machine and state maintenance.
*
* Three lists are maintained here:
* - A list of automatons (state machines): these hold a name, a unique id
* (in the "index" field) and the memory address of a cell that holds the
* current state of the automaton (in the "value" field).
* - A list of states for each automaton: a name, an automaton id (in the
* "index" field) and a unique id for the state (unique in the automaton;
* states belonging to different automatons may have the same id).
* - A list of state combinations. Each function may belong to a set of states.
* This list assigns a unique id to the combination of the automaton and all
* states.
*
* For a function/variable that has states, there is a fourth list, which is
* attached to the "symbol" structure. This list contains the code label (in
* the "name" field, only for functions), the id of the state combinations (the
* state list id; it is stored in the "index" field) and the code address at
* which the function starts. The latter is currently unused.
*
* At the start of the compiled code, a set of stub functions is generated.
* Each stub function looks up the value of the "state selector" value for the
* automaton, and goes with a "switch" instruction to the start address of the
* function. This happens in SC4.C.
*
*
* Copyright (c) ITB CompuPhase, 2005-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sc.h"
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
#include "sclinux.h"
#endif
#if defined FORTIFY
#include <alloc/fortify.h>
#endif
typedef struct s_statelist {
struct s_statelist *next;
int *states; /* list of states in this combination */
int numstates; /* number of items in the above list */
int fsa; /* automaton id */
int listid; /* unique id for this combination list */
} statelist;
static statelist statelist_tab = { NULL, NULL, 0, 0, 0}; /* state combinations table */
static constvalue *find_automaton(const char *name,int *last)
{
constvalue *ptr;
assert(last!=NULL);
*last=0;
ptr=sc_automaton_tab.next;
while (ptr!=NULL) {
if (strcmp(name,ptr->name)==0)
return ptr;
if (ptr->index>*last)
*last=ptr->index;
ptr=ptr->next;
} /* while */
return NULL;
}
constvalue *automaton_add(const char *name)
{
constvalue *ptr;
int last;
assert(strlen(name)<sizeof(ptr->name));
ptr=find_automaton(name,&last);
if (ptr==NULL) {
assert(last+1 <= SHRT_MAX);
ptr=append_constval(&sc_automaton_tab,name,(cell)0,(short)(last+1));
} /* if */
return ptr;
}
constvalue *automaton_find(const char *name)
{
int last;
return find_automaton(name,&last);
}
constvalue *automaton_findid(int id)
{
constvalue *ptr;
for (ptr=sc_automaton_tab.next; ptr!=NULL && ptr->index!=id; ptr=ptr->next)
/* nothing */;
return ptr;
}
static constvalue *find_state(const char *name,int fsa,int *last)
{
constvalue *ptr;
assert(last!=NULL);
*last=0;
ptr=sc_state_tab.next;
while (ptr!=NULL) {
if (ptr->index==fsa) {
if (strcmp(name,ptr->name)==0)
return ptr;
if ((int)ptr->value>*last)
*last=(int)ptr->value;
} /* if */
ptr=ptr->next;
} /* while */
return NULL;
}
constvalue *state_add(const char *name,int fsa)
{
constvalue *ptr;
int last;
assert(strlen(name)<sizeof(ptr->name));
ptr=find_state(name,fsa,&last);
if (ptr==NULL) {
assert(fsa <= SHRT_MAX);
ptr=append_constval(&sc_state_tab,name,(cell)(last+1),(short)fsa);
} /* if */
return ptr;
}
constvalue *state_find(const char *name,int fsa_id)
{
int last; /* dummy */
return find_state(name,fsa_id,&last);
}
constvalue *state_findid(int id)
{
constvalue *ptr;
for (ptr=sc_state_tab.next; ptr!=NULL && ptr->value!=id; ptr=ptr->next)
/* nothing */;
return ptr;
}
void state_buildlist(int **list,int *listsize,int *count,int stateid)
{
int idx;
assert(list!=NULL);
assert(listsize!=NULL);
assert(*listsize>=0);
assert(count!=NULL);
assert(*count>=0);
assert(*count<=*listsize);
if (*count==*listsize) {
/* To avoid constantly calling malloc(), the list is grown by 4 states at
* a time.
*/
*listsize+=4;
*list=(int*)realloc(*list,*listsize*sizeof(int));
if (*list==NULL)
error(103); /* insufficient memory */
} /* if */
/* find the insertion point (the list has to stay sorted) */
for (idx=0; idx<*count && *list[idx]<stateid; idx++)
/* nothing */;
if (idx<*count)
memmove(&(*list)[idx+1],&(*list)[idx],(int)((*count-idx+1)*sizeof(int)));
(*list)[idx]=stateid;
*count+=1;
}
static statelist *state_findlist(int *list,int count,int fsa,int *last)
{
statelist *ptr;
int i;
assert(count>0);
assert(last!=NULL);
*last=0;
ptr=statelist_tab.next;
while (ptr!=NULL) {
if (ptr->listid>*last)
*last=ptr->listid;
if (ptr->fsa==fsa && ptr->numstates==count) {
/* compare all states */
for (i=0; i<count && ptr->states[i]==list[i]; i++)
/* nothing */;
if (i==count)
return ptr;
} /* if */
ptr=ptr->next;
} /* while */
return NULL;
}
static statelist *state_getlist_ptr(int listid)
{
statelist *ptr;
assert(listid>0);
for (ptr=statelist_tab.next; ptr!=NULL && ptr->listid!=listid; ptr=ptr->next)
/* nothing */;
return ptr;
}
int state_addlist(int *list,int count,int fsa)
{
statelist *ptr;
int last;
assert(list!=NULL);
assert(count>0);
ptr=state_findlist(list,count,fsa,&last);
if (ptr==NULL) {
if ((ptr=(statelist*)malloc(sizeof(statelist)))==NULL)
error(103); /* insufficient memory */
if ((ptr->states=(int*)malloc(count*sizeof(int)))==NULL) {
free(ptr);
error(103); /* insufficient memory */
} /* if */
memcpy(ptr->states,list,count*sizeof(int));
ptr->numstates=count;
ptr->fsa=fsa;
ptr->listid=last+1;
ptr->next=statelist_tab.next;
statelist_tab.next=ptr;
} /* if */
assert(ptr!=NULL);
return ptr->listid;
}
void state_deletetable(void)
{
statelist *ptr;
while (statelist_tab.next!=NULL) {
ptr=statelist_tab.next;
/* unlink first */
statelist_tab.next=ptr->next;
/* then delete */
assert(ptr->states!=NULL);
free(ptr->states);
free(ptr);
} /* while */
}
int state_getfsa(int listid)
{
statelist *ptr;
assert(listid>=0);
if (listid==0)
return -1;
ptr=state_getlist_ptr(listid);
return (ptr!=NULL) ? ptr->fsa : -1; /* fsa 0 exists */
}
int state_count(int listid)
{
statelist *ptr=state_getlist_ptr(listid);
if (ptr==NULL)
return 0; /* unknown list, no states in it */
return ptr->numstates;
}
int state_inlist(int listid,int state)
{
statelist *ptr;
int i;
ptr=state_getlist_ptr(listid);
if (ptr==NULL)
return FALSE; /* unknown list, state not in it */
for (i=0; i<ptr->numstates; i++)
if (ptr->states[i]==state)
return TRUE;
return FALSE;
}
int state_listitem(int listid,int index)
{
statelist *ptr;
ptr=state_getlist_ptr(listid);
assert(ptr!=NULL);
assert(index>=0 && index<ptr->numstates);
return ptr->states[index];
}
static int checkconflict(statelist *psrc,statelist *ptgt)
{
int s,t;
assert(psrc!=NULL);
assert(ptgt!=NULL);
for (s=0; s<psrc->numstates; s++)
for (t=0; t<ptgt->numstates; t++)
if (psrc->states[s]==ptgt->states[t])
return 1; /* state conflict */
return 0;
}
/* This function searches whether one of the states in the list of statelist id's
* of a symbol exists in any other statelist id's of the same function; it also
* verifies that all definitions of the symbol are in the same automaton.
*/
void state_conflict(symbol *root)
{
statelist *psrc,*ptgt;
constvalue *srcptr,*tgtptr;
symbol *sym;
assert(root!=NULL);
for (sym=root->next; sym!=NULL; sym=sym->next) {
if (sym->parent!=NULL || sym->ident!=iFUNCTN)
continue; /* hierarchical data type or no function */
if (sym->states==NULL)
continue; /* this function has no states */
for (srcptr=sym->states->next; srcptr!=NULL; srcptr=srcptr->next) {
if (srcptr->index==-1)
continue; /* state list id -1 is a special case */
psrc=state_getlist_ptr(srcptr->index);
assert(psrc!=NULL);
for (tgtptr=srcptr->next; tgtptr!=NULL; tgtptr=tgtptr->next) {
if (tgtptr->index==-1)
continue; /* state list id -1 is a special case */
ptgt=state_getlist_ptr(tgtptr->index);
assert(ptgt!=NULL);
if (psrc->fsa!=ptgt->fsa && strcmp(sym->name,uENTRYFUNC)!=0)
error(83,sym->name); /* this function is part of another machine */
if (checkconflict(psrc,ptgt))
error(84,sym->name); /* state conflict */
} /* for (tgtptr) */
} /* for (srcptr) */
} /* for (sym) */
}
/* check whether the two state lists (whose ids are passed in) share any
* states
*/
int state_conflict_id(int listid1,int listid2)
{
statelist *psrc,*ptgt;
psrc=state_getlist_ptr(listid1);
assert(psrc!=NULL);
ptgt=state_getlist_ptr(listid2);
assert(ptgt!=NULL);
return checkconflict(psrc,ptgt);
}

View File

@ -1,614 +0,0 @@
/* vim: set ts=8 sts=2 sw=2 tw=99 et: */
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include "sc.h"
#include "sctracker.h"
memuse_list_t *heapusage = NULL;
memuse_list_t *stackusage = NULL;
funcenum_t *firstenum = NULL;
funcenum_t *lastenum = NULL;
pstruct_t *firststruct = NULL;
pstruct_t *laststruct = NULL;
methodmap_t *methodmap_first = NULL;
methodmap_t *methodmap_last = NULL;
structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member)
{
int i;
for (i=0; i<pstruct->argcount; i++) {
if (strcmp(pstruct->args[i]->name, member) == 0)
return pstruct->args[i];
}
return NULL;
}
pstruct_t *pstructs_add(const char *name)
{
pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t));
memset(p, 0, sizeof(pstruct_t));
strcpy(p->name, name);
if (!firststruct) {
firststruct = p;
laststruct = p;
} else {
laststruct->next = p;
laststruct = p;
}
return p;
}
void pstructs_free()
{
pstruct_t *p, *next;
p = firststruct;
while (p) {
while (p->argcount--)
free(p->args[p->argcount]);
free(p->args);
next = p->next;
free(p);
p = next;
}
firststruct = NULL;
laststruct = NULL;
}
pstruct_t *pstructs_find(const char *name)
{
pstruct_t *p = firststruct;
while (p) {
if (strcmp(p->name, name) == 0)
return p;
p = p->next;
}
return NULL;
}
structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg)
{
structarg_t *newarg;
int i;
for (i=0; i<pstruct->argcount; i++) {
if (strcmp(pstruct->args[i]->name, arg->name) == 0) {
/* Don't allow dup names */
return NULL;
}
}
newarg = (structarg_t *)malloc(sizeof(structarg_t));
memcpy(newarg, arg, sizeof(structarg_t));
if (pstruct->argcount == 0) {
pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1);
} else {
pstruct->args = (structarg_t **)realloc(
pstruct->args,
sizeof(structarg_t *) * (pstruct->argcount + 1));
}
newarg->offs = pstruct->argcount * sizeof(cell);
newarg->index = pstruct->argcount;
pstruct->args[pstruct->argcount++] = newarg;
return newarg;
}
void funcenums_free()
{
funcenum_t *e, *next;
e = firstenum;
while (e) {
functag_t *tag, *nexttag;
tag = e->first;
while (tag) {
nexttag = tag->next;
free(tag);
tag = nexttag;
}
next = e->next;
free(e);
e = next;
}
firstenum = NULL;
lastenum = NULL;
}
funcenum_t *funcenums_find_by_tag(int tag)
{
funcenum_t *e = firstenum;
while (e) {
if (e->tag == tag)
return e;
e = e->next;
}
return NULL;
}
funcenum_t *funcenums_add(const char *name)
{
funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
memset(e, 0, sizeof(funcenum_t));
if (!firstenum) {
firstenum = e;
lastenum = e;
} else {
lastenum->next = e;
lastenum = e;
}
strcpy(e->name, name);
e->tag = pc_addtag_flags((char *)name, FIXEDTAG|FUNCTAG);
return e;
}
funcenum_t *funcenum_for_symbol(symbol *sym)
{
functag_t ft;
memset(&ft, 0, sizeof(ft));
ft.ret_tag = sym->tag;
ft.usage = uPUBLIC & (sym->usage & uRETVALUE);
ft.argcount = 0;
ft.ommittable = FALSE;
for (arginfo *arg = sym->dim.arglist; arg->ident; arg++) {
funcarg_t *dest = &ft.args[ft.argcount++];
dest->tagcount = arg->numtags;
memcpy(dest->tags, arg->tags, arg->numtags * sizeof(int));
dest->dimcount = arg->numdim;
memcpy(dest->dims, arg->dim, arg->numdim * sizeof(int));
dest->ident = arg->ident;
dest->fconst = !!(arg->usage & uCONST);
dest->ommittable = FALSE;
}
char name[METHOD_NAMEMAX+1];
UTIL_Format(name, sizeof(name), "::ft:%s:%d:%d", sym->name, sym->addr, sym->codeaddr);
funcenum_t *fe = funcenums_add(name);
functags_add(fe, &ft);
return fe;
}
// Finds a functag that was created intrinsically.
functag_t *functag_find_intrinsic(int tag)
{
funcenum_t *fe = funcenums_find_by_tag(tag);
if (!fe)
return NULL;
if (strncmp(fe->name, "::ft:", 5) != 0)
return NULL;
assert(fe->first && fe->first == fe->last);
return fe->first;
}
functag_t *functags_add(funcenum_t *en, functag_t *src)
{
functag_t *t = (functag_t *)malloc(sizeof(functag_t));
memcpy(t, src, sizeof(functag_t));
t->next = NULL;
if (en->first == NULL) {
en->first = t;
en->last = t;
} else {
en->last->next = t;
en->last = t;
}
return t;
}
/**
* Creates a new mem usage tracker entry
*/
void _push_memlist(memuse_list_t **head)
{
memuse_list_t *newlist = (memuse_list_t *)malloc(sizeof(memuse_list_t));
if (*head != NULL)
{
newlist->list_id = (*head)->list_id + 1;
} else {
newlist->list_id = 0;
}
newlist->prev = *head;
newlist->head = NULL;
*head = newlist;
}
/**
* Pops a heap list but does not free it.
*/
memuse_list_t *_pop_save_memlist(memuse_list_t **head)
{
memuse_list_t *oldlist = *head;
*head = (*head)->prev;
return oldlist;
}
/**
* Marks a memory usage on a memory list
*/
int _mark_memlist(memuse_list_t *head, int type, int size)
{
memuse_t *use;
if (type==MEMUSE_STATIC && size==0)
{
return 0;
}
use=head->head;
if (use && (type==MEMUSE_STATIC)
&& (use->type == type))
{
use->size += size;
} else {
use=(memuse_t *)malloc(sizeof(memuse_t));
use->type=type;
use->size=size;
use->prev=head->head;
head->head=use;
}
return size;
}
void _reset_memlist(memuse_list_t **head)
{
memuse_list_t *curlist = *head;
memuse_list_t *tmplist;
while (curlist) {
memuse_t *curuse = curlist->head;
memuse_t *tmpuse;
while (curuse) {
tmpuse = curuse->prev;
free(curuse);
curuse = tmpuse;
}
tmplist = curlist->prev;
free(curlist);
curlist = tmplist;
}
*head = NULL;
}
/**
* Wrapper for pushing the heap list
*/
void pushheaplist()
{
_push_memlist(&heapusage);
}
/**
* Wrapper for popping and saving the heap list
*/
memuse_list_t *popsaveheaplist()
{
return _pop_save_memlist(&heapusage);
}
/**
* Wrapper for marking the heap
*/
int markheap(int type, int size)
{
return _mark_memlist(heapusage, type, size);
}
/**
* Wrapper for pushing the stack list
*/
void pushstacklist()
{
_push_memlist(&stackusage);
}
/**
* Wrapper for marking the stack
*/
int markstack(int type, int size)
{
return _mark_memlist(stackusage, type, size);
}
/**
* Generates code to free all heap allocations on a tracker
*/
void _heap_freeusage(memuse_list_t *heap, int dofree)
{
memuse_t *cur=heap->head;
memuse_t *tmp;
while (cur) {
if (cur->type == MEMUSE_STATIC) {
modheap((-1)*cur->size*sizeof(cell));
} else {
modheap_i();
}
if (dofree) {
tmp=cur->prev;
free(cur);
cur=tmp;
} else {
cur=cur->prev;
}
}
if (dofree)
heap->head=NULL;
}
void _stack_genusage(memuse_list_t *stack, int dofree)
{
memuse_t *cur = stack->head;
memuse_t *tmp;
while (cur)
{
if (cur->type == MEMUSE_DYNAMIC)
{
/* no idea yet */
assert(0);
} else {
modstk(cur->size * sizeof(cell));
}
if (dofree)
{
tmp = cur->prev;
free(cur);
cur = tmp;
} else {
cur = cur->prev;
}
}
if (dofree)
{
stack->head = NULL;
}
}
/**
* Pops a heap list and frees it.
*/
void popheaplist()
{
memuse_list_t *oldlist;
assert(heapusage!=NULL);
_heap_freeusage(heapusage, 1);
assert(heapusage->head==NULL);
oldlist=heapusage->prev;
free(heapusage);
heapusage=oldlist;
}
void genstackfree(int stop_id)
{
memuse_list_t *curlist = stackusage;
while (curlist && curlist->list_id > stop_id)
{
_stack_genusage(curlist, 0);
curlist = curlist->prev;
}
}
void genheapfree(int stop_id)
{
memuse_list_t *curlist = heapusage;
while (curlist && curlist->list_id > stop_id)
{
_heap_freeusage(curlist, 0);
curlist = curlist->prev;
}
}
void popstacklist(int codegen)
{
memuse_list_t *oldlist;
assert(stackusage != NULL);
if (codegen)
{
_stack_genusage(stackusage, 1);
assert(stackusage->head==NULL);
} else {
memuse_t *use = stackusage->head;
while (use) {
memuse_t *temp = use->prev;
free(use);
use = temp;
}
}
oldlist = stackusage->prev;
free(stackusage);
stackusage = oldlist;
}
void resetstacklist()
{
_reset_memlist(&stackusage);
}
void resetheaplist()
{
_reset_memlist(&heapusage);
}
void methodmap_add(methodmap_t *map)
{
if (!methodmap_first) {
methodmap_first = map;
methodmap_last = map;
} else {
methodmap_last->next = map;
methodmap_last = map;
}
}
methodmap_t *methodmap_find_by_tag(int tag)
{
methodmap_t *ptr = methodmap_first;
for (; ptr; ptr = ptr->next) {
if (ptr->tag == tag)
return ptr;
}
return NULL;
}
methodmap_t *methodmap_find_by_name(const char *name)
{
int tag = pc_findtag(name);
if (tag == -1)
return NULL;
return methodmap_find_by_tag(tag);
}
methodmap_method_t *methodmap_find_method(methodmap_t *map, const char *name)
{
size_t i;
for (i = 0; i < map->nummethods; i++) {
if (strcmp(map->methods[i]->name, name) == 0)
return map->methods[i];
}
if (map->parent)
return methodmap_find_method(map->parent, name);
return NULL;
}
void methodmaps_free()
{
methodmap_t *ptr = methodmap_first;
while (ptr) {
methodmap_t *next = ptr->next;
for (size_t i = 0; i < ptr->nummethods; i++)
free(ptr->methods[i]);
free(ptr->methods);
free(ptr);
ptr = next;
}
methodmap_first = NULL;
methodmap_last = NULL;
}
LayoutSpec deduce_layout_spec_by_tag(int tag)
{
symbol *sym;
const char *name;
methodmap_t *map;
if ((map = methodmap_find_by_tag(tag)) != NULL)
return map->spec;
if (tag & FUNCTAG)
return Layout_FuncTag;
name = pc_tagname(tag);
if (pstructs_find(name))
return Layout_PawnStruct;
if ((sym = findglb(name, sGLOBAL)) != NULL)
return Layout_Enum;
return Layout_None;
}
LayoutSpec deduce_layout_spec_by_name(const char *name)
{
symbol *sym;
methodmap_t *map;
int tag = pc_findtag(name);
if (tag != -1 && (tag & FUNCTAG))
return Layout_FuncTag;
if (pstructs_find(name))
return Layout_PawnStruct;
if ((map = methodmap_find_by_name(name)) != NULL)
return map->spec;
if ((sym = findglb(name, sGLOBAL)) != NULL)
return Layout_Enum;
return Layout_None;
}
const char *layout_spec_name(LayoutSpec spec)
{
switch (spec) {
case Layout_None:
return "<none>";
case Layout_Enum:
return "enum";
case Layout_FuncTag:
return "functag";
case Layout_PawnStruct:
return "deprecated-struct";
case Layout_MethodMap:
return "methodmap";
case Layout_Class:
return "class";
}
return "<unknown>";
}
int can_redef_layout_spec(LayoutSpec def1, LayoutSpec def2)
{
// Normalize the ordering, since these checks are symmetrical.
if (def1 > def2) {
LayoutSpec temp = def2;
def2 = def1;
def1 = temp;
}
switch (def1) {
case Layout_None:
return TRUE;
case Layout_Enum:
if (def2 == Layout_Enum || def2 == Layout_FuncTag)
return TRUE;
return def2 == Layout_MethodMap;
case Layout_FuncTag:
return def2 == Layout_Enum || def2 == Layout_FuncTag;
case Layout_PawnStruct:
case Layout_MethodMap:
return FALSE;
case Layout_Class:
return FALSE;
}
return FALSE;
}
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
va_end(ap);
if (len >= maxlength) {
buffer[maxlength - 1] = '\0';
return maxlength - 1;
}
return len;
}

View File

@ -1,189 +0,0 @@
/* vim: set sts=2 ts=8 sw=2 tw=99 et: */
#ifndef _INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
#define _INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_
#define MEMUSE_STATIC 0
#define MEMUSE_DYNAMIC 1
typedef struct memuse_s {
int type; /* MEMUSE_STATIC or MEMUSE_DYNAMIC */
int size; /* size of array for static (0 for dynamic) */
struct memuse_s *prev; /* previous block on the list */
} memuse_t;
typedef struct memuse_list_s {
struct memuse_list_s *prev; /* last used list */
int list_id;
memuse_t *head; /* head of the current list */
} memuse_list_t;
typedef struct funcarg_s
{
int tagcount;
int tags[sTAGS_MAX];
int dimcount;
int dims[sDIMEN_MAX];
int ident;
int fconst;
int ommittable;
} funcarg_t;
typedef struct functag_s
{
int ret_tag;
int usage;
int argcount;
int ommittable;
funcarg_t args[sARGS_MAX];
struct functag_s *next;
} functag_t;
typedef struct funcenum_s
{
int tag;
char name[METHOD_NAMEMAX+1];
functag_t *first;
functag_t *last;
struct funcenum_s *next;
} funcenum_t;
typedef struct structarg_s
{
int tag;
int dimcount;
int dims[sDIMEN_MAX];
char name[sNAMEMAX+1];
int fconst;
int ident;
unsigned int offs;
int index;
} structarg_t;
typedef struct pstruct_s
{
int argcount;
char name[sNAMEMAX+1];
structarg_t **args;
struct pstruct_s *next;
} pstruct_t;
// The ordering of these definitions should be preserved for
// can_redef_layout_spec().
typedef enum LayoutSpec_t
{
Layout_None,
Layout_Enum,
Layout_FuncTag,
Layout_PawnStruct,
Layout_MethodMap,
Layout_Class
} LayoutSpec;
typedef struct methodmap_method_s
{
char name[METHOD_NAMEMAX + 1];
symbol *target;
symbol *getter;
symbol *setter;
bool is_static;
int property_tag() const {
assert(getter || setter);
if (getter)
return getter->tag;
arginfo *thisp = &setter->dim.arglist[0];
if (thisp->ident == 0)
return pc_tag_void;
arginfo *valp = &setter->dim.arglist[1];
if (valp->ident != iVARIABLE || valp->numtags != 1)
return pc_tag_void;
return valp->tags[0];
}
} methodmap_method_t;
struct methodmap_t
{
methodmap_t *next;
methodmap_t *parent;
int tag;
int nullable;
LayoutSpec spec;
char name[sNAMEMAX+1];
methodmap_method_t **methods;
size_t nummethods;
// Shortcut.
methodmap_method_t *dtor;
methodmap_method_t *ctor;
};
/**
* Pawn Structs
*/
pstruct_t *pstructs_add(const char *name);
void pstructs_free();
pstruct_t *pstructs_find(const char *name);
structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg);
structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member);
/**
* Function enumeration tags
*/
void funcenums_free();
funcenum_t *funcenums_add(const char *name);
funcenum_t *funcenums_find_by_tag(int tag);
functag_t *functags_add(funcenum_t *en, functag_t *src);
funcenum_t *funcenum_for_symbol(symbol *sym);
functag_t *functag_find_intrinsic(int tag);
/**
* Given a name or tag, find any extra weirdness it has associated with it.
*/
LayoutSpec deduce_layout_spec_by_tag(int tag);
LayoutSpec deduce_layout_spec_by_name(const char *name);
const char *layout_spec_name(LayoutSpec spec);
int can_redef_layout_spec(LayoutSpec olddef, LayoutSpec newdef);
/**
* Heap functions
*/
void pushheaplist();
memuse_list_t *popsaveheaplist();
void popheaplist();
int markheap(int type, int size);
/**
* Stack functions
*/
void pushstacklist();
void popstacklist(int codegen);
int markstack(int type, int size);
/**
* Generates code to free mem usage, but does not pop the list.
* This is used for code like dobreak()/docont()/doreturn().
* stop_id is the list at which to stop generating.
*/
void genstackfree(int stop_id);
void genheapfree(int stop_id);
/**
* Resets a mem list by freeing everything
*/
void resetstacklist();
void resetheaplist();
/**
* Method maps.
*/
void methodmap_add(methodmap_t *map);
methodmap_t *methodmap_find_by_tag(int tag);
methodmap_t *methodmap_find_by_name(const char *name);
methodmap_method_t *methodmap_find_method(methodmap_t *map, const char *name);
void methodmaps_free();
extern memuse_list_t *heapusage;
extern memuse_list_t *stackusage;
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
#endif //_INCLUDE_SOURCEPAWN_COMPILER_TRACKER_H_

View File

@ -1,120 +0,0 @@
/* Pawn compiler
*
* Global (cross-module) variables.
*
* Copyright (c) ITB CompuPhase, 1997-2006
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <stdio.h>
#include <stdlib.h> /* for _MAX_PATH */
#include "sc.h"
#include "sp_symhash.h"
/* global variables
*
* All global variables that are shared amongst the compiler files are
* declared here.
*/
symbol loctab; /* local symbol table */
symbol glbtab; /* global symbol table */
cell *litq; /* the literal queue */
unsigned char pline[sLINEMAX+1]; /* the line read from the input file */
const unsigned char *lptr; /* points to the current position in "pline" */
constvalue tagname_tab = { NULL, "", 0, 0}; /* tagname table */
constvalue libname_tab = { NULL, "", 0, 0}; /* library table (#pragma library "..." syntax) */
constvalue *curlibrary = NULL; /* current library */
int pc_addlibtable = TRUE; /* is the library table added to the AMX file? */
symbol *curfunc; /* pointer to current function */
char *inpfname; /* pointer to name of the file currently read from */
char outfname[_MAX_PATH]; /* intermediate (assembler) file name */
char binfname[_MAX_PATH]; /* binary file name */
char errfname[_MAX_PATH]; /* error file name */
char sc_ctrlchar = CTRL_CHAR; /* the control character (or escape character)*/
char sc_ctrlchar_org = CTRL_CHAR;/* the default control character */
int litidx = 0; /* index to literal table */
int litmax = sDEF_LITMAX; /* current size of the literal table */
int stgidx = 0; /* index to the staging buffer */
int sc_labnum = 0; /* number of (internal) labels */
int staging = 0; /* true if staging output */
cell declared = 0; /* number of local cells declared */
cell glb_declared=0; /* number of global cells declared */
cell code_idx = 0; /* number of bytes with generated code */
int ntv_funcid= 0; /* incremental number of native function */
int errnum = 0; /* number of errors */
int warnnum = 0; /* number of warnings */
int sc_debug = sCHKBOUNDS; /* by default: bounds checking+assertions */
int sc_packstr= FALSE; /* strings are packed by default? */
int sc_asmfile= FALSE; /* create .ASM file? */
int sc_listing= FALSE; /* create .LST file? */
int sc_compress=TRUE; /* compress bytecode? */
int sc_needsemicolon=TRUE;/* semicolon required to terminate expressions? */
int sc_dataalign=sizeof(cell);/* data alignment value */
int sc_alignnext=FALSE; /* must frame of the next function be aligned? */
int pc_docexpr=FALSE; /* must expression be attached to documentation comment? */
int curseg = 0; /* 1 if currently parsing CODE, 2 if parsing DATA */
cell pc_stksize=sDEF_AMXSTACK;/* default stack size */
cell pc_amxlimit=0; /* default abstract machine size limit = none */
cell pc_amxram=0; /* default abstract machine data size limit = none */
int freading = FALSE; /* Is there an input file ready for reading? */
int fline = 0; /* the line number in the current file */
short fnumber = 0; /* the file number in the file table (debugging) */
short fcurrent= 0; /* current file being processed (debugging) */
short sc_intest=FALSE; /* true if inside a test */
int sideeffect= 0; /* true if an expression causes a side-effect */
int stmtindent= 0; /* current indent of the statement */
int indent_nowarn=FALSE;/* skip warning "217 loose indentation" */
int sc_tabsize=8; /* number of spaces that a TAB represents */
short sc_allowtags=TRUE; /* allow/detect tagnames in lex() */
int sc_status; /* read/write status */
int sc_err_status;
int sc_rationaltag=0; /* tag for rational numbers */
int rational_digits=0; /* number of fractional digits */
int sc_allowproccall=0; /* allow/detect tagnames in lex() */
short sc_is_utf8=FALSE; /* is this source file in UTF-8 encoding */
char *pc_deprecate=NULL;/* if non-null, mark next declaration as deprecated */
int sc_curstates=0; /* ID of the current state list */
int pc_optimize=sOPTIMIZE_NOMACRO; /* (peephole) optimization level */
int pc_memflags=0; /* special flags for the stack/heap usage */
int sc_showincludes=0; /* show include files */
int sc_require_newdecls=0; /* Require new-style declarations */
bool sc_warnings_are_errors=false;
constvalue sc_automaton_tab = { NULL, "", 0, 0}; /* automaton table */
constvalue sc_state_tab = { NULL, "", 0, 0}; /* state table */
void *inpf = NULL; /* file read from (source or include) */
void *inpf_org= NULL; /* main source file */
void *outf = NULL; /* (intermediate) text file written to */
jmp_buf errbuf;
HashTable *sp_Globals = NULL;
#if !defined SC_LIGHT
int sc_makereport=FALSE; /* generate a cross-reference report */
#endif
#if defined __WATCOMC__ && !defined NDEBUG
/* Watcom's CVPACK dislikes .OBJ files without functions */
static int dummyfunc(void)
{
return 0;
}
#endif

View File

@ -1,111 +0,0 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2012-2014 David Anderson
//
// This file is part of SourcePawn.
//
// SourcePawn is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
#include "smx-builder.h"
using namespace ke;
using namespace sp;
SmxBuilder::SmxBuilder()
{
}
bool
SmxBuilder::write(ISmxBuffer *buf)
{
sp_file_hdr_t header;
header.magic = SmxConsts::FILE_MAGIC;
header.version = SmxConsts::SP1_VERSION_1_1;
header.compression = SmxConsts::FILE_COMPRESSION_NONE;
header.disksize = sizeof(header) +
sizeof(sp_file_section_t) * sections_.length();
// Note that |dataoffs| here is just to mimic what it would be in earlier
// versions of Pawn. Its value does not actually matter per the SMX spec,
// aside from having to be >= sizeof(sp_file_hdr_t). Here, we hint that
// only the region after the section list and names should be compressed.
header.dataoffs = header.disksize;
size_t current_string_offset = 0;
for (size_t i = 0; i < sections_.length(); i++) {
Ref<SmxSection> section = sections_[i];
header.disksize += section->length();
current_string_offset += section->name().length() + 1;
}
header.disksize += current_string_offset;
header.dataoffs += current_string_offset;
header.imagesize = header.disksize;
header.sections = sections_.length();
// We put the string table after the sections table.
header.stringtab = sizeof(header) + sizeof(sp_file_section_t) * sections_.length();
if (!buf->write(&header, sizeof(header)))
return false;
size_t current_offset = sizeof(header);
size_t current_data_offset = header.stringtab + current_string_offset;
current_string_offset = 0;
for (size_t i = 0; i < sections_.length(); i++) {
sp_file_section_t s;
s.nameoffs = current_string_offset;
s.dataoffs = current_data_offset;
s.size = sections_[i]->length();
if (!buf->write(&s, sizeof(s)))
return false;
current_offset += sizeof(s);
current_data_offset += s.size;
current_string_offset += sections_[i]->name().length() + 1;
}
assert(buf->pos() == current_offset);
assert(current_offset == header.stringtab);
for (size_t i = 0; i < sections_.length(); i++) {
const AString &name = sections_[i]->name();
if (!buf->write(name.chars(), name.length() + 1))
return false;
}
current_offset += current_string_offset;
assert(buf->pos() == current_offset);
for (size_t i = 0; i < sections_.length(); i++) {
if (!sections_[i]->write(buf))
return false;
current_offset += sections_[i]->length();
}
assert(buf->pos() == current_offset);
assert(current_offset == header.disksize);
return true;
}
bool
SmxNameTable::write(ISmxBuffer *buf)
{
for (size_t i = 0; i < names_.length(); i++) {
Atom *str = names_[i];
if (!buf->write(str->chars(), str->length() + 1))
return false;
}
return true;
}

View File

@ -1,217 +0,0 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2012-2014 AlliedModders LLC, David Anderson
//
// This file is part of SourcePawn.
//
// SourcePawn is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
#ifndef _include_spcomp2_smx_builder_h_
#define _include_spcomp2_smx_builder_h_
#include <am-string.h>
#include <am-vector.h>
#include <am-hashmap.h>
#include <am-refcounting.h>
#include <smx/smx-headers.h>
#include "string-pool.h"
#include "memory-buffer.h"
namespace ke {
// An SmxSection is a named blob of data.
class SmxSection : public Refcounted<SmxSection>
{
public:
SmxSection(const char *name)
: name_(name)
{
}
virtual bool write(ISmxBuffer *buf) = 0;
virtual size_t length() const = 0;
const AString &name() const {
return name_;
}
private:
AString name_;
};
// An SmxBlobSection is a section that has some kind of header structure
// (specified as a template parameter), and then an arbitrary run of bytes
// immediately after.
template <typename T>
class SmxBlobSection : public SmxSection
{
public:
SmxBlobSection(const char *name)
: SmxSection(name),
extra_(nullptr),
extra_len_(0)
{
memset(&t_, 0, sizeof(t_));
}
T &header() {
return t_;
}
void setBlob(uint8_t *blob, size_t len) {
extra_ = blob;
extra_len_ = len;
}
bool write(ISmxBuffer *buf) KE_OVERRIDE {
if (!buf->write(&t_, sizeof(t_)))
return false;
if (!extra_len_)
return true;
return buf->write(extra_, extra_len_);
}
size_t length() const KE_OVERRIDE {
return sizeof(t_) + extra_len_;
}
private:
T t_;
uint8_t *extra_;
size_t extra_len_;
};
// An SmxBlobSection without headers.
template <>
class SmxBlobSection<void> : public SmxSection
{
public:
SmxBlobSection(const char *name)
: SmxSection(name)
{
}
void add(void *bytes, size_t len) {
buffer_.write(bytes, len);
}
bool write(ISmxBuffer *buf) KE_OVERRIDE {
return buf->write(buffer_.bytes(), buffer_.size());
}
size_t length() const KE_OVERRIDE {
return buffer_.size();
}
private:
MemoryBuffer buffer_;
};
// An SmxListSection is a section that is a simple table of uniformly-sized
// structures. It has no header of its own.
template <typename T>
class SmxListSection : public SmxSection
{
public:
SmxListSection(const char *name)
: SmxSection(name)
{
}
void append(const T &t) {
list_.append(t);
}
T &add() {
list_.append(T());
return list_.back();
}
void add(const T &t) {
list_.append(t);
}
bool write(ISmxBuffer *buf) KE_OVERRIDE {
return buf->write(list_.buffer(), list_.length() * sizeof(T));
}
size_t length() const KE_OVERRIDE {
return count() * sizeof(T);
}
size_t count() const {
return list_.length();
}
private:
Vector<T> list_;
};
// A name table is a blob of zero-terminated strings. Strings are entered
// into the table as atoms, so duplicate stings are not emitted.
class SmxNameTable : public SmxSection
{
public:
SmxNameTable(const char *name)
: SmxSection(name),
buffer_size_(0)
{
name_table_.init(64);
}
uint32_t add(StringPool &pool, const char *str) {
return add(pool.add(str));
}
uint32_t add(Atom *str) {
NameTable::Insert i = name_table_.findForAdd(str);
if (i.found())
return i->value;
assert(IsUint32AddSafe(buffer_size_, str->length() + 1));
uint32_t index = buffer_size_;
name_table_.add(i, str, index);
names_.append(str);
buffer_size_ += str->length() + 1;
return index;
}
bool write(ISmxBuffer *buf) KE_OVERRIDE;
size_t length() const KE_OVERRIDE {
return buffer_size_;
}
private:
struct HashPolicy {
static uint32_t hash(Atom *str) {
return HashPointer(str);
}
static bool matches(Atom *a, Atom *b) {
return a == b;
}
};
typedef HashMap<Atom *, size_t, HashPolicy> NameTable;
NameTable name_table_;
Vector<Atom *> names_;
uint32_t buffer_size_;
};
class SmxBuilder
{
public:
SmxBuilder();
bool write(ISmxBuffer *buf);
void add(const Ref<SmxSection> &section) {
sections_.append(section);
}
private:
Vector<Ref<SmxSection>> sections_;
};
} // namespace ke
#endif // _include_spcomp2_smx_builder_h_

View File

@ -1,129 +0,0 @@
// vim: set ts=8 sts=2 sw=2 tw=99 et:
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "sc.h"
#include "sp_symhash.h"
#include <am-hashtable.h>
struct NameAndScope
{
const char *name;
int fnumber;
int *cmptag;
mutable symbol *matched;
mutable int count;
NameAndScope(const char *name, int fnumber, int *cmptag)
: name(name),
fnumber(fnumber),
cmptag(cmptag),
matched(nullptr),
count(0)
{
}
};
struct SymbolHashPolicy
{
typedef symbol *Payload;
// Everything with the same name has the same hash, because the compiler
// wants to know two names that have the same tag for some reason. Even
// so, we can't be that accurate, since we might match the right symbol
// very early.
static uint32_t hash(const NameAndScope &key) {
return ke::HashCharSequence(key.name, strlen(key.name));
}
static uint32_t hash(const symbol *s) {
return ke::HashCharSequence(s->name, strlen(s->name));
}
static bool matches(const NameAndScope &key, symbol *sym) {
if (sym->parent && sym->ident != iCONSTEXPR)
return false;
if (sym->fnumber >= 0 && sym->fnumber != key.fnumber)
return false;
if (strcmp(key.name, sym->name) != 0)
return false;
if (key.cmptag) {
key.count++;
key.matched = sym;
if (*key.cmptag != sym->tag)
return false;
}
return true;
}
static bool matches(const symbol *key, symbol *sym) {
return key == sym;
}
};
struct HashTable : public ke::HashTable<SymbolHashPolicy>
{
};
uint32_t
NameHash(const char *str)
{
return ke::HashCharSequence(str, strlen(str));
}
HashTable *NewHashTable()
{
HashTable *ht = new HashTable();
if (!ht->init()) {
delete ht;
return nullptr;
}
return ht;
}
void
DestroyHashTable(HashTable *ht)
{
delete ht;
}
symbol *
FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber, int *cmptag)
{
NameAndScope nas(name, fnumber, cmptag);
HashTable::Result r = ht->find(nas);
if (!r.found()) {
if (nas.matched) {
*cmptag = nas.count;
return nas.matched;
}
return nullptr;
}
*cmptag = 1;
return *r;
}
symbol *
FindInHashTable(HashTable *ht, const char *name, int fnumber)
{
NameAndScope nas(name, fnumber, nullptr);
HashTable::Result r = ht->find(nas);
if (!r.found())
return nullptr;
return *r;
}
void
AddToHashTable(HashTable *ht, symbol *sym)
{
HashTable::Insert i = ht->findForAdd(sym);
assert(!i.found());
ht->add(i, sym);
}
void
RemoveFromHashTable(HashTable *ht, symbol *sym)
{
HashTable::Result r = ht->find(sym);
assert(r.found());
ht->remove(r);
}

View File

@ -1,18 +0,0 @@
/* vim: set ts=4 sw=4 tw=99 et: */
#ifndef _INCLUDE_SPCOMP_SYMHASH_H_
#define _INCLUDE_SPCOMP_SYMHASH_H_
uint32_t NameHash(const char *str);
struct HashTable;
HashTable *NewHashTable();
void DestroyHashTable(HashTable *ht);
void AddToHashTable(HashTable *ht, symbol *sym);
void RemoveFromHashTable(HashTable *ht, symbol *sym);
symbol *FindInHashTable(HashTable *ht, const char *name, int fnumber);
symbol *FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber,
int *cmptag);
#endif /* _INCLUDE_SPCOMP_SYMHASH_H_ */

View File

@ -1,146 +0,0 @@
/* vim: set ts=2 sw=2 tw=99 et:
*
* Copyright (C) 2012-2014 AlliedModders LLC, David Anderson
*
* This file is part of SourcePawn.
*
* SourcePawn is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* SourcePawn. If not, see http://www.gnu.org/licenses/.
*/
#ifndef _include_jitcraft_string_pool_h_
#define _include_jitcraft_string_pool_h_
// string-pool is a collection of helpers to atomize/internalize strings. The
// StringPool class provides Atom objects which can be used for efficiently
// handling string sets or dictionaries.
#include <am-hashtable.h>
#include <am-string.h>
#include <string.h>
namespace ke {
// An Atom is a string that has a unique instance. That is, any Atom("a") is
// guaranteed to be pointer-equivalent to another Atom("a"), as long as they
// originated from the same StringPool.
class Atom
{
friend class StringPool;
private:
Atom(const char *str, size_t len)
: str_(str, len)
{
}
public:
size_t length() const {
return str_.length();
}
const char *chars() const {
return str_.chars();
}
private:
AString str_;
};
// Helper class to use as a key for hash table lookups.
class CharsAndLength
{
public:
CharsAndLength()
: str_(nullptr),
length_(0)
{
}
CharsAndLength(const char *str, size_t length)
: str_(str),
length_(length)
{
}
const char *str() const {
return str_;
}
size_t length() const {
return length_;
}
private:
const char *str_;
size_t length_;
};
// Atom dictionary.
class StringPool
{
public:
StringPool()
: table_(SystemAllocatorPolicy())
{
init();
}
~StringPool()
{
if (!table_.elements())
return;
for (Table::iterator i(&table_); !i.empty(); i.next())
delete *i;
}
bool init() {
return table_.init(256);
}
Atom *add(const char *str, size_t length) {
CharsAndLength chars(str, length);
Table::Insert p = table_.findForAdd(chars);
if (!p.found() && !table_.add(p, new Atom(str, length)))
return nullptr;
return *p;
}
Atom *add(const char *str) {
return add(str, strlen(str));
}
private:
struct Policy {
typedef Atom *Payload;
static uint32_t hash(const char *key) {
return HashCharSequence(key, strlen(key));
}
static uint32_t hash(const CharsAndLength &key) {
return HashCharSequence(key.str(), key.length());
}
static bool matches(const CharsAndLength &key, const Payload &e) {
if (key.length() != e->length())
return false;
return strcmp(key.str(), e->chars()) == 0;
}
};
typedef HashTable<Policy> Table;
private:
Table table_;
};
} // namespace ke
#endif // _include_jitcraft_string_pool_h_

View File

@ -1,11 +0,0 @@
methodmap Y
{
};
class X < Y
{
};
public main()
{
}

View File

@ -1 +0,0 @@
cannot mix methodmaps and classes with inheritance

View File

@ -1,11 +0,0 @@
class Y
{
};
methodmap X < Y
{
};
public main()
{
}

View File

@ -1 +0,0 @@
cannot mix methodmaps and classes with inheritance

View File

@ -1,13 +0,0 @@
class X
{
};
f(X:x)
{
return 3
}
public main()
{
return f(2);
}

View File

@ -1 +0,0 @@
cannot coerce non-object type int to object type X

View File

@ -1,14 +0,0 @@
class X
{
};
f(any:x)
{
return 3
}
public main()
{
new X:x;
return f(x);
}

View File

@ -1 +0,0 @@
cannot coerce object type X to non-object type any

View File

@ -1,14 +0,0 @@
class X
{
};
f({X,Float}:x)
{
return 3
}
public main()
{
new X:x;
return f(x);
}

View File

@ -1 +0,0 @@
cannot use an object in a multi-tag selector

View File

@ -1,14 +0,0 @@
class X
{
};
f(x)
{
return 3
}
public main()
{
new X:x;
return f(x);
}

View File

@ -1 +0,0 @@
cannot coerce object type X to non-object type int

View File

@ -1,14 +0,0 @@
class X
{
};
f(...)
{
return 3
}
public main()
{
new X:x;
return f(x);
}

View File

@ -1 +0,0 @@
cannot coerce object type X to non-object type int

View File

@ -1,5 +0,0 @@
public Action:SomeEvent( Handle:event, const String:name[], bool:dontBroadcast)
{
// error 143: new-style declarations should not have "new"
new object = GetEventInt(event, "object");
}

View File

@ -1 +0,0 @@
(4) : error 157: 'object' is a reserved keyword

View File

@ -1,14 +0,0 @@
class X
{
};
f(X:x)
{
return 3
}
public main()
{
new x;
return f(X:x);
}

View File

@ -1 +0,0 @@
cannot coerce non-object type int to object type X

View File

@ -1,14 +0,0 @@
class X
{
};
f(x)
{
return 3
}
public main()
{
new X:x;
return f(_:x);
}

View File

@ -1 +0,0 @@
cannot coerce object type X to non-object type int

View File

@ -1,9 +0,0 @@
native CloseHandle(Handle:handle[]);
methodmap Handle {
public Close() = CloseHandle;
};
public main()
{
}

View File

@ -1 +0,0 @@
method must have a first argument compatible with the methodmap type (Handle)

View File

@ -1,4 +0,0 @@
Foo(any foo) {}
public Bar() {
Foo(null);
}

View File

@ -1 +0,0 @@
(3) : error 148: cannot assign null to a non-nullable type

View File

@ -1,7 +0,0 @@
public main()
{
char x[40];
any y[10];
x = y;
y = x;
}

View File

@ -1,2 +0,0 @@
(5) : error 179: cannot assign char[] to any[], storage classes differ
(6) : error 179: cannot assign any[] to char[], storage classes differ

View File

@ -1,12 +0,0 @@
methodmap Egg
{
public void illegal(Egg x) {
this = x;
}
};
public main()
{
Egg egg;
egg.illegal(egg);
}

View File

@ -1 +0,0 @@
(4) : error 022: must be lvalue (non-constant)

View File

@ -1,15 +0,0 @@
stock A(int)
{
}
stock B(int[5] N)
{
}
stock C(int:N)
{
}
public main()
{
}

View File

@ -1,3 +0,0 @@
(1) : error 001: expected token: "-identifier-", but found ")"
(5) : error 140: new-style array types cannot specify dimension sizes as part of their type
(9) : warning 238: 'int:' is an illegal cast; use view_as<int>(expression)

View File

@ -1,17 +0,0 @@
int[] gInvalid = {1};
public OnPluginStart()
{
int v = 10;
int invalid1[v];
int[] invalid2 = {1};
static int[] invalid3 = {1};
}
void invalid_arg1(int invalid[])
{
}
void invalid_arg2(int[] invalid = {1, 2, 3})
{
}

View File

@ -1,7 +0,0 @@
(1) : error 162: cannot create dynamic arrays in global scope - did you mean to create a fixed-length array with brackets after the variable name?
(6) : error 161: brackets after variable name indicate a fixed-size array, but a dynamic size was given - did you mean to use 'new int[size]' syntax?
(7) : error 160: brackets in between type and variable name indicate a dynamic-size array, but a fixed-size initializer was given
(8) : error 165: cannot create dynamic arrays in static scope - did you mean to create a fixed-length array with brackets after the variable name?
(11) : error 159: brackets after variable name indicate a fixed-size array, but size could not be determined - either specify sizes, an array initializer, or use dynamic syntax (such as 'char[] x')
(15) : error 160: brackets in between type and variable name indicate a dynamic-size array, but a fixed-size initializer was given

View File

@ -1,13 +0,0 @@
void[] Bad1()
{
}
void Bad2;
stock Bad3(void x)
{
}
public main()
{
}

View File

@ -1,3 +0,0 @@
(1) : error 145: invalid type expression
(5) : error 144: void cannot be used as a variable type
(7) : error 144: void cannot be used as a variable type

View File

@ -1,12 +0,0 @@
native printnum(t);
methodmap X
{
public int GetThing() {
return 10;
}
}
public main() {
printnum(X.GetThing());
}

View File

@ -1 +0,0 @@
(11) : error 176: non-static method or property 'GetThing' must be called with a value of type 'X'

View File

@ -1,13 +0,0 @@
native printnum(t);
methodmap X
{
public static int GetThing() {
return 10;
}
}
public main() {
X x;
printnum(x.GetThing());
}

View File

@ -1 +0,0 @@
(12) : error 177: static method 'GetThing' must be invoked via its type (try 'X.GetThing')

View File

@ -1,16 +0,0 @@
String:MyFunction()
{
new String:egg[10] = "egg";
return egg;
}
public crab()
{
new String:egg[10];
egg = MyFunction();
}
public Function:main()
{
return MyFunction;
}

View File

@ -1 +0,0 @@
(15) : error 182: functions that return arrays cannot be used as callbacks

View File

@ -1,3 +0,0 @@
public float egg() {
return view_as<void>(10);
}

View File

@ -1 +0,0 @@
(2) : error 144: void cannot be used as a variable type

View File

@ -1,9 +0,0 @@
f(any[] x)
{
}
public main()
{
char x[10];
f(x[1]);
}

View File

@ -1 +0,0 @@
(8) : error 178: cannot coerce char[] to any[]; storage classes differ

View File

@ -1,9 +0,0 @@
f(any[] x)
{
}
public main()
{
char x[10];
f(x);
}

View File

@ -1 +0,0 @@
(8) : error 178: cannot coerce char[] to any[]; storage classes differ

View File

@ -1,13 +0,0 @@
native Float:CreateHandle(count);
native CloseHandle(Handle:handle);
methodmap Handle {
public Handle() = CreateHandle;
public Close() = CloseHandle;
};
public main() {
new Handle:handle = Handle(3);
handle.Close();
}

View File

@ -1 +0,0 @@
constructor function must return tag Handle

View File

@ -1 +0,0 @@
public x(param = 1) {}

View File

@ -1 +0,0 @@
(1) : error 059: function argument may not have a default value (variable "param")

View File

@ -1,10 +0,0 @@
native Handle:CreateHandle();
methodmap Handle {
public Handle() = CreateHandle;
};
public main() {
new Handle:handle = Handle();
delete handle;
}

View File

@ -1 +0,0 @@
cannot use delete, methodmap Handle has no destructor

View File

@ -1,8 +0,0 @@
native Q(X:handle, a);
methodmap X {
public ~X() = Q;
}
public main() {
}

View File

@ -1 +0,0 @@
destructors cannot have extra arguments

View File

@ -1,10 +0,0 @@
Q(X:handle)
{
}
methodmap X {
public ~X() = Q;
}
public main() {
}

View File

@ -1 +0,0 @@
destructors must be native functions

View File

@ -1,8 +0,0 @@
native bool:Q();
methodmap X {
public ~X() = Q;
}
public main() {
}

View File

@ -1 +0,0 @@
destructor should not have an explicit return type

Some files were not shown because too many files have changed in this diff Show More