From 66f7568ce72854bd661cdc80253d26b864ab92c9 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 19 Jul 2006 00:53:26 +0000 Subject: [PATCH] added binary writer stuff --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4033 --- sourcepawn/compiler/amx.h | 92 ++++++------ sourcepawn/compiler/pawncc.c | 193 ++++++++++--------------- sourcepawn/compiler/scmemfil.c | 15 -- sourcepawn/compiler/sp_file.c | 224 ++++++++++++++++++++++++++++++ sourcepawn/compiler/sp_file.h | 160 +++++++++------------ sourcepawn/compiler/spcomp.vcproj | 12 ++ 6 files changed, 419 insertions(+), 277 deletions(-) create mode 100644 sourcepawn/compiler/sp_file.c diff --git a/sourcepawn/compiler/amx.h b/sourcepawn/compiler/amx.h index ca25a0da..3d497a0f 100644 --- a/sourcepawn/compiler/amx.h +++ b/sourcepawn/compiler/amx.h @@ -206,9 +206,9 @@ typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX #endif #if defined __GNUC__ - #define PACKED __attribute__((packed)) + #define PACKEDENTRY __attribute__((packed)) #else - #define PACKED + #define PACKEDENTRY #endif #if !defined AMX_NO_ALIGN @@ -226,8 +226,8 @@ typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX #endif typedef struct tagAMX_NATIVE_INFO { - const char _FAR *name PACKED; - AMX_NATIVE func PACKED; + const char _FAR *name PACKEDENTRY; + AMX_NATIVE func PACKEDENTRY; } AMX_NATIVE_INFO; #define AMX_USERNUM 4 @@ -235,48 +235,48 @@ typedef struct tagAMX_NATIVE_INFO { #define sNAMEMAX 31 /* maximum name length of symbol name */ typedef struct tagAMX_FUNCSTUB { - ucell address PACKED; - char name[sEXPMAX+1] PACKED; + ucell address PACKEDENTRY; + char name[sEXPMAX+1] PACKEDENTRY; } AMX_FUNCSTUB; typedef struct tagFUNCSTUBNT { - ucell address PACKED; - uint32_t nameofs PACKED; + ucell address PACKEDENTRY; + uint32_t nameofs PACKEDENTRY; } 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 PACKED; /* points to the AMX header plus the code, optionally also the data */ - unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */ - AMX_CALLBACK callback PACKED; - AMX_DEBUG debug PACKED; /* debug callback */ + unsigned char _FAR *base PACKEDENTRY; /* points to the AMX header plus the code, optionally also the data */ + unsigned char _FAR *data PACKEDENTRY; /* points to separate data+stack+heap, may be NULL */ + AMX_CALLBACK callback PACKEDENTRY; + AMX_DEBUG debug PACKEDENTRY; /* debug callback */ /* for external functions a few registers must be accessible from the outside */ - cell cip PACKED; /* instruction pointer: relative to base + amxhdr->cod */ - cell frm PACKED; /* stack frame base: relative to base + amxhdr->dat */ - cell hea PACKED; /* top of the heap: relative to base + amxhdr->dat */ - cell hlw PACKED; /* bottom of the heap: relative to base + amxhdr->dat */ - cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */ - cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */ - int flags PACKED; /* current status, see amx_Flags() */ + cell cip PACKEDENTRY; /* instruction pointer: relative to base + amxhdr->cod */ + cell frm PACKEDENTRY; /* stack frame base: relative to base + amxhdr->dat */ + cell hea PACKEDENTRY; /* top of the heap: relative to base + amxhdr->dat */ + cell hlw PACKEDENTRY; /* bottom of the heap: relative to base + amxhdr->dat */ + cell stk PACKEDENTRY; /* stack pointer: relative to base + amxhdr->dat */ + cell stp PACKEDENTRY; /* top of the stack: relative to base + amxhdr->dat */ + int flags PACKEDENTRY; /* current status, see amx_Flags() */ /* user data */ - long usertags[AMX_USERNUM] PACKED; - void _FAR *userdata[AMX_USERNUM] PACKED; + long usertags[AMX_USERNUM] PACKEDENTRY; + void _FAR *userdata[AMX_USERNUM] PACKEDENTRY; /* native functions can raise an error */ - int error PACKED; + int error PACKEDENTRY; /* passing parameters requires a "count" field */ int paramcount; /* the sleep opcode needs to store the full AMX status */ - cell pri PACKED; - cell alt PACKED; - cell reset_stk PACKED; - cell reset_hea PACKED; - cell sysreq_d PACKED; /* relocated address/value for the SYSREQ.D opcode */ + cell pri PACKEDENTRY; + cell alt PACKEDENTRY; + cell reset_stk PACKEDENTRY; + cell reset_hea PACKEDENTRY; + cell sysreq_d PACKEDENTRY; /* relocated address/value for the SYSREQ.D opcode */ #if defined JIT /* support variables for the JIT */ - int reloc_size PACKED; /* required temporary buffer for relocations */ - long code_size PACKED; /* estimated memory footprint of the native code */ + int reloc_size PACKEDENTRY; /* required temporary buffer for relocations */ + long code_size PACKEDENTRY; /* estimated memory footprint of the native code */ #endif } AMX; @@ -284,23 +284,23 @@ typedef struct tagAMX { * structure is used internaly. */ typedef struct tagAMX_HEADER { - int32_t size PACKED; /* size of the "file" */ - uint16_t magic PACKED; /* signature */ - char file_version PACKED; /* file format version */ - char amx_version PACKED; /* required version of the AMX */ - int16_t flags PACKED; - int16_t defsize PACKED; /* size of a definition record */ - int32_t cod PACKED; /* initial value of COD - code block */ - int32_t dat PACKED; /* initial value of DAT - data block */ - int32_t hea PACKED; /* initial value of HEA - start of the heap */ - int32_t stp PACKED; /* initial value of STP - stack top */ - int32_t cip PACKED; /* initial value of CIP - the instruction pointer */ - int32_t publics PACKED; /* offset to the "public functions" table */ - int32_t natives PACKED; /* offset to the "native functions" table */ - int32_t libraries PACKED; /* offset to the table of libraries */ - int32_t pubvars PACKED; /* the "public variables" table */ - int32_t tags PACKED; /* the "public tagnames" table */ - int32_t nametable PACKED; /* name table */ + int32_t size PACKEDENTRY; /* size of the "file" */ + uint16_t magic PACKEDENTRY; /* signature */ + char file_version PACKEDENTRY; /* file format version */ + char amx_version PACKEDENTRY; /* required version of the AMX */ + int16_t flags PACKEDENTRY; + int16_t defsize PACKEDENTRY; /* size of a definition record */ + int32_t cod PACKEDENTRY; /* initial value of COD - code block */ + int32_t dat PACKEDENTRY; /* initial value of DAT - data block */ + int32_t hea PACKEDENTRY; /* initial value of HEA - start of the heap */ + int32_t stp PACKEDENTRY; /* initial value of STP - stack top */ + int32_t cip PACKEDENTRY; /* initial value of CIP - the instruction pointer */ + int32_t publics PACKEDENTRY; /* offset to the "public functions" table */ + int32_t natives PACKEDENTRY; /* offset to the "native functions" table */ + int32_t libraries PACKEDENTRY; /* offset to the table of libraries */ + int32_t pubvars PACKEDENTRY; /* the "public variables" table */ + int32_t tags PACKEDENTRY; /* the "public tagnames" table */ + int32_t nametable PACKEDENTRY; /* name table */ } AMX_HEADER; #if PAWN_CELL_SIZE==16 diff --git a/sourcepawn/compiler/pawncc.c b/sourcepawn/compiler/pawncc.c index 2db16e1f..8da3e2e6 100644 --- a/sourcepawn/compiler/pawncc.c +++ b/sourcepawn/compiler/pawncc.c @@ -8,11 +8,27 @@ #include "osdefs.h" #include "zlib/zlib.h" -#define NUM_SECTIONS 6 +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_DbgAutomaton, + FS_DbgState, + /* --- */ + 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, FILE *fp); +void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf); memfile_t *bin_file = NULL; jmp_buf brkout; @@ -21,17 +37,11 @@ int main(int argc, char *argv[]) { if (pc_compile(argc,argv) == 0) { - FILE *fp; AMX_HEADER *hdr; - sp_file_hdr_t shdr; - uint32_t curoffs = 0; - uint32_t lastsection = 0; int err; - uint8_t i8; uint32_t i; - const char *tables[NUM_SECTIONS] = {".code", ".data", ".publics", ".pubvars", ".natives", ".names"}; - uint32_t offsets[NUM_SECTIONS] = {0,0,0,0,0,0}; - sp_file_section_t sh; + sp_file_t *spf; + uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0}; if (bin_file == NULL) { @@ -39,13 +49,12 @@ int main(int argc, char *argv[]) } hdr = (AMX_HEADER *)bin_file->base; - shdr.version = SPFILE_VERSION; - shdr.magic = SPFILE_MAGIC; - if ((fp=fopen(bin_file->name, "wb")) == NULL) + if ((spf=spfw_create(bin_file->name, NULL)) == NULL) { - pc_printf("Error writing to file: %s", bin_file->name); - return 1; + pc_printf("Error creating binary file!\n"); + memfile_destroy(bin_file); + return 0; } if ((err=setjmp(brkout))!=0) @@ -53,48 +62,34 @@ int main(int argc, char *argv[]) goto write_error; } - shdr.sections = NUM_SECTIONS; - shdr.stringtab = sizeof(shdr) + (sizeof(sp_file_section_t) * shdr.sections); + spfw_add_section(spf, ".code"); + spfw_add_section(spf, ".data"); - /** - * write the header - * unwritten values: - * imagesize - */ - sfwrite(&shdr, sizeof(shdr), 1, fp); - - curoffs = shdr.stringtab; - - /** - * write the sections - * unwritten values: - * dataoffs - * size - */ - for (i8=0; i8natives - hdr->publics) / hdr->defsize; + if (sections[FS_Publics]) { - /* set name offset to next in string table */ - sh.nameoffs = curoffs - shdr.stringtab; - /* save offset to this section */ - offsets[i8] = (uint32_t)ftell(fp) + sizeof(sh.nameoffs); - /* update `end of file` offset */ - curoffs += strlen(tables[i8]) + 1; - sfwrite(&sh, sizeof(sh), 1, fp); + 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"); } - /** write the string table */ - for (i8=0; i8natives - hdr->publics) / hdr->defsize; + uint32_t publics = sections[FS_Publics]; pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics); stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->publics); @@ -423,25 +404,18 @@ int main(int argc, char *argv[]) } if (publics) { - sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, fp); + sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf); } free(pbtbl); - /* backtrack and write section's header info */ - curoffs = ftell(fp); - fseek(fp, offsets[2], SEEK_SET); - sfwrite(&lastsection, sizeof(uint32_t), 1, fp); - publics *= sizeof(sp_file_publics_t); - sfwrite(&publics, sizeof(uint32_t), 1, fp); - fseek(fp, curoffs, SEEK_SET); - lastsection = curoffs; + spfw_next_section(spf); } - if (strcmp(tables[3], ".pubvars") == 0) + if (sections[FS_Pubvars]) { sp_file_pubvars_t *pbvars; AMX_FUNCSTUBNT *stub; - uint32_t pubvars = (hdr->tags - hdr->pubvars) / hdr->defsize; + uint32_t pubvars = sections[FS_Pubvars]; pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars); stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->pubvars); @@ -455,21 +429,13 @@ int main(int argc, char *argv[]) } if (pubvars) { - sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, fp); + sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf); } free(pbvars); - - /* backtrack and write section's header info */ - curoffs = ftell(fp); - fseek(fp, offsets[3], SEEK_SET); - sfwrite(&lastsection, sizeof(uint32_t), 1, fp); - pubvars *= sizeof(sp_file_pubvars_t); - sfwrite(&pubvars, sizeof(uint32_t), 1, fp); - fseek(fp, curoffs, SEEK_SET); - lastsection = curoffs; + spfw_next_section(spf); } - if (strcmp(tables[4], ".natives") == 0) + if (sections[FS_Natives]) { sp_file_natives_t *nvtbl; AMX_FUNCSTUBNT *stub; @@ -486,21 +452,13 @@ int main(int argc, char *argv[]) } if (natives) { - sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, fp); + sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf); } free(nvtbl); - - /* backtrack and write header */ - curoffs = ftell(fp); - fseek(fp, offsets[4], SEEK_SET); - sfwrite(&lastsection, sizeof(uint32_t), 1, fp); - natives *= sizeof(sp_file_natives_t); - sfwrite(&natives, sizeof(uint32_t), 1, fp); - fseek(fp, curoffs, SEEK_SET); - lastsection = curoffs; + spfw_next_section(spf); } - if (strcmp(tables[5], ".names") == 0) + if (sections[FS_Nametable]) { unsigned char *base; uint32_t namelen; @@ -512,25 +470,18 @@ int main(int argc, char *argv[]) * this may clip at most an extra three bytes in! */ namelen = hdr->cod - hdr->nametable; - sfwrite(base, namelen, 1, fp); - - /* backtrack and write header */ - curoffs = ftell(fp); - fseek(fp, offsets[5], SEEK_SET); - sfwrite(&lastsection, sizeof(uint32_t), 1, fp); - sfwrite(&namelen, sizeof(uint32_t), 1, fp); - fseek(fp, curoffs, SEEK_SET); - lastsection = curoffs; + sfwrite(base, namelen, 1, spf); + spfw_next_section(spf); } - fclose(fp); + spfw_finalize_all(spf); + spfw_destroy(spf); return 0; write_error: pc_printf("Error writing to file: %s", bin_file->name); unlink(bin_file->name); - fclose(fp); memfile_destroy(bin_file); bin_file = NULL; @@ -541,9 +492,9 @@ write_error: return 1; } -void sfwrite(const void *buf, size_t size, size_t count, FILE *fp) +void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf) { - if (fwrite(buf, size, count, fp) != count) + if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count) { longjmp(brkout, 1); } diff --git a/sourcepawn/compiler/scmemfil.c b/sourcepawn/compiler/scmemfil.c index 73a76c63..4924e71d 100644 --- a/sourcepawn/compiler/scmemfil.c +++ b/sourcepawn/compiler/scmemfil.c @@ -31,26 +31,11 @@ #include #include "memfile.h" -#if defined FORTIFY - #include -#endif - - -#define BUFFERSIZE 512u - -/* For every block, except the first: - * buffer points to a block that is BUFFERSIZE long that holds the data - * bufpos is the "used size" of the block - * For the first block: - * buffer points to the "file name" - * bufpos is the current "file pointer" - */ typedef memfile_t MEMFILE; #define tMEMFILE 1 #include "sc.h" - MEMFILE *mfcreate(char *filename) { return memfile_creat(filename, 4096); diff --git a/sourcepawn/compiler/sp_file.c b/sourcepawn/compiler/sp_file.c new file mode 100644 index 00000000..21f2980e --- /dev/null +++ b/sourcepawn/compiler/sp_file.c @@ -0,0 +1,224 @@ +#include +#include +#include +#include "sp_file.h" + +void *fp_open(const char *name); +void fp_close(void *handle); +size_t fp_write(const void *buf, size_t size, size_t count, void *handle); +size_t fp_read(void *buf, size_t size, size_t count, void *handle); +size_t fp_getpos(void *handle); +int fp_setpos(void *handle, size_t pos); + +sp_writefuncs_t cstd_funcs = +{ + fp_open, + fp_close, + fp_write, + fp_read, + fp_getpos, + fp_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->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; + 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.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; +} + +/** + * Default file operations... + * Based on C standard library calls. + */ + +void *fp_open(const char *name) +{ + return fopen(name, "wb"); +} + +void fp_close(void *handle) +{ + fclose((FILE *)handle); +} + +size_t fp_write(const void *buf, size_t size, size_t count, void *handle) +{ + return fwrite(buf, size, count, (FILE *)handle); +} + +size_t fp_read(void *buf, size_t size, size_t count, void *handle) +{ + return fread(buf, size, count, (FILE *)handle); +} + +size_t fp_getpos(void *handle) +{ + return (size_t)ftell((FILE *)handle); +} + +int fp_setpos(void *handle, size_t pos) +{ + return fseek((FILE *)handle, (long)pos, SEEK_SET); +} + + diff --git a/sourcepawn/compiler/sp_file.h b/sourcepawn/compiler/sp_file.h index b0aeb2c3..41ff70a9 100644 --- a/sourcepawn/compiler/sp_file.h +++ b/sourcepawn/compiler/sp_file.h @@ -1,110 +1,80 @@ #ifndef _INCLUDE_SPFILE_H #define _INCLUDE_SPFILE_H -#include -#if defined __GNUC__ || defined HAVE_STDINT_ -#include -#else - #if !defined HAVE_STDINT_H - typedef unsigned __int64 uint64_t; - typedef __int64 int64_t; - typedef unsigned __int32 uint32_t; - typedef __int32 int32_t; - typedef unsigned __int16 uint16_t; - typedef __int16 int16_t; - typedef unsigned __int8 uint8_t; - typedef __int8 int8_t; - #define HAVE_STDINT_H - #endif -#endif +#include "sp_file_headers.h" -#define SPFILE_MAGIC 0xDEADC0D3 -#define SPFILE_VERSION 0x0100 - -//:TODO: better compiler/nix support -#if defined __linux__ - #pragma pack(1) /* structures must be packed (byte-aligned) */ -#else - #pragma pack(push) - #pragma pack(1) /* structures must be packed (byte-aligned) */ -#endif - -typedef struct sp_file_section_s +/** + * Used for overwriting writing routines. + */ +typedef struct sp_writefuncs_s { - uint32_t nameoffs; /* rel offset into global string table */ - uint32_t dataoffs; - uint32_t size; -} sp_file_section_t; + 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_hdr_s +typedef struct sp_file_s { - uint32_t magic; - uint16_t version; - uint32_t imagesize; - uint8_t sections; - uint32_t stringtab; -} sp_file_hdr_t; + 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; -typedef enum -{ - SP_FILE_NONE = 0, - SP_FILE_DEBUG = 1, -} sp_file_flags_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); -/* section is ".code" */ -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 disksize; /* disksize in bytes */ - uint32_t compression; /* compression */ - uint32_t code; /* rel offset to code */ -} sp_file_code_t; +/** + * Closes file handle and frees memory. + */ +void spfw_destroy(sp_file_t *spf); -#define SPFILE_COMPRESSION_NONE 0 -#define SPFILE_COMPRESSION_GZ 1 +/** + * 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); -/* section is .data */ -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 disksize; /* size of data on disk (compressed) */ - uint8_t compression; /* compression */ - uint32_t data; /* file offset to data (helper) */ -} sp_file_data_t; +/** + * 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); -/* section is .publics */ -typedef struct sp_file_publics_s -{ - uint32_t address; /* address rel to code section */ - uint32_t name; /* index into nametable */ -} sp_file_publics_t; +/** + * 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); -/* section is .natives */ -typedef struct sp_file_natives_s -{ - uint32_t name; /* name of native at index */ -} sp_file_natives_t; - -/* section is .pubvars */ -typedef struct sp_file_pubvars_s -{ - uint32_t address; /* address rel to dat section */ - uint32_t name; /* index into nametable */ -} sp_file_pubvars_t; - -#if defined __linux__ - #pragma pack() /* reset default packing */ -#else - #pragma pack(pop) /* reset previous packing */ -#endif - - -/* section is .names */ -typedef char * sp_file_nametab_t; +/** + * Finalizes all sections. + * Cannot be called until all sections are used. + * Must be called with the file pointer at the end. + */ +int spfw_finalize_all(sp_file_t *spf); #endif //_INCLUDE_SPFILE_H diff --git a/sourcepawn/compiler/spcomp.vcproj b/sourcepawn/compiler/spcomp.vcproj index db52d001..44d6c891 100644 --- a/sourcepawn/compiler/spcomp.vcproj +++ b/sourcepawn/compiler/spcomp.vcproj @@ -250,6 +250,10 @@ RelativePath=".\scvars.c" > + + + + @@ -280,6 +288,10 @@ RelativePath=".\sp_file.h" > + +