Merge pull request #141 from alliedmodders/calli-5
Rewrite the assembly pipeline.
This commit is contained in:
commit
06f52aa7ce
@ -45,6 +45,7 @@ compiler.includes += [
|
|||||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||||
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
|
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
|
||||||
os.path.join(builder.sourcePath, 'sourcepawn', 'compiler'),
|
os.path.join(builder.sourcePath, 'sourcepawn', 'compiler'),
|
||||||
|
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||||
os.path.join(builder.buildPath, 'includes'),
|
os.path.join(builder.buildPath, 'includes'),
|
||||||
os.path.join(builder.buildPath, builder.buildFolder),
|
os.path.join(builder.buildPath, builder.buildFolder),
|
||||||
]
|
]
|
||||||
@ -54,7 +55,8 @@ if compiler.cc.behavior == 'gcc':
|
|||||||
compiler.cflags += ['-Wno-format']
|
compiler.cflags += ['-Wno-format']
|
||||||
compiler.c_only_flags += ['-std=c99']
|
compiler.c_only_flags += ['-std=c99']
|
||||||
if builder.target_platform == 'linux':
|
if builder.target_platform == 'linux':
|
||||||
compiler.postlink += ['-lgcc', '-lm']
|
compiler.postlink += ['-lm']
|
||||||
|
compiler.postlink += ['-lstdc++']
|
||||||
elif compiler.cc.behavior == 'msvc':
|
elif compiler.cc.behavior == 'msvc':
|
||||||
compiler.linkflags.remove('/SUBSYSTEM:WINDOWS')
|
compiler.linkflags.remove('/SUBSYSTEM:WINDOWS')
|
||||||
compiler.linkflags.append('/SUBSYSTEM:CONSOLE')
|
compiler.linkflags.append('/SUBSYSTEM:CONSOLE')
|
||||||
@ -95,7 +97,7 @@ binary.sources += [
|
|||||||
'scstate.cpp',
|
'scstate.cpp',
|
||||||
'sctracker.cpp',
|
'sctracker.cpp',
|
||||||
'scvars.cpp',
|
'scvars.cpp',
|
||||||
'sp_file.cpp',
|
'smx-builder.cpp',
|
||||||
'zlib/adler32.c',
|
'zlib/adler32.c',
|
||||||
'zlib/compress.c',
|
'zlib/compress.c',
|
||||||
'zlib/crc32.c',
|
'zlib/crc32.c',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// vim: set sts=8 ts=4 sw=4 tw=99 noet:
|
// vim: set sts=8 ts=2 sw=2 tw=99 noet:
|
||||||
/* LIBPAWNC.C
|
/* LIBPAWNC.C
|
||||||
*
|
*
|
||||||
* A "glue file" for building the Pawn compiler as a DLL or shared library.
|
* A "glue file" for building the Pawn compiler as a DLL or shared library.
|
||||||
@ -341,42 +341,3 @@ char *pc_readasm(void *handle, char *string, int maxchars)
|
|||||||
{
|
{
|
||||||
return mfgets((MEMFILE*)handle,string,maxchars);
|
return mfgets((MEMFILE*)handle,string,maxchars);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern memfile_t *bin_file;
|
|
||||||
|
|
||||||
/* Should return a pointer, which is used as a "magic cookie" to all I/O
|
|
||||||
* functions; return NULL for failure.
|
|
||||||
*/
|
|
||||||
void *pc_openbin(char *filename)
|
|
||||||
{
|
|
||||||
return memfile_creat(filename, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pc_closebin(void *handle,int deletefile)
|
|
||||||
{
|
|
||||||
if (deletefile) {
|
|
||||||
memfile_destroy((memfile_t *)handle);
|
|
||||||
bin_file = NULL;
|
|
||||||
} else {
|
|
||||||
bin_file = (memfile_t *)handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pc_resetbin()
|
|
||||||
* Can seek to any location in the file.
|
|
||||||
* The offset is always from the start of the file.
|
|
||||||
*/
|
|
||||||
void pc_resetbin(void *handle,long offset)
|
|
||||||
{
|
|
||||||
memfile_seek((memfile_t *)handle, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
int pc_writebin(void *handle,void *buffer,int size)
|
|
||||||
{
|
|
||||||
return memfile_write((memfile_t *)handle, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
long pc_lengthbin(void *handle)
|
|
||||||
{
|
|
||||||
return memfile_tell((memfile_t *)handle);
|
|
||||||
}
|
|
||||||
|
103
sourcepawn/compiler/memory-buffer.h
Normal file
103
sourcepawn/compiler/memory-buffer.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// 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_
|
@ -3,557 +3,19 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "memfile.h"
|
#include "memfile.h"
|
||||||
#include "sp_file.h"
|
|
||||||
#include "amx.h"
|
|
||||||
#include "amxdbg.h"
|
|
||||||
#include "osdefs.h"
|
#include "osdefs.h"
|
||||||
#include "zlib/zlib.h"
|
|
||||||
#if defined LINUX || defined DARWIN
|
#if defined LINUX || defined DARWIN
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#elif defined WIN32
|
#elif defined WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "sc.h"
|
||||||
enum FileSections
|
|
||||||
{
|
|
||||||
FS_Code, /* required */
|
|
||||||
FS_Data, /* required */
|
|
||||||
FS_Publics,
|
|
||||||
FS_Pubvars,
|
|
||||||
FS_Natives,
|
|
||||||
FS_Nametable, /* required */
|
|
||||||
FS_DbgFile,
|
|
||||||
FS_DbgSymbol,
|
|
||||||
FS_DbgLine,
|
|
||||||
FS_DbgTags,
|
|
||||||
FS_DbgNatives,
|
|
||||||
FS_DbgAutomaton,
|
|
||||||
FS_DbgState,
|
|
||||||
FS_DbgStrings,
|
|
||||||
FS_DbgInfo,
|
|
||||||
FS_Tags,
|
|
||||||
/* --- */
|
|
||||||
FS_Number,
|
|
||||||
};
|
|
||||||
|
|
||||||
int pc_printf(const char *message,...);
|
|
||||||
int pc_compile(int argc, char **argv);
|
|
||||||
void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf);
|
|
||||||
|
|
||||||
memfile_t *bin_file = NULL;
|
|
||||||
jmp_buf brkout;
|
|
||||||
|
|
||||||
#define sARGS_MAX 32 /* number of arguments a function can have, max */
|
|
||||||
#define sDIMEN_MAX 4 /* maximum number of array dimensions */
|
|
||||||
|
|
||||||
typedef struct t_arg_s
|
|
||||||
{
|
|
||||||
uint8_t ident;
|
|
||||||
int16_t tag;
|
|
||||||
char *name;
|
|
||||||
uint16_t dimcount;
|
|
||||||
sp_fdbg_arraydim_t dims[sDIMEN_MAX];
|
|
||||||
} t_arg;
|
|
||||||
|
|
||||||
typedef struct t_native_s
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
int16_t ret_tag;
|
|
||||||
uint16_t num_args;
|
|
||||||
t_arg args[sARGS_MAX];
|
|
||||||
} t_native;
|
|
||||||
|
|
||||||
t_native *native_list = NULL;
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (pc_compile(argc,argv) != 0)
|
return pc_compile(argc,argv);
|
||||||
return 1;
|
|
||||||
|
|
||||||
AMX_HEADER *hdr;
|
|
||||||
AMX_DBG_HDR *dbg = NULL;
|
|
||||||
int err;
|
|
||||||
uint32_t i;
|
|
||||||
sp_file_t *spf;
|
|
||||||
memfile_t *dbgtab = NULL; //dbgcrab
|
|
||||||
unsigned char *dbgptr = NULL;
|
|
||||||
uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0};
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
if (bin_file == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
hdr = (AMX_HEADER *)bin_file->base;
|
|
||||||
|
|
||||||
if ((spf=spfw_create(bin_file->name, NULL)) == NULL) {
|
|
||||||
pc_printf("Error creating binary file!\n");
|
|
||||||
memfile_destroy(bin_file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err=setjmp(brkout))!=0)
|
|
||||||
goto write_error;
|
|
||||||
|
|
||||||
spfw_add_section(spf, ".code");
|
|
||||||
spfw_add_section(spf, ".data");
|
|
||||||
|
|
||||||
sections[FS_Publics] = (hdr->natives - hdr->publics) / hdr->defsize;
|
|
||||||
if (sections[FS_Publics])
|
|
||||||
spfw_add_section(spf, ".publics");
|
|
||||||
sections[FS_Pubvars] = (hdr->tags - hdr->pubvars) / hdr->defsize;
|
|
||||||
if (sections[FS_Pubvars])
|
|
||||||
spfw_add_section(spf, ".pubvars");
|
|
||||||
sections[FS_Natives] = (hdr->libraries - hdr->natives) / hdr->defsize;
|
|
||||||
if (sections[FS_Natives])
|
|
||||||
spfw_add_section(spf, ".natives");
|
|
||||||
sections[FS_Tags] = (hdr->nametable - hdr->tags) / hdr->defsize;
|
|
||||||
if (sections[FS_Tags])
|
|
||||||
spfw_add_section(spf, ".tags");
|
|
||||||
|
|
||||||
spfw_add_section(spf, ".names");
|
|
||||||
|
|
||||||
if (hdr->flags & AMX_FLAG_DEBUG) {
|
|
||||||
dbg = (AMX_DBG_HDR *)((unsigned char *)hdr + hdr->size);
|
|
||||||
if (dbg->magic != AMX_DBG_MAGIC) {
|
|
||||||
pc_printf("Error reading AMX_DBG_HDR, debug data will not be written.");
|
|
||||||
} else {
|
|
||||||
dbgtab = memfile_creat("", 512);
|
|
||||||
dbgptr = (unsigned char *)dbg + sizeof(AMX_DBG_HDR);
|
|
||||||
if ((sections[FS_DbgNatives] = sections[FS_Natives]) > 0)
|
|
||||||
spfw_add_section(spf, ".dbg.natives");
|
|
||||||
if (dbg->files) {
|
|
||||||
spfw_add_section(spf, ".dbg.files");
|
|
||||||
sections[FS_DbgFile] = dbg->files;
|
|
||||||
}
|
|
||||||
if (dbg->lines) {
|
|
||||||
spfw_add_section(spf, ".dbg.lines");
|
|
||||||
sections[FS_DbgLine] = dbg->lines;
|
|
||||||
}
|
|
||||||
if (dbg->symbols) {
|
|
||||||
spfw_add_section(spf, ".dbg.symbols");
|
|
||||||
sections[FS_DbgSymbol] = dbg->symbols;
|
|
||||||
}
|
|
||||||
sections[FS_DbgInfo] = 1;
|
|
||||||
sections[FS_DbgStrings] = 1;
|
|
||||||
spfw_add_section(spf, ".dbg.info");
|
|
||||||
spfw_add_section(spf, ".dbg.strings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spfw_finalize_header(spf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Begin writing each of our known tables out
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (sections[FS_Code]) {
|
|
||||||
sp_file_code_t cod;
|
|
||||||
unsigned char *cbase;
|
|
||||||
|
|
||||||
cod.cellsize = sizeof(cell);
|
|
||||||
|
|
||||||
cod.codesize = hdr->dat - hdr->cod;
|
|
||||||
cod.codeversion = hdr->amx_version;
|
|
||||||
cod.flags = 0;
|
|
||||||
if (hdr->flags & AMX_FLAG_DEBUG)
|
|
||||||
{
|
|
||||||
cod.flags |= SP_FLAG_DEBUG;
|
|
||||||
}
|
|
||||||
cod.code = sizeof(cod);
|
|
||||||
cod.main = hdr->cip;
|
|
||||||
|
|
||||||
/* write the code */
|
|
||||||
cbase = (unsigned char *)hdr + hdr->cod;
|
|
||||||
sfwrite(&cod, sizeof(cod), 1, spf);
|
|
||||||
sfwrite(cbase, cod.codesize, 1, spf);
|
|
||||||
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_Data]) {
|
|
||||||
sp_file_data_t dat;
|
|
||||||
unsigned char *dbase = (unsigned char *)hdr + hdr->dat;
|
|
||||||
|
|
||||||
dat.datasize = hdr->hea - hdr->dat;
|
|
||||||
dat.memsize = hdr->stp;
|
|
||||||
dat.data = sizeof(dat);
|
|
||||||
|
|
||||||
/* write header */
|
|
||||||
sfwrite(&dat, sizeof(dat), 1, spf);
|
|
||||||
|
|
||||||
if (dat.datasize) {
|
|
||||||
/* write data */
|
|
||||||
sfwrite(dbase, dat.datasize, 1, spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_Publics]) {
|
|
||||||
sp_file_publics_t *pbtbl;
|
|
||||||
AMX_FUNCSTUBNT *stub;
|
|
||||||
unsigned char *stubptr;
|
|
||||||
uint32_t publics = sections[FS_Publics];
|
|
||||||
|
|
||||||
pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics);
|
|
||||||
stubptr = (unsigned char *)hdr + hdr->publics;
|
|
||||||
|
|
||||||
for (i=0; i<publics; i++) {
|
|
||||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
|
||||||
pbtbl[i].address = stub->address;
|
|
||||||
pbtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
|
||||||
|
|
||||||
stubptr += hdr->defsize;
|
|
||||||
}
|
|
||||||
if (publics)
|
|
||||||
sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf);
|
|
||||||
free(pbtbl);
|
|
||||||
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_Pubvars]) {
|
|
||||||
sp_file_pubvars_t *pbvars;
|
|
||||||
AMX_FUNCSTUBNT *stub;
|
|
||||||
unsigned char *stubptr;
|
|
||||||
uint32_t pubvars = sections[FS_Pubvars];
|
|
||||||
|
|
||||||
pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars);
|
|
||||||
stubptr = (unsigned char *)hdr + hdr->pubvars;
|
|
||||||
|
|
||||||
for (i=0; i<pubvars; i++) {
|
|
||||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
|
||||||
pbvars[i].address = stub->address;
|
|
||||||
pbvars[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
|
||||||
|
|
||||||
stubptr += hdr->defsize;
|
|
||||||
}
|
|
||||||
if (pubvars)
|
|
||||||
sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf);
|
|
||||||
free(pbvars);
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_Natives]) {
|
|
||||||
sp_file_natives_t *nvtbl;
|
|
||||||
AMX_FUNCSTUBNT *stub;
|
|
||||||
unsigned char *stubptr;
|
|
||||||
uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
|
|
||||||
|
|
||||||
nvtbl = (sp_file_natives_t *)malloc(sizeof(sp_file_natives_t) * natives);
|
|
||||||
stubptr = (unsigned char *)hdr + hdr->natives;
|
|
||||||
|
|
||||||
for (i=0; i<natives; i++) {
|
|
||||||
stub = (AMX_FUNCSTUBNT *)stubptr;
|
|
||||||
nvtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
|
||||||
|
|
||||||
stubptr += hdr->defsize;
|
|
||||||
}
|
|
||||||
if (natives) {
|
|
||||||
sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf);
|
|
||||||
}
|
|
||||||
free(nvtbl);
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_Tags]) {
|
|
||||||
uint32_t numTags = (uint32_t)sections[FS_Tags];
|
|
||||||
AMX_FUNCSTUBNT *stub;
|
|
||||||
sp_file_tag_t tag;
|
|
||||||
|
|
||||||
for (i=0; i<numTags; i++) {
|
|
||||||
stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->tags + (i * hdr->defsize));
|
|
||||||
tag.tag_id = stub->address;
|
|
||||||
tag.name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
|
|
||||||
sfwrite(&tag, sizeof(sp_file_tag_t), 1, spf);
|
|
||||||
}
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_Nametable]) {
|
|
||||||
unsigned char *base;
|
|
||||||
uint32_t namelen;
|
|
||||||
|
|
||||||
/* write the entire block */
|
|
||||||
base = (unsigned char *)hdr + hdr->nametable + sizeof(uint16_t);
|
|
||||||
/**
|
|
||||||
* note - the name table will be padded to sizeof(cell) bytes.
|
|
||||||
* this may clip at most an extra three bytes in!
|
|
||||||
*/
|
|
||||||
namelen = hdr->cod - hdr->nametable;
|
|
||||||
sfwrite(base, namelen, 1, spf);
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hdr->flags & AMX_FLAG_DEBUG) {
|
|
||||||
sp_fdbg_info_t info;
|
|
||||||
|
|
||||||
memset(&info, 0, sizeof(sp_fdbg_info_t));
|
|
||||||
|
|
||||||
if (sections[FS_Natives]) {
|
|
||||||
uint16_t j;
|
|
||||||
uint32_t idx;
|
|
||||||
uint32_t name;
|
|
||||||
uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
|
|
||||||
|
|
||||||
sfwrite(&natives, sizeof(uint32_t), 1, spf);
|
|
||||||
for (idx=0; idx<natives; idx++) {
|
|
||||||
sfwrite(&idx, sizeof(uint32_t), 1, spf);
|
|
||||||
name = (uint32_t)memfile_tell(dbgtab);
|
|
||||||
memfile_write(dbgtab, native_list[idx].name, strlen(native_list[idx].name) + 1);
|
|
||||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
|
||||||
sfwrite(&native_list[idx].ret_tag, sizeof(int16_t), 1, spf);
|
|
||||||
sfwrite(&native_list[idx].num_args, sizeof(uint16_t), 1, spf);
|
|
||||||
|
|
||||||
/* Go through arguments */
|
|
||||||
for (j = 0; j < native_list[idx].num_args; j++) {
|
|
||||||
sfwrite(&native_list[idx].args[j].ident, sizeof(uint8_t), 1, spf);
|
|
||||||
sfwrite(&native_list[idx].args[j].tag, sizeof(int16_t), 1, spf);
|
|
||||||
sfwrite(&native_list[idx].args[j].dimcount, sizeof(uint16_t), 1, spf);
|
|
||||||
name = (uint32_t)memfile_tell(dbgtab);
|
|
||||||
sfwrite(&name, sizeof(uint32_t), 1, spf);
|
|
||||||
memfile_write(dbgtab,
|
|
||||||
native_list[idx].args[j].name,
|
|
||||||
strlen(native_list[idx].args[j].name) + 1);
|
|
||||||
if (native_list[idx].args[j].dimcount) {
|
|
||||||
sfwrite(native_list[idx].args[j].dims,
|
|
||||||
sizeof(sp_fdbg_arraydim_t),
|
|
||||||
native_list[idx].args[j].dimcount,
|
|
||||||
spf);
|
|
||||||
}
|
|
||||||
free(native_list[idx].args[j].name);
|
|
||||||
}
|
|
||||||
free(native_list[idx].name);
|
|
||||||
}
|
|
||||||
free(native_list);
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_DbgFile]) {
|
|
||||||
uint32_t idx;
|
|
||||||
sp_fdbg_file_t dbgfile;
|
|
||||||
AMX_DBG_FILE *_ptr;
|
|
||||||
uint32_t len;
|
|
||||||
for (idx=0; idx<sections[FS_DbgFile]; idx++) {
|
|
||||||
/* get entry info */
|
|
||||||
_ptr = (AMX_DBG_FILE *)dbgptr;
|
|
||||||
len = strlen(_ptr->name);
|
|
||||||
/* store */
|
|
||||||
dbgfile.addr = _ptr->address;
|
|
||||||
dbgfile.name = (uint32_t)memfile_tell(dbgtab);
|
|
||||||
sfwrite(&dbgfile, sizeof(sp_fdbg_file_t), 1, spf);
|
|
||||||
/* write to tab, then move to next */
|
|
||||||
memfile_write(dbgtab, _ptr->name, len + 1);
|
|
||||||
dbgptr += sizeof(AMX_DBG_FILE) + len;
|
|
||||||
info.num_files++;
|
|
||||||
}
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_DbgLine]) {
|
|
||||||
uint32_t idx;
|
|
||||||
AMX_DBG_LINE *line;
|
|
||||||
sp_fdbg_line_t dbgline;
|
|
||||||
for (idx=0; idx<sections[FS_DbgLine]; idx++) {
|
|
||||||
/* get entry info */
|
|
||||||
line = (AMX_DBG_LINE *)dbgptr;
|
|
||||||
/* store */
|
|
||||||
dbgline.addr = (uint32_t)line->address;
|
|
||||||
dbgline.line = (uint32_t)line->line;
|
|
||||||
sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf);
|
|
||||||
/* move to next */
|
|
||||||
dbgptr += sizeof(AMX_DBG_LINE);
|
|
||||||
info.num_lines++;
|
|
||||||
}
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sections[FS_DbgSymbol]) {
|
|
||||||
uint32_t idx;
|
|
||||||
uint32_t dnum;
|
|
||||||
AMX_DBG_SYMBOL *sym;
|
|
||||||
AMX_DBG_SYMDIM *dim;
|
|
||||||
sp_fdbg_symbol_t dbgsym;
|
|
||||||
sp_fdbg_arraydim_t dbgdim;
|
|
||||||
uint32_t len;
|
|
||||||
|
|
||||||
for (idx=0; idx<sections[FS_DbgSymbol]; idx++) {
|
|
||||||
/* get entry info */
|
|
||||||
sym = (AMX_DBG_SYMBOL *)dbgptr;
|
|
||||||
/* store */
|
|
||||||
dbgsym.addr = (int32_t)sym->address;
|
|
||||||
dbgsym.tagid = sym->tag;
|
|
||||||
dbgsym.codestart = (uint32_t)sym->codestart;
|
|
||||||
dbgsym.codeend = (uint32_t)sym->codeend;
|
|
||||||
dbgsym.dimcount = (uint16_t)sym->dim;
|
|
||||||
dbgsym.vclass = (uint8_t)sym->vclass;
|
|
||||||
dbgsym.ident = (uint8_t)sym->ident;
|
|
||||||
dbgsym.name = (uint32_t)memfile_tell(dbgtab);
|
|
||||||
sfwrite(&dbgsym, sizeof(sp_fdbg_symbol_t), 1, spf);
|
|
||||||
/* write to tab */
|
|
||||||
len = strlen(sym->name);
|
|
||||||
memfile_write(dbgtab, sym->name, len + 1);
|
|
||||||
/* move to next */
|
|
||||||
dbgptr += sizeof(AMX_DBG_SYMBOL) + len;
|
|
||||||
/* look for any dimensions */
|
|
||||||
info.num_syms++;
|
|
||||||
for (dnum=0; dnum<dbgsym.dimcount; dnum++)
|
|
||||||
{
|
|
||||||
/* get entry info */
|
|
||||||
dim = (AMX_DBG_SYMDIM *)dbgptr;
|
|
||||||
/* store */
|
|
||||||
dbgdim.size = (uint32_t)dim->size;
|
|
||||||
dbgdim.tagid = dim->tag;
|
|
||||||
sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf);
|
|
||||||
/* move to next */
|
|
||||||
dbgptr += sizeof(AMX_DBG_SYMDIM);
|
|
||||||
info.num_arrays++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
sfwrite(&info, sizeof(sp_fdbg_info_t), 1, spf);
|
|
||||||
spfw_next_section(spf);
|
|
||||||
|
|
||||||
if (sections[FS_DbgStrings]) {
|
|
||||||
sfwrite(dbgtab->base, sizeof(char), dbgtab->usedoffs, spf);
|
|
||||||
spfw_next_section(spf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spfw_finalize_all(spf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* do compression
|
|
||||||
* new block for scoping only
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
memfile_t *pOrig = (memfile_t *)spf->handle;
|
|
||||||
sp_file_hdr_t *pHdr;
|
|
||||||
unsigned char *proper;
|
|
||||||
size_t size;
|
|
||||||
Bytef *zcmp;
|
|
||||||
uLong disksize;
|
|
||||||
size_t header_size;
|
|
||||||
int err = Z_OK;
|
|
||||||
|
|
||||||
/* reuse this memory block! */
|
|
||||||
memfile_reset(bin_file);
|
|
||||||
|
|
||||||
/* copy tip of header */
|
|
||||||
memfile_write(bin_file, pOrig->base, sizeof(sp_file_hdr_t));
|
|
||||||
|
|
||||||
/* get pointer to header */
|
|
||||||
pHdr = (sp_file_hdr_t *)bin_file->base;
|
|
||||||
|
|
||||||
/* copy the rest of the header */
|
|
||||||
memfile_write(bin_file,
|
|
||||||
(unsigned char *)pOrig->base + sizeof(sp_file_hdr_t),
|
|
||||||
pHdr->dataoffs - sizeof(sp_file_hdr_t));
|
|
||||||
|
|
||||||
header_size = pHdr->dataoffs;
|
|
||||||
size = pHdr->imagesize - header_size;
|
|
||||||
proper = (unsigned char *)pOrig->base + header_size;
|
|
||||||
|
|
||||||
/* get initial size estimate */
|
|
||||||
disksize = compressBound(pHdr->imagesize);
|
|
||||||
pHdr->disksize = (uint32_t)disksize;
|
|
||||||
zcmp = (Bytef *)malloc(pHdr->disksize);
|
|
||||||
|
|
||||||
if ((err=compress2(zcmp,
|
|
||||||
&disksize,
|
|
||||||
(Bytef *)proper,
|
|
||||||
(uLong)size,
|
|
||||||
Z_BEST_COMPRESSION))
|
|
||||||
!= Z_OK)
|
|
||||||
{
|
|
||||||
free(zcmp);
|
|
||||||
pc_printf("Unable to compress (Z): error %d\n", err);
|
|
||||||
pc_printf("Falling back to no compression.");
|
|
||||||
memfile_write(bin_file,
|
|
||||||
proper,
|
|
||||||
size);
|
|
||||||
} else {
|
|
||||||
pHdr->disksize = (uint32_t)disksize + header_size;
|
|
||||||
pHdr->compression = SPFILE_COMPRESSION_GZ;
|
|
||||||
memfile_write(bin_file,
|
|
||||||
(unsigned char *)zcmp,
|
|
||||||
disksize);
|
|
||||||
free(zcmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spfw_destroy(spf);
|
|
||||||
memfile_destroy(dbgtab);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* write file
|
|
||||||
*/
|
|
||||||
if ((fp=fopen(bin_file->name, "wb")) != NULL) {
|
|
||||||
fwrite(bin_file->base, bin_file->usedoffs, 1, fp);
|
|
||||||
fclose(fp);
|
|
||||||
} else {
|
|
||||||
pc_printf("Unable to open %s for writing!", bin_file->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
memfile_destroy(bin_file);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
write_error:
|
|
||||||
pc_printf("Error writing to file: %s", bin_file->name);
|
|
||||||
|
|
||||||
spfw_destroy(spf);
|
|
||||||
unlink(bin_file->name);
|
|
||||||
memfile_destroy(bin_file);
|
|
||||||
memfile_destroy(dbgtab);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf)
|
|
||||||
{
|
|
||||||
if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count)
|
|
||||||
longjmp(brkout, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sp_fdbg_ntv_start(int num_natives)
|
|
||||||
{
|
|
||||||
if (num_natives == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
native_list = (t_native *)malloc(sizeof(t_native) * num_natives);
|
|
||||||
memset(native_list, 0, sizeof(t_native) * num_natives);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "sc.h"
|
|
||||||
void sp_fdbg_ntv_hook(int index, symbol *sym)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
t_native *native;
|
|
||||||
|
|
||||||
native = &native_list[index];
|
|
||||||
native->name = strdup(sym->name);
|
|
||||||
|
|
||||||
for (i = 0; i < sMAXARGS; i++) {
|
|
||||||
if (sym->dim.arglist[i].ident == 0)
|
|
||||||
break;
|
|
||||||
native->num_args++;
|
|
||||||
native->args[i].tag = sym->dim.arglist[i].tags == NULL ? 0 : sym->dim.arglist[i].tags[0];
|
|
||||||
native->args[i].name = strdup(sym->dim.arglist[i].name);
|
|
||||||
native->args[i].ident = sym->dim.arglist[i].ident;
|
|
||||||
native->args[i].dimcount = sym->dim.arglist[i].numdim;
|
|
||||||
for (j = 0; j < native->args[i].dimcount; j++) {
|
|
||||||
native->args[i].dims[j].size = sym->dim.arglist[i].dim[j];
|
|
||||||
native->args[i].dims[j].tagid = sym->dim.arglist[i].idxtag[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
native->ret_tag = sym->tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined __linux__ || defined __APPLE__
|
#if defined __linux__ || defined __APPLE__
|
||||||
extern "C" void __cxa_pure_virtual(void)
|
extern "C" void __cxa_pure_virtual(void)
|
||||||
{
|
{
|
||||||
|
@ -579,13 +579,6 @@ void pc_resetasm(void *handle);
|
|||||||
int pc_writeasm(void *handle,const char *str);
|
int pc_writeasm(void *handle,const char *str);
|
||||||
char *pc_readasm(void *handle,char *target,int maxchars);
|
char *pc_readasm(void *handle,char *target,int maxchars);
|
||||||
|
|
||||||
/* output to binary (.AMX) file */
|
|
||||||
void *pc_openbin(char *filename);
|
|
||||||
void pc_closebin(void *handle,int deletefile);
|
|
||||||
void pc_resetbin(void *handle,long offset);
|
|
||||||
int pc_writebin(void *handle,void *buffer,int size);
|
|
||||||
long pc_lengthbin(void *handle); /* return the length of the file */
|
|
||||||
|
|
||||||
void sp_fdbg_ntv_start(int num_natives);
|
void sp_fdbg_ntv_start(int num_natives);
|
||||||
void sp_fdbg_ntv_hook(int index, symbol *sym);
|
void sp_fdbg_ntv_hook(int index, symbol *sym);
|
||||||
|
|
||||||
@ -768,7 +761,7 @@ int error(int number,...);
|
|||||||
void errorset(int code,int line);
|
void errorset(int code,int line);
|
||||||
|
|
||||||
/* function prototypes in SC6.C */
|
/* function prototypes in SC6.C */
|
||||||
int assemble(void *fout,void *fin);
|
void assemble(const char *outname, void *fin);
|
||||||
|
|
||||||
/* function prototypes in SC7.C */
|
/* function prototypes in SC7.C */
|
||||||
void stgbuffer_cleanup(void);
|
void stgbuffer_cleanup(void);
|
||||||
|
@ -201,16 +201,11 @@ int pc_compile(int argc, char *argv[])
|
|||||||
char incfname[_MAX_PATH];
|
char incfname[_MAX_PATH];
|
||||||
char reportname[_MAX_PATH];
|
char reportname[_MAX_PATH];
|
||||||
char codepage[MAXCODEPAGE+1];
|
char codepage[MAXCODEPAGE+1];
|
||||||
FILE *binf;
|
|
||||||
void *inpfmark;
|
void *inpfmark;
|
||||||
int lcl_packstr,lcl_needsemicolon,lcl_tabsize,lcl_require_newdecls;
|
int lcl_packstr,lcl_needsemicolon,lcl_tabsize,lcl_require_newdecls;
|
||||||
#if !defined SC_LIGHT
|
|
||||||
int hdrsize=0;
|
|
||||||
#endif
|
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
/* set global variables to their initial value */
|
/* set global variables to their initial value */
|
||||||
binf=NULL;
|
|
||||||
initglobals();
|
initglobals();
|
||||||
errorset(sRESET,0);
|
errorset(sRESET,0);
|
||||||
errorset(sEXPRRELEASE,0);
|
errorset(sEXPRRELEASE,0);
|
||||||
@ -316,14 +311,6 @@ int pc_compile(int argc, char *argv[])
|
|||||||
outf=(FILE*)pc_openasm(outfname); /* first write to assembler file (may be temporary) */
|
outf=(FILE*)pc_openasm(outfname); /* first write to assembler file (may be temporary) */
|
||||||
if (outf==NULL)
|
if (outf==NULL)
|
||||||
error(161,outfname);
|
error(161,outfname);
|
||||||
/* immediately open the binary file, for other programs to check */
|
|
||||||
if (sc_asmfile || sc_listing) {
|
|
||||||
binf=NULL;
|
|
||||||
} else {
|
|
||||||
binf=(FILE*)pc_openbin(binfname);
|
|
||||||
if (binf==NULL)
|
|
||||||
error(161,binfname);
|
|
||||||
} /* if */
|
|
||||||
setconstants(); /* set predefined constants and tagnames */
|
setconstants(); /* set predefined constants and tagnames */
|
||||||
for (i=0; i<skipinput; i++) /* skip lines in the input file */
|
for (i=0; i<skipinput; i++) /* skip lines in the input file */
|
||||||
if (pc_readsrc(inpf_org,pline,sLINEMAX)!=NULL)
|
if (pc_readsrc(inpf_org,pline,sLINEMAX)!=NULL)
|
||||||
@ -464,33 +451,27 @@ int pc_compile(int argc, char *argv[])
|
|||||||
cleanup:
|
cleanup:
|
||||||
if (inpf!=NULL) /* main source file is not closed, do it now */
|
if (inpf!=NULL) /* main source file is not closed, do it now */
|
||||||
pc_closesrc(inpf);
|
pc_closesrc(inpf);
|
||||||
/* write the binary file (the file is already open) */
|
|
||||||
|
// Write the binary file.
|
||||||
if (!(sc_asmfile || sc_listing) && errnum==0 && jmpcode==0) {
|
if (!(sc_asmfile || sc_listing) && errnum==0 && jmpcode==0) {
|
||||||
assert(binf!=NULL);
|
pc_resetasm(outf);
|
||||||
pc_resetasm(outf); /* flush and loop back, for reading */
|
assemble(binfname, outf);
|
||||||
#if !defined SC_LIGHT
|
}
|
||||||
hdrsize=
|
|
||||||
#endif
|
|
||||||
assemble(binf,outf); /* assembler file is now input */
|
|
||||||
} /* if */
|
|
||||||
if (outf!=NULL) {
|
if (outf!=NULL) {
|
||||||
pc_closeasm(outf,!(sc_asmfile || sc_listing));
|
pc_closeasm(outf,!(sc_asmfile || sc_listing));
|
||||||
outf=NULL;
|
outf=NULL;
|
||||||
} /* if */
|
} /* if */
|
||||||
if (binf!=NULL) {
|
|
||||||
pc_closebin(binf,errnum!=0);
|
|
||||||
binf=NULL;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
#if !defined SC_LIGHT
|
#if !defined SC_LIGHT
|
||||||
if (errnum==0 && strlen(errfname)==0) {
|
if (errnum==0 && strlen(errfname)==0) {
|
||||||
#if 0 //bug in compiler -- someone's script caused this function to infrecurs
|
# if 0 //bug in compiler -- someone's script caused this function to infrecurs
|
||||||
int recursion;
|
int recursion;
|
||||||
long stacksize=max_stacksize(&glbtab,&recursion);
|
long stacksize=max_stacksize(&glbtab,&recursion);
|
||||||
#endif
|
# endif
|
||||||
int flag_exceed=0;
|
int flag_exceed=0;
|
||||||
if (pc_amxlimit>0) {
|
if (pc_amxlimit>0) {
|
||||||
long totalsize=hdrsize+code_idx;
|
long totalsize=code_idx;
|
||||||
if (pc_amxram==0)
|
if (pc_amxram==0)
|
||||||
totalsize+=(glb_declared+pc_stksize)*sizeof(cell);
|
totalsize+=(glb_declared+pc_stksize)*sizeof(cell);
|
||||||
if (totalsize>=pc_amxlimit)
|
if (totalsize>=pc_amxlimit)
|
||||||
@ -499,20 +480,10 @@ cleanup:
|
|||||||
if (pc_amxram>0 && (glb_declared+pc_stksize)*sizeof(cell)>=(unsigned long)pc_amxram)
|
if (pc_amxram>0 && (glb_declared+pc_stksize)*sizeof(cell)>=(unsigned long)pc_amxram)
|
||||||
flag_exceed=1;
|
flag_exceed=1;
|
||||||
if ((!norun && (sc_debug & sSYMBOLIC)!=0) || verbosity>=2 || flag_exceed) {
|
if ((!norun && (sc_debug & sSYMBOLIC)!=0) || verbosity>=2 || flag_exceed) {
|
||||||
pc_printf("Header size: %8ld bytes\n", (long)hdrsize);
|
|
||||||
pc_printf("Code size: %8ld bytes\n", (long)code_idx);
|
pc_printf("Code size: %8ld bytes\n", (long)code_idx);
|
||||||
pc_printf("Data size: %8ld bytes\n", (long)glb_declared*sizeof(cell));
|
pc_printf("Data size: %8ld bytes\n", (long)glb_declared*sizeof(cell));
|
||||||
pc_printf("Stack/heap size: %8ld bytes\n", (long)pc_stksize*sizeof(cell));
|
pc_printf("Stack/heap size: %8ld bytes\n", (long)pc_stksize*sizeof(cell));
|
||||||
#if 0
|
pc_printf("Total requirements:%8ld bytes\n", (long)code_idx+(long)glb_declared*sizeof(cell)+(long)pc_stksize*sizeof(cell));
|
||||||
pc_printf("estimated max. usage");
|
|
||||||
if (recursion)
|
|
||||||
pc_printf(": unknown, due to recursion\n");
|
|
||||||
else if ((pc_memflags & suSLEEP_INSTR)!=0)
|
|
||||||
pc_printf(": unknown, due to the \"sleep\" instruction\n");
|
|
||||||
else
|
|
||||||
pc_printf("=%ld cells (%ld bytes)\n",stacksize,stacksize*sizeof(cell));
|
|
||||||
#endif
|
|
||||||
pc_printf("Total requirements:%8ld bytes\n", (long)hdrsize+(long)code_idx+(long)glb_declared*sizeof(cell)+(long)pc_stksize*sizeof(cell));
|
|
||||||
} /* if */
|
} /* if */
|
||||||
if (flag_exceed)
|
if (flag_exceed)
|
||||||
error(166,pc_amxlimit+pc_amxram); /* this causes a jump back to label "cleanup" */
|
error(166,pc_amxlimit+pc_amxram); /* this causes a jump back to label "cleanup" */
|
||||||
@ -2077,8 +2048,6 @@ static void declglb(declinfo_t *decl,int fpublic,int fstatic,int fstock)
|
|||||||
static void declloc(int tokid)
|
static void declloc(int tokid)
|
||||||
{
|
{
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
cell val;
|
|
||||||
char *str;
|
|
||||||
value lval = {0};
|
value lval = {0};
|
||||||
int cur_lit=0;
|
int cur_lit=0;
|
||||||
int staging_start;
|
int staging_start;
|
||||||
@ -2828,7 +2797,7 @@ static void decl_const(int vclass)
|
|||||||
char constname[sNAMEMAX+1];
|
char constname[sNAMEMAX+1];
|
||||||
cell val;
|
cell val;
|
||||||
token_t tok;
|
token_t tok;
|
||||||
int tag,exprtag;
|
int exprtag;
|
||||||
int symbolline;
|
int symbolline;
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
|
|
||||||
@ -2906,7 +2875,6 @@ static void declstruct(void)
|
|||||||
char *str;
|
char *str;
|
||||||
int tok;
|
int tok;
|
||||||
pstruct_t *pstruct;
|
pstruct_t *pstruct;
|
||||||
int size;
|
|
||||||
|
|
||||||
/* get the explicit tag (required!) */
|
/* get the explicit tag (required!) */
|
||||||
tok = lex(&val,&str);
|
tok = lex(&val,&str);
|
||||||
@ -3790,7 +3758,6 @@ methodmap_method_t *parse_method(methodmap_t *map)
|
|||||||
typeinfo_t type;
|
typeinfo_t type;
|
||||||
memset(&type, 0, sizeof(type));
|
memset(&type, 0, sizeof(type));
|
||||||
|
|
||||||
token_t tok;
|
|
||||||
if (matchtoken('~')) {
|
if (matchtoken('~')) {
|
||||||
// We got something like "public ~Blah = X"
|
// We got something like "public ~Blah = X"
|
||||||
is_bind = TRUE;
|
is_bind = TRUE;
|
||||||
@ -5076,9 +5043,8 @@ static cell fix_char_size(declinfo_t *decl)
|
|||||||
|
|
||||||
static symbol *funcstub(int tokid, declinfo_t *decl, const int *thistag)
|
static symbol *funcstub(int tokid, declinfo_t *decl, const int *thistag)
|
||||||
{
|
{
|
||||||
int tok;
|
|
||||||
char *str;
|
char *str;
|
||||||
cell val,size;
|
cell val;
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
int fnative = (tokid == tNATIVE || tokid == tMETHODMAP);
|
int fnative = (tokid == tNATIVE || tokid == tMETHODMAP);
|
||||||
int fpublic = (tokid == tPUBLIC);
|
int fpublic = (tokid == tPUBLIC);
|
||||||
@ -5182,10 +5148,9 @@ static symbol *funcstub(int tokid, declinfo_t *decl, const int *thistag)
|
|||||||
static int newfunc(declinfo_t *decl, const int *thistag, int fpublic, int fstatic, int stock, symbol **symp)
|
static int newfunc(declinfo_t *decl, const int *thistag, int fpublic, int fstatic, int stock, symbol **symp)
|
||||||
{
|
{
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
int argcnt,tok,funcline;
|
int argcnt,funcline;
|
||||||
int opererror;
|
int opererror;
|
||||||
char *str;
|
cell cidx,glbdecl;
|
||||||
cell val,cidx,glbdecl;
|
|
||||||
short filenum;
|
short filenum;
|
||||||
|
|
||||||
assert(litidx==0); /* literal queue should be empty */
|
assert(litidx==0); /* literal queue should be empty */
|
||||||
@ -5456,7 +5421,7 @@ static int argcompare(arginfo *a1,arginfo *a2)
|
|||||||
static int declargs(symbol *sym, int chkshadow, const int *thistag)
|
static int declargs(symbol *sym, int chkshadow, const int *thistag)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int argcnt,oldargcnt,tok;
|
int argcnt,oldargcnt;
|
||||||
arginfo arg, *arglist;
|
arginfo arg, *arglist;
|
||||||
char name[sNAMEMAX+1];
|
char name[sNAMEMAX+1];
|
||||||
int fpublic;
|
int fpublic;
|
||||||
|
File diff suppressed because it is too large
Load Diff
111
sourcepawn/compiler/smx-builder.cpp
Normal file
111
sourcepawn/compiler/smx-builder.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
214
sourcepawn/compiler/smx-builder.h
Normal file
214
sourcepawn/compiler/smx-builder.h
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
// 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();
|
||||||
|
}
|
||||||
|
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> §ion) {
|
||||||
|
sections_.append(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<Ref<SmxSection>> sections_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ke
|
||||||
|
|
||||||
|
#endif // _include_spcomp2_smx_builder_h_
|
@ -1,213 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "sp_file.h"
|
|
||||||
#include "memfile.h"
|
|
||||||
|
|
||||||
void *mf_open(const char *name);
|
|
||||||
void mf_close(void *handle);
|
|
||||||
size_t mf_write(const void *buf, size_t size, size_t count, void *handle);
|
|
||||||
size_t mf_read(void *buf, size_t size, size_t count, void *handle);
|
|
||||||
size_t mf_getpos(void *handle);
|
|
||||||
int mf_setpos(void *handle, size_t pos);
|
|
||||||
|
|
||||||
sp_writefuncs_t cstd_funcs =
|
|
||||||
{
|
|
||||||
mf_open,
|
|
||||||
mf_close,
|
|
||||||
mf_write,
|
|
||||||
mf_read,
|
|
||||||
mf_getpos,
|
|
||||||
mf_setpos
|
|
||||||
};
|
|
||||||
|
|
||||||
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs)
|
|
||||||
{
|
|
||||||
sp_file_t file;
|
|
||||||
sp_file_t *pFile;
|
|
||||||
|
|
||||||
if (!optfuncs)
|
|
||||||
optfuncs = &cstd_funcs;
|
|
||||||
|
|
||||||
file.handle = optfuncs->fnOpen(name);
|
|
||||||
if (!file.handle)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
pFile = (sp_file_t *)malloc(sizeof(sp_file_t));
|
|
||||||
|
|
||||||
pFile->handle = file.handle;
|
|
||||||
memcpy(&pFile->funcs, optfuncs, sizeof(sp_writefuncs_t));
|
|
||||||
pFile->curoffs = 0;
|
|
||||||
pFile->header.magic = SPFILE_MAGIC;
|
|
||||||
pFile->header.sections = 0;
|
|
||||||
pFile->header.stringtab = 0;
|
|
||||||
pFile->header.version = SPFILE_VERSION;
|
|
||||||
pFile->header.imagesize = 0;
|
|
||||||
pFile->header.disksize = 0;
|
|
||||||
pFile->header.compression = SPFILE_COMPRESSION_NONE;
|
|
||||||
pFile->header.dataoffs = 0;
|
|
||||||
pFile->lastsection = 0;
|
|
||||||
pFile->offsets = NULL;
|
|
||||||
pFile->sections = NULL;
|
|
||||||
pFile->state = -1;
|
|
||||||
pFile->nametab = NULL;
|
|
||||||
pFile->nametab_idx = 0;
|
|
||||||
|
|
||||||
return pFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spfw_destroy(sp_file_t *spf)
|
|
||||||
{
|
|
||||||
free(spf->sections);
|
|
||||||
free(spf->nametab);
|
|
||||||
free(spf->offsets);
|
|
||||||
spf->funcs.fnClose(spf->handle);
|
|
||||||
free(spf);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t spfw_add_section(sp_file_t *spf, const char *name)
|
|
||||||
{
|
|
||||||
size_t namelen;
|
|
||||||
uint8_t s;
|
|
||||||
if (spf->state != -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
namelen = strlen(name) + 1;
|
|
||||||
|
|
||||||
if (spf->header.sections == 0)
|
|
||||||
{
|
|
||||||
/** allocate for first section */
|
|
||||||
spf->sections = (sp_file_section_t *)malloc(sizeof(sp_file_section_t));
|
|
||||||
spf->offsets = (size_t *)malloc(sizeof(size_t));
|
|
||||||
spf->nametab = (char *)malloc(namelen);
|
|
||||||
} else {
|
|
||||||
uint16_t num = spf->header.sections + 1;
|
|
||||||
spf->sections = (sp_file_section_t *)realloc(spf->sections, sizeof(sp_file_section_t) * num);
|
|
||||||
spf->offsets = (size_t *)realloc(spf->offsets, sizeof(size_t) * num);
|
|
||||||
spf->nametab = (char *)realloc(spf->nametab, spf->nametab_idx + namelen);
|
|
||||||
}
|
|
||||||
|
|
||||||
s = spf->header.sections;
|
|
||||||
|
|
||||||
spf->sections[s].nameoffs = spf->nametab_idx;
|
|
||||||
/**
|
|
||||||
* "fix" offset will be the second uint2 slot, which is after the previous sections after the header.
|
|
||||||
*/
|
|
||||||
spf->offsets[s] = sizeof(spf->header) + (sizeof(sp_file_section_t) * spf->header.sections) + sizeof(uint32_t);
|
|
||||||
strcpy(&spf->nametab[spf->nametab_idx], name);
|
|
||||||
spf->nametab_idx += namelen;
|
|
||||||
|
|
||||||
return ++spf->header.sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spfw_finalize_header(sp_file_t *spf)
|
|
||||||
{
|
|
||||||
uint32_t size;
|
|
||||||
if (spf->state != -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
size = sizeof(sp_file_section_t) * spf->header.sections;
|
|
||||||
|
|
||||||
spf->header.stringtab = sizeof(spf->header) + size;
|
|
||||||
spf->header.dataoffs = spf->header.stringtab + spf->nametab_idx;
|
|
||||||
if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1)
|
|
||||||
return -1;
|
|
||||||
if (spf->funcs.fnWrite(spf->sections, sizeof(sp_file_section_t), spf->header.sections, spf->handle) !=
|
|
||||||
spf->header.sections)
|
|
||||||
return -1;
|
|
||||||
if (spf->funcs.fnWrite(spf->nametab, sizeof(char), spf->nametab_idx, spf->handle) != spf->nametab_idx)
|
|
||||||
return -1;
|
|
||||||
spf->curoffs = spf->funcs.fnGetPos(spf->handle);
|
|
||||||
spf->lastsection = spf->curoffs;
|
|
||||||
spf->state++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spfw_next_section(sp_file_t *spf)
|
|
||||||
{
|
|
||||||
uint8_t s;
|
|
||||||
uint32_t rest[2];
|
|
||||||
|
|
||||||
if (spf->state < 0 || spf->state > spf->header.sections)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (spf->state == (int)spf->header.sections)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
s = (uint8_t)spf->state;
|
|
||||||
|
|
||||||
spf->curoffs = spf->funcs.fnGetPos(spf->handle);
|
|
||||||
spf->funcs.fnSetPos(spf->handle, spf->offsets[s]);
|
|
||||||
|
|
||||||
rest[0] = spf->lastsection;
|
|
||||||
rest[1] = spf->curoffs - spf->lastsection;
|
|
||||||
if (spf->funcs.fnWrite(rest, sizeof(uint32_t), 2, spf->handle) != 2)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
spf->funcs.fnSetPos(spf->handle, spf->curoffs);
|
|
||||||
spf->lastsection = spf->curoffs;
|
|
||||||
|
|
||||||
spf->state++;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spfw_finalize_all(sp_file_t *spf)
|
|
||||||
{
|
|
||||||
uint8_t offs;
|
|
||||||
|
|
||||||
if (spf->state < spf->header.sections)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
offs = offsetof(sp_file_hdr_t, imagesize);
|
|
||||||
spf->header.disksize = spf->funcs.fnGetPos(spf->handle);
|
|
||||||
spf->header.imagesize = spf->funcs.fnGetPos(spf->handle);
|
|
||||||
spf->funcs.fnSetPos(spf->handle, offs);
|
|
||||||
spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle);
|
|
||||||
spf->funcs.fnSetPos(spf->handle, spf->header.imagesize);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* More memory file operations
|
|
||||||
*/
|
|
||||||
|
|
||||||
void *mf_open(const char *name)
|
|
||||||
{
|
|
||||||
return memfile_creat(name, 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mf_close(void *handle)
|
|
||||||
{
|
|
||||||
memfile_destroy((memfile_t *)handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t mf_write(const void *buf, size_t size, size_t count, void *handle)
|
|
||||||
{
|
|
||||||
if (!count)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (memfile_write((memfile_t *)handle, buf, size*count))
|
|
||||||
return count;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t mf_read(void *buf, size_t size, size_t count, void *handle)
|
|
||||||
{
|
|
||||||
return memfile_read((memfile_t *)handle, buf, size*count) / count;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t mf_getpos(void *handle)
|
|
||||||
{
|
|
||||||
return (long)memfile_tell((memfile_t *)handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mf_setpos(void *handle, size_t pos)
|
|
||||||
{
|
|
||||||
memfile_seek((memfile_t *)handle, (long)pos);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
|||||||
#ifndef _INCLUDE_SPFILE_H
|
|
||||||
#define _INCLUDE_SPFILE_H
|
|
||||||
|
|
||||||
#include "sp_file_headers.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for overwriting writing routines.
|
|
||||||
*/
|
|
||||||
typedef struct sp_writefuncs_s
|
|
||||||
{
|
|
||||||
void *(*fnOpen)(const char *); /* filename, returns handle */
|
|
||||||
void (*fnClose)(void *); /* handle */
|
|
||||||
/* buffer, size, count, handle, returns count written */
|
|
||||||
size_t (*fnWrite)(const void *, size_t, size_t, void *);
|
|
||||||
/* buffer, size, count, handle, returns count read */
|
|
||||||
size_t (*fnRead)(void *, size_t, size_t, void *);
|
|
||||||
/* returns current position from start */
|
|
||||||
size_t (*fnGetPos)(void *);
|
|
||||||
/* sets current position from start, return 0 for success, nonzero for error */
|
|
||||||
int (*fnSetPos)(void *, size_t);
|
|
||||||
} sp_writefuncs_t;
|
|
||||||
|
|
||||||
typedef struct sp_file_s
|
|
||||||
{
|
|
||||||
sp_file_hdr_t header;
|
|
||||||
sp_file_section_t *sections;
|
|
||||||
size_t *offsets;
|
|
||||||
sp_writefuncs_t funcs;
|
|
||||||
size_t lastsection;
|
|
||||||
size_t curoffs;
|
|
||||||
void *handle;
|
|
||||||
int state;
|
|
||||||
char *nametab;
|
|
||||||
size_t nametab_idx;
|
|
||||||
} sp_file_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new SourcePawn binary file.
|
|
||||||
* You may optionally specify alternative writing functions.
|
|
||||||
*/
|
|
||||||
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes file handle and frees memory.
|
|
||||||
*/
|
|
||||||
void spfw_destroy(sp_file_t *spf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a section name to the header.
|
|
||||||
* Only valid BEFORE finalization.
|
|
||||||
* Returns the number of sections, or 0 on failure.
|
|
||||||
*/
|
|
||||||
uint8_t spfw_add_section(sp_file_t *spf, const char *name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finalizes the section header.
|
|
||||||
* This means no more sections can be added after this call.
|
|
||||||
* Also, aligns the writer to the first section.
|
|
||||||
* Returns 0 on success, nonzero on error.
|
|
||||||
*/
|
|
||||||
int spfw_finalize_header(sp_file_t *spf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finalizes the current section and advances to the next.
|
|
||||||
* In order for this to be accurate, the file pointer must
|
|
||||||
* reside at the end before calling this, because the size
|
|
||||||
* is calculated by differencing with the last known offset.
|
|
||||||
* Returns 1 if there are more sections left, 0 otherwise.
|
|
||||||
* Returns -1 if the file state is wrong.
|
|
||||||
*/
|
|
||||||
int spfw_next_section(sp_file_t *spf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finalizes all sections.
|
|
||||||
* Cannot be called until all sections are used.
|
|
||||||
* Must be called with the file pointer at the end.
|
|
||||||
* Also does compression!
|
|
||||||
*/
|
|
||||||
int spfw_finalize_all(sp_file_t *spf);
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SPFILE_H
|
|
@ -1,291 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourcePawn
|
|
||||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
||||||
* =============================================================================
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
||||||
* Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program 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
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
||||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
||||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
||||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_SPFILE_HEADERS_H
|
|
||||||
#define _INCLUDE_SPFILE_HEADERS_H
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file sp_file_headers.h
|
|
||||||
* @brief Defines the structure present in a SourcePawn compiled binary.
|
|
||||||
*
|
|
||||||
* Note: These structures should be 1-byte packed to match the file format.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define SPFILE_MAGIC 0x53504646 /**< Source Pawn File Format (SPFF) */
|
|
||||||
#define SPFILE_VERSION 0x0102 /**< File format version */
|
|
||||||
|
|
||||||
//:TODO: better compiler/nix support
|
|
||||||
#if defined __GNUC__
|
|
||||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
|
||||||
#else
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SPFILE_COMPRESSION_NONE 0 /**< No compression in file */
|
|
||||||
#define SPFILE_COMPRESSION_GZ 1 /**< GZ compression */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File section header format.
|
|
||||||
*/
|
|
||||||
typedef struct sp_file_section_s
|
|
||||||
{
|
|
||||||
uint32_t nameoffs; /**< Relative offset into global string table */
|
|
||||||
uint32_t dataoffs; /**< Offset into the data section of the file */
|
|
||||||
uint32_t size; /**< Size of the section's entry in the data section */
|
|
||||||
} sp_file_section_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File header format. If compression is 0, then disksize may be 0
|
|
||||||
* to mean that only the imagesize is needed.
|
|
||||||
*/
|
|
||||||
typedef struct sp_file_hdr_s
|
|
||||||
{
|
|
||||||
uint32_t magic; /**< Magic number */
|
|
||||||
uint16_t version; /**< Version code */
|
|
||||||
uint8_t compression;/**< Compression algorithm */
|
|
||||||
uint32_t disksize; /**< Size on disk */
|
|
||||||
uint32_t imagesize; /**< Size in memory */
|
|
||||||
uint8_t sections; /**< Number of sections */
|
|
||||||
uint32_t stringtab; /**< Offset to string table */
|
|
||||||
uint32_t dataoffs; /**< Offset to file proper (any compression starts here) */
|
|
||||||
} sp_file_hdr_t;
|
|
||||||
|
|
||||||
#define SP_FLAG_DEBUG (1<<0) /**< Debug information is present in the file */
|
|
||||||
|
|
||||||
#define SP_CODEVERS_JIT1 9 /**< Code version for JIT1 */
|
|
||||||
#define SP_CODEVERS_JIT2 10 /**< Code version for JIT2 */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded format of the ".code" section.
|
|
||||||
*/
|
|
||||||
typedef struct sp_file_code_s
|
|
||||||
{
|
|
||||||
uint32_t codesize; /**< Codesize in bytes */
|
|
||||||
uint8_t cellsize; /**< Cellsize in bytes */
|
|
||||||
uint8_t codeversion; /**< Version of opcodes supported */
|
|
||||||
uint16_t flags; /**< Flags */
|
|
||||||
uint32_t main; /**< Address to "main," if any */
|
|
||||||
uint32_t code; /**< Relative offset to code */
|
|
||||||
} sp_file_code_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded format of the ".data" section.
|
|
||||||
*/
|
|
||||||
typedef struct sp_file_data_s
|
|
||||||
{
|
|
||||||
uint32_t datasize; /**< Size of data section in memory */
|
|
||||||
uint32_t memsize; /**< Total mem required (includes data) */
|
|
||||||
uint32_t data; /**< File offset to data (helper) */
|
|
||||||
} sp_file_data_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded format of the ".publics" section.
|
|
||||||
*/
|
|
||||||
typedef struct sp_file_publics_s
|
|
||||||
{
|
|
||||||
uint32_t address; /**< Address relative to code section */
|
|
||||||
uint32_t name; /**< Index into nametable */
|
|
||||||
} sp_file_publics_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded format of the ".natives" section.
|
|
||||||
*/
|
|
||||||
typedef struct sp_file_natives_s
|
|
||||||
{
|
|
||||||
uint32_t name; /**< Index into nametable */
|
|
||||||
} sp_file_natives_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded format of the ".pubvars" section.
|
|
||||||
*/
|
|
||||||
typedef struct sp_file_pubvars_s
|
|
||||||
{
|
|
||||||
uint32_t address; /**< Address relative to the DAT section */
|
|
||||||
uint32_t name; /**< Index into nametable */
|
|
||||||
} sp_file_pubvars_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded tag info.
|
|
||||||
*/
|
|
||||||
typedef struct sp_file_tag_s
|
|
||||||
{
|
|
||||||
uint32_t tag_id; /**< Tag ID from compiler */
|
|
||||||
uint32_t name; /**< Index into nametable */
|
|
||||||
} sp_file_tag_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded debug information table.
|
|
||||||
*/
|
|
||||||
typedef struct sp_fdbg_info_s
|
|
||||||
{
|
|
||||||
uint32_t num_files; /**< number of files */
|
|
||||||
uint32_t num_lines; /**< number of lines */
|
|
||||||
uint32_t num_syms; /**< number of symbols */
|
|
||||||
uint32_t num_arrays; /**< number of symbols which are arrays */
|
|
||||||
} sp_fdbg_info_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded debug file table.
|
|
||||||
*/
|
|
||||||
typedef struct sp_fdbg_file_s
|
|
||||||
{
|
|
||||||
uint32_t addr; /**< Address into code */
|
|
||||||
uint32_t name; /**< Offset into debug nametable */
|
|
||||||
} sp_fdbg_file_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded debug line table.
|
|
||||||
*/
|
|
||||||
typedef struct sp_fdbg_line_s
|
|
||||||
{
|
|
||||||
uint32_t addr; /**< Address into code */
|
|
||||||
uint32_t line; /**< Line number */
|
|
||||||
} sp_fdbg_line_t;
|
|
||||||
|
|
||||||
#define SP_SYM_VARIABLE 1 /**< Cell that has an address and that can be fetched directly (lvalue) */
|
|
||||||
#define SP_SYM_REFERENCE 2 /**< VARIABLE, but must be dereferenced */
|
|
||||||
#define SP_SYM_ARRAY 3 /**< Symbol is an array */
|
|
||||||
#define SP_SYM_REFARRAY 4 /**< An array passed by reference (i.e. a pointer) */
|
|
||||||
#define SP_SYM_FUNCTION 9 /**< Symbol is a function */
|
|
||||||
#define SP_SYM_VARARGS 11 /**< Variadic argument start. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded debug symbol information.
|
|
||||||
*/
|
|
||||||
typedef struct sp_fdbg_symbol_s
|
|
||||||
{
|
|
||||||
int32_t addr; /**< Address rel to DAT or stack frame */
|
|
||||||
int16_t tagid; /**< Tag id */
|
|
||||||
uint32_t codestart; /**< Start scope validity in code */
|
|
||||||
uint32_t codeend; /**< End scope validity in code */
|
|
||||||
uint8_t ident; /**< Variable type */
|
|
||||||
uint8_t vclass; /**< Scope class (local vs global) */
|
|
||||||
uint16_t dimcount; /**< Dimension count (for arrays) */
|
|
||||||
uint32_t name; /**< Offset into debug nametable */
|
|
||||||
} sp_fdbg_symbol_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File-encoded debug symbol array dimension info.
|
|
||||||
*/
|
|
||||||
typedef struct sp_fdbg_arraydim_s
|
|
||||||
{
|
|
||||||
int16_t tagid; /**< Tag id */
|
|
||||||
uint32_t size; /**< Size of dimension */
|
|
||||||
} sp_fdbg_arraydim_t;
|
|
||||||
|
|
||||||
/** Typedef for .names table */
|
|
||||||
typedef char * sp_file_nametab_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File encoding for the dbg.natives table.
|
|
||||||
*
|
|
||||||
* This header is followed by variable length entries of sp_fdbg_native.
|
|
||||||
*/
|
|
||||||
typedef struct sp_fdbg_ntvtab_s
|
|
||||||
{
|
|
||||||
uint32_t num_entries; /**< Number of entries. */
|
|
||||||
} sp_fdbg_ntvtab_t;
|
|
||||||
|
|
||||||
#define SP_NTVDBG_VARARGS (1<<0) /**< Formal args are followed by '...' */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File encoding of native debug info.
|
|
||||||
*
|
|
||||||
* Each entry is followed by an sp_fdbg_ntvarg_t for each narg.
|
|
||||||
*/
|
|
||||||
typedef struct sp_fdbg_native_s
|
|
||||||
{
|
|
||||||
uint32_t index; /**< Native index in the plugin. */
|
|
||||||
uint32_t name; /**< Offset into debug nametable. */
|
|
||||||
int16_t tagid; /**< Return tag. */
|
|
||||||
uint16_t nargs; /**< Number of formal arguments. */
|
|
||||||
} sp_fdbg_native_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief File encoding of native arguments.
|
|
||||||
*
|
|
||||||
* Each entry is followed by an sp_fdbg_arraydim_t for each dimcount.
|
|
||||||
*/
|
|
||||||
typedef struct fp_fdbg_ntvarg_s
|
|
||||||
{
|
|
||||||
uint8_t ident; /**< Variable type */
|
|
||||||
int16_t tagid; /**< Tag id */
|
|
||||||
uint16_t dimcount; /**< Dimension count (for arrays) */
|
|
||||||
uint32_t name; /**< Offset into debug nametable */
|
|
||||||
} sp_fdbg_ntvarg_t;
|
|
||||||
|
|
||||||
#if defined __GNUC__
|
|
||||||
#pragma pack() /* reset default packing */
|
|
||||||
#else
|
|
||||||
#pragma pack(pop) /* reset previous packing */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Okay, my mistake here. I apologize. I changed the packing by accident and there is no
|
|
||||||
* version bump aside from the presence of the native debug table. Cat's out of the bag
|
|
||||||
* for SourceMod and we have no choice but to shim compat for the old version. For people
|
|
||||||
* parsing plugins on their own, use the presence of the native debug table to decide this.
|
|
||||||
* If there are no natives (really, there is a very very low chance of this), heuristics
|
|
||||||
* might be necessary. I've bumped the version to 0x0102 but there may have been plugins
|
|
||||||
* in the 0x0101 window with no natives.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unpacked file-encoded debug symbol array dimension info.
|
|
||||||
*/
|
|
||||||
typedef struct sp_u_fdbg_arraydim_s
|
|
||||||
{
|
|
||||||
int16_t tagid; /**< Tag id */
|
|
||||||
uint32_t size; /**< Size of dimension */
|
|
||||||
} sp_u_fdbg_arraydim_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unpacked file-encoded debug symbol information.
|
|
||||||
*/
|
|
||||||
typedef struct sp_u_fdbg_symbol_s
|
|
||||||
{
|
|
||||||
int32_t addr; /**< Address rel to DAT or stack frame */
|
|
||||||
int16_t tagid; /**< Tag id */
|
|
||||||
uint32_t codestart; /**< Start scope validity in code */
|
|
||||||
uint32_t codeend; /**< End scope validity in code */
|
|
||||||
uint8_t ident; /**< Variable type */
|
|
||||||
uint8_t vclass; /**< Scope class (local vs global) */
|
|
||||||
uint16_t dimcount; /**< Dimension count (for arrays) */
|
|
||||||
uint32_t name; /**< Offset into debug nametable */
|
|
||||||
} sp_u_fdbg_symbol_t;
|
|
||||||
|
|
||||||
|
|
||||||
#endif //_INCLUDE_SPFILE_HEADERS_H
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "sp_file_headers.h"
|
|
||||||
#include "sc.h"
|
#include "sc.h"
|
||||||
#include "sp_symhash.h"
|
#include "sp_symhash.h"
|
||||||
#include <am-hashtable.h>
|
#include <am-hashtable.h>
|
||||||
|
146
sourcepawn/compiler/string-pool.h
Normal file
146
sourcepawn/compiler/string-pool.h
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/* 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_
|
@ -39,9 +39,8 @@ struct SmxConsts
|
|||||||
static const uint32_t FILE_MAGIC = 0x53504646;
|
static const uint32_t FILE_MAGIC = 0x53504646;
|
||||||
|
|
||||||
// File format verison number.
|
// File format verison number.
|
||||||
// 0x0101 - Initial version used by spcomp1 and SourceMod 1.0.
|
// 0x0101 - SourcePawn 1.0; initial version used by SourceMod 1.0.
|
||||||
// 0x0102 - Used by spcomp1 and SourceMod 1.1+.
|
// 0x0102 - SourcePawn 1.1; used by SourceMod 1.1+.
|
||||||
// 0x0103 - Used by SourceMod 1.7+.
|
|
||||||
// 0x0200 - Used by spcomp2.
|
// 0x0200 - Used by spcomp2.
|
||||||
//
|
//
|
||||||
// The major version bits (8-15) indicate a product number. Consumers should
|
// The major version bits (8-15) indicate a product number. Consumers should
|
||||||
@ -49,8 +48,11 @@ struct SmxConsts
|
|||||||
//
|
//
|
||||||
// The minor version bits (0-7) indicate a compatibility revision. Any minor
|
// The minor version bits (0-7) indicate a compatibility revision. Any minor
|
||||||
// version higher than the current version should be rejected.
|
// version higher than the current version should be rejected.
|
||||||
static const uint16_t SP1_VERSION_MIN = 0x0101;
|
static const uint16_t SP1_VERSION_1_0 = 0x0101;
|
||||||
static const uint16_t SP1_VERSION_MAX = 0x0103;
|
static const uint16_t SP1_VERSION_1_1 = 0x0102;
|
||||||
|
static const uint16_t SP1_VERSION_1_7 = 0x0107;
|
||||||
|
static const uint16_t SP1_VERSION_MIN = SP1_VERSION_1_0;
|
||||||
|
static const uint16_t SP1_VERSION_MAX = SP1_VERSION_1_7;
|
||||||
static const uint16_t SP2_VERSION_MIN = 0x0200;
|
static const uint16_t SP2_VERSION_MIN = 0x0200;
|
||||||
static const uint16_t SP2_VERSION_MAX = 0x0200;
|
static const uint16_t SP2_VERSION_MAX = 0x0200;
|
||||||
|
|
||||||
@ -58,11 +60,12 @@ struct SmxConsts
|
|||||||
static const uint8_t FILE_COMPRESSION_NONE = 0;
|
static const uint8_t FILE_COMPRESSION_NONE = 0;
|
||||||
static const uint8_t FILE_COMPRESSION_GZ = 1;
|
static const uint8_t FILE_COMPRESSION_GZ = 1;
|
||||||
|
|
||||||
// SourcePawn 1.0.
|
// SourcePawn 1.
|
||||||
static const uint8_t CODE_VERSION_JIT1 = 9;
|
static const uint8_t CODE_VERSION_JIT_1_0 = 9;
|
||||||
|
static const uint8_t CODE_VERSION_JIT_1_1 = 10;
|
||||||
// SourcePawn 1.1.
|
static const uint8_t CODE_VERSION_JIT_1_7 = 11;
|
||||||
static const uint8_t CODE_VERSION_JIT2 = 10;
|
static const uint8_t CODE_VERSION_SP1_MIN = CODE_VERSION_JIT_1_0;
|
||||||
|
static const uint8_t CODE_VERSION_SP1_MAX = CODE_VERSION_JIT_1_1;
|
||||||
|
|
||||||
// For SP1 consumers, the container version may not be checked, but usually
|
// For SP1 consumers, the container version may not be checked, but usually
|
||||||
// the code version is. This constant allows newer containers to be rejected
|
// the code version is. This constant allows newer containers to be rejected
|
||||||
@ -94,18 +97,28 @@ typedef struct sp_file_hdr_s
|
|||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
|
|
||||||
// Compression algorithm. If the file is not compressed, then imagesize and
|
// disksize, imagesize, and dataoffs (at the end) describe a region of the
|
||||||
// disksize are the same value, and dataoffs is 0.
|
// file that may be compressed. The region must occur after the initial
|
||||||
|
// sp_file_hdr_t header. For SourceMod compatibility, the meanings are as
|
||||||
|
// follows.
|
||||||
//
|
//
|
||||||
// The start of the compressed region is indicated by dataoffs. The length
|
// Without compression:
|
||||||
// of the compressed region is (disksize - dataoffs). The amount of memory
|
// imagesize is the amount of bytes that must be read into memory to parse
|
||||||
// required to hold the decompressed bytes is (imagesize - dataoffs). The
|
// the SMX container, starting from the first byte of the file.
|
||||||
// compressed region should be expanded in-place. That is, bytes before
|
// disksize is undefined.
|
||||||
// "dataoffs" should be retained, and the decompressed region should be
|
// dataoffs is undefined.
|
||||||
// appended.
|
|
||||||
//
|
//
|
||||||
// |imagesize| is the amount of memory required to hold the entire container
|
// With compression:
|
||||||
// in memory.
|
// dataoffs is an offset to the start of the compression region.
|
||||||
|
// disksize is the length of the compressed region, in bytes, plus dataoffs.
|
||||||
|
// imagesize is the size of the entire SMX container after decompression.
|
||||||
|
//
|
||||||
|
// This means that at least |imagesize-dataoffs| must be allocated to
|
||||||
|
// decompress, and the compressed region's length is |datasize-dataoffs|.
|
||||||
|
//
|
||||||
|
// The compressed region should always be expanded "in-place". That is, to
|
||||||
|
// parse the container, the compressed bytes should be replaced with
|
||||||
|
// decompressed bytes.
|
||||||
//
|
//
|
||||||
// Note: This scheme may seem odd. It's a combination of historical debt and
|
// Note: This scheme may seem odd. It's a combination of historical debt and
|
||||||
// previously unspecified behavior. The original .amx file format contained
|
// previously unspecified behavior. The original .amx file format contained
|
||||||
|
@ -161,6 +161,10 @@ typedef struct sp_fdbg_ntvarg_s
|
|||||||
uint32_t name; /**< Offset into debug nametable */
|
uint32_t name; /**< Offset into debug nametable */
|
||||||
} sp_fdbg_ntvarg_t;
|
} sp_fdbg_ntvarg_t;
|
||||||
|
|
||||||
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
// DO NOT DEFINE NEW STRUCTURES BELOW.
|
||||||
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
#if defined __GNUC__
|
#if defined __GNUC__
|
||||||
# pragma pack() /* reset default packing */
|
# pragma pack() /* reset default packing */
|
||||||
#else
|
#else
|
||||||
|
@ -172,9 +172,9 @@ int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
|
|||||||
if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) {
|
if (!(m_plugin.pcode) && !strcmp(nameptr, ".code")) {
|
||||||
sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
|
sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
|
||||||
|
|
||||||
if (cod->codeversion < SmxConsts::CODE_VERSION_JIT1)
|
if (cod->codeversion < SmxConsts::CODE_VERSION_SP1_MIN)
|
||||||
return SP_ERROR_CODE_TOO_OLD;
|
return SP_ERROR_CODE_TOO_OLD;
|
||||||
if (cod->codeversion > SmxConsts::CODE_VERSION_JIT2)
|
if (cod->codeversion > SmxConsts::CODE_VERSION_SP1_MAX)
|
||||||
return SP_ERROR_CODE_TOO_NEW;
|
return SP_ERROR_CODE_TOO_NEW;
|
||||||
|
|
||||||
m_plugin.pcode = base + secptr->dataoffs + cod->code;
|
m_plugin.pcode = base + secptr->dataoffs + cod->code;
|
||||||
|
@ -53,7 +53,7 @@ LINK = -m32 -lm -lpthread -lrt
|
|||||||
|
|
||||||
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
|
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
|
||||||
-I$(SMSDK)/public/sourcepawn -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/knight/shared -Ix86 \
|
-I$(SMSDK)/public/sourcepawn -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/knight/shared -Ix86 \
|
||||||
-I$(SMSDK)/public/amtl
|
-I$(SMSDK)/public/amtl -I$(SMSDK)/sourcepawn/include
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
||||||
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
|
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
|
||||||
|
@ -147,7 +147,7 @@ void SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
|
|||||||
|
|
||||||
const char *SourcePawnEngine2::GetEngineName()
|
const char *SourcePawnEngine2::GetEngineName()
|
||||||
{
|
{
|
||||||
return "SourcePawn 1.3, jit-x86";
|
return "SourcePawn 1.7, jit-x86";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *SourcePawnEngine2::GetVersionString()
|
const char *SourcePawnEngine2::GetVersionString()
|
||||||
|
Loading…
Reference in New Issue
Block a user