added binary writer stuff
authorDavid Anderson <dvander@alliedmods.net>
Wed Jul 19 00:53:26 2006 +0000 (2006-07-19)
changeset 29e0b15a294a0d
parent 28 65250169626b
child 30 daf290787910
added binary writer stuff
sourcepawn/compiler/amx.h
sourcepawn/compiler/pawncc.c
sourcepawn/compiler/scmemfil.c
sourcepawn/compiler/sp_file.c
sourcepawn/compiler/sp_file.h
sourcepawn/compiler/spcomp.vcproj
     1.1 --- a/sourcepawn/compiler/amx.h	Sat Jul 15 19:23:07 2006 +0000
     1.2 +++ b/sourcepawn/compiler/amx.h	Wed Jul 19 00:53:26 2006 +0000
     1.3 @@ -206,9 +206,9 @@
     1.4  #endif
     1.5  
     1.6  #if defined __GNUC__
     1.7 -  #define PACKED        __attribute__((packed))
     1.8 +  #define PACKEDENTRY        __attribute__((packed))
     1.9  #else
    1.10 -  #define PACKED
    1.11 +  #define PACKEDENTRY
    1.12  #endif
    1.13  
    1.14  #if !defined AMX_NO_ALIGN
    1.15 @@ -226,8 +226,8 @@
    1.16  #endif
    1.17  
    1.18  typedef struct tagAMX_NATIVE_INFO {
    1.19 -  const char _FAR *name PACKED;
    1.20 -  AMX_NATIVE func       PACKED;
    1.21 +  const char _FAR *name PACKEDENTRY;
    1.22 +  AMX_NATIVE func       PACKEDENTRY;
    1.23  } AMX_NATIVE_INFO;
    1.24  
    1.25  #define AMX_USERNUM     4
    1.26 @@ -235,48 +235,48 @@
    1.27  #define sNAMEMAX        31      /* maximum name length of symbol name */
    1.28  
    1.29  typedef struct tagAMX_FUNCSTUB {
    1.30 -  ucell address         PACKED;
    1.31 -  char name[sEXPMAX+1]  PACKED;
    1.32 +  ucell address         PACKEDENTRY;
    1.33 +  char name[sEXPMAX+1]  PACKEDENTRY;
    1.34  } AMX_FUNCSTUB;
    1.35  
    1.36  typedef struct tagFUNCSTUBNT {
    1.37 -  ucell address         PACKED;
    1.38 -  uint32_t nameofs      PACKED;
    1.39 +  ucell address         PACKEDENTRY;
    1.40 +  uint32_t nameofs      PACKEDENTRY;
    1.41  } AMX_FUNCSTUBNT;
    1.42  
    1.43  /* The AMX structure is the internal structure for many functions. Not all
    1.44   * fields are valid at all times; many fields are cached in local variables.
    1.45   */
    1.46  typedef struct tagAMX {
    1.47 -  unsigned char _FAR *base PACKED; /* points to the AMX header plus the code, optionally also the data */
    1.48 -  unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */
    1.49 -  AMX_CALLBACK callback PACKED;
    1.50 -  AMX_DEBUG debug       PACKED; /* debug callback */
    1.51 +  unsigned char _FAR *base PACKEDENTRY; /* points to the AMX header plus the code, optionally also the data */
    1.52 +  unsigned char _FAR *data PACKEDENTRY; /* points to separate data+stack+heap, may be NULL */
    1.53 +  AMX_CALLBACK callback PACKEDENTRY;
    1.54 +  AMX_DEBUG debug       PACKEDENTRY; /* debug callback */
    1.55    /* for external functions a few registers must be accessible from the outside */
    1.56 -  cell cip              PACKED; /* instruction pointer: relative to base + amxhdr->cod */
    1.57 -  cell frm              PACKED; /* stack frame base: relative to base + amxhdr->dat */
    1.58 -  cell hea              PACKED; /* top of the heap: relative to base + amxhdr->dat */
    1.59 -  cell hlw              PACKED; /* bottom of the heap: relative to base + amxhdr->dat */
    1.60 -  cell stk              PACKED; /* stack pointer: relative to base + amxhdr->dat */
    1.61 -  cell stp              PACKED; /* top of the stack: relative to base + amxhdr->dat */
    1.62 -  int flags             PACKED; /* current status, see amx_Flags() */
    1.63 +  cell cip              PACKEDENTRY; /* instruction pointer: relative to base + amxhdr->cod */
    1.64 +  cell frm              PACKEDENTRY; /* stack frame base: relative to base + amxhdr->dat */
    1.65 +  cell hea              PACKEDENTRY; /* top of the heap: relative to base + amxhdr->dat */
    1.66 +  cell hlw              PACKEDENTRY; /* bottom of the heap: relative to base + amxhdr->dat */
    1.67 +  cell stk              PACKEDENTRY; /* stack pointer: relative to base + amxhdr->dat */
    1.68 +  cell stp              PACKEDENTRY; /* top of the stack: relative to base + amxhdr->dat */
    1.69 +  int flags             PACKEDENTRY; /* current status, see amx_Flags() */
    1.70    /* user data */
    1.71 -  long usertags[AMX_USERNUM] PACKED;
    1.72 -  void _FAR *userdata[AMX_USERNUM] PACKED;
    1.73 +  long usertags[AMX_USERNUM] PACKEDENTRY;
    1.74 +  void _FAR *userdata[AMX_USERNUM] PACKEDENTRY;
    1.75    /* native functions can raise an error */
    1.76 -  int error             PACKED;
    1.77 +  int error             PACKEDENTRY;
    1.78    /* passing parameters requires a "count" field */
    1.79    int paramcount;
    1.80    /* the sleep opcode needs to store the full AMX status */
    1.81 -  cell pri              PACKED;
    1.82 -  cell alt              PACKED;
    1.83 -  cell reset_stk        PACKED;
    1.84 -  cell reset_hea        PACKED;
    1.85 -  cell sysreq_d         PACKED; /* relocated address/value for the SYSREQ.D opcode */
    1.86 +  cell pri              PACKEDENTRY;
    1.87 +  cell alt              PACKEDENTRY;
    1.88 +  cell reset_stk        PACKEDENTRY;
    1.89 +  cell reset_hea        PACKEDENTRY;
    1.90 +  cell sysreq_d         PACKEDENTRY; /* relocated address/value for the SYSREQ.D opcode */
    1.91    #if defined JIT
    1.92      /* support variables for the JIT */
    1.93 -    int reloc_size      PACKED; /* required temporary buffer for relocations */
    1.94 -    long code_size      PACKED; /* estimated memory footprint of the native code */
    1.95 +    int reloc_size      PACKEDENTRY; /* required temporary buffer for relocations */
    1.96 +    long code_size      PACKEDENTRY; /* estimated memory footprint of the native code */
    1.97    #endif
    1.98  } AMX;
    1.99  
   1.100 @@ -284,23 +284,23 @@
   1.101   * structure is used internaly.
   1.102   */
   1.103  typedef struct tagAMX_HEADER {
   1.104 -  int32_t size          PACKED; /* size of the "file" */
   1.105 -  uint16_t magic        PACKED; /* signature */
   1.106 -  char    file_version  PACKED; /* file format version */
   1.107 -  char    amx_version   PACKED; /* required version of the AMX */
   1.108 -  int16_t flags         PACKED;
   1.109 -  int16_t defsize       PACKED; /* size of a definition record */
   1.110 -  int32_t cod           PACKED; /* initial value of COD - code block */
   1.111 -  int32_t dat           PACKED; /* initial value of DAT - data block */
   1.112 -  int32_t hea           PACKED; /* initial value of HEA - start of the heap */
   1.113 -  int32_t stp           PACKED; /* initial value of STP - stack top */
   1.114 -  int32_t cip           PACKED; /* initial value of CIP - the instruction pointer */
   1.115 -  int32_t publics       PACKED; /* offset to the "public functions" table */
   1.116 -  int32_t natives       PACKED; /* offset to the "native functions" table */
   1.117 -  int32_t libraries     PACKED; /* offset to the table of libraries */
   1.118 -  int32_t pubvars       PACKED; /* the "public variables" table */
   1.119 -  int32_t tags          PACKED; /* the "public tagnames" table */
   1.120 -  int32_t nametable     PACKED; /* name table */
   1.121 +  int32_t size          PACKEDENTRY; /* size of the "file" */
   1.122 +  uint16_t magic        PACKEDENTRY; /* signature */
   1.123 +  char    file_version  PACKEDENTRY; /* file format version */
   1.124 +  char    amx_version   PACKEDENTRY; /* required version of the AMX */
   1.125 +  int16_t flags         PACKEDENTRY;
   1.126 +  int16_t defsize       PACKEDENTRY; /* size of a definition record */
   1.127 +  int32_t cod           PACKEDENTRY; /* initial value of COD - code block */
   1.128 +  int32_t dat           PACKEDENTRY; /* initial value of DAT - data block */
   1.129 +  int32_t hea           PACKEDENTRY; /* initial value of HEA - start of the heap */
   1.130 +  int32_t stp           PACKEDENTRY; /* initial value of STP - stack top */
   1.131 +  int32_t cip           PACKEDENTRY; /* initial value of CIP - the instruction pointer */
   1.132 +  int32_t publics       PACKEDENTRY; /* offset to the "public functions" table */
   1.133 +  int32_t natives       PACKEDENTRY; /* offset to the "native functions" table */
   1.134 +  int32_t libraries     PACKEDENTRY; /* offset to the table of libraries */
   1.135 +  int32_t pubvars       PACKEDENTRY; /* the "public variables" table */
   1.136 +  int32_t tags          PACKEDENTRY; /* the "public tagnames" table */
   1.137 +  int32_t nametable     PACKEDENTRY; /* name table */
   1.138  } AMX_HEADER;
   1.139  
   1.140  #if PAWN_CELL_SIZE==16
     2.1 --- a/sourcepawn/compiler/pawncc.c	Sat Jul 15 19:23:07 2006 +0000
     2.2 +++ b/sourcepawn/compiler/pawncc.c	Wed Jul 19 00:53:26 2006 +0000
     2.3 @@ -8,11 +8,27 @@
     2.4  #include "osdefs.h"
     2.5  #include "zlib/zlib.h"
     2.6  
     2.7 -#define NUM_SECTIONS	6
     2.8 +enum FileSections
     2.9 +{
    2.10 +	FS_Code,			/* required */
    2.11 +	FS_Data,			/* required */
    2.12 +	FS_Publics,
    2.13 +	FS_Pubvars,
    2.14 +	FS_Natives,
    2.15 +	FS_Nametable,		/* required */
    2.16 +	FS_DbgFile,
    2.17 +	FS_DbgSymbol,
    2.18 +	FS_DbgLine,
    2.19 +	FS_DbgTags,
    2.20 +	FS_DbgAutomaton,
    2.21 +	FS_DbgState,
    2.22 +	/* --- */
    2.23 +	FS_Number,
    2.24 +};
    2.25  
    2.26  int pc_printf(const char *message,...);
    2.27  int pc_compile(int argc, char **argv);
    2.28 -void sfwrite(const void *buf, size_t size, size_t count, FILE *fp);
    2.29 +void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf);
    2.30  
    2.31  memfile_t *bin_file = NULL;
    2.32  jmp_buf brkout;
    2.33 @@ -21,17 +37,11 @@
    2.34  {
    2.35  	if (pc_compile(argc,argv) == 0)
    2.36  	{
    2.37 -		FILE *fp;
    2.38  		AMX_HEADER *hdr;
    2.39 -		sp_file_hdr_t shdr;
    2.40 -		uint32_t curoffs = 0;
    2.41 -		uint32_t lastsection = 0;
    2.42  		int err;
    2.43 -		uint8_t i8;
    2.44  		uint32_t i;
    2.45 -		const char *tables[NUM_SECTIONS] = {".code", ".data", ".publics", ".pubvars", ".natives", ".names"};
    2.46 -		uint32_t offsets[NUM_SECTIONS] = {0,0,0,0,0,0};
    2.47 -		sp_file_section_t sh;
    2.48 +		sp_file_t *spf;
    2.49 +		uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0};
    2.50  
    2.51  		if (bin_file == NULL)
    2.52  		{
    2.53 @@ -39,13 +49,12 @@
    2.54  		}
    2.55  
    2.56  		hdr = (AMX_HEADER *)bin_file->base;
    2.57 -		shdr.version = SPFILE_VERSION;
    2.58 -		shdr.magic = SPFILE_MAGIC;
    2.59  
    2.60 -		if ((fp=fopen(bin_file->name, "wb")) == NULL)
    2.61 +		if ((spf=spfw_create(bin_file->name, NULL)) == NULL)
    2.62  		{
    2.63 -			pc_printf("Error writing to file: %s", bin_file->name);
    2.64 -			return 1;
    2.65 +			pc_printf("Error creating binary file!\n");
    2.66 +			memfile_destroy(bin_file);
    2.67 +			return 0;
    2.68  		}
    2.69  
    2.70  		if ((err=setjmp(brkout))!=0)
    2.71 @@ -53,48 +62,34 @@
    2.72  			goto write_error;
    2.73  		}
    2.74  
    2.75 -		shdr.sections = NUM_SECTIONS;
    2.76 -		shdr.stringtab = sizeof(shdr) + (sizeof(sp_file_section_t) * shdr.sections);
    2.77 -
    2.78 -		/**
    2.79 -		 * write the header
    2.80 -		 * unwritten values:
    2.81 -		 *  imagesize
    2.82 -		 */
    2.83 -		sfwrite(&shdr, sizeof(shdr), 1, fp);
    2.84 -
    2.85 -		curoffs = shdr.stringtab;
    2.86 +		spfw_add_section(spf, ".code");
    2.87 +		spfw_add_section(spf, ".data");
    2.88  
    2.89 -		/**
    2.90 -		 * write the sections 
    2.91 -		 * unwritten values:
    2.92 -		 *  dataoffs
    2.93 -		 *  size
    2.94 -		 */
    2.95 -		for (i8=0; i8<shdr.sections; i8++)
    2.96 +		sections[FS_Publics] = (hdr->natives - hdr->publics) / hdr->defsize;
    2.97 +		if (sections[FS_Publics])
    2.98  		{
    2.99 -			/* set name offset to next in string table */
   2.100 -			sh.nameoffs = curoffs - shdr.stringtab;
   2.101 -			/* save offset to this section */
   2.102 -			offsets[i8] = (uint32_t)ftell(fp) + sizeof(sh.nameoffs);
   2.103 -			/* update `end of file` offset */
   2.104 -			curoffs += strlen(tables[i8]) + 1;
   2.105 -			sfwrite(&sh, sizeof(sh), 1, fp);
   2.106 +			spfw_add_section(spf, ".publics");
   2.107 +		}
   2.108 +		sections[FS_Pubvars] = (hdr->tags - hdr->pubvars) / hdr->defsize;
   2.109 +		if (sections[FS_Pubvars])
   2.110 +		{
   2.111 +			spfw_add_section(spf, ".pubvars");
   2.112 +		}
   2.113 +		sections[FS_Natives] = (hdr->libraries - hdr->natives) / hdr->defsize;
   2.114 +		if (sections[FS_Natives])
   2.115 +		{
   2.116 +			spfw_add_section(spf, ".natives");
   2.117  		}
   2.118  
   2.119 -		/** write the string table */
   2.120 -		for (i8=0; i8<shdr.sections; i8++)
   2.121 -		{
   2.122 -			sfwrite(tables[i8], 1, strlen(tables[i8])+1, fp);
   2.123 -		}
   2.124 +		spfw_add_section(spf, ".names");
   2.125  
   2.126 -		lastsection = curoffs;
   2.127 -
   2.128 +		spfw_finalize_header(spf);
   2.129 +		
   2.130  		/** 
   2.131  		 * Begin writing each of our known tables out
   2.132  		 */
   2.133  		
   2.134 -		if (strcmp(tables[0], ".code") == 0)
   2.135 +		if (sections[FS_Code])
   2.136  		{
   2.137  			sp_file_code_t cod;
   2.138  			cell cip;
   2.139 @@ -331,21 +326,14 @@
   2.140  			cod.codesize = (uint32_t)(tptr - tbase);
   2.141  			cod.disksize = cod.codesize;
   2.142  			cod.compression = SPFILE_COMPRESSION_NONE;
   2.143 -			sfwrite(&cod, sizeof(cod), 1, fp);
   2.144 -			sfwrite(tbase, cod.codesize, 1, fp);
   2.145 +			sfwrite(&cod, sizeof(cod), 1, spf);
   2.146 +			sfwrite(tbase, cod.codesize, 1, spf);
   2.147  			free(tbase);
   2.148  
   2.149 -			/* backtrack and write this section's header info */
   2.150 -			curoffs = (uint32_t)ftell(fp);
   2.151 -			fseek(fp, offsets[0], SEEK_SET);
   2.152 -			sfwrite(&lastsection, sizeof(uint32_t), 1, fp);
   2.153 -			cod.codesize += sizeof(cod);
   2.154 -			sfwrite(&cod.codesize, sizeof(uint32_t), 1, fp);
   2.155 -			fseek(fp, curoffs, SEEK_SET);
   2.156 -			lastsection = curoffs;
   2.157 +			spfw_next_section(spf);
   2.158  		}
   2.159  
   2.160 -		if (strcmp(tables[1], ".data") == 0)
   2.161 +		if (sections[FS_Data])
   2.162  		{
   2.163  			sp_file_data_t dat;
   2.164  			unsigned char *dbase;
   2.165 @@ -366,7 +354,7 @@
   2.166  				cmp_dbase = (Bytef *)malloc(dat.disksize);
   2.167  
   2.168  				/* compress */
   2.169 -				err = compress2(cmp_dbase, &disksize, (Bytef *)dbase, dat.datasize, Z_BEST_COMPRESSION);
   2.170 +				err = compress2(cmp_dbase, &disksize, (Bytef *)dbase, (uLong)dat.datasize, Z_BEST_COMPRESSION);
   2.171  
   2.172  				if (err != Z_OK)
   2.173  				{
   2.174 @@ -376,40 +364,33 @@
   2.175  					dat.disksize = dat.datasize;
   2.176  
   2.177  					/* write header */
   2.178 -					sfwrite(&dat, sizeof(dat), 1, fp);
   2.179 +					sfwrite(&dat, sizeof(dat), 1, spf);
   2.180  					/* write data */
   2.181 -					sfwrite(&dbase, dat.datasize, 1, fp);
   2.182 +					sfwrite(&dbase, dat.datasize, 1, spf);
   2.183  				} else {
   2.184  					dat.disksize = (uint32_t)disksize;
   2.185  
   2.186  					/* write header */
   2.187 -					sfwrite(&dat, sizeof(dat), 1, fp);
   2.188 +					sfwrite(&dat, sizeof(dat), 1, spf);
   2.189  					/* write data */
   2.190 -					sfwrite(&cmp_dbase, dat.disksize, 1, fp);
   2.191 +					sfwrite(cmp_dbase, dat.disksize, 1, spf);
   2.192  				}
   2.193  				
   2.194  				free(cmp_dbase);
   2.195  			} else {
   2.196  				/* should be 0 */
   2.197  				dat.disksize = dat.datasize;
   2.198 -				sfwrite(&dat, sizeof(dat), 1, fp);
   2.199 +				sfwrite(&dat, sizeof(dat), 1, spf);
   2.200  			}
   2.201  
   2.202 -			/* backtrack and write this section's header info */
   2.203 -			curoffs = ftell(fp);
   2.204 -			fseek(fp, offsets[1], SEEK_SET);
   2.205 -			sfwrite(&lastsection, sizeof(uint32_t), 1, fp);
   2.206 -			disksize += sizeof(dat);
   2.207 -			sfwrite(&disksize, sizeof(uint32_t),1, fp);
   2.208 -			fseek(fp, curoffs, SEEK_SET);
   2.209 -			lastsection = curoffs;
   2.210 +			spfw_next_section(spf);
   2.211  		}
   2.212  
   2.213 -		if (strcmp(tables[2], ".publics") == 0)
   2.214 +		if (sections[FS_Publics])
   2.215  		{
   2.216  			sp_file_publics_t *pbtbl;
   2.217  			AMX_FUNCSTUBNT *stub;
   2.218 -			uint32_t publics = (hdr->natives - hdr->publics) / hdr->defsize;
   2.219 +			uint32_t publics = sections[FS_Publics];
   2.220  
   2.221  			pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics);
   2.222  			stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->publics);
   2.223 @@ -423,25 +404,18 @@
   2.224  			}
   2.225  			if (publics)
   2.226  			{
   2.227 -				sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, fp);
   2.228 +				sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf);
   2.229  			}
   2.230  			free(pbtbl);
   2.231  
   2.232 -			/* backtrack and write section's header info */
   2.233 -			curoffs = ftell(fp);
   2.234 -			fseek(fp, offsets[2], SEEK_SET);
   2.235 -			sfwrite(&lastsection, sizeof(uint32_t), 1, fp);
   2.236 -			publics *= sizeof(sp_file_publics_t);
   2.237 -			sfwrite(&publics, sizeof(uint32_t), 1, fp);
   2.238 -			fseek(fp, curoffs, SEEK_SET);
   2.239 -			lastsection = curoffs;
   2.240 +			spfw_next_section(spf);
   2.241  		}
   2.242  
   2.243 -		if (strcmp(tables[3], ".pubvars") == 0)
   2.244 +		if (sections[FS_Pubvars])
   2.245  		{
   2.246  			sp_file_pubvars_t *pbvars;
   2.247  			AMX_FUNCSTUBNT *stub;
   2.248 -			uint32_t pubvars = (hdr->tags - hdr->pubvars) / hdr->defsize;
   2.249 +			uint32_t pubvars = sections[FS_Pubvars];
   2.250  
   2.251  			pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars);
   2.252  			stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->pubvars);
   2.253 @@ -455,21 +429,13 @@
   2.254  			}
   2.255  			if (pubvars)
   2.256  			{
   2.257 -				sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, fp);
   2.258 +				sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf);
   2.259  			}
   2.260  			free(pbvars);
   2.261 -
   2.262 -			/* backtrack and write section's header info */
   2.263 -			curoffs = ftell(fp);
   2.264 -			fseek(fp, offsets[3], SEEK_SET);
   2.265 -			sfwrite(&lastsection, sizeof(uint32_t), 1, fp);
   2.266 -			pubvars *= sizeof(sp_file_pubvars_t);
   2.267 -			sfwrite(&pubvars, sizeof(uint32_t), 1, fp);
   2.268 -			fseek(fp, curoffs, SEEK_SET);
   2.269 -			lastsection = curoffs;
   2.270 +			spfw_next_section(spf);
   2.271  		}
   2.272  
   2.273 -		if (strcmp(tables[4], ".natives") == 0)
   2.274 +		if (sections[FS_Natives])
   2.275  		{
   2.276  			sp_file_natives_t *nvtbl;
   2.277  			AMX_FUNCSTUBNT *stub;
   2.278 @@ -486,21 +452,13 @@
   2.279  			}
   2.280  			if (natives)
   2.281  			{
   2.282 -				sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, fp);
   2.283 +				sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf);
   2.284  			}
   2.285  			free(nvtbl);
   2.286 -
   2.287 -			/* backtrack and write header */
   2.288 -			curoffs = ftell(fp);
   2.289 -			fseek(fp, offsets[4], SEEK_SET);
   2.290 -			sfwrite(&lastsection, sizeof(uint32_t), 1, fp);
   2.291 -			natives *= sizeof(sp_file_natives_t);
   2.292 -			sfwrite(&natives, sizeof(uint32_t), 1, fp);
   2.293 -			fseek(fp, curoffs, SEEK_SET);
   2.294 -			lastsection = curoffs;
   2.295 +			spfw_next_section(spf);
   2.296  		}
   2.297  
   2.298 -		if (strcmp(tables[5], ".names") == 0)
   2.299 +		if (sections[FS_Nametable])
   2.300  		{
   2.301  			unsigned char *base;
   2.302  			uint32_t namelen;
   2.303 @@ -512,25 +470,18 @@
   2.304  			 * this may clip at most an extra three bytes in!
   2.305  			 */
   2.306  			namelen = hdr->cod - hdr->nametable;
   2.307 -			sfwrite(base, namelen, 1, fp);
   2.308 -
   2.309 -			/* backtrack and write header */
   2.310 -			curoffs = ftell(fp);
   2.311 -			fseek(fp, offsets[5], SEEK_SET);
   2.312 -			sfwrite(&lastsection, sizeof(uint32_t), 1, fp);
   2.313 -			sfwrite(&namelen, sizeof(uint32_t), 1, fp);
   2.314 -			fseek(fp, curoffs, SEEK_SET);
   2.315 -			lastsection = curoffs;
   2.316 +			sfwrite(base, namelen, 1, spf);
   2.317 +			spfw_next_section(spf);
   2.318  		}
   2.319  
   2.320 -		fclose(fp);
   2.321 +		spfw_finalize_all(spf);
   2.322 +		spfw_destroy(spf);
   2.323  
   2.324  		return 0;
   2.325  
   2.326  write_error:
   2.327  		pc_printf("Error writing to file: %s", bin_file->name);
   2.328  		unlink(bin_file->name);
   2.329 -		fclose(fp);
   2.330  
   2.331  		memfile_destroy(bin_file);
   2.332  		bin_file = NULL;
   2.333 @@ -541,9 +492,9 @@
   2.334  	return 1;
   2.335  }
   2.336  
   2.337 -void sfwrite(const void *buf, size_t size, size_t count, FILE *fp)
   2.338 +void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf)
   2.339  {
   2.340 -	if (fwrite(buf, size, count, fp) != count)
   2.341 +	if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count)
   2.342  	{
   2.343  		longjmp(brkout, 1);
   2.344  	}
     3.1 --- a/sourcepawn/compiler/scmemfil.c	Sat Jul 15 19:23:07 2006 +0000
     3.2 +++ b/sourcepawn/compiler/scmemfil.c	Wed Jul 19 00:53:26 2006 +0000
     3.3 @@ -31,26 +31,11 @@
     3.4  #include <string.h>
     3.5  #include "memfile.h"
     3.6  
     3.7 -#if defined FORTIFY
     3.8 -  #include <alloc/fortify.h>
     3.9 -#endif
    3.10 -
    3.11 -
    3.12 -#define BUFFERSIZE 512u
    3.13 -
    3.14 -/* For every block, except the first:
    3.15 - *   buffer points to a block that is BUFFERSIZE long that holds the data
    3.16 - *   bufpos is the "used size" of the block
    3.17 - * For the first block:
    3.18 - *   buffer points to the "file name"
    3.19 - *   bufpos is the current "file pointer"
    3.20 - */
    3.21  typedef memfile_t MEMFILE;
    3.22  #define tMEMFILE  1
    3.23  
    3.24  #include "sc.h"
    3.25  
    3.26 -
    3.27  MEMFILE *mfcreate(char *filename)
    3.28  {
    3.29    return memfile_creat(filename, 4096);
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/sourcepawn/compiler/sp_file.c	Wed Jul 19 00:53:26 2006 +0000
     4.3 @@ -0,0 +1,224 @@
     4.4 +#include <stdio.h>
     4.5 +#include <string.h>
     4.6 +#include <malloc.h>
     4.7 +#include "sp_file.h"
     4.8 +
     4.9 +void *fp_open(const char *name);
    4.10 +void fp_close(void *handle);
    4.11 +size_t fp_write(const void *buf, size_t size, size_t count, void *handle);
    4.12 +size_t fp_read(void *buf, size_t size, size_t count, void *handle);
    4.13 +size_t fp_getpos(void *handle);
    4.14 +int fp_setpos(void *handle, size_t pos);
    4.15 +
    4.16 +sp_writefuncs_t cstd_funcs = 
    4.17 +{
    4.18 +	fp_open,
    4.19 +	fp_close,
    4.20 +	fp_write,
    4.21 +	fp_read,
    4.22 +	fp_getpos,
    4.23 +	fp_setpos
    4.24 +};
    4.25 +
    4.26 +sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs)
    4.27 +{
    4.28 +	sp_file_t file;
    4.29 +	sp_file_t *pFile;
    4.30 +
    4.31 +	if (!optfuncs)
    4.32 +	{
    4.33 +		optfuncs = &cstd_funcs;
    4.34 +	}
    4.35 +
    4.36 +	file.handle = optfuncs->fnOpen(name);
    4.37 +	if (!file.handle)
    4.38 +	{
    4.39 +		return NULL;
    4.40 +	}
    4.41 +
    4.42 +	pFile = (sp_file_t *)malloc(sizeof(sp_file_t));
    4.43 +
    4.44 +	pFile->handle = file.handle;
    4.45 +	memcpy(&pFile->funcs, optfuncs, sizeof(sp_writefuncs_t));
    4.46 +	pFile->curoffs = 0;
    4.47 +	pFile->header.magic = SPFILE_MAGIC;
    4.48 +	pFile->header.sections = 0;
    4.49 +	pFile->header.stringtab = 0;
    4.50 +	pFile->header.version = SPFILE_VERSION;
    4.51 +	pFile->header.imagesize = 0;
    4.52 +	pFile->lastsection = 0;
    4.53 +	pFile->offsets = NULL;
    4.54 +	pFile->sections = NULL;
    4.55 +	pFile->state = -1;
    4.56 +	pFile->nametab = NULL;
    4.57 +	pFile->nametab_idx = 0;
    4.58 +
    4.59 +	return pFile;
    4.60 +}
    4.61 +
    4.62 +void spfw_destroy(sp_file_t *spf)
    4.63 +{
    4.64 +	free(spf->sections);
    4.65 +	free(spf->nametab);
    4.66 +	free(spf->offsets);
    4.67 +	spf->funcs.fnClose(spf->handle);
    4.68 +	free(spf);
    4.69 +}
    4.70 +
    4.71 +uint8_t spfw_add_section(sp_file_t *spf, const char *name)
    4.72 +{
    4.73 +	size_t namelen;
    4.74 +	uint8_t s;
    4.75 +	if (spf->state != -1)
    4.76 +	{
    4.77 +		return 0;
    4.78 +	}
    4.79 +
    4.80 +	namelen = strlen(name) + 1;
    4.81 +
    4.82 +	if (spf->header.sections == 0)
    4.83 +	{
    4.84 +		/** allocate for first section */
    4.85 +		spf->sections = (sp_file_section_t *)malloc(sizeof(sp_file_section_t));
    4.86 +		spf->offsets = (size_t *)malloc(sizeof(size_t));
    4.87 +		spf->nametab = (char *)malloc(namelen);
    4.88 +	} else {
    4.89 +		uint16_t num = spf->header.sections + 1;
    4.90 +		spf->sections = (sp_file_section_t *)realloc(spf->sections, sizeof(sp_file_section_t) * num);
    4.91 +		spf->offsets = (size_t *)realloc(spf->offsets, sizeof(size_t) * num);
    4.92 +		spf->nametab = (char *)realloc(spf->nametab, spf->nametab_idx + namelen);
    4.93 +	}
    4.94 +
    4.95 +	s = spf->header.sections;
    4.96 +
    4.97 +	spf->sections[s].nameoffs = spf->nametab_idx;
    4.98 +	/** 
    4.99 +	 * "fix" offset will be the second uint2 slot, which is after the previous sections after the header.
   4.100 +	 */
   4.101 +	spf->offsets[s] = sizeof(spf->header) + (sizeof(sp_file_section_t) * spf->header.sections) + sizeof(uint32_t);
   4.102 +	strcpy(&spf->nametab[spf->nametab_idx], name);
   4.103 +	spf->nametab_idx += namelen;
   4.104 +
   4.105 +	return ++spf->header.sections;
   4.106 +}
   4.107 +
   4.108 +int spfw_finalize_header(sp_file_t *spf)
   4.109 +{
   4.110 +	uint32_t size;
   4.111 +	if (spf->state != -1)
   4.112 +	{
   4.113 +		return -1;
   4.114 +	}
   4.115 +
   4.116 +	size = sizeof(sp_file_section_t) * spf->header.sections;
   4.117 +
   4.118 +	spf->header.stringtab = sizeof(spf->header) + size;
   4.119 +	if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1)
   4.120 +	{
   4.121 +		return -1;
   4.122 +	}
   4.123 +	if (spf->funcs.fnWrite(spf->sections, sizeof(sp_file_section_t), spf->header.sections, spf->handle) != 
   4.124 +		spf->header.sections)
   4.125 +	{
   4.126 +		return -1;
   4.127 +	}
   4.128 +	if (spf->funcs.fnWrite(spf->nametab, sizeof(char), spf->nametab_idx, spf->handle) != spf->nametab_idx)
   4.129 +	{
   4.130 +		return -1;
   4.131 +	}
   4.132 +	spf->curoffs = spf->funcs.fnGetPos(spf->handle);
   4.133 +	spf->lastsection = spf->curoffs;
   4.134 +	spf->state++;
   4.135 +
   4.136 +	return 0;
   4.137 +}
   4.138 +
   4.139 +int spfw_next_section(sp_file_t *spf)
   4.140 +{
   4.141 +	uint8_t s;
   4.142 +	uint32_t rest[2];
   4.143 +
   4.144 +	if (spf->state < 0 || spf->state > spf->header.sections)
   4.145 +	{
   4.146 +		return -1;
   4.147 +	}
   4.148 +
   4.149 +	if (spf->state == (int)spf->header.sections)
   4.150 +	{
   4.151 +		return 0;
   4.152 +	}
   4.153 +
   4.154 +	s = (uint8_t)spf->state;
   4.155 +
   4.156 +	spf->curoffs = spf->funcs.fnGetPos(spf->handle);
   4.157 +	spf->funcs.fnSetPos(spf->handle, spf->offsets[s]);
   4.158 +	
   4.159 +	rest[0] = spf->lastsection;
   4.160 +	rest[1] = spf->curoffs - spf->lastsection;
   4.161 +	if (spf->funcs.fnWrite(rest, sizeof(uint32_t), 2, spf->handle) != 2)
   4.162 +	{
   4.163 +		return -1;
   4.164 +	}
   4.165 +
   4.166 +	spf->funcs.fnSetPos(spf->handle, spf->curoffs);
   4.167 +	spf->lastsection = spf->curoffs;
   4.168 +
   4.169 +	spf->state++;
   4.170 +
   4.171 +	return 1;
   4.172 +}
   4.173 +
   4.174 +int spfw_finalize_all(sp_file_t *spf)
   4.175 +{
   4.176 +	uint8_t offs;
   4.177 +
   4.178 +	if (spf->state < spf->header.sections)
   4.179 +	{
   4.180 +		return -1;
   4.181 +	}
   4.182 +
   4.183 +	offs = offsetof(sp_file_hdr_t, imagesize);
   4.184 +	spf->header.imagesize = spf->funcs.fnGetPos(spf->handle);
   4.185 +	spf->funcs.fnSetPos(spf->handle, offs);
   4.186 +	spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle);
   4.187 +	spf->funcs.fnSetPos(spf->handle, spf->header.imagesize);
   4.188 +
   4.189 +	return 1;
   4.190 +}
   4.191 +
   4.192 +/**
   4.193 + * Default file operations...
   4.194 + * Based on C standard library calls.
   4.195 + */
   4.196 +
   4.197 +void *fp_open(const char *name)
   4.198 +{
   4.199 +	return fopen(name, "wb");
   4.200 +}
   4.201 +
   4.202 +void fp_close(void *handle)
   4.203 +{
   4.204 +	fclose((FILE *)handle);
   4.205 +}
   4.206 +
   4.207 +size_t fp_write(const void *buf, size_t size, size_t count, void *handle)
   4.208 +{
   4.209 +	return fwrite(buf, size, count, (FILE *)handle);
   4.210 +}
   4.211 +
   4.212 +size_t fp_read(void *buf, size_t size, size_t count, void *handle)
   4.213 +{
   4.214 +	return fread(buf, size, count, (FILE *)handle);
   4.215 +}
   4.216 +
   4.217 +size_t fp_getpos(void *handle)
   4.218 +{
   4.219 +	return (size_t)ftell((FILE *)handle);
   4.220 +}
   4.221 +
   4.222 +int fp_setpos(void *handle, size_t pos)
   4.223 +{
   4.224 +	return fseek((FILE *)handle, (long)pos, SEEK_SET);
   4.225 +}
   4.226 +
   4.227 +
     5.1 --- a/sourcepawn/compiler/sp_file.h	Sat Jul 15 19:23:07 2006 +0000
     5.2 +++ b/sourcepawn/compiler/sp_file.h	Wed Jul 19 00:53:26 2006 +0000
     5.3 @@ -1,110 +1,80 @@
     5.4  #ifndef _INCLUDE_SPFILE_H
     5.5  #define _INCLUDE_SPFILE_H
     5.6  
     5.7 -#include <stddef.h>
     5.8 -#if defined __GNUC__ || defined HAVE_STDINT_
     5.9 -#include <stdint.h>
    5.10 -#else
    5.11 - #if !defined HAVE_STDINT_H
    5.12 -	typedef unsigned __int64	uint64_t;
    5.13 -	typedef __int64				int64_t;
    5.14 -	typedef unsigned __int32	uint32_t;
    5.15 -	typedef __int32				int32_t;
    5.16 -	typedef unsigned __int16	uint16_t;
    5.17 -	typedef __int16				int16_t;
    5.18 -	typedef unsigned __int8		uint8_t;
    5.19 -	typedef __int8				int8_t;
    5.20 - #define HAVE_STDINT_H
    5.21 - #endif
    5.22 -#endif
    5.23 -
    5.24 -#define SPFILE_MAGIC	0xDEADC0D3
    5.25 -#define SPFILE_VERSION	0x0100
    5.26 +#include "sp_file_headers.h"
    5.27  
    5.28 -//:TODO: better compiler/nix support
    5.29 -#if defined __linux__
    5.30 -	#pragma pack(1)         /* structures must be packed (byte-aligned) */
    5.31 -#else
    5.32 -	#pragma pack(push)
    5.33 -	#pragma pack(1)         /* structures must be packed (byte-aligned) */
    5.34 -#endif
    5.35 -
    5.36 -typedef struct sp_file_section_s
    5.37 +/** 
    5.38 + * Used for overwriting writing routines.
    5.39 + */
    5.40 +typedef struct sp_writefuncs_s
    5.41  {
    5.42 -	uint32_t	nameoffs;	/* rel offset into global string table */
    5.43 -	uint32_t	dataoffs;
    5.44 -	uint32_t	size;
    5.45 -} sp_file_section_t;
    5.46 +	void *(*fnOpen)(const char *);	/* filename, returns handle */
    5.47 +	void (*fnClose)(void *);			/* handle */
    5.48 +	/* buffer, size, count, handle, returns count written */
    5.49 +	size_t (*fnWrite)(const void *, size_t, size_t, void *);	
    5.50 +	/* buffer, size, count, handle, returns count read */
    5.51 +	size_t (*fnRead)(void *, size_t, size_t, void *);
    5.52 +	/* returns current position from start */
    5.53 +	size_t (*fnGetPos)(void *);
    5.54 +	/* sets current position from start, return 0 for success, nonzero for error */
    5.55 +	int (*fnSetPos)(void *, size_t);
    5.56 +} sp_writefuncs_t;
    5.57  
    5.58 -typedef struct sp_file_hdr_s
    5.59 -{
    5.60 -	uint32_t	magic;
    5.61 -	uint16_t	version;
    5.62 -	uint32_t	imagesize;
    5.63 -	uint8_t		sections;
    5.64 -	uint32_t	stringtab;
    5.65 -} sp_file_hdr_t;
    5.66 -
    5.67 -typedef enum
    5.68 -{
    5.69 -	SP_FILE_NONE = 0,
    5.70 -	SP_FILE_DEBUG = 1,
    5.71 -} sp_file_flags_t;
    5.72 -
    5.73 -/* section is ".code" */
    5.74 -typedef struct sp_file_code_s
    5.75 +typedef struct sp_file_s
    5.76  {
    5.77 -	uint32_t	codesize;		/* codesize in bytes */
    5.78 -	uint8_t		cellsize;		/* cellsize in bytes */
    5.79 -	uint8_t		codeversion;	/* version of opcodes supported */
    5.80 -	uint16_t	flags;			/* flags */
    5.81 -	uint32_t	main;			/* address to "main" if any */
    5.82 -	uint32_t	disksize;		/* disksize in bytes */
    5.83 -	uint32_t	compression;	/* compression */
    5.84 -	uint32_t	code;			/* rel offset to code */
    5.85 -} sp_file_code_t;
    5.86 +	sp_file_hdr_t header;
    5.87 +	sp_file_section_t *sections;
    5.88 +	size_t *offsets;
    5.89 +	sp_writefuncs_t funcs;
    5.90 +	size_t lastsection;
    5.91 +	size_t curoffs;
    5.92 +	void *handle;
    5.93 +	int state;
    5.94 +	char *nametab;
    5.95 +	size_t nametab_idx;
    5.96 +} sp_file_t;
    5.97  
    5.98 -#define SPFILE_COMPRESSION_NONE		0
    5.99 -#define SPFILE_COMPRESSION_GZ		1
   5.100 +/**
   5.101 + * Creates a new SourcePawn binary file.  
   5.102 + * You may optionally specify alternative writing functions.
   5.103 + */
   5.104 +sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs);
   5.105  
   5.106 -/* section is .data */
   5.107 -typedef struct sp_file_data_s
   5.108 -{
   5.109 -	uint32_t	datasize;		/* size of data section in memory */
   5.110 -	uint32_t	memsize;		/* total mem required (includes data) */
   5.111 -	uint32_t	disksize;		/* size of data on disk (compressed) */
   5.112 -	uint8_t		compression;	/* compression */
   5.113 -	uint32_t	data;			/* file offset to data (helper) */
   5.114 -} sp_file_data_t;
   5.115 +/**
   5.116 + * Closes file handle and frees memory.
   5.117 + */
   5.118 +void spfw_destroy(sp_file_t *spf);
   5.119  
   5.120 -/* section is .publics */
   5.121 -typedef struct sp_file_publics_s
   5.122 -{
   5.123 -	uint32_t	address;		/* address rel to code section */
   5.124 -	uint32_t	name;			/* index into nametable */
   5.125 -} sp_file_publics_t;
   5.126 +/**
   5.127 + * Adds a section name to the header. 
   5.128 + * Only valid BEFORE finalization.
   5.129 + * Returns the number of sections, or 0 on failure.
   5.130 + */
   5.131 +uint8_t spfw_add_section(sp_file_t *spf, const char *name);
   5.132  
   5.133 -/* section is .natives */
   5.134 -typedef struct sp_file_natives_s
   5.135 -{
   5.136 -	uint32_t	name;			/* name of native at index */
   5.137 -} sp_file_natives_t;
   5.138 +/**
   5.139 + * Finalizes the section header.
   5.140 + * This means no more sections can be added after this call.
   5.141 + * Also, aligns the writer to the first section.
   5.142 + * Returns 0 on success, nonzero on error.
   5.143 + */
   5.144 +int spfw_finalize_header(sp_file_t *spf);
   5.145  
   5.146 -/* section is .pubvars */
   5.147 -typedef struct sp_file_pubvars_s
   5.148 -{
   5.149 -	uint32_t	address;		/* address rel to dat section */
   5.150 -	uint32_t	name;			/* index into nametable */
   5.151 -} sp_file_pubvars_t;
   5.152 +/**
   5.153 + * Finalizes the current section and advances to the next.
   5.154 + * In order for this to be accurate, the file pointer must
   5.155 + *  reside at the end before calling this, because the size
   5.156 + *  is calculated by differencing with the last known offset.
   5.157 + * Returns 1 if there are more sections left, 0 otherwise.
   5.158 + * Returns -1 if the file state is wrong.
   5.159 + */
   5.160 +int spfw_next_section(sp_file_t *spf);
   5.161  
   5.162 -#if defined __linux__
   5.163 -	#pragma pack()    /* reset default packing */
   5.164 -#else
   5.165 -	#pragma pack(pop) /* reset previous packing */
   5.166 -#endif
   5.167 -
   5.168 -
   5.169 -/* section is .names */
   5.170 -typedef char * sp_file_nametab_t;
   5.171 +/**
   5.172 + * Finalizes all sections.
   5.173 + * Cannot be called until all sections are used.
   5.174 + * Must be called with the file pointer at the end.
   5.175 + */
   5.176 +int spfw_finalize_all(sp_file_t *spf);
   5.177  
   5.178  #endif //_INCLUDE_SPFILE_H
     6.1 --- a/sourcepawn/compiler/spcomp.vcproj	Sat Jul 15 19:23:07 2006 +0000
     6.2 +++ b/sourcepawn/compiler/spcomp.vcproj	Wed Jul 19 00:53:26 2006 +0000
     6.3 @@ -250,6 +250,10 @@
     6.4  				RelativePath=".\scvars.c"
     6.5  				>
     6.6  			</File>
     6.7 +			<File
     6.8 +				RelativePath=".\sp_file.c"
     6.9 +				>
    6.10 +			</File>
    6.11  		</Filter>
    6.12  		<Filter
    6.13  			Name="Header Files"
    6.14 @@ -261,6 +265,10 @@
    6.15  				>
    6.16  			</File>
    6.17  			<File
    6.18 +				RelativePath=".\amxdbg.h"
    6.19 +				>
    6.20 +			</File>
    6.21 +			<File
    6.22  				RelativePath=".\lstring.h"
    6.23  				>
    6.24  			</File>
    6.25 @@ -281,6 +289,10 @@
    6.26  				>
    6.27  			</File>
    6.28  			<File
    6.29 +				RelativePath=".\sp_file_headers.h"
    6.30 +				>
    6.31 +			</File>
    6.32 +			<File
    6.33  				RelativePath=".\svnrev.h"
    6.34  				>
    6.35  			</File>