added binary writer stuff

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4033
This commit is contained in:
David Anderson 2006-07-19 00:53:26 +00:00
parent b712d61b47
commit 66f7568ce7
6 changed files with 419 additions and 277 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View 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);
}

View File

@ -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

View File

@ -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"
>