added binary writer stuff
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4033
This commit is contained in:
parent
b712d61b47
commit
66f7568ce7
@ -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
|
||||
|
@ -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; i8<shdr.sections; i8++)
|
||||
sections[FS_Publics] = (hdr->natives - 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; i8<shdr.sections; i8++)
|
||||
{
|
||||
sfwrite(tables[i8], 1, strlen(tables[i8])+1, fp);
|
||||
}
|
||||
|
||||
lastsection = curoffs;
|
||||
spfw_add_section(spf, ".names");
|
||||
|
||||
spfw_finalize_header(spf);
|
||||
|
||||
/**
|
||||
* Begin writing each of our known tables out
|
||||
*/
|
||||
|
||||
if (strcmp(tables[0], ".code") == 0)
|
||||
if (sections[FS_Code])
|
||||
{
|
||||
sp_file_code_t cod;
|
||||
cell cip;
|
||||
@ -331,21 +326,14 @@ 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, fp);
|
||||
sfwrite(tbase, cod.codesize, 1, fp);
|
||||
sfwrite(&cod, sizeof(cod), 1, spf);
|
||||
sfwrite(tbase, cod.codesize, 1, spf);
|
||||
free(tbase);
|
||||
|
||||
/* backtrack and write this section's header info */
|
||||
curoffs = (uint32_t)ftell(fp);
|
||||
fseek(fp, offsets[0], SEEK_SET);
|
||||
sfwrite(&lastsection, sizeof(uint32_t), 1, fp);
|
||||
cod.codesize += sizeof(cod);
|
||||
sfwrite(&cod.codesize, sizeof(uint32_t), 1, fp);
|
||||
fseek(fp, curoffs, SEEK_SET);
|
||||
lastsection = curoffs;
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (strcmp(tables[1], ".data") == 0)
|
||||
if (sections[FS_Data])
|
||||
{
|
||||
sp_file_data_t dat;
|
||||
unsigned char *dbase;
|
||||
@ -366,7 +354,7 @@ int main(int argc, char *argv[])
|
||||
cmp_dbase = (Bytef *)malloc(dat.disksize);
|
||||
|
||||
/* compress */
|
||||
err = compress2(cmp_dbase, &disksize, (Bytef *)dbase, dat.datasize, Z_BEST_COMPRESSION);
|
||||
err = compress2(cmp_dbase, &disksize, (Bytef *)dbase, (uLong)dat.datasize, Z_BEST_COMPRESSION);
|
||||
|
||||
if (err != Z_OK)
|
||||
{
|
||||
@ -376,40 +364,33 @@ int main(int argc, char *argv[])
|
||||
dat.disksize = dat.datasize;
|
||||
|
||||
/* write header */
|
||||
sfwrite(&dat, sizeof(dat), 1, fp);
|
||||
sfwrite(&dat, sizeof(dat), 1, spf);
|
||||
/* write data */
|
||||
sfwrite(&dbase, dat.datasize, 1, fp);
|
||||
sfwrite(&dbase, dat.datasize, 1, spf);
|
||||
} else {
|
||||
dat.disksize = (uint32_t)disksize;
|
||||
|
||||
/* write header */
|
||||
sfwrite(&dat, sizeof(dat), 1, fp);
|
||||
sfwrite(&dat, sizeof(dat), 1, spf);
|
||||
/* write data */
|
||||
sfwrite(&cmp_dbase, dat.disksize, 1, fp);
|
||||
sfwrite(cmp_dbase, dat.disksize, 1, spf);
|
||||
}
|
||||
|
||||
free(cmp_dbase);
|
||||
} else {
|
||||
/* should be 0 */
|
||||
dat.disksize = dat.datasize;
|
||||
sfwrite(&dat, sizeof(dat), 1, fp);
|
||||
sfwrite(&dat, sizeof(dat), 1, spf);
|
||||
}
|
||||
|
||||
/* backtrack and write this section's header info */
|
||||
curoffs = ftell(fp);
|
||||
fseek(fp, offsets[1], SEEK_SET);
|
||||
sfwrite(&lastsection, sizeof(uint32_t), 1, fp);
|
||||
disksize += sizeof(dat);
|
||||
sfwrite(&disksize, sizeof(uint32_t),1, fp);
|
||||
fseek(fp, curoffs, SEEK_SET);
|
||||
lastsection = curoffs;
|
||||
spfw_next_section(spf);
|
||||
}
|
||||
|
||||
if (strcmp(tables[2], ".publics") == 0)
|
||||
if (sections[FS_Publics])
|
||||
{
|
||||
sp_file_publics_t *pbtbl;
|
||||
AMX_FUNCSTUBNT *stub;
|
||||
uint32_t publics = (hdr->natives - 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);
|
||||
}
|
||||
|
@ -31,26 +31,11 @@
|
||||
#include <string.h>
|
||||
#include "memfile.h"
|
||||
|
||||
#if defined FORTIFY
|
||||
#include <alloc/fortify.h>
|
||||
#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);
|
||||
|
224
sourcepawn/compiler/sp_file.c
Normal file
224
sourcepawn/compiler/sp_file.c
Normal file
@ -0,0 +1,224 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
@ -1,110 +1,80 @@
|
||||
#ifndef _INCLUDE_SPFILE_H
|
||||
#define _INCLUDE_SPFILE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#if defined __GNUC__ || defined HAVE_STDINT_
|
||||
#include <stdint.h>
|
||||
#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
|
||||
|
@ -250,6 +250,10 @@
|
||||
RelativePath=".\scvars.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sp_file.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
@ -260,6 +264,10 @@
|
||||
RelativePath=".\amx.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\amxdbg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\lstring.h"
|
||||
>
|
||||
@ -280,6 +288,10 @@
|
||||
RelativePath=".\sp_file.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sp_file_headers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\svnrev.h"
|
||||
>
|
||||
|
Loading…
Reference in New Issue
Block a user