1.1 --- a/compiler-init/sc6.c Sat Jul 15 05:02:38 2006 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1298 +0,0 @@
1.4 -/* Pawn compiler - Binary code generation (the "assembler")
1.5 - *
1.6 - * Copyright (c) ITB CompuPhase, 1997-2006
1.7 - *
1.8 - * This software is provided "as-is", without any express or implied warranty.
1.9 - * In no event will the authors be held liable for any damages arising from
1.10 - * the use of this software.
1.11 - *
1.12 - * Permission is granted to anyone to use this software for any purpose,
1.13 - * including commercial applications, and to alter it and redistribute it
1.14 - * freely, subject to the following restrictions:
1.15 - *
1.16 - * 1. The origin of this software must not be misrepresented; you must not
1.17 - * claim that you wrote the original software. If you use this software in
1.18 - * a product, an acknowledgment in the product documentation would be
1.19 - * appreciated but is not required.
1.20 - * 2. Altered source versions must be plainly marked as such, and must not be
1.21 - * misrepresented as being the original software.
1.22 - * 3. This notice may not be removed or altered from any source distribution.
1.23 - *
1.24 - * Version: $Id: sc6.c 3579 2006-06-06 13:35:29Z thiadmer $
1.25 - */
1.26 -#include <assert.h>
1.27 -#include <stdio.h>
1.28 -#include <stdlib.h> /* for macro max() */
1.29 -#include <stddef.h> /* for macro offsetof() */
1.30 -#include <string.h>
1.31 -#include <ctype.h>
1.32 -#if defined FORTIFY
1.33 - #include <alloc/fortify.h>
1.34 -#endif
1.35 -#include "lstring.h"
1.36 -#include "sc.h"
1.37 -#include "amxdbg.h"
1.38 -#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
1.39 - #include <sclinux.h>
1.40 -#endif
1.41 -
1.42 -
1.43 -static void append_dbginfo(FILE *fout);
1.44 -
1.45 -
1.46 -typedef cell (*OPCODE_PROC)(FILE *fbin,char *params,cell opcode);
1.47 -
1.48 -typedef struct {
1.49 - cell opcode;
1.50 - char *name;
1.51 - int segment; /* sIN_CSEG=parse in cseg, sIN_DSEG=parse in dseg */
1.52 - OPCODE_PROC func;
1.53 -} OPCODEC;
1.54 -
1.55 -static cell codeindex; /* similar to "code_idx" */
1.56 -static cell *lbltab; /* label table */
1.57 -static int writeerror;
1.58 -static int bytes_in, bytes_out;
1.59 -static jmp_buf compact_err;
1.60 -
1.61 -/* apparently, strtol() does not work correctly on very large (unsigned)
1.62 - * hexadecimal values */
1.63 -static ucell hex2long(const char *s,char **n)
1.64 -{
1.65 - ucell result=0L;
1.66 - int negate=FALSE;
1.67 - int digit;
1.68 -
1.69 - /* ignore leading whitespace */
1.70 - while (*s==' ' || *s=='\t')
1.71 - s++;
1.72 -
1.73 - /* allow a negation sign to create the two's complement of numbers */
1.74 - if (*s=='-') {
1.75 - negate=TRUE;
1.76 - s++;
1.77 - } /* if */
1.78 -
1.79 - assert((*s>='0' && *s<='9') || (*s>='a' && *s<='f') || (*s>='a' && *s<='f'));
1.80 - for ( ;; ) {
1.81 - if (*s>='0' && *s<='9')
1.82 - digit=*s-'0';
1.83 - else if (*s>='a' && *s<='f')
1.84 - digit=*s-'a' + 10;
1.85 - else if (*s>='A' && *s<='F')
1.86 - digit=*s-'A' + 10;
1.87 - else
1.88 - break; /* probably whitespace */
1.89 - result=(result<<4) | digit;
1.90 - s++;
1.91 - } /* for */
1.92 - if (n!=NULL)
1.93 - *n=(char*)s;
1.94 - if (negate)
1.95 - result=(~result)+1; /* take two's complement of the result */
1.96 - return (ucell)result;
1.97 -}
1.98 -
1.99 -static ucell getparam(const char *s,char **n)
1.100 -{
1.101 - ucell result=0;
1.102 - for ( ;; ) {
1.103 - result+=hex2long(s,(char**)&s);
1.104 - if (*s!='+')
1.105 - break;
1.106 - s++;
1.107 - } /* for */
1.108 - if (n!=NULL)
1.109 - *n=(char*)s;
1.110 - return result;
1.111 -}
1.112 -
1.113 -#if BYTE_ORDER==BIG_ENDIAN
1.114 -static uint16_t *align16(uint16_t *v)
1.115 -{
1.116 - unsigned char *s = (unsigned char *)v;
1.117 - unsigned char t;
1.118 -
1.119 - /* swap two bytes */
1.120 - t=s[0];
1.121 - s[0]=s[1];
1.122 - s[1]=t;
1.123 - return v;
1.124 -}
1.125 -
1.126 -static uint32_t *align32(uint32_t *v)
1.127 -{
1.128 - unsigned char *s = (unsigned char *)v;
1.129 - unsigned char t;
1.130 -
1.131 - /* swap outer two bytes */
1.132 - t=s[0];
1.133 - s[0]=s[3];
1.134 - s[3]=t;
1.135 - /* swap inner two bytes */
1.136 - t=s[1];
1.137 - s[1]=s[2];
1.138 - s[2]=t;
1.139 - return v;
1.140 -}
1.141 -
1.142 -#if PAWN_CELL_SIZE>=64
1.143 -static uint64_t *align64(uint64_t *v)
1.144 -{
1.145 - unsigned char *s = (unsigned char *)v;
1.146 - unsigned char t;
1.147 -
1.148 - t=s[0];
1.149 - s[0]=s[7];
1.150 - s[7]=t;
1.151 -
1.152 - t=s[1];
1.153 - s[1]=s[6];
1.154 - s[6]=t;
1.155 -
1.156 - t=s[2];
1.157 - s[2]=s[5];
1.158 - s[5]=t;
1.159 -
1.160 - t=s[3];
1.161 - s[3]=s[4];
1.162 - s[4]=t;
1.163 -
1.164 - return v;
1.165 -}
1.166 -#endif
1.167 -
1.168 - #if PAWN_CELL_SIZE==16
1.169 - #define aligncell(v) align16(v)
1.170 - #elif PAWN_CELL_SIZE==32
1.171 - #define aligncell(v) align32(v)
1.172 - #elif PAWN_CELL_SIZE==64
1.173 - #define aligncell(v) align64(v)
1.174 - #endif
1.175 -#else
1.176 - #define align16(v) (v)
1.177 - #define align32(v) (v)
1.178 - #define aligncell(v) (v)
1.179 -#endif
1.180 -
1.181 -static char *skipwhitespace(char *str)
1.182 -{
1.183 - while (isspace(*str))
1.184 - str++;
1.185 - return str;
1.186 -}
1.187 -
1.188 -static char *stripcomment(char *str)
1.189 -{
1.190 - char *ptr=strchr(str,';');
1.191 - if (ptr!=NULL) {
1.192 - *ptr++='\n'; /* terminate the line, but leave the '\n' */
1.193 - *ptr='\0';
1.194 - } /* if */
1.195 - return str;
1.196 -}
1.197 -
1.198 -static void write_encoded(FILE *fbin,ucell *c,int num)
1.199 -{
1.200 - #if PAWN_CELL_SIZE == 16
1.201 - #define ENC_MAX 3 /* a 16-bit cell is encoded in max. 3 bytes */
1.202 - #define ENC_MASK 0x03 /* after 2x7 bits, 2 bits remain to make 16 bits */
1.203 - #elif PAWN_CELL_SIZE == 32
1.204 - #define ENC_MAX 5 /* a 32-bit cell is encoded in max. 5 bytes */
1.205 - #define ENC_MASK 0x0f /* after 4x7 bits, 4 bits remain to make 32 bits */
1.206 - #elif PAWN_CELL_SIZE == 64
1.207 - #define ENC_MAX 10 /* a 32-bit cell is encoded in max. 10 bytes */
1.208 - #define ENC_MASK 0x01 /* after 9x7 bits, 1 bit remains to make 64 bits */
1.209 - #endif
1.210 -
1.211 - assert(fbin!=NULL);
1.212 - while (num-->0) {
1.213 - if (sc_compress) {
1.214 - ucell p=(ucell)*c;
1.215 - unsigned char t[ENC_MAX];
1.216 - unsigned char code;
1.217 - int index;
1.218 - for (index=0; index<ENC_MAX; index++) {
1.219 - t[index]=(unsigned char)(p & 0x7f); /* store 7 bits */
1.220 - p>>=7;
1.221 - } /* for */
1.222 - /* skip leading zeros */
1.223 - while (index>1 && t[index-1]==0 && (t[index-2] & 0x40)==0)
1.224 - index--;
1.225 - /* skip leading -1s */
1.226 - if (index==ENC_MAX && t[index-1]==ENC_MASK && (t[index-2] & 0x40)!=0)
1.227 - index--;
1.228 - while (index>1 && t[index-1]==0x7f && (t[index-2] & 0x40)!=0)
1.229 - index--;
1.230 - /* write high byte first, write continuation bits */
1.231 - assert(index>0);
1.232 - while (index-->0) {
1.233 - code=(unsigned char)((index==0) ? t[index] : (t[index]|0x80));
1.234 - writeerror |= !pc_writebin(fbin,&code,1);
1.235 - bytes_out++;
1.236 - } /* while */
1.237 - bytes_in+=sizeof *c;
1.238 - assert(AMX_COMPACTMARGIN>2);
1.239 - if (bytes_out-bytes_in>=AMX_COMPACTMARGIN-2)
1.240 - longjmp(compact_err,1);
1.241 - } else {
1.242 - assert((pc_lengthbin(fbin) % sizeof(cell)) == 0);
1.243 - writeerror |= !pc_writebin(fbin,aligncell(c),sizeof *c);
1.244 - } /* if */
1.245 - c++;
1.246 - } /* while */
1.247 -}
1.248 -
1.249 -#if defined __BORLANDC__ || defined __WATCOMC__
1.250 - #pragma argsused
1.251 -#endif
1.252 -static cell noop(FILE *fbin,char *params,cell opcode)
1.253 -{
1.254 - return 0;
1.255 -}
1.256 -
1.257 -#if defined __BORLANDC__ || defined __WATCOMC__
1.258 - #pragma argsused
1.259 -#endif
1.260 -static cell set_currentfile(FILE *fbin,char *params,cell opcode)
1.261 -{
1.262 - fcurrent=(short)getparam(params,NULL);
1.263 - return 0;
1.264 -}
1.265 -
1.266 -#if defined __BORLANDC__ || defined __WATCOMC__
1.267 - #pragma argsused
1.268 -#endif
1.269 -static cell parm0(FILE *fbin,char *params,cell opcode)
1.270 -{
1.271 - if (fbin!=NULL)
1.272 - write_encoded(fbin,(ucell*)&opcode,1);
1.273 - return opcodes(1);
1.274 -}
1.275 -
1.276 -static cell parm1(FILE *fbin,char *params,cell opcode)
1.277 -{
1.278 - ucell p=getparam(params,NULL);
1.279 - if (fbin!=NULL) {
1.280 - write_encoded(fbin,(ucell*)&opcode,1);
1.281 - write_encoded(fbin,&p,1);
1.282 - } /* if */
1.283 - return opcodes(1)+opargs(1);
1.284 -}
1.285 -
1.286 -static cell parm2(FILE *fbin,char *params,cell opcode)
1.287 -{
1.288 - ucell p1=getparam(params,¶ms);
1.289 - ucell p2=getparam(params,NULL);
1.290 - if (fbin!=NULL) {
1.291 - write_encoded(fbin,(ucell*)&opcode,1);
1.292 - write_encoded(fbin,&p1,1);
1.293 - write_encoded(fbin,&p2,1);
1.294 - } /* if */
1.295 - return opcodes(1)+opargs(2);
1.296 -}
1.297 -
1.298 -static cell parm3(FILE *fbin,char *params,cell opcode)
1.299 -{
1.300 - ucell p1=getparam(params,¶ms);
1.301 - ucell p2=getparam(params,¶ms);
1.302 - ucell p3=getparam(params,NULL);
1.303 - if (fbin!=NULL) {
1.304 - write_encoded(fbin,(ucell*)&opcode,1);
1.305 - write_encoded(fbin,&p1,1);
1.306 - write_encoded(fbin,&p2,1);
1.307 - write_encoded(fbin,&p3,1);
1.308 - } /* if */
1.309 - return opcodes(1)+opargs(3);
1.310 -}
1.311 -
1.312 -static cell parm4(FILE *fbin,char *params,cell opcode)
1.313 -{
1.314 - ucell p1=getparam(params,¶ms);
1.315 - ucell p2=getparam(params,¶ms);
1.316 - ucell p3=getparam(params,¶ms);
1.317 - ucell p4=getparam(params,NULL);
1.318 - if (fbin!=NULL) {
1.319 - write_encoded(fbin,(ucell*)&opcode,1);
1.320 - write_encoded(fbin,&p1,1);
1.321 - write_encoded(fbin,&p2,1);
1.322 - write_encoded(fbin,&p3,1);
1.323 - write_encoded(fbin,&p4,1);
1.324 - } /* if */
1.325 - return opcodes(1)+opargs(4);
1.326 -}
1.327 -
1.328 -static cell parm5(FILE *fbin,char *params,cell opcode)
1.329 -{
1.330 - ucell p1=getparam(params,¶ms);
1.331 - ucell p2=getparam(params,¶ms);
1.332 - ucell p3=getparam(params,¶ms);
1.333 - ucell p4=getparam(params,¶ms);
1.334 - ucell p5=getparam(params,NULL);
1.335 - if (fbin!=NULL) {
1.336 - write_encoded(fbin,(ucell*)&opcode,1);
1.337 - write_encoded(fbin,&p1,1);
1.338 - write_encoded(fbin,&p2,1);
1.339 - write_encoded(fbin,&p3,1);
1.340 - write_encoded(fbin,&p4,1);
1.341 - write_encoded(fbin,&p5,1);
1.342 - } /* if */
1.343 - return opcodes(1)+opargs(5);
1.344 -}
1.345 -
1.346 -#if defined __BORLANDC__ || defined __WATCOMC__
1.347 - #pragma argsused
1.348 -#endif
1.349 -static cell do_dump(FILE *fbin,char *params,cell opcode)
1.350 -{
1.351 - ucell p;
1.352 - int num = 0;
1.353 -
1.354 - while (*params!='\0') {
1.355 - p=getparam(params,¶ms);
1.356 - if (fbin!=NULL)
1.357 - write_encoded(fbin,&p,1);
1.358 - num++;
1.359 - while (isspace(*params))
1.360 - params++;
1.361 - } /* while */
1.362 - return num*sizeof(cell);
1.363 -}
1.364 -
1.365 -static cell do_call(FILE *fbin,char *params,cell opcode)
1.366 -{
1.367 - char name[sNAMEMAX+1];
1.368 - int i;
1.369 - symbol *sym;
1.370 - ucell p;
1.371 -
1.372 - for (i=0; !isspace(*params); i++,params++) {
1.373 - assert(*params!='\0');
1.374 - assert(i<sNAMEMAX);
1.375 - name[i]=*params;
1.376 - } /* for */
1.377 - name[i]='\0';
1.378 -
1.379 - if (name[0]=='l' && name[1]=='.') {
1.380 - /* this is a label, not a function symbol */
1.381 - i=(int)hex2long(name+2,NULL);
1.382 - assert(i>=0 && i<sc_labnum);
1.383 - if (fbin!=NULL) {
1.384 - assert(lbltab!=NULL);
1.385 - p=lbltab[i];
1.386 - } /* if */
1.387 - } else {
1.388 - /* look up the function address; note that the correct file number must
1.389 - * already have been set (in order for static globals to be found).
1.390 - */
1.391 - sym=findglb(name,sGLOBAL);
1.392 - assert(sym!=NULL);
1.393 - assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC);
1.394 - assert(sym->vclass==sGLOBAL);
1.395 - p=sym->addr;
1.396 - } /* if */
1.397 -
1.398 - if (fbin!=NULL) {
1.399 - write_encoded(fbin,(ucell*)&opcode,1);
1.400 - write_encoded(fbin,&p,1);
1.401 - } /* if */
1.402 - return opcodes(1)+opargs(1);
1.403 -}
1.404 -
1.405 -static cell do_jump(FILE *fbin,char *params,cell opcode)
1.406 -{
1.407 - int i;
1.408 - ucell p;
1.409 -
1.410 - i=(int)hex2long(params,NULL);
1.411 - assert(i>=0 && i<sc_labnum);
1.412 -
1.413 - if (fbin!=NULL) {
1.414 - assert(lbltab!=NULL);
1.415 - p=lbltab[i];
1.416 - write_encoded(fbin,(ucell*)&opcode,1);
1.417 - write_encoded(fbin,&p,1);
1.418 - } /* if */
1.419 - return opcodes(1)+opargs(1);
1.420 -}
1.421 -
1.422 -static cell do_switch(FILE *fbin,char *params,cell opcode)
1.423 -{
1.424 - int i;
1.425 - ucell p;
1.426 -
1.427 - i=(int)hex2long(params,NULL);
1.428 - assert(i>=0 && i<sc_labnum);
1.429 -
1.430 - if (fbin!=NULL) {
1.431 - assert(lbltab!=NULL);
1.432 - p=lbltab[i];
1.433 - write_encoded(fbin,(ucell*)&opcode,1);
1.434 - write_encoded(fbin,&p,1);
1.435 - } /* if */
1.436 - return opcodes(1)+opargs(1);
1.437 -}
1.438 -
1.439 -#if defined __BORLANDC__ || defined __WATCOMC__
1.440 - #pragma argsused
1.441 -#endif
1.442 -static cell do_case(FILE *fbin,char *params,cell opcode)
1.443 -{
1.444 - int i;
1.445 - ucell p,v;
1.446 -
1.447 - v=hex2long(params,¶ms);
1.448 - i=(int)hex2long(params,NULL);
1.449 - assert(i>=0 && i<sc_labnum);
1.450 -
1.451 - if (fbin!=NULL) {
1.452 - assert(lbltab!=NULL);
1.453 - p=lbltab[i];
1.454 - write_encoded(fbin,&v,1);
1.455 - write_encoded(fbin,&p,1);
1.456 - } /* if */
1.457 - return opcodes(0)+opargs(2);
1.458 -}
1.459 -
1.460 -static OPCODEC opcodelist[] = {
1.461 - /* node for "invalid instruction" */
1.462 - { 0, NULL, 0, noop },
1.463 - /* opcodes in sorted order */
1.464 - { 78, "add", sIN_CSEG, parm0 },
1.465 - { 87, "add.c", sIN_CSEG, parm1 },
1.466 - { 14, "addr.alt", sIN_CSEG, parm1 },
1.467 - { 13, "addr.pri", sIN_CSEG, parm1 },
1.468 - { 30, "align.alt", sIN_CSEG, parm1 },
1.469 - { 29, "align.pri", sIN_CSEG, parm1 },
1.470 - { 81, "and", sIN_CSEG, parm0 },
1.471 - {121, "bounds", sIN_CSEG, parm1 },
1.472 - {137, "break", sIN_CSEG, parm0 }, /* version 8 */
1.473 - { 49, "call", sIN_CSEG, do_call },
1.474 - { 50, "call.pri", sIN_CSEG, parm0 },
1.475 - { 0, "case", sIN_CSEG, do_case },
1.476 - {130, "casetbl", sIN_CSEG, parm0 }, /* version 1 */
1.477 - {118, "cmps", sIN_CSEG, parm1 },
1.478 - { 0, "code", sIN_CSEG, set_currentfile },
1.479 - {156, "const", sIN_CSEG, parm2 }, /* version 9 */
1.480 - { 12, "const.alt", sIN_CSEG, parm1 },
1.481 - { 11, "const.pri", sIN_CSEG, parm1 },
1.482 - {157, "const.s", sIN_CSEG, parm2 }, /* version 9 */
1.483 - { 0, "data", sIN_DSEG, set_currentfile },
1.484 - {114, "dec", sIN_CSEG, parm1 },
1.485 - {113, "dec.alt", sIN_CSEG, parm0 },
1.486 - {116, "dec.i", sIN_CSEG, parm0 },
1.487 - {112, "dec.pri", sIN_CSEG, parm0 },
1.488 - {115, "dec.s", sIN_CSEG, parm1 },
1.489 - { 0, "dump", sIN_DSEG, do_dump },
1.490 - { 95, "eq", sIN_CSEG, parm0 },
1.491 - {106, "eq.c.alt", sIN_CSEG, parm1 },
1.492 - {105, "eq.c.pri", sIN_CSEG, parm1 },
1.493 -/*{124, "file", sIN_CSEG, do_file }, */
1.494 - {119, "fill", sIN_CSEG, parm1 },
1.495 - {100, "geq", sIN_CSEG, parm0 },
1.496 - { 99, "grtr", sIN_CSEG, parm0 },
1.497 - {120, "halt", sIN_CSEG, parm1 },
1.498 - { 45, "heap", sIN_CSEG, parm1 },
1.499 - { 27, "idxaddr", sIN_CSEG, parm0 },
1.500 - { 28, "idxaddr.b", sIN_CSEG, parm1 },
1.501 - {109, "inc", sIN_CSEG, parm1 },
1.502 - {108, "inc.alt", sIN_CSEG, parm0 },
1.503 - {111, "inc.i", sIN_CSEG, parm0 },
1.504 - {107, "inc.pri", sIN_CSEG, parm0 },
1.505 - {110, "inc.s", sIN_CSEG, parm1 },
1.506 - { 86, "invert", sIN_CSEG, parm0 },
1.507 - { 55, "jeq", sIN_CSEG, do_jump },
1.508 - { 60, "jgeq", sIN_CSEG, do_jump },
1.509 - { 59, "jgrtr", sIN_CSEG, do_jump },
1.510 - { 58, "jleq", sIN_CSEG, do_jump },
1.511 - { 57, "jless", sIN_CSEG, do_jump },
1.512 - { 56, "jneq", sIN_CSEG, do_jump },
1.513 - { 54, "jnz", sIN_CSEG, do_jump },
1.514 - { 52, "jrel", sIN_CSEG, parm1 }, /* always a number */
1.515 - { 64, "jsgeq", sIN_CSEG, do_jump },
1.516 - { 63, "jsgrtr", sIN_CSEG, do_jump },
1.517 - { 62, "jsleq", sIN_CSEG, do_jump },
1.518 - { 61, "jsless", sIN_CSEG, do_jump },
1.519 - { 51, "jump", sIN_CSEG, do_jump },
1.520 - {128, "jump.pri", sIN_CSEG, parm0 }, /* version 1 */
1.521 - { 53, "jzer", sIN_CSEG, do_jump },
1.522 - { 31, "lctrl", sIN_CSEG, parm1 },
1.523 - { 98, "leq", sIN_CSEG, parm0 },
1.524 - { 97, "less", sIN_CSEG, parm0 },
1.525 - { 25, "lidx", sIN_CSEG, parm0 },
1.526 - { 26, "lidx.b", sIN_CSEG, parm1 },
1.527 -/*{125, "line", sIN_CSEG, parm2 }, */
1.528 - { 2, "load.alt", sIN_CSEG, parm1 },
1.529 - {154, "load.both", sIN_CSEG, parm2 }, /* version 9 */
1.530 - { 9, "load.i", sIN_CSEG, parm0 },
1.531 - { 1, "load.pri", sIN_CSEG, parm1 },
1.532 - { 4, "load.s.alt", sIN_CSEG, parm1 },
1.533 - {155, "load.s.both",sIN_CSEG, parm2 }, /* version 9 */
1.534 - { 3, "load.s.pri", sIN_CSEG, parm1 },
1.535 - { 10, "lodb.i", sIN_CSEG, parm1 },
1.536 - { 6, "lref.alt", sIN_CSEG, parm1 },
1.537 - { 5, "lref.pri", sIN_CSEG, parm1 },
1.538 - { 8, "lref.s.alt", sIN_CSEG, parm1 },
1.539 - { 7, "lref.s.pri", sIN_CSEG, parm1 },
1.540 - { 34, "move.alt", sIN_CSEG, parm0 },
1.541 - { 33, "move.pri", sIN_CSEG, parm0 },
1.542 - {117, "movs", sIN_CSEG, parm1 },
1.543 - { 85, "neg", sIN_CSEG, parm0 },
1.544 - { 96, "neq", sIN_CSEG, parm0 },
1.545 - {134, "nop", sIN_CSEG, parm0 }, /* version 6 */
1.546 - { 84, "not", sIN_CSEG, parm0 },
1.547 - { 82, "or", sIN_CSEG, parm0 },
1.548 - { 43, "pop.alt", sIN_CSEG, parm0 },
1.549 - { 42, "pop.pri", sIN_CSEG, parm0 },
1.550 - { 46, "proc", sIN_CSEG, parm0 },
1.551 - { 40, "push", sIN_CSEG, parm1 },
1.552 - {133, "push.adr", sIN_CSEG, parm1 }, /* version 4 */
1.553 - { 37, "push.alt", sIN_CSEG, parm0 },
1.554 - { 39, "push.c", sIN_CSEG, parm1 },
1.555 - { 36, "push.pri", sIN_CSEG, parm0 },
1.556 - { 38, "push.r", sIN_CSEG, parm1 }, /* obsolete (never generated) */
1.557 - { 41, "push.s", sIN_CSEG, parm1 },
1.558 - {139, "push2", sIN_CSEG, parm2 }, /* version 9 */
1.559 - {141, "push2.adr", sIN_CSEG, parm2 }, /* version 9 */
1.560 - {138, "push2.c", sIN_CSEG, parm2 }, /* version 9 */
1.561 - {140, "push2.s", sIN_CSEG, parm2 }, /* version 9 */
1.562 - {143, "push3", sIN_CSEG, parm3 }, /* version 9 */
1.563 - {145, "push3.adr", sIN_CSEG, parm3 }, /* version 9 */
1.564 - {142, "push3.c", sIN_CSEG, parm3 }, /* version 9 */
1.565 - {144, "push3.s", sIN_CSEG, parm3 }, /* version 9 */
1.566 - {147, "push4", sIN_CSEG, parm4 }, /* version 9 */
1.567 - {149, "push4.adr", sIN_CSEG, parm4 }, /* version 9 */
1.568 - {146, "push4.c", sIN_CSEG, parm4 }, /* version 9 */
1.569 - {148, "push4.s", sIN_CSEG, parm4 }, /* version 9 */
1.570 - {151, "push5", sIN_CSEG, parm5 }, /* version 9 */
1.571 - {153, "push5.adr", sIN_CSEG, parm5 }, /* version 9 */
1.572 - {150, "push5.c", sIN_CSEG, parm5 }, /* version 9 */
1.573 - {152, "push5.s", sIN_CSEG, parm5 }, /* version 9 */
1.574 - { 47, "ret", sIN_CSEG, parm0 },
1.575 - { 48, "retn", sIN_CSEG, parm0 },
1.576 - { 32, "sctrl", sIN_CSEG, parm1 },
1.577 - { 73, "sdiv", sIN_CSEG, parm0 },
1.578 - { 74, "sdiv.alt", sIN_CSEG, parm0 },
1.579 - {104, "sgeq", sIN_CSEG, parm0 },
1.580 - {103, "sgrtr", sIN_CSEG, parm0 },
1.581 - { 65, "shl", sIN_CSEG, parm0 },
1.582 - { 69, "shl.c.alt", sIN_CSEG, parm1 },
1.583 - { 68, "shl.c.pri", sIN_CSEG, parm1 },
1.584 - { 66, "shr", sIN_CSEG, parm0 },
1.585 - { 71, "shr.c.alt", sIN_CSEG, parm1 },
1.586 - { 70, "shr.c.pri", sIN_CSEG, parm1 },
1.587 - { 94, "sign.alt", sIN_CSEG, parm0 },
1.588 - { 93, "sign.pri", sIN_CSEG, parm0 },
1.589 - {102, "sleq", sIN_CSEG, parm0 },
1.590 - {101, "sless", sIN_CSEG, parm0 },
1.591 - { 72, "smul", sIN_CSEG, parm0 },
1.592 - { 88, "smul.c", sIN_CSEG, parm1 },
1.593 -/*{127, "srange", sIN_CSEG, parm2 }, -- version 1 */
1.594 - { 20, "sref.alt", sIN_CSEG, parm1 },
1.595 - { 19, "sref.pri", sIN_CSEG, parm1 },
1.596 - { 22, "sref.s.alt", sIN_CSEG, parm1 },
1.597 - { 21, "sref.s.pri", sIN_CSEG, parm1 },
1.598 - { 67, "sshr", sIN_CSEG, parm0 },
1.599 - { 44, "stack", sIN_CSEG, parm1 },
1.600 - { 0, "stksize", 0, noop },
1.601 - { 16, "stor.alt", sIN_CSEG, parm1 },
1.602 - { 23, "stor.i", sIN_CSEG, parm0 },
1.603 - { 15, "stor.pri", sIN_CSEG, parm1 },
1.604 - { 18, "stor.s.alt", sIN_CSEG, parm1 },
1.605 - { 17, "stor.s.pri", sIN_CSEG, parm1 },
1.606 - { 24, "strb.i", sIN_CSEG, parm1 },
1.607 - { 79, "sub", sIN_CSEG, parm0 },
1.608 - { 80, "sub.alt", sIN_CSEG, parm0 },
1.609 - {132, "swap.alt", sIN_CSEG, parm0 }, /* version 4 */
1.610 - {131, "swap.pri", sIN_CSEG, parm0 }, /* version 4 */
1.611 - {129, "switch", sIN_CSEG, do_switch }, /* version 1 */
1.612 -/*{126, "symbol", sIN_CSEG, do_symbol }, */
1.613 -/*{136, "symtag", sIN_CSEG, parm1 }, -- version 7 */
1.614 - {123, "sysreq.c", sIN_CSEG, parm1 },
1.615 - {135, "sysreq.n", sIN_CSEG, parm2 }, /* version 9 (replaces SYSREQ.d from earlier version) */
1.616 - {122, "sysreq.pri", sIN_CSEG, parm0 },
1.617 - { 76, "udiv", sIN_CSEG, parm0 },
1.618 - { 77, "udiv.alt", sIN_CSEG, parm0 },
1.619 - { 75, "umul", sIN_CSEG, parm0 },
1.620 - { 35, "xchg", sIN_CSEG, parm0 },
1.621 - { 83, "xor", sIN_CSEG, parm0 },
1.622 - { 91, "zero", sIN_CSEG, parm1 },
1.623 - { 90, "zero.alt", sIN_CSEG, parm0 },
1.624 - { 89, "zero.pri", sIN_CSEG, parm0 },
1.625 - { 92, "zero.s", sIN_CSEG, parm1 },
1.626 -};
1.627 -
1.628 -#define MAX_INSTR_LEN 30
1.629 -static int findopcode(char *instr,int maxlen)
1.630 -{
1.631 - int low,high,mid,cmp;
1.632 - char str[MAX_INSTR_LEN];
1.633 -
1.634 - if (maxlen>=MAX_INSTR_LEN)
1.635 - return 0;
1.636 - strlcpy(str,instr,maxlen+1);
1.637 - /* look up the instruction with a binary search
1.638 - * the assembler is case insensitive to instructions (but case sensitive
1.639 - * to symbols)
1.640 - */
1.641 - low=1; /* entry 0 is reserved (for "not found") */
1.642 - high=(sizeof opcodelist / sizeof opcodelist[0])-1;
1.643 - while (low<high) {
1.644 - mid=(low+high)/2;
1.645 - assert(opcodelist[mid].name!=NULL);
1.646 - cmp=stricmp(str,opcodelist[mid].name);
1.647 - if (cmp>0)
1.648 - low=mid+1;
1.649 - else
1.650 - high=mid;
1.651 - } /* while */
1.652 -
1.653 - assert(low==high);
1.654 - if (stricmp(str,opcodelist[low].name)==0)
1.655 - return low; /* found */
1.656 - return 0; /* not found, return special index */
1.657 -}
1.658 -
1.659 -SC_FUNC int assemble(FILE *fout,FILE *fin)
1.660 -{
1.661 - AMX_HEADER hdr;
1.662 - AMX_FUNCSTUBNT func;
1.663 - int numpublics,numnatives,numlibraries,numpubvars,numtags,padding;
1.664 - long nametablesize,nameofs;
1.665 - #if PAWN_CELL_SIZE > 32
1.666 - char line[512];
1.667 - #else
1.668 - char line[256];
1.669 - #endif
1.670 - char *instr,*params;
1.671 - int i,pass,size;
1.672 - int16_t count;
1.673 - symbol *sym, **nativelist;
1.674 - constvalue *constptr;
1.675 - cell mainaddr;
1.676 - char nullchar = 0;
1.677 -
1.678 - /* if compression failed, restart the assembly with compaction switched off */
1.679 - if (setjmp(compact_err)!=0) {
1.680 - assert(sc_compress); /* cannot arrive here if compact encoding was disabled */
1.681 - sc_compress=FALSE;
1.682 - pc_resetbin(fout,0);
1.683 - error(232); /* disabled compact encoding */
1.684 - } /* if */
1.685 -
1.686 - #if !defined NDEBUG
1.687 - /* verify that the opcode list is sorted (skip entry 1; it is reserved
1.688 - * for a non-existant opcode)
1.689 - */
1.690 - assert(opcodelist[1].name!=NULL);
1.691 - for (i=2; i<(sizeof opcodelist / sizeof opcodelist[0]); i++) {
1.692 - assert(opcodelist[i].name!=NULL);
1.693 - assert(stricmp(opcodelist[i].name,opcodelist[i-1].name)>0);
1.694 - } /* for */
1.695 - #endif
1.696 -
1.697 - writeerror=FALSE;
1.698 - nametablesize=sizeof(int16_t);
1.699 - numpublics=0;
1.700 - numnatives=0;
1.701 - numpubvars=0;
1.702 - mainaddr=-1;
1.703 - /* count number of public and native functions and public variables */
1.704 - for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
1.705 - int match=0;
1.706 - if (sym->ident==iFUNCTN) {
1.707 - if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)!=0 && sym->addr>=0)
1.708 - match=++numnatives;
1.709 - if ((sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0)
1.710 - match=++numpublics;
1.711 - if (strcmp(sym->name,uMAINFUNC)==0) {
1.712 - assert(sym->vclass==sGLOBAL);
1.713 - mainaddr=sym->addr;
1.714 - } /* if */
1.715 - } else if (sym->ident==iVARIABLE) {
1.716 - if ((sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0)
1.717 - match=++numpubvars;
1.718 - } /* if */
1.719 - if (match) {
1.720 - char alias[sNAMEMAX+1];
1.721 - assert(sym!=NULL);
1.722 - if ((sym->usage & uNATIVE)==0 || !lookup_alias(alias,sym->name)) {
1.723 - assert(strlen(sym->name)<=sNAMEMAX);
1.724 - strcpy(alias,sym->name);
1.725 - } /* if */
1.726 - nametablesize+=strlen(alias)+1;
1.727 - } /* if */
1.728 - } /* for */
1.729 - assert(numnatives==ntv_funcid);
1.730 -
1.731 - /* count number of libraries */
1.732 - numlibraries=0;
1.733 - if (pc_addlibtable) {
1.734 - for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) {
1.735 - if (constptr->value>0) {
1.736 - assert(strlen(constptr->name)>0);
1.737 - numlibraries++;
1.738 - nametablesize+=strlen(constptr->name)+1;
1.739 - } /* if */
1.740 - } /* for */
1.741 - } /* if */
1.742 -
1.743 - /* count number of public tags */
1.744 - numtags=0;
1.745 - for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
1.746 - if ((constptr->value & PUBLICTAG)!=0) {
1.747 - assert(strlen(constptr->name)>0);
1.748 - numtags++;
1.749 - nametablesize+=strlen(constptr->name)+1;
1.750 - } /* if */
1.751 - } /* for */
1.752 -
1.753 - /* pad the header to sc_dataalign
1.754 - * => thereby the code segment is aligned
1.755 - * => since the code segment is padded to a sc_dataalign boundary, the data segment is aligned
1.756 - * => and thereby the stack top is aligned too
1.757 - */
1.758 - assert(sc_dataalign!=0);
1.759 - padding= (int)(sc_dataalign - (sizeof hdr + nametablesize) % sc_dataalign);
1.760 - if (padding==sc_dataalign)
1.761 - padding=0;
1.762 -
1.763 - /* write the abstract machine header */
1.764 - memset(&hdr, 0, sizeof hdr);
1.765 - hdr.magic=(unsigned short)AMX_MAGIC;
1.766 - hdr.file_version=(char)((pc_optimize<=sOPTIMIZE_NOMACRO) ? MAX_FILE_VER_JIT : CUR_FILE_VERSION);
1.767 - hdr.amx_version=(char)((pc_optimize<=sOPTIMIZE_NOMACRO) ? MIN_AMX_VER_JIT : MIN_AMX_VERSION);
1.768 - hdr.flags=(short)(sc_debug & sSYMBOLIC);
1.769 - if (sc_compress)
1.770 - hdr.flags|=AMX_FLAG_COMPACT;
1.771 - if (sc_debug==0)
1.772 - hdr.flags|=AMX_FLAG_NOCHECKS;
1.773 - if (pc_memflags & suSLEEP_INSTR)
1.774 - hdr.flags|=AMX_FLAG_SLEEP;
1.775 - hdr.defsize=sizeof(AMX_FUNCSTUBNT);
1.776 - hdr.publics=sizeof hdr; /* public table starts right after the header */
1.777 - hdr.natives=hdr.publics + numpublics*sizeof(AMX_FUNCSTUBNT);
1.778 - hdr.libraries=hdr.natives + numnatives*sizeof(AMX_FUNCSTUBNT);
1.779 - hdr.pubvars=hdr.libraries + numlibraries*sizeof(AMX_FUNCSTUBNT);
1.780 - hdr.tags=hdr.pubvars + numpubvars*sizeof(AMX_FUNCSTUBNT);
1.781 - hdr.nametable=hdr.tags + numtags*sizeof(AMX_FUNCSTUBNT);
1.782 - hdr.cod=hdr.nametable + nametablesize + padding;
1.783 - hdr.dat=hdr.cod + code_idx;
1.784 - hdr.hea=hdr.dat + glb_declared*sizeof(cell);
1.785 - hdr.stp=hdr.hea + pc_stksize*sizeof(cell);
1.786 - hdr.cip=mainaddr;
1.787 - hdr.size=hdr.hea; /* preset, this is incorrect in case of compressed output */
1.788 - pc_writebin(fout,&hdr,sizeof hdr);
1.789 -
1.790 - /* dump zeros up to the rest of the header, so that we can easily "seek" */
1.791 - for (nameofs=sizeof hdr; nameofs<hdr.cod; nameofs++)
1.792 - pc_writebin(fout, &nullchar, 1);
1.793 - nameofs=hdr.nametable+sizeof(int16_t);
1.794 -
1.795 - /* write the public functions table */
1.796 - count=0;
1.797 - for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
1.798 - if (sym->ident==iFUNCTN
1.799 - && (sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0)
1.800 - {
1.801 - assert(sym->vclass==sGLOBAL);
1.802 - func.address=sym->addr;
1.803 - func.nameofs=nameofs;
1.804 - #if BYTE_ORDER==BIG_ENDIAN
1.805 - align32(&func.address);
1.806 - align32(&func.nameofs);
1.807 - #endif
1.808 - pc_resetbin(fout,hdr.publics+count*sizeof(AMX_FUNCSTUBNT));
1.809 - pc_writebin(fout,&func,sizeof func);
1.810 - pc_resetbin(fout,nameofs);
1.811 - pc_writebin(fout,sym->name,strlen(sym->name)+1);
1.812 - nameofs+=strlen(sym->name)+1;
1.813 - count++;
1.814 - } /* if */
1.815 - } /* for */
1.816 -
1.817 - /* write the natives table */
1.818 - /* The native functions must be written in sorted order. (They are
1.819 - * sorted on their "id", not on their name). A nested loop to find
1.820 - * each successive function would be an O(n^2) operation. But we
1.821 - * do not really need to sort, because the native function id's
1.822 - * are sequential and there are no duplicates. So we first walk
1.823 - * through the complete symbol list and store a pointer to every
1.824 - * native function of interest in a temporary table, where its id
1.825 - * serves as the index in the table. Now we can walk the table and
1.826 - * have all native functions in sorted order.
1.827 - */
1.828 - if (numnatives>0) {
1.829 - nativelist=(symbol **)malloc(numnatives*sizeof(symbol *));
1.830 - if (nativelist==NULL)
1.831 - error(103); /* insufficient memory */
1.832 - #if !defined NDEBUG
1.833 - memset(nativelist,0,numnatives*sizeof(symbol *)); /* for NULL checking */
1.834 - #endif
1.835 - for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
1.836 - if (sym->ident==iFUNCTN && (sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)!=0 && sym->addr>=0) {
1.837 - assert(sym->addr < numnatives);
1.838 - nativelist[(int)sym->addr]=sym;
1.839 - } /* if */
1.840 - } /* for */
1.841 - count=0;
1.842 - for (i=0; i<numnatives; i++) {
1.843 - char alias[sNAMEMAX+1];
1.844 - sym=nativelist[i];
1.845 - assert(sym!=NULL);
1.846 - if (!lookup_alias(alias,sym->name)) {
1.847 - assert(strlen(sym->name)<=sNAMEMAX);
1.848 - strcpy(alias,sym->name);
1.849 - } /* if */
1.850 - assert(sym->vclass==sGLOBAL);
1.851 - func.address=0;
1.852 - func.nameofs=nameofs;
1.853 - #if BYTE_ORDER==BIG_ENDIAN
1.854 - align32(&func.address);
1.855 - align32(&func.nameofs);
1.856 - #endif
1.857 - pc_resetbin(fout,hdr.natives+count*sizeof(AMX_FUNCSTUBNT));
1.858 - pc_writebin(fout,&func,sizeof func);
1.859 - pc_resetbin(fout,nameofs);
1.860 - pc_writebin(fout,alias,strlen(alias)+1);
1.861 - nameofs+=strlen(alias)+1;
1.862 - count++;
1.863 - } /* for */
1.864 - free(nativelist);
1.865 - } /* if */
1.866 -
1.867 - /* write the libraries table */
1.868 - if (pc_addlibtable) {
1.869 - count=0;
1.870 - for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) {
1.871 - if (constptr->value>0) {
1.872 - assert(strlen(constptr->name)>0);
1.873 - func.address=0;
1.874 - func.nameofs=nameofs;
1.875 - #if BYTE_ORDER==BIG_ENDIAN
1.876 - align32(&func.address);
1.877 - align32(&func.nameofs);
1.878 - #endif
1.879 - pc_resetbin(fout,hdr.libraries+count*sizeof(AMX_FUNCSTUBNT));
1.880 - pc_writebin(fout,&func,sizeof func);
1.881 - pc_resetbin(fout,nameofs);
1.882 - pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
1.883 - nameofs+=strlen(constptr->name)+1;
1.884 - count++;
1.885 - } /* if */
1.886 - } /* for */
1.887 - } /* if */
1.888 -
1.889 - /* write the public variables table */
1.890 - count=0;
1.891 - for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
1.892 - if (sym->ident==iVARIABLE && (sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) {
1.893 - assert((sym->usage & uDEFINE)!=0);
1.894 - assert(sym->vclass==sGLOBAL);
1.895 - func.address=sym->addr;
1.896 - func.nameofs=nameofs;
1.897 - #if BYTE_ORDER==BIG_ENDIAN
1.898 - align32(&func.address);
1.899 - align32(&func.nameofs);
1.900 - #endif
1.901 - pc_resetbin(fout,hdr.pubvars+count*sizeof(AMX_FUNCSTUBNT));
1.902 - pc_writebin(fout,&func,sizeof func);
1.903 - pc_resetbin(fout,nameofs);
1.904 - pc_writebin(fout,sym->name,strlen(sym->name)+1);
1.905 - nameofs+=strlen(sym->name)+1;
1.906 - count++;
1.907 - } /* if */
1.908 - } /* for */
1.909 -
1.910 - /* write the public tagnames table */
1.911 - count=0;
1.912 - for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
1.913 - if ((constptr->value & PUBLICTAG)!=0) {
1.914 - assert(strlen(constptr->name)>0);
1.915 - func.address=constptr->value & TAGMASK;
1.916 - func.nameofs=nameofs;
1.917 - #if BYTE_ORDER==BIG_ENDIAN
1.918 - align32(&func.address);
1.919 - align32(&func.nameofs);
1.920 - #endif
1.921 - pc_resetbin(fout,hdr.tags+count*sizeof(AMX_FUNCSTUBNT));
1.922 - pc_writebin(fout,&func,sizeof func);
1.923 - pc_resetbin(fout,nameofs);
1.924 - pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
1.925 - nameofs+=strlen(constptr->name)+1;
1.926 - count++;
1.927 - } /* if */
1.928 - } /* for */
1.929 -
1.930 - /* write the "maximum name length" field in the name table */
1.931 - assert(nameofs==hdr.nametable+nametablesize);
1.932 - pc_resetbin(fout,hdr.nametable);
1.933 - count=sNAMEMAX;
1.934 - #if BYTE_ORDER==BIG_ENDIAN
1.935 - align16(&count);
1.936 - #endif
1.937 - pc_writebin(fout,&count,sizeof count);
1.938 - pc_resetbin(fout,hdr.cod);
1.939 -
1.940 - /* First pass: relocate all labels */
1.941 - /* This pass is necessary because the code addresses of labels is only known
1.942 - * after the peephole optimization flag. Labels can occur inside expressions
1.943 - * (e.g. the conditional operator), which are optimized.
1.944 - */
1.945 - lbltab=NULL;
1.946 - if (sc_labnum>0) {
1.947 - /* only very short programs have zero labels; no first pass is needed
1.948 - * if there are no labels */
1.949 - lbltab=(cell *)malloc(sc_labnum*sizeof(cell));
1.950 - if (lbltab==NULL)
1.951 - error(103); /* insufficient memory */
1.952 - codeindex=0;
1.953 - pc_resetasm(fin);
1.954 - while (pc_readasm(fin,line,sizeof line)!=NULL) {
1.955 - stripcomment(line);
1.956 - instr=skipwhitespace(line);
1.957 - /* ignore empty lines */
1.958 - if (*instr=='\0')
1.959 - continue;
1.960 - if (tolower(*instr)=='l' && *(instr+1)=='.') {
1.961 - int lindex=(int)hex2long(instr+2,NULL);
1.962 - assert(lindex>=0 && lindex<sc_labnum);
1.963 - lbltab[lindex]=codeindex;
1.964 - } else {
1.965 - /* get to the end of the instruction (make use of the '\n' that fgets()
1.966 - * added at the end of the line; this way we will *always* drop on a
1.967 - * whitespace character) */
1.968 - for (params=instr; *params!='\0' && !isspace(*params); params++)
1.969 - /* nothing */;
1.970 - assert(params>instr);
1.971 - i=findopcode(instr,(int)(params-instr));
1.972 - if (opcodelist[i].name==NULL) {
1.973 - *params='\0';
1.974 - error(104,instr); /* invalid assembler instruction */
1.975 - } /* if */
1.976 - if (opcodelist[i].segment==sIN_CSEG)
1.977 - codeindex+=opcodelist[i].func(NULL,skipwhitespace(params),opcodelist[i].opcode);
1.978 - } /* if */
1.979 - } /* while */
1.980 - } /* if */
1.981 -
1.982 - /* Second pass (actually 2 more passes, one for all code and one for all data) */
1.983 - bytes_in=0;
1.984 - bytes_out=0;
1.985 - for (pass=sIN_CSEG; pass<=sIN_DSEG; pass++) {
1.986 - pc_resetasm(fin);
1.987 - while (pc_readasm(fin,line,sizeof line)!=NULL) {
1.988 - stripcomment(line);
1.989 - instr=skipwhitespace(line);
1.990 - /* ignore empty lines and labels (labels have a special syntax, so these
1.991 - * must be parsed separately) */
1.992 - if (*instr=='\0' || tolower(*instr)=='l' && *(instr+1)=='.')
1.993 - continue;
1.994 - /* get to the end of the instruction (make use of the '\n' that fgets()
1.995 - * added at the end of the line; this way we will *always* drop on a
1.996 - * whitespace character) */
1.997 - for (params=instr; *params!='\0' && !isspace(*params); params++)
1.998 - /* nothing */;
1.999 - assert(params>instr);
1.1000 - i=findopcode(instr,(int)(params-instr));
1.1001 - assert(opcodelist[i].name!=NULL);
1.1002 - if (opcodelist[i].segment==pass)
1.1003 - opcodelist[i].func(fout,skipwhitespace(params),opcodelist[i].opcode);
1.1004 - } /* while */
1.1005 - } /* for */
1.1006 - if (bytes_out-bytes_in>0)
1.1007 - error(106); /* compression buffer overflow */
1.1008 -
1.1009 - if (lbltab!=NULL) {
1.1010 - free(lbltab);
1.1011 - #if !defined NDEBUG
1.1012 - lbltab=NULL;
1.1013 - #endif
1.1014 - } /* if */
1.1015 -
1.1016 - if (sc_compress)
1.1017 - hdr.size=pc_lengthbin(fout);/* get this value before appending debug info */
1.1018 - if (!writeerror && (sc_debug & sSYMBOLIC)!=0)
1.1019 - append_dbginfo(fout); /* optionally append debug file */
1.1020 -
1.1021 - if (writeerror)
1.1022 - error(101,"disk full");
1.1023 -
1.1024 - /* adjust the header */
1.1025 - size=(int)hdr.cod; /* save, the value in the header may be swapped */
1.1026 - #if BYTE_ORDER==BIG_ENDIAN
1.1027 - align32(&hdr.size);
1.1028 - align16(&hdr.magic);
1.1029 - align16(&hdr.flags);
1.1030 - align16(&hdr.defsize);
1.1031 - align32(&hdr.publics);
1.1032 - align32(&hdr.natives);
1.1033 - align32(&hdr.libraries);
1.1034 - align32(&hdr.pubvars);
1.1035 - align32(&hdr.tags);
1.1036 - align32(&hdr.nametable);
1.1037 - align32(&hdr.cod);
1.1038 - align32(&hdr.dat);
1.1039 - align32(&hdr.hea);
1.1040 - align32(&hdr.stp);
1.1041 - align32(&hdr.cip);
1.1042 - #endif
1.1043 - pc_resetbin(fout,0);
1.1044 - pc_writebin(fout,&hdr,sizeof hdr);
1.1045 -
1.1046 - /* return the size of the header (including name tables, but excluding code
1.1047 - * or data sections)
1.1048 - */
1.1049 - return size;
1.1050 -}
1.1051 -
1.1052 -static void append_dbginfo(FILE *fout)
1.1053 -{
1.1054 - AMX_DBG_HDR dbghdr;
1.1055 - AMX_DBG_LINE dbgline;
1.1056 - AMX_DBG_SYMBOL dbgsym;
1.1057 - AMX_DBG_SYMDIM dbgidxtag[sDIMEN_MAX];
1.1058 - int index,dim,dbgsymdim;
1.1059 - char *str,*prevstr,*name,*prevname;
1.1060 - ucell codeidx,previdx;
1.1061 - constvalue *constptr;
1.1062 - char symname[2*sNAMEMAX+16];
1.1063 - int16_t id1,id2;
1.1064 - ucell address;
1.1065 -
1.1066 - /* header with general information */
1.1067 - memset(&dbghdr, 0, sizeof dbghdr);
1.1068 - dbghdr.size=sizeof dbghdr;
1.1069 - dbghdr.magic=AMX_DBG_MAGIC;
1.1070 - dbghdr.file_version=CUR_FILE_VERSION;
1.1071 - dbghdr.amx_version=MIN_AMX_VERSION;
1.1072 -
1.1073 - /* first pass: collect the number of items in various tables */
1.1074 -
1.1075 - /* file table */
1.1076 - previdx=0;
1.1077 - prevstr=NULL;
1.1078 - prevname=NULL;
1.1079 - for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
1.1080 - assert(str!=NULL);
1.1081 - assert(str[0]!='\0' && str[1]==':');
1.1082 - if (str[0]=='F') {
1.1083 - codeidx=hex2long(str+2,&name);
1.1084 - if (codeidx!=previdx) {
1.1085 - if (prevstr!=NULL) {
1.1086 - assert(prevname!=NULL);
1.1087 - dbghdr.files++;
1.1088 - dbghdr.size+=sizeof(cell)+strlen(prevname)+1;
1.1089 - } /* if */
1.1090 - previdx=codeidx;
1.1091 - } /* if */
1.1092 - prevstr=str;
1.1093 - prevname=skipwhitespace(name);
1.1094 - } /* if */
1.1095 - } /* for */
1.1096 - if (prevstr!=NULL) {
1.1097 - assert(prevname!=NULL);
1.1098 - dbghdr.files++;
1.1099 - dbghdr.size+=sizeof(cell)+strlen(prevname)+1;
1.1100 - } /* if */
1.1101 -
1.1102 - /* line number table */
1.1103 - for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
1.1104 - assert(str!=NULL);
1.1105 - assert(str[0]!='\0' && str[1]==':');
1.1106 - if (str[0]=='L') {
1.1107 - dbghdr.lines++;
1.1108 - dbghdr.size+=sizeof(AMX_DBG_LINE);
1.1109 - } /* if */
1.1110 - } /* for */
1.1111 -
1.1112 - /* symbol table */
1.1113 - for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
1.1114 - assert(str!=NULL);
1.1115 - assert(str[0]!='\0' && str[1]==':');
1.1116 - if (str[0]=='S') {
1.1117 - dbghdr.symbols++;
1.1118 - name=strchr(str+2,':');
1.1119 - assert(name!=NULL);
1.1120 - dbghdr.size+=sizeof(AMX_DBG_SYMBOL)+strlen(skipwhitespace(name+1));
1.1121 - if ((prevstr=strchr(name,'['))!=NULL)
1.1122 - while ((prevstr=strchr(prevstr+1,':'))!=NULL)
1.1123 - dbghdr.size+=sizeof(AMX_DBG_SYMDIM);
1.1124 - } /* if */
1.1125 - } /* for */
1.1126 -
1.1127 - /* tag table */
1.1128 - for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
1.1129 - assert(strlen(constptr->name)>0);
1.1130 - dbghdr.tags++;
1.1131 - dbghdr.size+=sizeof(AMX_DBG_TAG)+strlen(constptr->name);
1.1132 - } /* for */
1.1133 -
1.1134 - /* automaton table */
1.1135 - for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) {
1.1136 - assert(constptr->index==0 && strlen(constptr->name)==0 || strlen(constptr->name)>0);
1.1137 - dbghdr.automatons++;
1.1138 - dbghdr.size+=sizeof(AMX_DBG_MACHINE)+strlen(constptr->name);
1.1139 - } /* for */
1.1140 -
1.1141 - /* state table */
1.1142 - for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) {
1.1143 - assert(strlen(constptr->name)>0);
1.1144 - dbghdr.states++;
1.1145 - dbghdr.size+=sizeof(AMX_DBG_STATE)+strlen(constptr->name);
1.1146 - } /* for */
1.1147 -
1.1148 -
1.1149 - /* pass 2: generate the tables */
1.1150 - #if BYTE_ORDER==BIG_ENDIAN
1.1151 - align32((uint32_t*)&dbghdr.size);
1.1152 - align16(&dbghdr.magic);
1.1153 - align16(&dbghdr.flags);
1.1154 - align16(&dbghdr.files);
1.1155 - align16(&dbghdr.lines);
1.1156 - align16(&dbghdr.symbols);
1.1157 - align16(&dbghdr.tags);
1.1158 - align16(&dbghdr.automatons);
1.1159 - align16(&dbghdr.states);
1.1160 - #endif
1.1161 - writeerror |= !pc_writebin(fout,&dbghdr,sizeof dbghdr);
1.1162 -
1.1163 - /* file table */
1.1164 - previdx=0;
1.1165 - prevstr=NULL;
1.1166 - prevname=NULL;
1.1167 - for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
1.1168 - assert(str!=NULL);
1.1169 - assert(str[0]!='\0' && str[1]==':');
1.1170 - if (str[0]=='F') {
1.1171 - codeidx=hex2long(str+2,&name);
1.1172 - if (codeidx!=previdx) {
1.1173 - if (prevstr!=NULL) {
1.1174 - assert(prevname!=NULL);
1.1175 - #if BYTE_ORDER==BIG_ENDIAN
1.1176 - aligncell(&previdx);
1.1177 - #endif
1.1178 - writeerror |= !pc_writebin(fout,&previdx,sizeof previdx);
1.1179 - writeerror |= !pc_writebin(fout,prevname,strlen(prevname)+1);
1.1180 - } /* if */
1.1181 - previdx=codeidx;
1.1182 - } /* if */
1.1183 - prevstr=str;
1.1184 - prevname=skipwhitespace(name);
1.1185 - } /* if */
1.1186 - } /* for */
1.1187 - if (prevstr!=NULL) {
1.1188 - assert(prevname!=NULL);
1.1189 - #if BYTE_ORDER==BIG_ENDIAN
1.1190 - aligncell(&previdx);
1.1191 - #endif
1.1192 - writeerror |= !pc_writebin(fout,&previdx,sizeof previdx);
1.1193 - writeerror |= !pc_writebin(fout,prevname,strlen(prevname)+1);
1.1194 - } /* if */
1.1195 -
1.1196 - /* line number table */
1.1197 - for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
1.1198 - assert(str!=NULL);
1.1199 - assert(str[0]!='\0' && str[1]==':');
1.1200 - if (str[0]=='L') {
1.1201 - dbgline.address=hex2long(str+2,&str);
1.1202 - dbgline.line=(int32_t)hex2long(str,NULL);
1.1203 - #if BYTE_ORDER==BIG_ENDIAN
1.1204 - aligncell(&dbgline.address);
1.1205 - align32(&dbgline.line);
1.1206 - #endif
1.1207 - writeerror |= !pc_writebin(fout,&dbgline,sizeof dbgline);
1.1208 - } /* if */
1.1209 - } /* for */
1.1210 -
1.1211 - /* symbol table */
1.1212 - for (index=0; (str=get_dbgstring(index))!=NULL; index++) {
1.1213 - assert(str!=NULL);
1.1214 - assert(str[0]!='\0' && str[1]==':');
1.1215 - if (str[0]=='S') {
1.1216 - dbgsym.address=hex2long(str+2,&str);
1.1217 - dbgsym.tag=(int16_t)hex2long(str,&str);
1.1218 - str=skipwhitespace(str);
1.1219 - assert(*str==':');
1.1220 - name=skipwhitespace(str+1);
1.1221 - str=strchr(name,' ');
1.1222 - assert(str!=NULL);
1.1223 - assert((int)(str-name)<sizeof symname);
1.1224 - strlcpy(symname,name,(int)(str-name)+1);
1.1225 - dbgsym.codestart=hex2long(str,&str);
1.1226 - dbgsym.codeend=hex2long(str,&str);
1.1227 - dbgsym.ident=(char)hex2long(str,&str);
1.1228 - dbgsym.vclass=(char)hex2long(str,&str);
1.1229 - dbgsym.dim=0;
1.1230 - str=skipwhitespace(str);
1.1231 - if (*str=='[') {
1.1232 - while (*(str=skipwhitespace(str+1))!=']') {
1.1233 - dbgidxtag[dbgsym.dim].tag=(int16_t)hex2long(str,&str);
1.1234 - str=skipwhitespace(str);
1.1235 - assert(*str==':');
1.1236 - dbgidxtag[dbgsym.dim].size=hex2long(str+1,&str);
1.1237 - dbgsym.dim++;
1.1238 - } /* while */
1.1239 - } /* if */
1.1240 - dbgsymdim = dbgsym.dim;
1.1241 - #if BYTE_ORDER==BIG_ENDIAN
1.1242 - aligncell(&dbgsym.address);
1.1243 - align16(&dbgsym.tag);
1.1244 - aligncell(&dbgsym.codestart);
1.1245 - aligncell(&dbgsym.codeend);
1.1246 - align16(&dbgsym.dim);
1.1247 - #endif
1.1248 - writeerror |= !pc_writebin(fout,&dbgsym,offsetof(AMX_DBG_SYMBOL, name));
1.1249 - writeerror |= !pc_writebin(fout,symname,strlen(symname)+1);
1.1250 - for (dim=0; dim<dbgsymdim; dim++) {
1.1251 - #if BYTE_ORDER==BIG_ENDIAN
1.1252 - align16(&dbgidxtag[dim].tag);
1.1253 - aligncell(&dbgidxtag[dim].size);
1.1254 - #endif
1.1255 - writeerror |= !pc_writebin(fout,&dbgidxtag[dim],sizeof dbgidxtag[dim]);
1.1256 - } /* for */
1.1257 - } /* if */
1.1258 - } /* for */
1.1259 -
1.1260 - /* tag table */
1.1261 - for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
1.1262 - assert(strlen(constptr->name)>0);
1.1263 - id1=(int16_t)(constptr->value & TAGMASK);
1.1264 - #if BYTE_ORDER==BIG_ENDIAN
1.1265 - align16(&id1);
1.1266 - #endif
1.1267 - writeerror |= !pc_writebin(fout,&id1,sizeof id1);
1.1268 - writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
1.1269 - } /* for */
1.1270 -
1.1271 - /* automaton table */
1.1272 - for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) {
1.1273 - assert(constptr->index==0 && strlen(constptr->name)==0 || strlen(constptr->name)>0);
1.1274 - id1=(int16_t)constptr->index;
1.1275 - address=(ucell)constptr->value;
1.1276 - #if BYTE_ORDER==BIG_ENDIAN
1.1277 - align16(&id1);
1.1278 - aligncell(&address);
1.1279 - #endif
1.1280 - writeerror |= !pc_writebin(fout,&id1,sizeof id1);
1.1281 - writeerror |= !pc_writebin(fout,&address,sizeof address);
1.1282 - writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
1.1283 - } /* for */
1.1284 -
1.1285 - /* state table */
1.1286 - for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) {
1.1287 - assert(strlen(constptr->name)>0);
1.1288 - id1=(int16_t)constptr->value;
1.1289 - id2=(int16_t)constptr->index;
1.1290 - address=(ucell)constptr->value;
1.1291 - #if BYTE_ORDER==BIG_ENDIAN
1.1292 - align16(&id1);
1.1293 - align16(&id2);
1.1294 - #endif
1.1295 - writeerror |= !pc_writebin(fout,&id1,sizeof id1);
1.1296 - writeerror |= !pc_writebin(fout,&id2,sizeof id2);
1.1297 - writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
1.1298 - } /* for */
1.1299 -
1.1300 - delete_dbgstringtable();
1.1301 -}