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