sourcepawn/compiler/pawncc.c
author David Anderson <dvander@alliedmods.net>
Wed Feb 25 20:07:12 2009 -0500 (2009-02-25)
changeset 2607 f3b8bbe17f85
parent 2326 73d538a35c26
child 2783 5f333027ef04
permissions -rw-r--r--
Backed out changeset fa286305bd3f
     1 #include <stdio.h>
     2 #include <setjmp.h>
     3 #include <assert.h>
     4 #include <string.h>
     5 #include "memfile.h"
     6 #include "sp_file.h"
     7 #include "amx.h"
     8 #include "amxdbg.h"
     9 #include "osdefs.h"
    10 #include "zlib/zlib.h"
    11 
    12 enum FileSections
    13 {
    14 	FS_Code,			/* required */
    15 	FS_Data,			/* required */
    16 	FS_Publics,
    17 	FS_Pubvars,
    18 	FS_Natives,
    19 	FS_Nametable,		/* required */
    20 	FS_DbgFile,
    21 	FS_DbgSymbol,
    22 	FS_DbgLine,
    23 	FS_DbgTags,
    24 	FS_DbgNatives,
    25 	FS_DbgAutomaton,
    26 	FS_DbgState,
    27 	FS_DbgStrings,
    28 	FS_DbgInfo,
    29 	FS_Tags,
    30 	/* --- */
    31 	FS_Number,
    32 };
    33 
    34 int pc_printf(const char *message,...);
    35 int pc_compile(int argc, char **argv);
    36 void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf);
    37 
    38 memfile_t *bin_file = NULL;
    39 jmp_buf brkout;
    40 
    41 #define sARGS_MAX		32	/* number of arguments a function can have, max */
    42 #define sDIMEN_MAX     4    /* maximum number of array dimensions */
    43 
    44 typedef struct t_arg_s
    45 {
    46 	uint8_t ident;
    47 	int16_t tag;
    48 	char *name;
    49 	uint16_t dimcount;
    50 	sp_fdbg_arraydim_t dims[sDIMEN_MAX];
    51 } t_arg;
    52 
    53 typedef struct t_native_s
    54 {
    55 	char *name;
    56 	int16_t ret_tag;
    57 	uint16_t num_args;
    58 	t_arg args[sARGS_MAX];
    59 } t_native;
    60 
    61 t_native *native_list = NULL;
    62 
    63 int main(int argc, char *argv[])
    64 {
    65 #if defined _DEBUG
    66 	getchar();
    67 #endif
    68 	if (pc_compile(argc,argv) == 0)
    69 	{
    70 		AMX_HEADER *hdr;
    71 		AMX_DBG_HDR *dbg = NULL;
    72 		int err;
    73 		uint32_t i;
    74 		sp_file_t *spf;
    75 		memfile_t *dbgtab = NULL;		//dbgcrab
    76 		unsigned char *dbgptr = NULL;
    77 		uint32_t sections[FS_Number] = {1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0};
    78 		FILE *fp;
    79 
    80 		if (bin_file == NULL)
    81 		{
    82 			return 0;
    83 		}
    84 
    85 		hdr = (AMX_HEADER *)bin_file->base;
    86 
    87 		if ((spf=spfw_create(bin_file->name, NULL)) == NULL)
    88 		{
    89 			pc_printf("Error creating binary file!\n");
    90 			memfile_destroy(bin_file);
    91 			return 0;
    92 		}
    93 
    94 		if ((err=setjmp(brkout))!=0)
    95 		{
    96 			goto write_error;
    97 		}
    98 
    99 		spfw_add_section(spf, ".code");
   100 		spfw_add_section(spf, ".data");
   101 
   102 		sections[FS_Publics] = (hdr->natives - hdr->publics) / hdr->defsize;
   103 		if (sections[FS_Publics])
   104 		{
   105 			spfw_add_section(spf, ".publics");
   106 		}
   107 		sections[FS_Pubvars] = (hdr->tags - hdr->pubvars) / hdr->defsize;
   108 		if (sections[FS_Pubvars])
   109 		{
   110 			spfw_add_section(spf, ".pubvars");
   111 		}
   112 		sections[FS_Natives] = (hdr->libraries - hdr->natives) / hdr->defsize;
   113 		if (sections[FS_Natives])
   114 		{
   115 			spfw_add_section(spf, ".natives");
   116 		}
   117 		sections[FS_Tags] = (hdr->nametable - hdr->tags) / hdr->defsize;
   118 		if (sections[FS_Tags])
   119 		{
   120 			spfw_add_section(spf, ".tags");
   121 		}
   122 
   123 		spfw_add_section(spf, ".names");
   124 
   125 		if (hdr->flags & AMX_FLAG_DEBUG)
   126 		{
   127 			dbg = (AMX_DBG_HDR *)((unsigned char *)hdr + hdr->size);
   128 			if (dbg->magic != AMX_DBG_MAGIC)
   129 			{
   130 				pc_printf("Error reading AMX_DBG_HDR, debug data will not be written.");
   131 			} else {
   132 				dbgtab = memfile_creat("", 512);
   133 				dbgptr = (unsigned char *)dbg + sizeof(AMX_DBG_HDR);
   134 				if ((sections[FS_DbgNatives] = sections[FS_Natives]) > 0)
   135 				{
   136 					spfw_add_section(spf, ".dbg.natives");
   137 				}
   138 				if (dbg->files)
   139 				{
   140 					spfw_add_section(spf, ".dbg.files");
   141 					sections[FS_DbgFile] = dbg->files;
   142 				}
   143 				if (dbg->lines)
   144 				{
   145 					spfw_add_section(spf, ".dbg.lines");
   146 					sections[FS_DbgLine] = dbg->lines;
   147 				}
   148 				if (dbg->symbols)
   149 				{
   150 					spfw_add_section(spf, ".dbg.symbols");
   151 					sections[FS_DbgSymbol] = dbg->symbols;
   152 				}
   153 				sections[FS_DbgInfo] = 1;
   154 				sections[FS_DbgStrings] = 1;
   155 				spfw_add_section(spf, ".dbg.info");
   156 				spfw_add_section(spf, ".dbg.strings");
   157 			}
   158 		}
   159 
   160 		spfw_finalize_header(spf);
   161 		
   162 		/** 
   163 		 * Begin writing each of our known tables out
   164 		 */
   165 		
   166 		if (sections[FS_Code])
   167 		{
   168 			sp_file_code_t cod;
   169 			unsigned char *cbase;
   170 
   171 			cod.cellsize = sizeof(cell);
   172 
   173 			cod.codesize = hdr->dat - hdr->cod;
   174 			cod.codeversion = hdr->amx_version;
   175 			cod.flags = 0;
   176 			if (hdr->flags & AMX_FLAG_DEBUG)
   177 			{
   178 				cod.flags |= SP_FLAG_DEBUG;
   179 			}
   180 			cod.code = sizeof(cod);
   181 			cod.main = hdr->cip;
   182 
   183 			/* write the code */
   184 			cbase = (unsigned char *)hdr + hdr->cod;
   185 			sfwrite(&cod, sizeof(cod), 1, spf);
   186 			sfwrite(cbase, cod.codesize, 1, spf);
   187 
   188 			spfw_next_section(spf);
   189 		}
   190 
   191 		if (sections[FS_Data])
   192 		{
   193 			sp_file_data_t dat;
   194 			unsigned char *dbase = (unsigned char *)hdr + hdr->dat;
   195 
   196 			dat.datasize = hdr->hea - hdr->dat;
   197 			dat.memsize = hdr->stp;
   198 			dat.data = sizeof(dat);
   199 
   200 			/* write header */
   201 			sfwrite(&dat, sizeof(dat), 1, spf);
   202 
   203 			if (dat.datasize)
   204 			{
   205 				/* write data */
   206 				sfwrite(dbase, dat.datasize, 1, spf);
   207 			}
   208 
   209 			spfw_next_section(spf);
   210 		}
   211 
   212 		if (sections[FS_Publics])
   213 		{
   214 			sp_file_publics_t *pbtbl;
   215 			AMX_FUNCSTUBNT *stub;
   216 			unsigned char *stubptr;
   217 			uint32_t publics = sections[FS_Publics];
   218 
   219 			pbtbl = (sp_file_publics_t *)malloc(sizeof(sp_file_publics_t) * publics);
   220 			stubptr = (unsigned char *)hdr + hdr->publics;
   221 
   222 			for (i=0; i<publics; i++)
   223 			{
   224 				stub = (AMX_FUNCSTUBNT *)stubptr;
   225 				pbtbl[i].address = stub->address;
   226 				pbtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
   227 
   228 				stubptr += hdr->defsize;
   229 			}
   230 			if (publics)
   231 			{
   232 				sfwrite(pbtbl, sizeof(sp_file_publics_t), publics, spf);
   233 			}
   234 			free(pbtbl);
   235 
   236 			spfw_next_section(spf);
   237 		}
   238 
   239 		if (sections[FS_Pubvars])
   240 		{
   241 			sp_file_pubvars_t *pbvars;
   242 			AMX_FUNCSTUBNT *stub;
   243 			unsigned char *stubptr;
   244 			uint32_t pubvars = sections[FS_Pubvars];
   245 
   246 			pbvars = (sp_file_pubvars_t *)malloc(sizeof(sp_file_pubvars_t) * pubvars);
   247 			stubptr = (unsigned char *)hdr + hdr->pubvars;
   248 
   249 			for (i=0; i<pubvars; i++)
   250 			{
   251 				stub = (AMX_FUNCSTUBNT *)stubptr;
   252 				pbvars[i].address = stub->address;
   253 				pbvars[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
   254 
   255 				stubptr += hdr->defsize;
   256 			}
   257 			if (pubvars)
   258 			{
   259 				sfwrite(pbvars, sizeof(sp_file_pubvars_t), pubvars, spf);
   260 			}
   261 			free(pbvars);
   262 			spfw_next_section(spf);
   263 		}
   264 
   265 		if (sections[FS_Natives])
   266 		{
   267 			sp_file_natives_t *nvtbl;
   268 			AMX_FUNCSTUBNT *stub;
   269 			unsigned char *stubptr;
   270 			uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
   271 
   272 			nvtbl = (sp_file_natives_t *)malloc(sizeof(sp_file_natives_t) * natives);
   273 			stubptr = (unsigned char *)hdr + hdr->natives;
   274 
   275 			for (i=0; i<natives; i++)
   276 			{
   277 				stub = (AMX_FUNCSTUBNT *)stubptr;
   278 				nvtbl[i].name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
   279 
   280 				stubptr += hdr->defsize;
   281 			}
   282 			if (natives)
   283 			{
   284 				sfwrite(nvtbl, sizeof(sp_file_natives_t), natives, spf);
   285 			}
   286 			free(nvtbl);
   287 			spfw_next_section(spf);
   288 		}
   289 
   290 		if (sections[FS_Tags])
   291 		{
   292 			uint32_t numTags = (uint32_t)sections[FS_Tags];
   293 			AMX_FUNCSTUBNT *stub;
   294 			sp_file_tag_t tag;
   295 
   296 			for (i=0; i<numTags; i++)
   297 			{
   298 				stub = (AMX_FUNCSTUBNT *)((unsigned char *)hdr + hdr->tags + (i * hdr->defsize));
   299 				tag.tag_id = stub->address;
   300 				tag.name = stub->nameofs - (hdr->nametable + sizeof(uint16_t));
   301 				sfwrite(&tag, sizeof(sp_file_tag_t), 1, spf);
   302 			}
   303 			spfw_next_section(spf);
   304 		}
   305 
   306 		if (sections[FS_Nametable])
   307 		{
   308 			unsigned char *base;
   309 			uint32_t namelen;
   310 
   311 			/* write the entire block */
   312 			base = (unsigned char *)hdr + hdr->nametable + sizeof(uint16_t);
   313 			/**
   314 			 * note - the name table will be padded to sizeof(cell) bytes.
   315 			 * this may clip at most an extra three bytes in!
   316 			 */
   317 			namelen = hdr->cod - hdr->nametable;
   318 			sfwrite(base, namelen, 1, spf);
   319 			spfw_next_section(spf);
   320 		}
   321 
   322 		if (hdr->flags & AMX_FLAG_DEBUG)
   323 		{
   324 			sp_fdbg_info_t info;
   325 
   326 			memset(&info, 0, sizeof(sp_fdbg_info_t));
   327 
   328 			if (sections[FS_Natives])
   329 			{
   330 				uint16_t j;
   331 				uint32_t idx;
   332 				uint32_t name;
   333 				uint32_t natives = (hdr->libraries - hdr->natives) / hdr->defsize;
   334 
   335 				sfwrite(&natives, sizeof(uint32_t), 1, spf);
   336 				for (idx=0; idx<natives; idx++)
   337 				{
   338 					sfwrite(&idx, sizeof(uint32_t), 1, spf);
   339 					name = (uint32_t)memfile_tell(dbgtab);
   340 					memfile_write(dbgtab, native_list[idx].name, strlen(native_list[idx].name) + 1);
   341 					sfwrite(&name, sizeof(uint32_t), 1, spf);
   342 					sfwrite(&native_list[idx].ret_tag, sizeof(int16_t), 1, spf);
   343 					sfwrite(&native_list[idx].num_args, sizeof(uint16_t), 1, spf);
   344 
   345 					/* Go through arguments */
   346 					for (j = 0; j < native_list[idx].num_args; j++)
   347 					{
   348 						sfwrite(&native_list[idx].args[j].ident, sizeof(uint8_t), 1, spf);
   349 						sfwrite(&native_list[idx].args[j].tag, sizeof(int16_t), 1, spf);
   350 						sfwrite(&native_list[idx].args[j].dimcount, sizeof(uint16_t), 1, spf);
   351 						name = (uint32_t)memfile_tell(dbgtab);
   352 						sfwrite(&name, sizeof(uint32_t), 1, spf);
   353 						memfile_write(dbgtab, 
   354 							native_list[idx].args[j].name, 
   355 							strlen(native_list[idx].args[j].name) + 1);
   356 						if (native_list[idx].args[j].dimcount)
   357 						{
   358 							sfwrite(native_list[idx].args[j].dims,
   359 								sizeof(sp_fdbg_arraydim_t),
   360 								native_list[idx].args[j].dimcount,
   361 								spf);
   362 						}
   363 						free(native_list[idx].args[j].name);
   364 					}
   365 					free(native_list[idx].name);
   366 				}
   367 				free(native_list);
   368 				spfw_next_section(spf);
   369 			}
   370 
   371 			if (sections[FS_DbgFile])
   372 			{
   373 				uint32_t idx;
   374 				sp_fdbg_file_t dbgfile;
   375 				AMX_DBG_FILE *_ptr;
   376 				uint32_t len;
   377 				for (idx=0; idx<sections[FS_DbgFile]; idx++)
   378 				{
   379 					/* get entry info */
   380 					_ptr = (AMX_DBG_FILE *)dbgptr;
   381 					len = strlen(_ptr->name);
   382 					/* store */
   383 					dbgfile.addr = _ptr->address;
   384 					dbgfile.name = (uint32_t)memfile_tell(dbgtab);
   385 					sfwrite(&dbgfile, sizeof(sp_fdbg_file_t), 1, spf);
   386 					/* write to tab, then move to next */
   387 					memfile_write(dbgtab, _ptr->name, len + 1);
   388 					dbgptr += sizeof(AMX_DBG_FILE) + len;
   389 					info.num_files++;
   390 				}
   391 				spfw_next_section(spf);
   392 			}
   393 
   394 			if (sections[FS_DbgLine])
   395 			{
   396 				uint32_t idx;
   397 				AMX_DBG_LINE *line;
   398 				sp_fdbg_line_t dbgline;
   399 				for (idx=0; idx<sections[FS_DbgLine]; idx++)
   400 				{
   401 					/* get entry info */
   402 					line = (AMX_DBG_LINE *)dbgptr;
   403 					/* store */
   404 					dbgline.addr = (uint32_t)line->address;
   405 					dbgline.line = (uint32_t)line->line;
   406 					sfwrite(&dbgline, sizeof(sp_fdbg_line_t), 1, spf);
   407 					/* move to next */
   408 					dbgptr += sizeof(AMX_DBG_LINE);
   409 					info.num_lines++;
   410 				}
   411 				spfw_next_section(spf);
   412 			}
   413 
   414 			if (sections[FS_DbgSymbol])
   415 			{
   416 				uint32_t idx;
   417 				uint32_t dnum;
   418 				AMX_DBG_SYMBOL *sym;
   419 				AMX_DBG_SYMDIM *dim;
   420 				sp_fdbg_symbol_t dbgsym;
   421 				sp_fdbg_arraydim_t dbgdim;
   422 				uint32_t len;
   423 
   424 				for (idx=0; idx<sections[FS_DbgSymbol]; idx++)
   425 				{
   426 					/* get entry info */
   427 					sym = (AMX_DBG_SYMBOL *)dbgptr;
   428 					/* store */
   429 					dbgsym.addr = *(int32_t *)&sym->address;
   430 					dbgsym.tagid = sym->tag;
   431 					dbgsym.codestart = (uint32_t)sym->codestart;
   432 					dbgsym.codeend = (uint32_t)sym->codeend;
   433 					dbgsym.dimcount = (uint16_t)sym->dim;
   434 					dbgsym.vclass = (uint8_t)sym->vclass;
   435 					dbgsym.ident = (uint8_t)sym->ident;
   436 					dbgsym.name = (uint32_t)memfile_tell(dbgtab);
   437 					sfwrite(&dbgsym, sizeof(sp_fdbg_symbol_t), 1, spf);
   438 					/* write to tab */
   439 					len = strlen(sym->name);
   440 					memfile_write(dbgtab, sym->name, len + 1);
   441 					/* move to next */
   442 					dbgptr += sizeof(AMX_DBG_SYMBOL) + len;
   443 					/* look for any dimensions */
   444 					info.num_syms++;
   445 					for (dnum=0; dnum<dbgsym.dimcount; dnum++)
   446 					{
   447 						/* get entry info */
   448 						dim = (AMX_DBG_SYMDIM *)dbgptr;
   449 						/* store */
   450 						dbgdim.size = (uint32_t)dim->size;
   451 						dbgdim.tagid = dim->tag;
   452 						sfwrite(&dbgdim, sizeof(sp_fdbg_arraydim_t), 1, spf);
   453 						/* move to next */
   454 						dbgptr += sizeof(AMX_DBG_SYMDIM);
   455 						info.num_arrays++;
   456 					}
   457 				}
   458 				spfw_next_section(spf);
   459 			}
   460 
   461 			sfwrite(&info, sizeof(sp_fdbg_info_t), 1, spf);
   462 			spfw_next_section(spf);
   463 
   464 			if (sections[FS_DbgStrings])
   465 			{
   466 				sfwrite(dbgtab->base, sizeof(char), dbgtab->usedoffs, spf);
   467 				spfw_next_section(spf);
   468 			}
   469 		}
   470 
   471 		spfw_finalize_all(spf);
   472 
   473 		/** 
   474 		 * do compression
   475 		 * new block for scoping only
   476 		 */
   477 		{
   478 			memfile_t *pOrig = (memfile_t *)spf->handle;
   479 			sp_file_hdr_t *pHdr;
   480 			unsigned char *proper;
   481 			size_t size;
   482 			Bytef *zcmp;
   483 			uLong disksize;
   484 			size_t header_size;
   485 			int err = Z_OK;
   486 
   487 			/* reuse this memory block! */
   488 			memfile_reset(bin_file);
   489 
   490 			/* copy tip of header */
   491 			memfile_write(bin_file, pOrig->base, sizeof(sp_file_hdr_t));
   492 
   493 			/* get pointer to header */
   494 			pHdr = (sp_file_hdr_t *)bin_file->base;
   495 
   496 			/* copy the rest of the header */
   497 			memfile_write(bin_file, 
   498 							(unsigned char *)pOrig->base + sizeof(sp_file_hdr_t),
   499 							pHdr->dataoffs - sizeof(sp_file_hdr_t));
   500 
   501 			header_size = pHdr->dataoffs;
   502 			size = pHdr->imagesize - header_size;
   503 			proper = (unsigned char *)pOrig->base + header_size;
   504 
   505 			/* get initial size estimate */
   506 			disksize = compressBound(pHdr->imagesize);
   507 			pHdr->disksize = (uint32_t)disksize;
   508 			zcmp = (Bytef *)malloc(pHdr->disksize);
   509 
   510 			if ((err=compress2(zcmp, 
   511 					&disksize, 
   512 					(Bytef *)proper,
   513 					(uLong)size,
   514 					Z_BEST_COMPRESSION))
   515 				!= Z_OK)
   516 			{
   517 				free(zcmp);
   518 				pc_printf("Unable to compress (Z): error %d\n", err);
   519 				pc_printf("Falling back to no compression.");
   520 				memfile_write(bin_file, 
   521 							proper,
   522 							size);
   523 			} else {
   524 				pHdr->disksize = (uint32_t)disksize + header_size;
   525 				pHdr->compression = SPFILE_COMPRESSION_GZ;
   526 				memfile_write(bin_file,
   527 							(unsigned char *)zcmp,
   528 							disksize);
   529 				free(zcmp);
   530 			}
   531 		}
   532 
   533 		spfw_destroy(spf);
   534 		memfile_destroy(dbgtab);
   535 
   536 		/** 
   537 		 * write file 
   538 		 */
   539 		if ((fp=fopen(bin_file->name, "wb")) != NULL)
   540 		{
   541 			fwrite(bin_file->base, bin_file->usedoffs, 1, fp);
   542 			fclose(fp);
   543 		} else {
   544 			pc_printf("Unable to open %s for writing!", bin_file->name);
   545 		}
   546 
   547 		memfile_destroy(bin_file);
   548 
   549 		return 0;
   550 
   551 write_error:
   552 		pc_printf("Error writing to file: %s", bin_file->name);
   553 		
   554 		spfw_destroy(spf);
   555 		unlink(bin_file->name);
   556 		memfile_destroy(bin_file);
   557 		memfile_destroy(dbgtab);
   558 
   559 		return 1;
   560 	}
   561 
   562 	return 1;
   563 }
   564 
   565 void sfwrite(const void *buf, size_t size, size_t count, sp_file_t *spf)
   566 {
   567 	if (spf->funcs.fnWrite(buf, size, count, spf->handle) != count)
   568 	{
   569 		longjmp(brkout, 1);
   570 	}
   571 }
   572 
   573 void sp_fdbg_ntv_start(int num_natives)
   574 {
   575 	if (num_natives == 0)
   576 	{
   577 		return;
   578 	}
   579 
   580 	native_list = (t_native *)malloc(sizeof(t_native) * num_natives);
   581 	memset(native_list, 0, sizeof(t_native) * num_natives);
   582 }
   583 
   584 #include "sc.h"
   585 
   586 void sp_fdbg_ntv_hook(int index, symbol *sym)
   587 {
   588 	int i, j;
   589 	t_native *native;
   590 
   591 	native = &native_list[index];
   592 	native->name = strdup(sym->name);
   593 	
   594 	for (i = 0; i < sMAXARGS; i++)
   595 	{
   596 		if (sym->dim.arglist[i].ident == 0)
   597 		{
   598 			break;
   599 		}
   600 		native->num_args++;
   601 		native->args[i].tag = sym->dim.arglist[i].tags == NULL ? 0 : sym->dim.arglist[i].tags[0];
   602 		native->args[i].name = strdup(sym->dim.arglist[i].name);
   603 		native->args[i].ident = sym->dim.arglist[i].ident;
   604 		native->args[i].dimcount = sym->dim.arglist[i].numdim;
   605 		for (j = 0; j < native->args[i].dimcount; j++)
   606 		{
   607 			native->args[i].dims[j].size = sym->dim.arglist[i].dim[j];
   608 			native->args[i].dims[j].tagid = sym->dim.arglist[i].idxtag[j];
   609 		}
   610 	}
   611 
   612 	native->ret_tag = sym->tag;
   613 }