diff --git a/sourcepawn/compiler/amx.h b/sourcepawn/compiler/amx.h index 3d497a0f..6ba09a92 100644 --- a/sourcepawn/compiler/amx.h +++ b/sourcepawn/compiler/amx.h @@ -205,12 +205,6 @@ typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX #define AMX_NO_ALIGN #endif -#if defined __GNUC__ - #define PACKEDENTRY __attribute__((packed)) -#else - #define PACKEDENTRY -#endif - #if !defined AMX_NO_ALIGN #if defined LINUX || defined __FreeBSD__ #pragma pack(1) /* structures must be packed (byte-aligned) */ @@ -226,8 +220,8 @@ typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX #endif typedef struct tagAMX_NATIVE_INFO { - const char _FAR *name PACKEDENTRY; - AMX_NATIVE func PACKEDENTRY; + const char _FAR *name; + AMX_NATIVE func; } AMX_NATIVE_INFO; #define AMX_USERNUM 4 @@ -235,48 +229,48 @@ typedef struct tagAMX_NATIVE_INFO { #define sNAMEMAX 31 /* maximum name length of symbol name */ typedef struct tagAMX_FUNCSTUB { - ucell address PACKEDENTRY; - char name[sEXPMAX+1] PACKEDENTRY; + ucell address; + char name[sEXPMAX+1]; } AMX_FUNCSTUB; typedef struct tagFUNCSTUBNT { - ucell address PACKEDENTRY; - uint32_t nameofs PACKEDENTRY; + ucell address; + uint32_t nameofs; } AMX_FUNCSTUBNT; /* The AMX structure is the internal structure for many functions. Not all * fields are valid at all times; many fields are cached in local variables. */ typedef struct tagAMX { - unsigned char _FAR *base 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 */ + unsigned char _FAR *base; /* points to the AMX header plus the code, optionally also the data */ + unsigned char _FAR *data; /* points to separate data+stack+heap, may be NULL */ + AMX_CALLBACK callback; + AMX_DEBUG debug ; /* debug callback */ /* for external functions a few registers must be accessible from the outside */ - cell cip 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() */ + cell cip ; /* instruction pointer: relative to base + amxhdr->cod */ + cell frm ; /* stack frame base: relative to base + amxhdr->dat */ + cell hea ; /* top of the heap: relative to base + amxhdr->dat */ + cell hlw ; /* bottom of the heap: relative to base + amxhdr->dat */ + cell stk ; /* stack pointer: relative to base + amxhdr->dat */ + cell stp ; /* top of the stack: relative to base + amxhdr->dat */ + int flags ; /* current status, see amx_Flags() */ /* user data */ - long usertags[AMX_USERNUM] PACKEDENTRY; - void _FAR *userdata[AMX_USERNUM] PACKEDENTRY; + long usertags[AMX_USERNUM] ; + void _FAR *userdata[AMX_USERNUM] ; /* native functions can raise an error */ - int error PACKEDENTRY; + int error ; /* passing parameters requires a "count" field */ int paramcount; /* the sleep opcode needs to store the full AMX status */ - 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 */ + cell pri ; + cell alt ; + cell reset_stk ; + cell reset_hea ; + cell sysreq_d ; /* relocated address/value for the SYSREQ.D opcode */ #if defined JIT /* support variables for the JIT */ - int reloc_size PACKEDENTRY; /* required temporary buffer for relocations */ - long code_size PACKEDENTRY; /* estimated memory footprint of the native code */ + int reloc_size ; /* required temporary buffer for relocations */ + long code_size ; /* estimated memory footprint of the native code */ #endif } AMX; @@ -284,23 +278,23 @@ typedef struct tagAMX { * structure is used internaly. */ typedef struct tagAMX_HEADER { - 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 */ + int32_t size ; /* size of the "file" */ + uint16_t magic ; /* signature */ + char file_version ; /* file format version */ + char amx_version ; /* required version of the AMX */ + int16_t flags ; + int16_t defsize ; /* size of a definition record */ + int32_t cod ; /* initial value of COD - code block */ + int32_t dat ; /* initial value of DAT - data block */ + int32_t hea ; /* initial value of HEA - start of the heap */ + int32_t stp ; /* initial value of STP - stack top */ + int32_t cip ; /* initial value of CIP - the instruction pointer */ + int32_t publics ; /* offset to the "public functions" table */ + int32_t natives ; /* offset to the "native functions" table */ + int32_t libraries ; /* offset to the table of libraries */ + int32_t pubvars ; /* the "public variables" table */ + int32_t tags ; /* the "public tagnames" table */ + int32_t nametable ; /* name table */ } AMX_HEADER; #if PAWN_CELL_SIZE==16 diff --git a/sourcepawn/compiler/amxdbg.h b/sourcepawn/compiler/amxdbg.h index acc4d1b3..4fc3c1c1 100644 --- a/sourcepawn/compiler/amxdbg.h +++ b/sourcepawn/compiler/amxdbg.h @@ -42,12 +42,6 @@ extern "C" { #define AMX_NO_ALIGN #endif -#if defined __GNUC__ - #define PACKED __attribute__((packed)) -#else - #define PACKED -#endif - #if !defined AMX_NO_ALIGN #if defined LINUX || defined __FreeBSD__ #pragma pack(1) /* structures must be packed (byte-aligned) */ @@ -63,72 +57,72 @@ extern "C" { #endif typedef struct tagAMX_DBG_HDR { - int32_t size PACKED; /* size of the debug information chunk */ - uint16_t magic PACKED; /* signature, must be 0xf1ef */ - char file_version PACKED; /* file format version */ - char amx_version PACKED; /* required version of the AMX */ - int16_t flags PACKED; /* currently unused */ - int16_t files PACKED; /* number of entries in the "file" table */ - int16_t lines PACKED; /* number of entries in the "line" table */ - int16_t symbols PACKED; /* number of entries in the "symbol" table */ - int16_t tags PACKED; /* number of entries in the "tag" table */ - int16_t automatons PACKED; /* number of entries in the "automaton" table */ - int16_t states PACKED; /* number of entries in the "state" table */ -} PACKED AMX_DBG_HDR; + int32_t size ; /* size of the debug information chunk */ + uint16_t magic ; /* signature, must be 0xf1ef */ + char file_version ; /* file format version */ + char amx_version ; /* required version of the AMX */ + int16_t flags ; /* currently unused */ + int16_t files ; /* number of entries in the "file" table */ + int16_t lines ; /* number of entries in the "line" table */ + int16_t symbols ; /* number of entries in the "symbol" table */ + int16_t tags ; /* number of entries in the "tag" table */ + int16_t automatons ; /* number of entries in the "automaton" table */ + int16_t states ; /* number of entries in the "state" table */ +} AMX_DBG_HDR; #define AMX_DBG_MAGIC 0xf1ef typedef struct tagAMX_DBG_FILE { - ucell address PACKED; /* address in the code segment where generated code (for this file) starts */ - const char name[1] PACKED; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_FILE; + ucell address ; /* address in the code segment where generated code (for this file) starts */ + const char name[1] ; /* ASCII string, zero-terminated */ +} AMX_DBG_FILE; typedef struct tagAMX_DBG_LINE { - ucell address PACKED; /* address in the code segment where generated code (for this line) starts */ - int32_t line PACKED; /* line number */ -} PACKED AMX_DBG_LINE; + ucell address ; /* address in the code segment where generated code (for this line) starts */ + int32_t line ; /* line number */ +} AMX_DBG_LINE; typedef struct tagAMX_DBG_SYMBOL { - ucell address PACKED; /* address in the data segment or relative to the frame */ - int16_t tag PACKED; /* tag for the symbol */ - ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */ - ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */ - char ident PACKED; /* kind of symbol (function/variable) */ - char vclass PACKED; /* class of symbol (global/local) */ - int16_t dim PACKED; /* number of dimensions */ - const char name[1] PACKED; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_SYMBOL; + ucell address ; /* address in the data segment or relative to the frame */ + int16_t tag ; /* tag for the symbol */ + ucell codestart ; /* address in the code segment from which this symbol is valid (in scope) */ + ucell codeend ; /* address in the code segment until which this symbol is valid (in scope) */ + char ident ; /* kind of symbol (function/variable) */ + char vclass ; /* class of symbol (global/local) */ + int16_t dim ; /* number of dimensions */ + const char name[1] ; /* ASCII string, zero-terminated */ +} AMX_DBG_SYMBOL; typedef struct tagAMX_DBG_SYMDIM { - int16_t tag PACKED; /* tag for the array dimension */ - ucell size PACKED; /* size of the array dimension */ -} PACKED AMX_DBG_SYMDIM; + int16_t tag ; /* tag for the array dimension */ + ucell size ; /* size of the array dimension */ +} AMX_DBG_SYMDIM; typedef struct tagAMX_DBG_TAG { - int16_t tag PACKED; /* tag id */ - const char name[1] PACKED; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_TAG; + int16_t tag ; /* tag id */ + const char name[1] ; /* ASCII string, zero-terminated */ +} AMX_DBG_TAG; typedef struct tagAMX_DBG_MACHINE { - int16_t automaton PACKED; /* automaton id */ - ucell address PACKED; /* address of state variable */ - const char name[1] PACKED; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_MACHINE; + int16_t automaton ; /* automaton id */ + ucell address ; /* address of state variable */ + const char name[1] ; /* ASCII string, zero-terminated */ +} AMX_DBG_MACHINE; typedef struct tagAMX_DBG_STATE { - int16_t state PACKED; /* state id */ - int16_t automaton PACKED; /* automaton id */ - const char name[1] PACKED; /* ASCII string, zero-terminated */ -} PACKED AMX_DBG_STATE; + int16_t state ; /* state id */ + int16_t automaton ; /* automaton id */ + const char name[1] ; /* ASCII string, zero-terminated */ +} AMX_DBG_STATE; typedef struct tagAMX_DBG { - AMX_DBG_HDR *hdr PACKED; /* points to the AMX_DBG header */ - AMX_DBG_FILE **filetbl PACKED; - AMX_DBG_LINE *linetbl PACKED; - AMX_DBG_SYMBOL **symboltbl PACKED; - AMX_DBG_TAG **tagtbl PACKED; - AMX_DBG_MACHINE **automatontbl PACKED; - AMX_DBG_STATE **statetbl PACKED; -} PACKED AMX_DBG; + AMX_DBG_HDR *hdr ; /* points to the AMX_DBG header */ + AMX_DBG_FILE **filetbl ; + AMX_DBG_LINE *linetbl ; + AMX_DBG_SYMBOL **symboltbl ; + AMX_DBG_TAG **tagtbl ; + AMX_DBG_MACHINE **automatontbl ; + AMX_DBG_STATE **statetbl ; +} AMX_DBG; #if !defined iVARIABLE #define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */ diff --git a/sourcepawn/compiler/memfile.c b/sourcepawn/compiler/memfile.c index 2047f710..bc572e7f 100644 --- a/sourcepawn/compiler/memfile.c +++ b/sourcepawn/compiler/memfile.c @@ -28,6 +28,11 @@ memfile_t *memfile_creat(const char *name, size_t init) void memfile_destroy(memfile_t *mf) { + if (!mf) + { + return; + } + if (!mf->_static) { free(mf->name); @@ -69,7 +74,7 @@ size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize) return maxsize; } -int memfile_write(memfile_t *mf, void *buffer, size_t size) +int memfile_write(memfile_t *mf, const void *buffer, size_t size) { if (mf->offs + size > mf->size) { @@ -103,3 +108,9 @@ int memfile_write(memfile_t *mf, void *buffer, size_t size) return 1; } + +void memfile_reset(memfile_t *mf) +{ + mf->usedoffs = 0; + mf->offs = 0; +} diff --git a/sourcepawn/compiler/memfile.h b/sourcepawn/compiler/memfile.h index f5222a9e..7f953f20 100644 --- a/sourcepawn/compiler/memfile.h +++ b/sourcepawn/compiler/memfile.h @@ -13,11 +13,43 @@ typedef struct memfile_s int _static; } memfile_t; +/** + * Creates a new memory file + * init is the initial size in bytes + */ memfile_t *memfile_creat(const char *name, size_t init); + +/** + * Frees the memory associated. + */ void memfile_destroy(memfile_t *mf); + +/** + * Seeks to a given offset (always from start) + */ void memfile_seek(memfile_t *mf, long seek); -int memfile_write(memfile_t *mf, void *buffer, size_t size); + +/** + * Writes to a memory buffer (expands as necessary). + * Returns 1 on success, 0 on failure. + */ +int memfile_write(memfile_t *mf, const void *buffer, size_t size); + +/** + * Reads a number of bytes from a memory buffer. + * Returns the number of bytes read until the end was hit. + */ size_t memfile_read(memfile_t *mf, void *buffer, size_t maxsize); + +/** + * Returns the current position from the start. + */ long memfile_tell(memfile_t *mf); +/** + * Resets all the states of the memory buffer. + * (does not actually free or zero memory) + */ +void memfile_reset(memfile_t *mf); + #endif //_INCLUDE_MEMFILE_H diff --git a/sourcepawn/compiler/pawncc.c b/sourcepawn/compiler/pawncc.c index 8da3e2e6..d8073e2d 100644 --- a/sourcepawn/compiler/pawncc.c +++ b/sourcepawn/compiler/pawncc.c @@ -5,6 +5,7 @@ #include "memfile.h" #include "sp_file.h" #include "amx.h" +#include "amxdbg.h" #include "osdefs.h" #include "zlib/zlib.h" @@ -22,6 +23,7 @@ enum FileSections FS_DbgTags, FS_DbgAutomaton, FS_DbgState, + FS_DbgStrings, /* --- */ FS_Number, }; @@ -38,10 +40,14 @@ int main(int argc, char *argv[]) if (pc_compile(argc,argv) == 0) { AMX_HEADER *hdr; + AMX_DBG_HDR *dbg = NULL; int err; uint32_t i; sp_file_t *spf; + memfile_t *dbgtab = NULL; + unsigned char *dbgptr = NULL; uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0}; + FILE *fp; if (bin_file == NULL) { @@ -83,6 +89,35 @@ int main(int argc, char *argv[]) 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 (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_DbgStrings] = 1; + spfw_add_section(spf, ".dbg.strings"); + } + } + spfw_finalize_header(spf); /** @@ -324,8 +359,6 @@ int main(int argc, char *argv[]) } } cod.codesize = (uint32_t)(tptr - tbase); - cod.disksize = cod.codesize; - cod.compression = SPFILE_COMPRESSION_NONE; sfwrite(&cod, sizeof(cod), 1, spf); sfwrite(tbase, cod.codesize, 1, spf); free(tbase); @@ -336,51 +369,19 @@ int main(int argc, char *argv[]) if (sections[FS_Data]) { sp_file_data_t dat; - unsigned char *dbase; - Bytef *cmp_dbase; - uLong disksize; - int err; + unsigned char *dbase = (unsigned char *)hdr + hdr->dat; dat.datasize = hdr->hea - hdr->dat; dat.memsize = hdr->stp; dat.data = sizeof(dat); - dat.compression = SPFILE_COMPRESSION_GZ; + + /* write header */ + sfwrite(&dat, sizeof(dat), 1, spf); if (dat.datasize) { - dat.disksize = (uint32_t)compressBound((uLong)dat.datasize); - - dbase = (unsigned char *)hdr + hdr->dat; - cmp_dbase = (Bytef *)malloc(dat.disksize); - - /* compress */ - err = compress2(cmp_dbase, &disksize, (Bytef *)dbase, (uLong)dat.datasize, Z_BEST_COMPRESSION); - - if (err != Z_OK) - { - pc_printf("Failed to compress DAT section with error: %d\n", err); - pc_printf("Defaulting to no compression.\n"); - dat.compression = SPFILE_COMPRESSION_NONE; - dat.disksize = dat.datasize; - - /* write header */ - sfwrite(&dat, sizeof(dat), 1, spf); - /* write data */ - sfwrite(&dbase, dat.datasize, 1, spf); - } else { - dat.disksize = (uint32_t)disksize; - - /* write header */ - sfwrite(&dat, sizeof(dat), 1, spf); - /* write data */ - sfwrite(cmp_dbase, dat.disksize, 1, spf); - } - - free(cmp_dbase); - } else { - /* should be 0 */ - dat.disksize = dat.datasize; - sfwrite(&dat, sizeof(dat), 1, spf); + /* write data */ + sfwrite(dbase, dat.datasize, 1, spf); } spfw_next_section(spf); @@ -474,17 +475,186 @@ int main(int argc, char *argv[]) spfw_next_section(spf); } + if (hdr->flags & AMX_FLAG_DEBUG) + { + if (sections[FS_DbgFile]) + { + uint32_t idx; + sp_fdbg_file_t dbgfile; + AMX_DBG_FILE *_ptr; + uint32_t len; + for (idx=0; idxname); + /* 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; + } + spfw_next_section(spf); + } + + if (sections[FS_DbgLine]) + { + uint32_t idx; + AMX_DBG_LINE *line; + sp_fdbg_line_t dbgline; + for (idx=0; idxaddress; + dbgline.line = (uint32_t)line->line; + sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf); + /* move to next */ + dbgptr += sizeof(AMX_DBG_LINE); + } + 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; idxaddress; + 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 */ + for (dnum=0; dnumsize; + dbgdim.tagid = dim->tag; + sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf); + /* move to next */ + dbgptr += sizeof(AMX_DBG_SYMDIM); + } + } + 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 + */ + if (1) + { + memfile_t *pOrig = (memfile_t *)spf->handle; + sp_file_hdr_t *pHdr; + unsigned char *proper; + size_t size; + Bytef *zcmp; + uLong disksize; + 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)); + + size = pHdr->imagesize - pHdr->dataoffs; + proper = (unsigned char *)pOrig->base + pHdr->dataoffs; + + /* get initial size estimate */ + pHdr->disksize = (uint32_t)compressBound(pHdr->imagesize); + 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", err); + pc_printf("Falling back to no compression."); + memfile_write(bin_file, + proper, + size); + } else { + pHdr->disksize = (uint32_t)disksize; + pHdr->compression = SPFILE_COMPRESSION_GZ; + memfile_write(bin_file, + (unsigned char *)zcmp, + pHdr->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); - bin_file = NULL; + memfile_destroy(dbgtab); return 1; } diff --git a/sourcepawn/compiler/sp_file.c b/sourcepawn/compiler/sp_file.c index 21f2980e..a83d290d 100644 --- a/sourcepawn/compiler/sp_file.c +++ b/sourcepawn/compiler/sp_file.c @@ -2,22 +2,23 @@ #include #include #include "sp_file.h" +#include "memfile.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); +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 = { - fp_open, - fp_close, - fp_write, - fp_read, - fp_getpos, - fp_setpos + mf_open, + mf_close, + mf_write, + mf_read, + mf_getpos, + mf_setpos }; sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs) @@ -46,6 +47,9 @@ sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs) 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; @@ -113,6 +117,7 @@ int spfw_finalize_header(sp_file_t *spf) 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; @@ -178,6 +183,7 @@ int spfw_finalize_all(sp_file_t *spf) } 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); @@ -186,6 +192,53 @@ int spfw_finalize_all(sp_file_t *spf) 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; +} + + +#if UNUSED_FOR_NOW /** * Default file operations... * Based on C standard library calls. @@ -220,5 +273,4 @@ int fp_setpos(void *handle, size_t pos) { return fseek((FILE *)handle, (long)pos, SEEK_SET); } - - +#endif diff --git a/sourcepawn/compiler/sp_file.h b/sourcepawn/compiler/sp_file.h index 41ff70a9..f2d39786 100644 --- a/sourcepawn/compiler/sp_file.h +++ b/sourcepawn/compiler/sp_file.h @@ -74,6 +74,7 @@ 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); diff --git a/sourcepawn/compiler/sp_file_headers.h b/sourcepawn/compiler/sp_file_headers.h index bb60aee8..b83fff38 100644 --- a/sourcepawn/compiler/sp_file_headers.h +++ b/sourcepawn/compiler/sp_file_headers.h @@ -29,6 +29,9 @@ #pragma pack(1) /* structures must be packed (byte-aligned) */ #endif +#define SPFILE_COMPRESSION_NONE 0 +#define SPFILE_COMPRESSION_GZ 1 + typedef struct sp_file_section_s { uint32_t nameoffs; /* rel offset into global string table */ @@ -36,13 +39,21 @@ typedef struct sp_file_section_s uint32_t size; } sp_file_section_t; +/** + * 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; - uint16_t version; - uint32_t imagesize; - uint8_t sections; - uint32_t stringtab; + 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; typedef enum @@ -59,21 +70,14 @@ typedef struct sp_file_code_s 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 */ - uint8_t compression; /* compression */ uint32_t code; /* rel offset to code */ } sp_file_code_t; -#define SPFILE_COMPRESSION_NONE 0 -#define SPFILE_COMPRESSION_GZ 1 - /* 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; @@ -103,6 +107,44 @@ typedef struct sp_file_pubvars_s #pragma pack(pop) /* reset previous packing */ #endif +/** + * Debug information structures + */ +typedef struct sp_fdbg_file_s +{ + uint32_t addr; /* address into code */ + uint32_t name; /* offset into debug nametable */ +} sp_fdbg_file_t; + +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 +#define SP_SYM_REFARRAY 4 /* an array passed by reference (i.e. a pointer) */ +#define SP_SYM_FUNCTION 9 + +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; + +typedef struct sp_fdbg_arraydim_s +{ + int16_t tagid; /* tag id */ + uint32_t size; /* size of dimension */ +} sp_fdbg_arraydim_t; /* section is .names */ typedef char * sp_file_nametab_t;