3 * Drafted after the Small-C compiler Version 2.01, originally created
4 * by Ron Cain, july 1980, and enhanced by James E. Hendrix.
6 * This version comes close to a complete rewrite.
8 * Copyright R. Cain, 1980
9 * Copyright J.E. Hendrix, 1982, 1983
10 * Copyright T. Riemersma, 1997-2003
14 * This software is provided "as-is", without any express or implied warranty.
15 * In no event will the authors be held liable for any damages arising from
16 * the use of this software.
18 * Permission is granted to anyone to use this software for any purpose,
19 * including commercial applications, and to alter it and redistribute it
20 * freely, subject to the following restrictions:
22 * 1. The origin of this software must not be misrepresented; you must not
23 * claim that you wrote the original software. If you use this software in
24 * a product, an acknowledgment in the product documentation would be
25 * appreciated but is not required.
26 * 2. Altered source versions must be plainly marked as such, and must not be
27 * misrepresented as being the original software.
28 * 3. This notice may not be removed or altered from any source distribution.
31 #ifndef EMBRYO_CC_SC_H
32 #define EMBRYO_CC_SC_H
39 #include <eina_types.h>
41 #include "embryo_cc_osdefs.h"
42 #include "embryo_cc_amx.h"
44 /* Note: the "cell" and "ucell" types are defined in AMX.H */
46 #define PUBLIC_CHAR '@' /* character that defines a function "public" */
47 #define CTRL_CHAR '\\' /* default control character */
49 #define DIRSEP_CHAR '/' /* directory separator character */
51 #define sDIMEN_MAX 2 /* maximum number of array dimensions */
52 #define sDEF_LITMAX 500 /* initial size of the literal pool, in "cells" */
53 #define sLINEMAX 65535 /* input line length (in characters) */
54 #define sDEF_AMXSTACK 4096 /* default stack size for AMX files */
55 #define sSTKMAX 80 /* stack for nested #includes and other uses */
56 #define PREPROC_TERM '\x7f' /* termination character for preprocessor expressions (the "DEL" code) */
57 #define sDEF_PREFIX "default.inc" /* default prefix filename */
59 typedef void *stkitem; /* type of items stored on the stack */
61 typedef struct __s_arginfo
62 { /* function argument info */
63 char name[sNAMEMAX + 1];
64 char ident; /* iVARIABLE, iREFERENCE, iREFARRAY or iVARARGS */
65 char usage; /* uCONST */
66 int *tags; /* argument tag id. list */
67 int numtags; /* number of tags in the tag list */
69 int numdim; /* number of dimensions */
70 unsigned char hasdefault; /* bit0: is there a default value? bit6: "tagof"; bit7: "sizeof" */
73 cell val; /* default value */
76 char *symname; /* name of another symbol */
77 short level; /* indirection level for that symbol */
78 } size; /* used for "sizeof" default value */
81 cell *data; /* values of default array */
82 int size; /* complete length of default array */
83 int arraysize; /* size to reserve on the heap */
84 cell addr; /* address of the default array in the data segment */
86 } defvalue; /* default value, or pointer to default array */
87 int defvalue_tag; /* tag of the default value */
90 /* Equate table, tagname table, library table */
91 typedef struct __s_constvalue
93 struct __s_constvalue *next;
94 char name[sNAMEMAX + 1];
99 /* Symbol table format
101 * The symbol name read from the input file is stored in "name", the
102 * value of "addr" is written to the output file. The address in "addr"
103 * depends on the class of the symbol:
104 * global offset into the data segment
105 * local offset relative to the stack frame
106 * label generated hexadecimal number
107 * function offset into code segment
109 typedef struct __s_symbol
111 struct __s_symbol *next;
112 struct __s_symbol *parent; /* hierarchical types (multi-dimensional arrays) */
113 char name[sNAMEMAX + 1];
114 unsigned int hash; /* value derived from name, for quicker searching */
115 cell addr; /* address or offset (or value for constant, index for native function) */
116 char vclass; /* sLOCAL if "addr" refers to a local symbol */
117 char ident; /* see below for possible values */
118 char usage; /* see below for possible values */
119 int compound; /* compound level (braces nesting level) */
120 int tag; /* tagname id */
123 int declared; /* label: how many local variables are declared */
124 int idxtag; /* array: tag of array indices */
125 constvalue *lib; /* native function: library it is part of *///??? use "stringlist"
126 } x; /* 'x' for 'extra' */
129 arginfo *arglist; /* types of all parameters for functions */
132 cell length; /* arrays: length (size) */
133 short level; /* number of dimensions below this level */
135 } dim; /* for 'dimension', both functions and arrays */
136 int fnumber; /* static global variables: file number in which the declaration is visible */
137 struct __s_symbol **refer; /* referrer list, functions that "use" this symbol */
138 int numrefers; /* number of entries in the referrer list */
141 /* Possible entries for "ident". These are used in the "symbol", "value"
142 * and arginfo structures. Not every constant is valid for every use.
143 * In an argument list, the list is terminated with a "zero" ident; labels
144 * cannot be passed as function arguments, so the value 0 is overloaded.
147 #define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
148 #define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
150 #define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
151 #define iARRAYCELL 5 /* array element, cell that must be fetched indirectly */
152 #define iARRAYCHAR 6 /* array element, character from cell from array */
153 #define iEXPRESSION 7 /* expression result, has no address (rvalue) */
154 #define iCONSTEXPR 8 /* constant expression (or constant symbol) */
156 #define iREFFUNC 10 /* function passed as a parameter */
157 #define iVARARGS 11 /* function specified ... as argument(s) */
159 /* Possible entries for "usage"
161 * This byte is used as a serie of bits, the syntax is different for
162 * functions and other symbols:
165 * bits: 0 (uDEFINE) the variable is defined in the source file
166 * 1 (uREAD) the variable is "read" (accessed) in the source file
167 * 2 (uWRITTEN) the variable is altered (assigned a value)
168 * 3 (uCONST) the variable is constant (may not be assigned to)
169 * 4 (uPUBLIC) the variable is public
170 * 6 (uSTOCK) the variable is discardable (without warning)
173 * bits: 0 (uDEFINE) the function is defined ("implemented") in the source file
174 * 1 (uREAD) the function is invoked in the source file
175 * 2 (uRETVALUE) the function returns a value (or should return a value)
176 * 3 (uPROTOTYPED) the function was prototyped
177 * 4 (uPUBLIC) the function is public
178 * 5 (uNATIVE) the function is native
179 * 6 (uSTOCK) the function is discardable (without warning)
180 * 7 (uMISSING) the function is not implemented in this source file
183 * bits: 0 (uDEFINE) the symbol is defined in the source file
184 * 1 (uREAD) the constant is "read" (accessed) in the source file
185 * 3 (uPREDEF) the constant is pre-defined and should be kept between passes
189 #define uWRITTEN 0x04
190 #define uRETVALUE 0x04 /* function returns (or should return) a value */
192 #define uPROTOTYPED 0x08
193 #define uPREDEF 0x08 /* constant is pre-defined */
197 #define uMISSING 0x80
198 /* uRETNONE is not stored in the "usage" field of a symbol. It is
199 * used during parsing a function, to detect a mix of "return;" and
200 * "return value;" in a few special cases.
202 #define uRETNONE 0x10
204 #define uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */
205 #define uSIZEOF 0x80 /* set in the "hasdefault" field of the arginfo struct */
207 #define uMAINFUNC "main"
209 #define sGLOBAL 0 /* global/local variable/constant class */
211 #define sSTATIC 2 /* global life, local scope */
215 symbol *sym; /* symbol in symbol table, NULL for (constant) expression */
216 cell constval; /* value of the constant expression (if ident==iCONSTEXPR)
217 * also used for the size of a literal array */
218 int tag; /* tagname id (of the expression) */
219 char ident; /* iCONSTEXPR, iVARIABLE, iARRAY, iARRAYCELL,
220 * iEXPRESSION or iREFERENCE */
221 char boolresult; /* boolean result for relational operators */
222 cell *arrayidx; /* last used array indices, for checking self assignment */
225 /* "while" statement queue (also used for "for" and "do - while" loops) */
228 wqBRK, /* used to restore stack for "break" */
229 wqCONT, /* used to restore stack for "continue" */
230 wqLOOP, /* loop start label number */
231 wqEXIT, /* loop exit label number (jump if false) */
233 wqSIZE /* "while queue" size */
236 #define wqTABSZ (24*wqSIZE) /* 24 nested loop statements */
240 statIDLE, /* not compiling yet */
241 statFIRST, /* first pass */
242 statWRITE, /* writing output */
243 statSKIP, /* skipping output */
246 typedef struct __s_stringlist
248 struct __s_stringlist *next;
252 typedef struct __s_stringpair
254 struct __s_stringpair *next;
260 /* macros for code generation */
261 #define opcodes(n) ((n)*sizeof(cell)) /* opcode size */
262 #define opargs(n) ((n)*sizeof(cell)) /* size of typical argument */
264 /* Tokens recognized by lex()
265 * Some of these constants are assigned as well to the variable "lastst"
267 #define tFIRST 256 /* value of first multi-character operator */
268 #define tMIDDLE 279 /* value of last multi-character operator */
269 #define tLAST 320 /* value of last multi-character match-able token */
270 /* multi-character operators */
271 #define taMULT 256 /* *= */
272 #define taDIV 257 /* /= */
273 #define taMOD 258 /* %= */
274 #define taADD 259 /* += */
275 #define taSUB 260 /* -= */
276 #define taSHL 261 /* <<= */
277 #define taSHRU 262 /* >>>= */
278 #define taSHR 263 /* >>= */
279 #define taAND 264 /* &= */
280 #define taXOR 265 /* ^= */
281 #define taOR 266 /* |= */
282 #define tlOR 267 /* || */
283 #define tlAND 268 /* && */
284 #define tlEQ 269 /* == */
285 #define tlNE 270 /* != */
286 #define tlLE 271 /* <= */
287 #define tlGE 272 /* >= */
288 #define tSHL 273 /* << */
289 #define tSHRU 274 /* >>> */
290 #define tSHR 275 /* >> */
291 #define tINC 276 /* ++ */
292 #define tDEC 277 /* -- */
293 #define tELLIPS 278 /* ... */
294 #define tDBLDOT 279 /* .. */
295 /* reserved words (statements) */
301 #define tCONTINUE 285
314 #define tOPERATOR 298
324 /* compiler directives */
325 #define tpASSERT 308 /* #assert */
327 #define tpELSE 310 /* #else */
330 #define tpENDINPUT 313
331 #define tpENDSCRPT 314
333 #define tpIF 316 /* #if */
338 /* semicolon is a special case, because it can be optional */
339 #define tTERM 321 /* semicolon or newline */
340 #define tENDEXPR 322 /* forced end of expression */
341 /* other recognized tokens */
342 #define tNUMBER 323 /* integer number */
343 #define tRATIONAL 324 /* rational number */
347 #define tEXPR 328 /* for assigment to "lastst" only */
349 /* (reversed) evaluation of staging buffer */
350 #define sSTARTREORDER 1
351 #define sENDREORDER 2
352 #define sEXPRSTART 0xc0 /* top 2 bits set, rest is free */
353 #define sMAXARGS 64 /* relates to the bit pattern of sEXPRSTART */
355 /* codes for ffabort() */
356 #define xEXIT 1 /* exit code in PRI */
357 #define xASSERTION 2 /* abort caused by failing assertion */
358 #define xSTACKERROR 3 /* stack/heap overflow */
359 #define xBOUNDSERROR 4 /* array index out of bounds */
360 #define xMEMACCESS 5 /* data access error */
361 #define xINVINSTR 6 /* invalid instruction */
362 #define xSTACKUNDERFLOW 7 /* stack underflow */
363 #define xHEAPUNDERFLOW 8 /* heap underflow */
364 #define xCALLBACKERR 9 /* no, or invalid, callback */
365 #define xSLEEP 12 /* sleep, exit code in PRI, tag in ALT */
372 #define sIN_CSEG 1 /* if parsing CODE */
373 #define sIN_DSEG 2 /* if parsing DATA */
374 #define sCHKBOUNDS 1 /* bit position in "debug" variable: check bounds */
375 #define sSYMBOLIC 2 /* bit position in "debug" variable: symbolic info */
376 #define sNOOPTIMIZE 4 /* bit position in "debug" variable: no optimization */
377 #define sRESET 0 /* reset error flag */
378 #define sFORCESET 1 /* force error flag on */
379 #define sEXPRMARK 2 /* mark start of expression */
380 #define sEXPRRELEASE 3 /* mark end of expression */
383 #define PUBLICTAG 0x8000u
384 #define FIXEDTAG 0x4000u
386 #define PUBLICTAG 0x80000000Lu
387 #define FIXEDTAG 0x40000000Lu
389 #define TAGMASK (~PUBLICTAG)
393 * Functions you call from the "driver" program
395 int sc_compile(int argc, char **argv);
396 int sc_addconstant(char *name, cell value, int tag);
397 int sc_addtag(char *name);
400 * Functions called from the compiler (to be implemented by you)
403 /* general console output */
404 int sc_printf(const char *message, ...);
406 /* error report function */
407 int sc_error(int number, char *message, char *filename,
408 int firstline, int lastline, va_list argptr);
410 /* input from source file */
411 void *sc_opensrc(char *filename); /* reading only */
412 void sc_closesrc(void *handle); /* never delete */
413 void sc_resetsrc(void *handle, void *position); /* reset to a position marked earlier */
414 char *sc_readsrc(void *handle, char *target, int maxchars);
415 void *sc_getpossrc(void *handle); /* mark the current position */
416 int sc_eofsrc(void *handle);
418 /* output to intermediate (.ASM) file */
419 void *sc_openasm(int fd); /* read/write */
420 void sc_closeasm(void *handle);
421 void sc_resetasm(void *handle);
422 int sc_writeasm(void *handle, char *str);
423 char *sc_readasm(void *handle, char *target, int maxchars);
425 /* output to binary (.AMX) file */
426 void *sc_openbin(char *filename);
427 void sc_closebin(void *handle, int deletefile);
428 void sc_resetbin(void *handle);
429 int sc_writebin(void *handle, void *buffer, int size);
430 long sc_lengthbin(void *handle); /* return the length of the file */
432 /* function prototypes in SC1.C */
433 symbol *fetchfunc(char *name, int tag);
434 char *operator_symname(char *symname, char *opername, int tag1,
435 int tag2, int numtags, int resulttag);
436 char *funcdisplayname(char *dest, char *funcname);
437 int constexpr(cell * val, int *tag);
438 constvalue *append_constval(constvalue * table, char *name, cell val,
440 constvalue *find_constval(constvalue * table, char *name, short index);
441 void delete_consttable(constvalue * table);
442 void add_constant(char *name, cell val, int vclass, int tag);
443 void exporttag(int tag);
445 /* function prototypes in SC2.C */
446 void pushstk(stkitem val);
447 stkitem popstk(void);
448 int plungequalifiedfile(char *name); /* explicit path included */
449 int plungefile(char *name, int try_currentpath, int try_includepaths); /* search through "include" paths */
450 void preprocess(void);
452 int lex(cell * lexvalue, char **lexsym);
454 void lexclr(int clreol);
455 int matchtoken(int token);
456 int tokeninfo(cell * val, char **str);
457 int needtoken(int token);
458 void stowlit(cell value);
459 int alphanum(char c);
460 void delete_symbol(symbol * root, symbol * sym);
461 void delete_symbols(symbol * root, int level, int del_labels,
462 int delete_functions);
463 int refer_symbol(symbol * entry, symbol * bywhom);
464 void markusage(symbol * sym, int usage);
465 unsigned int namehash(char *name);
466 symbol *findglb(char *name);
467 symbol *findloc(char *name);
468 symbol *findconst(char *name);
469 symbol *finddepend(symbol * parent);
470 symbol *addsym(char *name, cell addr, int ident, int vclass,
472 symbol *addvariable(char *name, cell addr, int ident, int vclass,
473 int tag, int dim[], int numdim, int idxtag[]);
475 char *itoh(ucell val);
477 /* function prototypes in SC3.C */
478 int check_userop(void (*oper) (void), int tag1, int tag2,
479 int numparam, value * lval, int *resulttag);
480 int matchtag(int formaltag, int actualtag, int allowcoerce);
481 int expression(int *constant, cell * val, int *tag,
483 int hier14(value * lval1); /* the highest expression level */
485 /* function prototypes in SC4.C */
486 void writeleader(void);
487 void writetrailer(void);
490 void setactivefile(int fnumber);
491 cell nameincells(char *name);
492 void setfile(char *name, int fileno);
493 void setline(int line, int fileno);
494 void setlabel(int index);
495 void endexpr(int fullexpr);
496 void startfunc(char *fname);
498 void alignframe(int numbytes);
499 void defsymbol(char *name, int ident, int vclass, cell offset,
501 void symbolrange(int level, cell size);
502 void rvalue(value * lval);
503 void address(symbol * ptr);
504 void store(value * lval);
505 void memcopy(cell size);
506 void copyarray(symbol * sym, cell size);
507 void fillarray(symbol * sym, cell size, cell value);
508 void const1(cell val);
509 void const2(cell val);
513 void pushval(cell val);
517 void ffswitch(int label);
518 void ffcase(cell value, char *labelname, int newtable);
519 void ffcall(symbol * sym, int numargs);
521 void ffabort(int reason);
522 void ffbounds(cell size);
523 void jumplabel(int number);
524 void defstorage(void);
525 void modstk(int delta);
526 void setstk(cell value);
527 void modheap(int delta);
528 void setheap_pri(void);
529 void setheap(cell value);
530 void cell2addr(void);
531 void cell2addr_alt(void);
532 void addr2cell(void);
533 void char2addr(void);
534 void charalign(void);
535 void addconst(cell value);
537 /* Code generation functions for arithmetic operators.
539 * Syntax: o[u|s|b]_name
540 * | | | +--- name of operator
541 * | | +----- underscore
542 * | +--------- "u"nsigned operator, "s"igned operator or "b"oth
543 * +------------- "o"perator
545 void os_mult(void); /* multiplication (signed) */
546 void os_div(void); /* division (signed) */
547 void os_mod(void); /* modulus (signed) */
548 void ob_add(void); /* addition */
549 void ob_sub(void); /* subtraction */
550 void ob_sal(void); /* shift left (arithmetic) */
551 void os_sar(void); /* shift right (arithmetic, signed) */
552 void ou_sar(void); /* shift right (logical, unsigned) */
553 void ob_or(void); /* bitwise or */
554 void ob_xor(void); /* bitwise xor */
555 void ob_and(void); /* bitwise and */
556 void ob_eq(void); /* equality */
557 void ob_ne(void); /* inequality */
558 void relop_prefix(void);
559 void relop_suffix(void);
560 void os_le(void); /* less or equal (signed) */
561 void os_ge(void); /* greater or equal (signed) */
562 void os_lt(void); /* less (signed) */
563 void os_gt(void); /* greater (signed) */
568 void nooperation(void);
569 void inc(value * lval);
570 void dec(value * lval);
571 void jmp_ne0(int number);
572 void jmp_eq0(int number);
573 void outval(cell val, int newline);
575 /* function prototypes in SC5.C */
576 int error(int number, ...);
577 void errorset(int code);
579 /* function prototypes in SC6.C */
580 void assemble(FILE * fout, FILE * fin);
582 /* function prototypes in SC7.C */
583 void stgbuffer_cleanup(void);
584 void stgmark(char mark);
585 void stgwrite(char *st);
586 void stgout(int index);
587 void stgdel(int index, cell code_index);
588 int stgget(int *index, cell * code_index);
589 void stgset(int onoff);
590 int phopt_init(void);
591 int phopt_cleanup(void);
593 /* function prototypes in SCLIST.C */
594 stringpair *insert_alias(char *name, char *alias);
595 stringpair *find_alias(char *name);
596 int lookup_alias(char *target, char *name);
597 void delete_aliastable(void);
598 stringlist *insert_path(char *path);
599 char *get_path(int index);
600 void delete_pathtable(void);
601 stringpair *insert_subst(char *pattern, char *substitution,
603 int get_subst(int index, char **pattern, char **substitution);
604 stringpair *find_subst(char *name, int length);
605 int delete_subst(char *name, int length);
606 void delete_substtable(void);
608 /* external variables (defined in scvars.c) */
609 extern symbol loctab; /* local symbol table */
610 extern symbol glbtab; /* global symbol table */
611 extern cell *litq; /* the literal queue */
612 extern char pline[]; /* the line read from the input file */
613 extern char *lptr; /* points to the current position in "pline" */
614 extern constvalue tagname_tab; /* tagname table */
615 extern constvalue libname_tab; /* library table (#pragma library "..." syntax) *///??? use "stringlist" type
616 extern constvalue *curlibrary; /* current library */
617 extern symbol *curfunc; /* pointer to current function */
618 extern char *inpfname; /* name of the file currently read from */
619 extern char outfname[]; /* output file name */
620 extern char sc_ctrlchar; /* the control character (or escape character) */
621 extern int litidx; /* index to literal table */
622 extern int litmax; /* current size of the literal table */
623 extern int stgidx; /* index to the staging buffer */
624 extern int labnum; /* number of (internal) labels */
625 extern int staging; /* true if staging output */
626 extern cell declared; /* number of local cells declared */
627 extern cell glb_declared; /* number of global cells declared */
628 extern cell code_idx; /* number of bytes with generated code */
629 extern int ntv_funcid; /* incremental number of native function */
630 extern int errnum; /* number of errors */
631 extern int warnnum; /* number of warnings */
632 extern int sc_debug; /* debug/optimization options (bit field) */
633 extern int charbits; /* number of bits for a character */
634 extern int sc_packstr; /* strings are packed by default? */
635 extern int sc_asmfile; /* create .ASM file? */
636 extern int sc_listing; /* create .LST file? */
637 extern int sc_compress; /* compress bytecode? */
638 extern int sc_needsemicolon; /* semicolon required to terminate expressions? */
639 extern int sc_dataalign; /* data alignment value */
640 extern int sc_alignnext; /* must frame of the next function be aligned? */
641 extern int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */
642 extern cell sc_stksize; /* stack size */
643 extern int freading; /* is there an input file ready for reading? */
644 extern int fline; /* the line number in the current file */
645 extern int fnumber; /* number of files in the file table (debugging) */
646 extern int fcurrent; /* current file being processed (debugging) */
647 extern int intest; /* true if inside a test */
648 extern int sideeffect; /* true if an expression causes a side-effect */
649 extern int stmtindent; /* current indent of the statement */
650 extern int indent_nowarn; /* skip warning "217 loose indentation" */
651 extern int sc_tabsize; /* number of spaces that a TAB represents */
652 extern int sc_allowtags; /* allow/detect tagnames in lex() */
653 extern int sc_status; /* read/write status */
654 extern int sc_rationaltag; /* tag for rational numbers */
655 extern int rational_digits; /* number of fractional digits */
657 extern FILE *inpf; /* file read from (source or include) */
658 extern FILE *inpf_org; /* main source file */
659 extern FILE *outf; /* file written to */
661 extern jmp_buf errbuf; /* target of longjmp() on a fatal error */