I've attached the 6809 code generator for the older compiler version as well.
We should be able to get a real C compiler in the space we have (CP/M manages it
for a passable ANSI C) but this will be fun for now and for debugging work.
--- /dev/null
+.SUFFIXES: .o .c .asm
+
+ASSEMS = bdos.asm bdos1.asm chio8080.asm exit.asm io8080.asm sbrk.asm
+
+.c.asm:
+ tscc $*.c
+
+all: $(ASSEMS)
--- /dev/null
+/* Interpret CPM argument list to produce C style
+ argc/argv
+ default dma buffer has it, form:
+ ---------------------------------
+ |count|characters ... |
+ ---------------------------------
+*/
+int Xargc;
+int Xargv[30];
+Xarglist(ap) char *ap; {
+ char qc;
+ Xargc = 0;
+ ap[(*ap)+1 <tel:+1>] = '\0';
+ ap++;
+ while (isspace(*ap)) ap++;
+ Xargv[Xargc++] = "arg0";
+ if (*ap)
+ do {
+ if (*ap == '\'' || *ap == '\"') {
+ qc = *ap;
+ Xargv[Xargc++] = ++ap;
+ while (*ap&&*ap != qc) ap++;
+ } else {
+ Xargv[Xargc++] = ap;
+ while (*ap&&!isspace(*ap)) ap++;
+ }
+ if (!*ap) break;
+ *ap++='\0';
+ while (isspace(*ap)) ap++;
+ } while(*ap);
+ Xargv[Xargc] = 0;
+
+}
+
--- /dev/null
+bdos (c, de) int c, de; {
+#asm
+; CP/M support routine
+; bdos(C,DE);
+; char *DE; int C;
+; returns H=B,L=A per CPM standard
+ pop h ; hold return address
+ pop d ; get bdos function number
+ pop b ; get DE register argument
+ push d
+ push b
+ push h
+ call 5
+ mov h,b
+ mov l,a
+#endasm
+}
+
--- /dev/null
+bdos1(c, de) int c, de; {
+ /* returns only single byte (top half is 0) */
+ return (255 & bdos(c, de));
+}
+
--- /dev/null
+#define EOL 10
+getchar() {
+ return (bdos(1,1));
+
+}
+
+putchar (c) char c; {
+ if (c == EOL) bdos(2,13);
+ bdos(2,c);
+ return c;
+}
+
--- /dev/null
+; Run time start off for Small C.
+ cseg
+ sphl ; save the stack pointer
+ shld ?stksav
+ lhld 6 ; pick up core top
+ lxi d,-10 ; decrease by 10 for safety
+ dad d
+ sphl ; set stack pointer
+ call stdioinit ; initialize stdio
+ call Xarglist
+ lhld Xargc
+ push h
+ lxi h,Xargv
+ push h
+ call main ; call main program
+ pop d
+ pop d
+ lhld ?stksav ; restore stack pointer
+ ret ; go back to CCP
+ dseg
+?stksav ds 2
+ extrn stdioinit
+ extrn Xarglist
+ extrn Xargc
+ extrn Xargv
+ extrn main
+ end
--- /dev/null
+;
+;*****************************************************
+; *
+; runtime library for small C compiler *
+; *
+; c.s - runtime routine for basic C code *
+; *
+; Ron Cain *
+; *
+;*****************************************************
+;
+ cseg
+;
+ public ?gchar,?gint,?pchar,?pint
+ public ?sxt
+ public ?or,?and,?xor
+ public ?eq,?ne,?gt,?le,?ge,?lt,?uge,?ult,?ugt,?ule
+ public ?asr,?asl
+ public ?sub,?neg,?com,?lneg,?bool,?mul,?div
+ public ?case,brkend,Xstktop
+ public etext
+ public edata
+;
+; fetch char from (HL) and sign extend into HL
+?gchar: mov a,m
+?sxt: mov l,a
+ rlc
+ sbb a
+ mov h,a
+ ret
+; fetch int from (HL)
+?gint: mov a,m
+ inx h
+ mov h,m
+ mov l,a
+ ret
+; store char from HL into (DE)
+?pchar: mov a,l
+ stax d
+ ret
+; store int from HL into (DE)
+?pint: mov a,l
+ stax d
+ inx d
+ mov a,h
+ stax d
+ ret
+; "or" HL and DE into HL
+?or: mov a,l
+ ora e
+ mov l,a
+ mov a,h
+ ora d
+ mov h,a
+ ret
+; "xor" HL and DE into HL
+?xor: mov a,l
+ xra e
+ mov l,a
+ mov a,h
+ xra d
+ mov h,a
+ ret
+; "and" HL and DE into HL
+?and: mov a,l
+ ana e
+ mov l,a
+ mov a,h
+ ana d
+ mov h,a
+ ret
+;
+;......logical operations: HL set to 0 (false) or 1 (true)
+;
+; DE == HL
+?eq: call ?cmp
+ rz
+ dcx h
+ ret
+; DE != HL
+?ne: call ?cmp
+ rnz
+ dcx h
+ ret
+; DE > HL [signed]
+?gt: xchg
+ call ?cmp
+ rc
+ dcx h
+ ret
+; DE <= HL [signed]
+?le: call ?cmp
+ rz
+ rc
+ dcx h
+ ret
+; DE >= HL [signed]
+?ge: call ?cmp
+ rnc
+ dcx h
+ ret
+; DE < HL [signed]
+?lt: call ?cmp
+ rc
+ dcx h
+ ret
+; DE >= HL [unsigned]
+?uge: call ?ucmp
+ rnc
+ dcx h
+ ret
+; DE < HL [unsigned]
+?ult: call ?ucmp
+ rc
+ dcx h
+ ret
+; DE > HL [unsigned]
+?ugt: xchg
+ call ?ucmp
+ rc
+ dcx h
+ ret
+; DE <= HL [unsigned]
+?ule: call ?ucmp
+ rz
+ rc
+ dcx h
+ ret
+; signed compare of DE and HL
+; carry is sign of difference [set => DE < HL]
+; zero is zero/non-zero
+?cmp: mov a,e
+ sub l
+ mov e,a
+ mov a,d
+ sbb h
+ lxi h,1 ;preset true
+ jm ?cmp1
+ ora e ;resets carry
+ ret
+?cmp1: ora e
+ stc
+ ret
+; unsigned compare of DE and HL
+; carry is sign of difference [set => DE < HL]
+; zero is zero/non-zero
+?ucmp: mov a,d
+ cmp h
+ jnz ?ucmp1
+ mov a,e
+ cmp l
+?ucmp1: lxi h,1 ;preset true
+ ret
+; shift DE right arithmetically by HL, move to HL
+?asr: xchg
+?asr1: dcr e
+ rm
+ mov a,h
+ ral
+ mov a,h
+ rar
+ mov h,a
+ mov a,l
+ rar
+ mov l,a
+ jmp ?asr1
+; shift DE left arithmetically by HL, move to HL
+?asl: xchg
+?asl1: dcr e
+ rm
+ dad h
+ jmp ?asl1
+; HL = DE - HL
+?sub: mov a,e
+ sub l
+ mov l,a
+ mov a,d
+ sbb h
+ mov h,a
+ ret
+; HL = -HL
+?neg: call ?com
+ inx h
+ ret
+; HL = ~HL
+?com: mov a,h
+ cma
+ mov h,a
+ mov a,l
+ cma
+ mov l,a
+ ret
+; HL = !HL
+?lneg: mov a,h
+ ora l
+ jz ?lneg1
+ lxi h,0
+ ret
+?lneg1: inx h
+ ret
+; HL = !!HL
+?bool: call ?lneg
+ jmp ?lneg
+;
+; HL = DE * HL [signed]
+?mul: mov b,h
+ mov c,l
+ lxi h,0
+?mul1: mov a,c
+ rrc
+ jnc ?mul2
+ dad d
+?mul2: xra a
+ mov a,b
+ rar
+ mov b,a
+ mov a,c
+ rar
+ mov c,a
+ ora b
+ rz
+ xra a
+ mov a,e
+ ral
+ mov e,a
+ mov a,d
+ ral
+ mov d,a
+ ora e
+ rz
+ jmp ?mul1
+; HL = DE / HL, DE = DE % HL
+?div: mov b,h
+ mov c,l
+ mov a,d
+ xra b
+ push psw
+ mov a,d
+ ora a
+ cm ?deneg
+ mov a,b
+ ora a
+ cm ?bcneg
+ mvi a,16
+ push psw
+ xchg
+ lxi d,0
+?div1: dad h
+ call ?rdel
+ jz ?div2
+ call ?cmpbd
+ jm ?div2
+ mov a,l
+ ori 1
+ mov l,a
+ mov a,e
+ sub c
+ mov e,a
+ mov a,d
+ sbb b
+ mov d,a
+?div2: pop psw
+ dcr a
+ jz ?div3
+ push psw
+ jmp ?div1
+?div3: pop psw
+ rp
+ call ?deneg
+ xchg
+ call ?deneg
+ xchg
+ ret
+; {DE = -DE}
+?deneg: mov a,d
+ cma
+ mov d,a
+ mov a,e
+ cma
+ mov e,a
+ inx d
+ ret
+; {BC = -BC}
+?bcneg: mov a,b
+ cma
+ mov b,a
+ mov a,c
+ cma
+ mov c,a
+ inx b
+ ret
+; {DE <r<r 1}
+?rdel: mov a,e
+ ral
+ mov e,a
+ mov a,d
+ ral
+ mov d,a
+ ora e
+ ret
+; {BC : DE}
+?cmpbd: mov a,e
+ sub c
+ mov a,d
+ sbb b
+ ret
+; case jump
+?case: xchg ;switch value to DE
+ pop h ;get table address
+?case1: call ?case4 ;get case value
+ mov a,e
+ cmp c ;equal to switch value ?
+ jnz ?case2 ;no
+ mov a,d
+ cmp b ;equal to switch value ?
+ jnz ?case2 ;no
+ call ?case4 ;get case label
+ jz ?case3 ;end of table, go to default
+ push b
+ ret ;case jump
+?case2: call ?case4 ;get case label
+ jnz ?case1 ;next case
+?case3: dcx h
+ dcx h
+ dcx h
+ mov d,m
+ dcx h
+ mov e,m
+ xchg
+ pchl ;default jump
+?case4: mov c,m
+ inx h
+ mov b,m
+ inx h
+ mov a,c
+ ora b
+ ret
+;
+;
+;
+Xstktop: lxi h,0 ;return current stack pointer (for sbrk)
+ dad sp
+ ret
+ cseg
+etext:
+ dseg
+brkend: dw edata ;current "break"
+edata:
+;
+;
+;
+ end
--- /dev/null
+exit(retcode) int retcode; {
+#asm
+ jmp 0
+#endasm
+}
+
--- /dev/null
+inp(pno) char pno; {
+ pno;
+#asm
+ mov a,l
+ sta ininst+1 <tel:+1>
+ininst in 0 ; self modifying code...
+ mov l,a
+ xra a
+ mov h,a
+ ret
+#endasm
+
+}
+
+outp(pno, val) char pno, val; {
+ pno;
+#asm
+ mov a,l
+ sta outinst+1 <tel:+1>
+#endasm
+ val;
+#asm
+ mov a,l
+outinst out 0
+ ret
+#endasm
+}
+
--- /dev/null
+/* Basic CP/M file I/O:
+fopen,fclose,fgetc,fputc,feof
+
+Original: Paul Tarvydas
+Fixed by: Chris Lewis
+*/
+#include <stdio.h>
+
+#define EOL 10
+#define EOL2 13
+#define CPMEOF 26
+#define CPMERR 255
+#define UNIT_OFFSET 3
+#define CPMCIN 1
+#define CPMCOUT 2
+#define READ_EOF 3
+#define SETDMA 26
+#define DEFAULT_DMA 128
+#define CPMREAD 20
+#define CPMWR 21
+#define WRITE 2
+#define READ 1
+#define FREE 0
+#define NBUFFS 4
+#define BUFSIZ 512
+#define FCBSIZ 33
+#define ALLBUFFS 2048
+#define ALLFCBS 132
+#define CPMERA 19
+#define CPMCREAT 22
+#define CPMOPEN 15
+#define NBLOCKS 4
+#define BLKSIZ 128
+#define BKSP 8
+#define CTRLU 21
+#define FWSP ' '
+#define CPMCLOSE 16
+
+char buffs[ALLBUFFS], /* disk buffers */
+fcbs[ALLFCBS]; /* fcbs for buffers */
+int bptr[NBUFFS]; /* ptrs into buffers */
+int modes[NBUFFS]; /* mode for each open file */
+int eptr[NBUFFS]; /* buffers' ends */
+char eofstdin; /* flag end of file on stdin */
+
+fgetc(unit) int unit;
+{
+ int c;
+ while ((c = Xfgetc(unit)) == EOL2);
+ return c;
+
+}
+
+Xfgetc(unit) int unit;
+{
+ int i;
+ int c;
+ char *buff;
+ char *fcba;
+ if ((unit == stdin) & !eofstdin) {
+ c = bdos1(CPMCIN, 0);
+ if (c == 4) {
+ eofstdin = 1;
+ return (EOF);
+ }
+ else if (c == 3)
+ exit (1);
+ else {
+ if (c == EOL2) {
+ c = EOL;
+ bdos (CPMCOUT, EOL);
+ }
+ return (c);
+ }
+ }
+ if (modes[unit = unit - UNIT_OFFSET] == READ) {
+ if (bptr[unit] >= eptr[unit]) {
+ fcba = fcbaddr(unit);
+ /* fill da buffer again */
+ i = 0; /* block counter */
+ buff = buffaddr(unit); /* dma ptr */
+ /* if buffer wasn't totally
+ filled last time, we already
+ eof */
+ if (eptr[unit] == buffaddr(unit + 1))
+ do {
+ bdos(SETDMA, buff);
+ if (0!=bdos1(CPMREAD, fcba))
+ break;
+ buff = buff + BLKSIZ;
+ }
+ while (++i<NBLOCKS);
+ bdos(SETDMA, DEFAULT_DMA);
+ /* if i still 0, no blocks read =>eof*/
+ if (i==0) {
+ modes[unit] = READ_EOF;
+ return EOF;
+ }
+ /* o.k. set start & end ptrs */
+ eptr[unit] =
+ (bptr[unit]=buffaddr(unit))
+ + (i * BLKSIZ);
+ }
+ c = (*(bptr[unit]++)) & 0xff;
+ if (c == CPMEOF) {
+ c = EOF;
+ modes[unit] = READ_EOF;
+ }
+ return c;
+ }
+ return EOF;
+
+}
+
+fclose(unit) int unit;
+{
+ int i;
+ if ((unit==stdin)|(unit==stdout)|(unit==stderr))
+ return NULL;
+ if (modes[unit = unit - UNIT_OFFSET] != FREE) {
+ if (modes[unit] == WRITE)
+ fflush(unit + UNIT_OFFSET);
+ modes[unit] = FREE;
+ return bdos1(CPMCLOSE, fcbaddr(unit));
+ }
+ return EOF;
+
+}
+
+fflush(unit) int unit;
+{
+ char *buffa;
+ char *fcba;
+ if ((unit!=stdin)|(unit!=stdout)|(unit!=stderr)) {
+ /* put an eof at end of file */
+ fputc(CPMEOF, unit);
+ if (bptr[unit = unit - UNIT_OFFSET] !=
+ (buffa = buffaddr(unit))) {
+ /* some chars in buffer - flush them */
+ fcba = fcbaddr(unit);
+ do {
+ bdos(SETDMA, buffa);
+ if (0 != bdos1(CPMWR, fcba))
+ return (EOF);
+ }
+ while (bptr[unit] >
+ (buffa=buffa+BLKSIZ));
+ bdos(SETDMA, DEFAULT_DMA);
+ }
+ }
+ return NULL;
+
+}
+
+fputc(c, unit) char c;
+int unit;
+{
+ char *buffa;
+ char *fcba;
+ if (c == EOL) fputc(EOL2, unit);
+ if ((unit == stdout) | (unit == stderr)) {
+ bdos(CPMCOUT, c);
+ return c;
+ }
+ if (WRITE == modes[unit = unit - UNIT_OFFSET]) {
+ if (bptr[unit] >= eptr[unit]) {
+ /* no room - dump buffer */
+ fcba = fcbaddr(unit);
+ buffa=buffaddr(unit);
+ while (buffa < eptr[unit]) {
+ bdos(SETDMA, buffa);
+ if (0 != bdos1(CPMWR, fcba)) break;
+ buffa = buffa + BLKSIZ;
+ }
+ bdos(SETDMA, DEFAULT_DMA);
+ bptr[unit] = buffaddr(unit);
+ if (buffa < eptr[unit]) return EOF;
+ }
+ *(bptr[unit]++) = c;
+ return c;
+ }
+ return EOF;
+
+}
+
+allocunitno() {
+ int i;
+ /* returns # of first free buffer, EOF if none */
+ /* buffer is not reserved (ie. mode remains FREE) */
+ for (i = 0; i < NBUFFS; ++i)
+ if (modes[i] == FREE) break;
+ if (i >= NBUFFS) return EOF;
+ else return (i + UNIT_OFFSET);
+
+}
+
+fopen(name, mode) char *name, *mode;
+{
+ int fileno, fno2;
+ if (EOF != (fileno = allocunitno())) {
+ /* internal file # excludes units 0,1 & 2
+ since there's no buffers associated with
+ these units */
+ movname(clearfcb(fcbaddr(fno2 = fileno
+ - UNIT_OFFSET)), name);
+ if ('r' == *mode) {
+ if (bdos1(CPMOPEN, fcbaddr(fno2)) != CPMERR)
+ {
+ modes[fno2] = READ;
+ /* ptr>bufsiz => buffer empty*/
+ eptr[fno2] =
+ bptr[fno2] = buffaddr(fno2+1 <tel:+1>);
+ return fileno;
+ }
+ }
+ else if ('w' == *mode) {
+ bdos(CPMERA, fcbaddr(fno2));
+ if (bdos1(CPMCREAT, fcbaddr(fno2)) != CPMERR){
+ modes[fno2] = WRITE;
+ bptr[fno2] = buffaddr(fno2);
+ eptr[fno2] = buffaddr(fno2+1 <tel:+1>);
+ return fileno;
+ }
+ }
+ }
+ return NULL;
+
+}
+
+clearfcb(fcb) char fcb[];
+{
+ int i;
+ for (i=0; i<FCBSIZ; fcb[i++] = 0);
+ /* blank out name field */
+ for (i=1; i<12; fcb[i++] = ' ');
+ return fcb;
+
+}
+
+movname(fcb, str) char fcb[], *str;
+{
+ int i;
+ char c;
+ i = 1; /* first char of name @ pos 1 */
+ *fcb = 0;
+ if (':' == str[1]) {
+ c = toupper(str[0]);
+ if (('A' <= c) & ('B' >= c)) {
+ *fcb = (c - 'A' + 1);
+ str++;
+ str++;
+ }
+ }
+ while ((NULL != *str) & (i<9)) {
+ /* up to 8 chars into file name field */
+ if ('.' == *str) break;
+ fcb[i++] = toupper(*str++);
+ }
+ /* strip off excess chars - up to '.' (beginning of
+ extension name ) */
+ while ((NULL != *str) & ((*str) != '.')) ++str;
+ if (*str)
+ /* '.' is first char of *str now */
+ /* copy 3 chars of ext. if there */
+ for ( /* first char of ext @ pos 9 (8+1 <tel:+1>)*/
+i = 8;
+/* '.' is stripped by ++ 1st time */
+/* around */
+(NULL != *++str) & (12 > ++i);
+fcb[i] = toupper(*str)
+);
+ return fcb;
+
+}
+
+stdioinit() {
+ int i;
+ eofstdin = 0;
+ for (i=0; i<NBUFFS; modes[i++] = FREE);
+
+}
+
+fcbaddr(unit) int unit;
+{
+ /* returns address of fcb associated with given unit -
+ unit taken with origin 0 (ie. std's not included) */
+ return &fcbs[unit * FCBSIZ];
+
+}
+
+buffaddr(unit) int unit;
+{
+ return &buffs[unit * BUFSIZ];
+
+}
+
+feof (unit) FILE *unit;
+{
+ if ((unit == stdin) & eofstdin)
+ return 1;
+ if (modes[unit - UNIT_OFFSET] == READ_EOF)
+ return 1;
+ return 0;
+}
+
--- /dev/null
+ *** Moderator's README ***
+
+This directory contains the base source code for the smallC compiler
+(actually three versions: the 8080, 6809 and vax code generators are
+here also.)
+
+The "includes" directory contains headers which are intended to be
+included in
+user programs - the place where these files reside should be set in the
+Makefile
+as INCDIR. The directories "6809", "8080", and "vax" contain runtime
+support
+for the respective compilers. The directory "lib" contains the source code
+for some common C library functions (portable ones).
--- /dev/null
+.SUFFIXES: .c .rel
+
+CC = fcc
+CFLAGS = -DTINY -DM8080
+COPT = -O2
+
+OBJS = initials.rel data.rel error.rel expr.rel function.rel gen.rel io.rel lex.rel main.rel preproc.rel \
+ primary.rel stmt.rel sym.rel while.rel code6809.rel code8080.rel struct.rel
+
+INC = data.h defs.h prototype.h
+
+all: scc8080
+
+
+scc8080: $(OBJS)
+ $(CC) -o scc8080 --nostdio $(OBJS)
+
+#scc6809: $(OBJS)
+# $(CC) -o scc8080 --nostdio $(OBJS)
+
+clean:
+ rm -f $(OBJ) scc8080 *.rel *~
+
+.c.rel:
+ $(CC) $(COPT) $(CFLAGS) -c $< -o $@
+
+$(OBJS) : $(INC)
--- /dev/null
+
+README for version imported from github SmallC-85
+-------------------------------------------------
+
+Revived version of SmallC based on Chris Lewis' port to UNIX V. I have
+mainly rewritten code to use structures and to make it compile using GCC
+silently without warnigns.
+
+Support for one line comments from C99 specification was added as well
+as capability to handle Windows EOLs.
+
+Initialisation of global variables is also possible. When not initialised
+global var is assigned zero at compile time.
+
+Furthermore support for ANSI style method declaration, support for unsigned types,
+support for undocumented 8085 istructions LHLX, SHLX, LDSI, ARHL and support
+for structs and unions have been added.
+
+Generated code is suitable for ASXXXX assembler/linker.
+
+
+SmallC compiled for win32 can be downloaded here:
+https://drive.google.com/file/d/0B2TmWnRjWCj2alRqZHM1VEgwNFE/edit?usp=sharing
+
+-------------------------- original posting ------------------------------
+
+Small C version C3.0R1.1
+ (SCC3)
+
+ Chris Lewis
+
+This directory contains the source for a version of Ron Cain's Small C
+compiler that I have heavily modified - beyond the Small-C V2.0 later
+published in Dr. Dobbs. This compiler generates assembler source code that
+needs to be assembled and linked to make a running program.
+
+Small C is a public domain compiler for a subset of C. The main things
+lacking are "#if", structs/unions, doubles/floats/longs and more than
+one level of indirection. Even so, it's powerful enough to be able to
+compile itself. It's also lots of fun to play around with. It could
+use lots of more work (eg: a real scanner), but what the heck...
+Retargetting the compiler requires only relinking the frontend with a new
+code generator.
+
+Code generators for 6809 (MIT UNIX-like assembler), M68K (Motorola V/68
+UNIX
+assembler), VAX (BSD 4.1 assembler), and 8080 (RMAC assembler) are
+provided.
+
+Users having access to System V make should be able to use the Makefile
+without any modification except for INCDIR and LIBDIR (where you'd like
+to put the compiler itself).
+
+Users not having access to System V will probably have to rewrite the
+Makefile.
+[ I have provided a Makefile that seems to work with bsd systems - mod]
+
+WARNING: you will probably see a great deal of compilation warnings when
+you compile this compiler with a "real" UNIX C. Don't worry - this is
+*perfectly* normal - Small C is a subset of real C, and in order to
+keep the compiler in this subset you have to bend the rules somewhat.
+The only time where this might cause a problem is where pointers are
+"different" from ints (ie: different length or on non-byte-addressible
+machines). Small C assumes that ints are the same as pointers.
+
+Invocation:
+ scc<6809|vax|m68k|8080> filename
+
+There are other options available - see main.c for details.
+
+The code generated by these compilers need a run-time support library
+for two things: operations that are "hard" on a particular processor
+(eg: 16 bit multiply on an 8080), or O/S interface (vax is BSD 4.1,
+6809 is FLEX, 8080 is CPM, never had one for M68k).
+
+Status: the 6809, VAX and 8080 versions work last I checked - a problem or
+two may have crept in during the implementation of the compile/assemble/and
+link code for machines that support it. The M68k version has never been
+tested. I don't have a Pyramid version because Pyrcorp seems reluctant
+to publish instruction set information.
+
+So you want to write a new coder do you? Well, it's easy - read the
+comments in one of the coders. You should not have to modify *any* of
+the existing files, just write a new codexxx.c file. Please contact
+me if you run into trouble. I would be greatly interested in any new
+coders or bug reports in the compilers. As far as I am aware, the
+major restriction on porting this thing for different targets is that
+pointers and integers *must* be the same length, alignment, and be
+interchangeable.
--- /dev/null
+ Small C version C3.0R1.1
+ (SCC3)
+
+ Chris Lewis
+
+This directory contains the source for a version of Ron Cain's Small C
+compiler that I have heavily modified - beyond the Small-C V2.0 later
+published in Dr. Dobbs. This compiler generates assembler source code that
+needs to be assembled and linked to make a running program.
+
+Small C is a public domain compiler for a subset of C. The main things
+lacking are "#if", structs/unions, doubles/floats/longs and more than
+one level of indirection. Even so, it's powerful enough to be able to
+compile itself. It's also lots of fun to play around with. It could
+use lots of more work (eg: a real scanner), but what the heck...
+Retargetting the compiler requires only relinking the frontend with a new
+code generator.
+
+Code generators for 6809 (MIT UNIX-like assembler), M68K (Motorola V/68
+UNIX
+assembler), VAX (BSD 4.1 assembler), and 8080 (RMAC assembler) are
+provided.
+
+Users having access to System V make should be able to use the Makefile
+without any modification except for INCDIR and LIBDIR (where you'd like
+to put the compiler itself).
+
+Users not having access to System V will probably have to rewrite the
+Makefile.
+[ I have provided a Makefile that seems to work with bsd systems - mod]
+
+WARNING: you will probably see a great deal of compilation warnings when
+you compile this compiler with a "real" UNIX C. Don't worry - this is
+*perfectly* normal - Small C is a subset of real C, and in order to
+keep the compiler in this subset you have to bend the rules somewhat.
+The only time where this might cause a problem is where pointers are
+"different" from ints (ie: different length or on non-byte-addressible
+machines). Small C assumes that ints are the same as pointers.
+
+Invocation:
+ scc<6809|vax|m68k|8080> filename
+
+There are other options available - see main.c for details.
+
+The code generated by these compilers need a run-time support library
+for two things: operations that are "hard" on a particular processor
+(eg: 16 bit multiply on an 8080), or O/S interface (vax is BSD 4.1,
+6809 is FLEX, 8080 is CPM, never had one for M68k).
+
+Status: the 6809, VAX and 8080 versions work last I checked - a problem or
+two may have crept in during the implementation of the compile/assemble/and
+link code for machines that support it. The M68k version has never been
+tested. I don't have a Pyramid version because Pyrcorp seems reluctant
+to publish instruction set information.
+
+So you want to write a new coder do you? Well, it's easy - read the
+comments in one of the coders. You should not have to modify *any* of
+the existing files, just write a new codexxx.c file. Please contact
+me if you run into trouble. I would be greatly interested in any new
+coders or bug reports in the compilers. As far as I am aware, the
+major restriction on porting this thing for different targets is that
+pointers and integers *must* be the same length, alignment, and be
+interchangeable.
--- /dev/null
+/* File codeas09.c: 2.2 (84/08/31,10:05:13) */
+/*% cc -O -c %
+ *
+ * THIS IS FROM AN OLDER VERSION OF THE COMPILER: WILL NEED PORTING
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+#ifdef M6809
+
+/* Define ASNM and LDNM to the names of the assembler and linker
+ respectively */
+
+/*
+ * Some predefinitions:
+ *
+ * INTSIZE is the size of an integer in the target machine
+ * BYTEOFF is the offset of an byte within an integer on the
+ * target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
+ * 360 = 3)
+ * This compiler assumes that an integer is the SAME length as
+ * a pointer - in fact, the compiler uses INTSIZE for both.
+ */
+#define INTSIZE 2
+#define BYTEOFF 1
+
+void tab(void)
+{
+ output_byte('\t');
+}
+
+void ot(char ptr[])
+{
+ tab ();
+ output_string (ptr);
+
+}
+
+void ol(char ptr[])
+{
+ ot (ptr);
+ newline();
+}
+
+
+
+/*
+ * print all assembler info before any code is generated
+ *
+ */
+void header(void)
+{
+ output_string("|\tSmall C MC6809\n|\tCoder (2.4,84/11/27)\n|");
+ frontend_version();
+ newline();
+ ol (".globl\tsmul,sdiv,smod,asr,asl,neg,lneg,case");
+ ol (".globl\teq,ne,lt,le,gt,ge,ult,ule,ugt,uge,bool");
+
+}
+
+
+void initmac(void) {
+ defmac("mc6809\t1");
+ defmac("mitas09\t1");
+ defmac("smallc\t1");
+
+}
+
+int galign(int t)
+{
+ return (t);
+
+}
+
+/*
+ * return size of an integer
+ */
+int intsize(void) {
+ return(INTSIZE);
+
+}
+
+/*
+ * return offset of ls byte within word
+ * (ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
+ */
+int byteoff(void) {
+ return(BYTEOFF);
+}
+
+/*
+ * Output internal generated label prefix
+ */
+void olprfix(void) {
+ output_string("LL");
+
+}
+
+/*
+ * Output a label definition terminator
+ */
+void col(void)
+{
+ output_string ("=.\n");
+
+}
+
+/*
+ * begin a comment line for the assembler
+ *
+ */
+void comment(void)
+{
+ output_byte ('|');
+
+}
+
+/*
+ * Output a prefix in front of user labels
+ */
+void prefix(void) {
+ output_byte('_');
+
+}
+
+/*
+ * print any assembler stuff needed after all code
+ *
+ */
+void trailer(void)
+{
+ ol (".end");
+
+}
+
+/*
+ * function prologue
+ */
+void prologue(void)
+{
+
+}
+
+/*
+ * text (code) segment
+ */
+
+void gtext(void)
+{
+ ol (".text");
+
+}
+
+/*
+ * data segment
+ */
+void gdata(void)
+{
+ ol (".data");
+
+}
+
+/*
+ * Output the variable symbol at scptr as an extrn or a public
+ */
+void ppubext(char *scptr)
+{
+ if (scptr[STORAGE] == STATIC)
+ return;
+ ot (".globl\t");
+ prefix ();
+ output_string (scptr);
+ nl();
+
+}
+
+/*
+ * Output the function symbol at scptr as an extrn or a public
+ */
+void fpubext(char *scptr) {
+ ppubext(scptr);
+
+}
+
+/*
+ * Output a decimal number to the assembler file
+ */
+void onum(int num) {
+ output_decimal(num); /* pdp11 needs a "." here */
+ output_byte('.');
+}
+
+/*
+ * fetch a static memory cell into the primary register
+ */
+
+void getmem(char *sym)
+{
+ if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
+ ot ("ldb\t");
+ prefix ();
+ output_string (sym + NAME);
+ newline();
+ ot ("sex");
+ newline();
+ } else {
+ ot ("ldd\t");
+ prefix ();
+ output_string (sym + NAME);
+ newline();
+ }
+}
+
+/*
+ * fetch the address of the specified symbol into the primary register
+ *
+ */
+void getloc(char *sym)
+{
+ if (sym[STORAGE] == LSTATIC) {
+ immed();
+ printlabel(glint(sym));
+ nl();
+ } else {
+ ot ("leay\t");
+ onum (glint(sym) - stkp);
+ output_string ("(s)\n\ttfr\ty,d\n");
+ }
+
+}
+
+/*
+ * store the primary register into the specified static memory cell
+ *
+ */
+void putmem (char *sym)
+{
+ if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
+ ot ("stb\t");
+ } else
+ ot ("std\t");
+ prefix ();
+ output_string (sym + NAME);
+ newline();
+
+}
+
+/*
+ * store the specified object type in the primary register
+ * at the address on the top of the stack
+ *
+ */
+void putstk(char typeobj)
+{
+ if (typeobj == CCHAR)
+ ol ("stb\t@(s)++");
+ else
+ ol ("std\t@(s)++");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * fetch the specified object type indirect through the primary
+ * register into the primary register
+ *
+ */
+void indirect (char typeobj)
+{
+ ol("tfr\td,y");
+ if (typeobj == CCHAR)
+ ol ("ldb\t(y)\n\tsex");
+ else
+ ol ("ldd\t(y)");
+
+}
+
+/*
+ * swap the primary and secondary registers
+ *
+ */
+void swap(void)
+{
+ ol ("exg\td,x");
+
+}
+
+/*
+ * print partial instruction to get an immediate value into
+ * the primary register
+ *
+ */
+void immed(void)
+{
+ ot ("ldd\t#");
+
+}
+
+/*
+ * push the primary register onto the stack
+ *
+ */
+void gpush(void)
+{
+ ol ("pshs\td");
+ stkp = stkp - INTSIZE;
+
+}
+
+/*
+ * pop the top of the stack into the secondary register
+ *
+ */
+void gpop(void)
+{
+ ol ("puls\td");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * swap the primary register and the top of the stack
+ *
+ */
+void swapstk(void)
+{
+ ol ("ldy\t(s)\nstd\t(s)\n\ttfr\ty,d");
+
+}
+
+/*
+ * call the specified subroutine name
+ *
+ */
+void gcall(char *sname)
+{
+ ot ("jsr\t");
+ if (*sname == '^')
+ output_string (++sname);
+ else {
+ prefix ();
+ output_string (sname);
+ }
+ newline();
+
+}
+
+/*
+ * return from subroutine
+ *
+ */
+void gret(void)
+{
+ ol ("rts");
+
+}
+
+/*
+ * perform subroutine call to value on top of stack
+ *
+ */
+void callstk(void)
+{
+ gpop();
+ ol("jsr\t(x)");
+
+}
+
+/*
+ * jump to specified internal label number
+ *
+ */
+void jump(int label)
+{
+ ot ("lbra\t");
+ printlabel(label);
+ nl();
+
+}
+
+/*
+ * test the primary register and jump if false to label
+ *
+ */
+void testjump (int label, int ft)
+{
+ ol ("cmpd\t#0");
+ if (ft)
+ ot ("lbne\t");
+ else
+ ot ("lbeq\t");
+ printlabel (label);
+ newline();
+
+}
+
+/*
+ * print pseudo-op to define a byte
+ *
+ */
+void defbyte(void)
+{
+ ot (".byte\t");
+
+}
+
+/*
+ * print pseudo-op to define storage
+ *
+ */
+void defstorage(void)
+{
+ ot (".blkb\t");
+
+}
+
+/*
+ * print pseudo-op to define a word
+ *
+ */
+
+void defword(void)
+{
+ ot (".word\t");
+
+}
+
+/*
+ * modify the stack pointer to the new value indicated
+ *
+ */
+void modstk(int newstkp)
+{
+ int k;
+
+ k = galign(newstkp - stkp);
+ if (k == 0)
+ return (newstkp);
+ ot ("leas\t");
+ onum (k);
+ output_string ("(s)\n");
+ return (newstkp);
+
+}
+
+/*
+ * multiply the primary register by INTSIZE
+ */
+void gaslint(void)
+{
+ ol ("aslb\n\trola");
+
+}
+
+/*
+ * divide the primary register by INTSIZE
+ */
+void gasrint(void)
+{
+ ol ("asra\n\trorb");
+
+}
+
+/*
+ * Case jump instruction
+ */
+void gjcase(void) {
+ ot ("jmp\tcase");
+ newline();
+
+}
+
+/*
+ * add the primary and secondary registers
+ * if lval2 is int pointer and lval is int, scale lval
+ */
+void gadd (LVALUE *lval, LVALUE *lval2)
+{
+ if (dbltest (lval2, lval)) {
+ ol ("asl\t1(s)\n\trol\t(s)");
+ }
+ ol ("addd\t(s)++");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * subtract the primary register from the secondary
+ *
+ */
+void gsub(void)
+{
+ ol ("subd\t(s)++\n\tcoma\n\tcomb\n\taddd\t#1");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * multiply the primary and secondary registers
+ * (result in primary)
+ *
+ */
+void gmult(void)
+{
+ gcall ("^smul");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * divide the secondary register by the primary
+ * (quotient in primary, remainder in secondary)
+ *
+ */
+void gdiv(void)
+{
+ gcall ("^sdiv");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * compute the remainder (mod) of the secondary register
+ * divided by the primary register
+ * (remainder in primary, quotient in secondary)
+ *
+ */
+void gmod(void)
+{
+ gcall ("^smod");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * inclusive 'or' the primary and secondary registers
+ *
+ */
+void gor(void)
+{
+ ol ("ora\t(s)+\n\torb\t(s)+");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * exclusive 'or' the primary and secondary registers
+ *
+ */
+void gxor(void)
+{
+ ol ("eora\t(s)+\n\teorb\t(s)+");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * 'and' the primary and secondary registers
+ *
+ */
+void gand(void)
+{
+ ol ("anda\t(s)+\n\tandb\t(s)+");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * arithmetic shift right the secondary register the number of
+ * times in the primary register
+ * (results in primary register)
+ *
+ */
+void gasr(void)
+{
+ gcall ("^asr");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * arithmetic shift left the secondary register the number of
+ * times in the primary register
+ * (results in primary register)
+ *
+ */
+void gasl(void)
+{
+ gcall ("^asl");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * two's complement of primary register
+ *
+ */
+void gneg(void)
+{
+ gcall ("^neg");
+
+}
+
+/*
+ * logical complement of primary register
+ *
+ */
+void glneg(void)
+{
+ gcall ("^lneg");
+
+}
+
+/*
+ * one's complement of primary register
+ *
+ */
+void gcom(void)
+{
+ ol ("coma\n\tcomb");
+
+}
+
+/*
+ * convert primary register into logical value
+ *
+ */
+void gbool(void)
+{
+ gcall ("^bool");
+}
+
+/*
+ * increment the primary register by 1 if char, INTSIZE if
+ * int
+ */
+void ginc (int lval[])
+{
+ if (lval[2] == CINT)
+ ol ("addd\t#2");
+ else
+ ol ("addd\t#1");
+
+}
+
+/*
+ * decrement the primary register by one if char, INTSIZE if
+ * int
+ */
+void gdec(int lval[])
+{
+ if (lval[2] == CINT)
+ ol ("subd\t#2");
+ else
+ ol ("subd\t#1");
+
+}
+
+/*
+ * following are the conditional operators.
+ * they compare the secondary register against the primary register
+ * and put a literl 1 in the primary if the condition is true,
+ * otherwise they clear the primary register
+ *
+ */
+
+/*
+ * equal
+ *
+ */
+void geq(void)
+{
+ gcall ("^eq");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * not equal
+ *
+ */
+void gne(void)
+{
+ gcall ("^ne");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * less than (signed)
+ *
+ */
+void glt(void)
+{
+ gcall ("^lt");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * less than or equal (signed)
+ *
+ */
+void gle(void)
+{
+ gcall ("^le");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * greater than (signed)
+ *
+ */
+void ggt(void)
+{
+ gcall ("^gt");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * greater than or equal (signed)
+ *
+ */
+void gge(void)
+{
+ gcall ("^ge");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * less than (unsigned)
+ *
+ */
+void gult(void)
+{
+ gcall ("^ult");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * less than or equal (unsigned)
+ *
+ */
+void gule(void)
+{
+ gcall ("^ule");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * greater than (unsigned)
+ *
+ */
+void gugt(void)
+{
+ gcall ("^ugt");
+ stkp = stkp + INTSIZE;
+
+}
+
+/*
+ * greater than or equal (unsigned)
+ *
+ */
+void guge(void)
+{
+ gcall ("^uge");
+ stkp = stkp + INTSIZE;
+
+}
+
+char *inclib(void) {
+#ifdef flex
+ return("B.");
+#endif
+#ifdef unix
+ return(INCDIR);
+#endif
+#ifdef cpm
+ return("B:");
+#endif
+
+}
+
+/* Squirrel away argument count in a register that modstk/getloc/stloc
+ doesn't touch.
+*/
+
+void gnargs(int d)
+{
+ ot ("ldu\t#");
+ onum(d);
+ newline();
+
+}
+
+#endif
--- /dev/null
+/* File code8080.c: 2.2 (84/08/31,10:05:09) */
+/*% cc -O -c %
+ *
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+#ifdef M8080
+
+/* Define ASNM and LDNM to the names of the assembler and linker
+ respectively */
+
+/*
+ * Some predefinitions:
+ *
+ * INTSIZE is the size of an integer in the target machine
+ * BYTEOFF is the offset of an byte within an integer on the
+ * target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
+ * 360 = 3)
+ * This compiler assumes that an integer is the SAME length as
+ * a pointer - in fact, the compiler uses INTSIZE for both.
+ */
+
+/**
+ * print all assembler info before any code is generated
+ */
+void header (void) {
+ output_string ("; Small C 8080\n;\tCoder (2.4,84/11/27)\n;");
+ frontend_version();
+ newline ();
+ output_line ("\t;program area SMALLC_GENERATED is RELOCATABLE");
+ output_line ("\t.module SMALLC_GENERATED");
+ output_line ("\t.list (err, loc, bin, eqt, cyc, lin, src, lst, md)");
+ output_line ("\t.nlist (pag)");
+}
+
+/**
+ * prints new line
+ * @return
+ */
+void newline (void) {
+#if __CYGWIN__ == 1
+ output_byte (CR);
+#endif
+ output_byte (LF);
+}
+
+void initmac(void) {
+ defmac("cpm\t1");
+ defmac("I8080\t1");
+ defmac("RMAC\t1");
+ defmac("smallc\t1");
+}
+
+/**
+ * Output internal generated label prefix
+ */
+void output_label_prefix(void) {
+ output_byte('$');
+}
+
+/**
+ * Output a label definition terminator
+ */
+void output_label_terminator (void) {
+ output_byte (':');
+}
+
+/**
+ * begin a comment line for the assembler
+ */
+void gen_comment(void) {
+ output_byte (';');
+}
+
+/**
+ * print any assembler stuff needed after all code
+ */
+void trailer(void) {
+ output_line (";\t.end");
+}
+
+/**
+ * text (code) segment
+ */
+void code_segment_gtext(void) {
+ output_line ("\t.area SMALLC_GENERATED (REL,CON,CSEG)");
+}
+
+/**
+ * data segment
+ */
+void data_segment_gdata(void) {
+ output_line ("\t.area SMALLC_GENERATED_DATA (REL,CON,DSEG)");
+}
+
+/**
+ * Output the variable symbol at scptr as an extrn or a public
+ * @param scptr
+ */
+void ppubext(SYMBOL *scptr) {
+ if (symbol_table[current_symbol_table_idx].storage == STATIC) return;
+ output_with_tab (scptr->storage == EXTERN ? ";extrn\t" : ".globl\t");
+ output_string (scptr->name);
+ newline();
+}
+
+/**
+ * Output the function symbol at scptr as an extrn or a public
+ * @param scptr
+ */
+void fpubext(SYMBOL *scptr) {
+ if (scptr->storage == STATIC) return;
+ output_with_tab (scptr->offset == FUNCTION ? ".globl\t" : ";extrn\t");
+ output_string (scptr->name);
+ newline ();
+}
+
+/**
+ * Output a decimal number to the assembler file, with # prefix
+ * @param num
+ */
+void output_number(int num) {
+ output_byte('#');
+ output_decimal(num);
+}
+
+/**
+ * fetch a static memory cell into the primary register
+ * @param sym
+ */
+void gen_get_memory(SYMBOL *sym) {
+ if ((sym->identity != POINTER) && (sym->type == CCHAR)) {
+ output_with_tab ("lda\t");
+ output_string (sym->name);
+ newline ();
+ gen_call ("ccsxt");
+ } else if ((sym->identity != POINTER) && (sym->type == UCHAR)) {
+ output_with_tab("lda\t");
+ output_string(sym->name);
+ newline();
+ output_line("mov \tl,a");
+ output_line("mvi \th,#0");
+ } else {
+ output_with_tab ("lhld\t");
+ output_string (sym->name);
+ newline ();
+ }
+}
+
+/**
+ * asm - fetch the address of the specified symbol into the primary register
+ * @param sym the symbol name
+ * @return which register pair contains result
+ */
+int gen_get_locale(SYMBOL *sym) {
+ if (sym->storage == LSTATIC) {
+ gen_immediate();
+ print_label(sym->offset);
+ newline();
+ return HL_REG;
+ } else {
+ if (uflag && !(sym->identity == ARRAY)) {// ||
+ //(sym->identity == VARIABLE && sym->type == STRUCT))) {
+ output_with_tab("ldsi\t");
+ output_number(sym->offset - stkp);
+ newline ();
+ return DE_REG;
+ } else {
+ gen_immediate();
+ output_number(sym->offset - stkp);
+ newline ();
+ output_line ("dad \tsp");
+ return HL_REG;
+ }
+ }
+}
+
+/**
+ * asm - store the primary register into the specified static memory cell
+ * @param sym
+ */
+void gen_put_memory(SYMBOL *sym) {
+ if ((sym->identity != POINTER) && (sym->type & CCHAR)) {
+ output_line ("mov \ta,l");
+ output_with_tab ("sta \t");
+ } else {
+ output_with_tab ("shld\t");
+ }
+ output_string (sym->name);
+ newline ();
+}
+
+/**
+ * store the specified object type in the primary register
+ * at the address in secondary register (on the top of the stack)
+ * @param typeobj
+ */
+void gen_put_indirect(char typeobj) {
+ gen_pop ();
+ if (typeobj & CCHAR) {
+ //gen_call("ccpchar");
+ output_line("mov \ta,l");
+ output_line("stax\td");
+ } else {
+ if (uflag) {
+ output_line("shlx");
+ } else {
+ gen_call("ccpint");
+ }
+ }
+}
+
+/**
+ * fetch the specified object type indirect through the primary
+ * register into the primary register
+ * @param typeobj object type
+ */
+void gen_get_indirect(char typeobj, int reg) {
+ if (typeobj == CCHAR) {
+ if (reg & DE_REG) {
+ gen_swap();
+ }
+ gen_call("ccgchar");
+ } else if (typeobj == UCHAR) {
+ if (reg & DE_REG) {
+ gen_swap();
+ }
+ //gen_call("cguchar");
+ output_line("mov \tl,m");
+ output_line("mvi \th,0");
+ } else { // int
+ if (uflag) {
+ if (reg & HL_REG) {
+ gen_swap();
+ }
+ output_line("lhlx");
+ } else {
+ gen_call("ccgint");
+ }
+ }
+}
+
+/**
+ * swap the primary and secondary registers
+ */
+void gen_swap(void) {
+ output_line("xchg");
+}
+
+/**
+ * print partial instruction to get an immediate value into
+ * the primary register
+ */
+void gen_immediate(void) {
+ output_with_tab ("lxi \th,");
+}
+
+/**
+ * push the primary register onto the stack
+ */
+void gen_push(int reg) {
+ if (reg & DE_REG) {
+ output_line ("push\td");
+ stkp = stkp - INTSIZE;
+ } else {
+ output_line ("push\th");
+ stkp = stkp - INTSIZE;
+ }
+}
+
+/**
+ * pop the top of the stack into the secondary register
+ */
+void gen_pop(void) {
+ output_line ("pop \td");
+ stkp = stkp + INTSIZE;
+}
+
+/**
+ * swap the primary register and the top of the stack
+ */
+void gen_swap_stack(void) {
+ output_line ("xthl");
+}
+
+/**
+ * call the specified subroutine name
+ * @param sname subroutine name
+ */
+void gen_call(char *sname) {
+ output_with_tab ("call\t");
+ output_string (sname);
+ newline ();
+}
+
+/**
+ * declare entry point
+ */
+void declare_entry_point(char *symbol_name) {
+ output_string(symbol_name);
+ output_label_terminator();
+ //newline();
+}
+
+/**
+ * return from subroutine
+ */
+void gen_ret(void) {
+ output_line ("ret");
+}
+
+/**
+ * perform subroutine call to value on top of stack
+ */
+void callstk(void) {
+ gen_immediate ();
+ output_string ("#.+5");
+ newline ();
+ gen_swap_stack ();
+ output_line ("pchl");
+ stkp = stkp + INTSIZE;
+}
+
+/**
+ * jump to specified internal label number
+ * @param label the label
+ */
+void gen_jump(int label)
+{
+ output_with_tab ("jmp \t");
+ print_label (label);
+ newline ();
+}
+
+/**
+ * test the primary register and jump if false to label
+ * @param label the label
+ * @param ft if true jnz is generated, jz otherwise
+ */
+void gen_test_jump(int label, int ft)
+{
+ output_line ("mov \ta,h");
+ output_line ("ora \tl");
+ if (ft)
+ output_with_tab ("jnz \t");
+ else
+ output_with_tab ("jz \t");
+ print_label (label);
+ newline ();
+}
+
+/**
+ * print pseudo-op to define a byte
+ */
+void gen_def_byte(void) {
+ output_with_tab (".db\t");
+}
+
+/**
+ * print pseudo-op to define storage
+ */
+void gen_def_storage(void) {
+ output_with_tab (".ds\t");
+}
+
+/**
+ * print pseudo-op to define a word
+ */
+void gen_def_word(void) {
+ output_with_tab (".dw\t");
+}
+
+/**
+ * modify the stack pointer to the new value indicated
+ * @param newstkp new value
+ */
+int gen_modify_stack(int newstkp) {
+ int k;
+
+ k = newstkp - stkp;
+ if (k == 0)
+ return (newstkp);
+ if (k > 0) {
+ if (k < 7) {
+ if (k & 1) {
+ output_line ("inx \tsp");
+ k--;
+ }
+ while (k) {
+ output_line ("pop \tb");
+ k = k - INTSIZE;
+ }
+ return (newstkp);
+ }
+ } else {
+ if (k > -7) {
+ if (k & 1) {
+ output_line ("dcx \tsp");
+ k++;
+ }
+ while (k) {
+ output_line ("push\tb");
+ k = k + INTSIZE;
+ }
+ return (newstkp);
+ }
+ }
+ gen_swap ();
+ gen_immediate ();
+ output_number (k);
+ newline ();
+ output_line ("dad \tsp");
+ output_line ("sphl");
+ gen_swap ();
+ return (newstkp);
+}
+
+/**
+ * multiply the primary register by INTSIZE
+ */
+void gen_multiply_by_two(void) {
+ output_line ("dad \th");
+}
+
+/**
+ * divide the primary register by INTSIZE, never used
+ */
+void gen_divide_by_two(void) {
+ gen_push(HL_REG); /* push primary in prep for gasr */
+ gen_immediate ();
+ output_number (1);
+ newline ();
+ gen_arithm_shift_right (); /* divide by two */
+}
+
+/**
+ * Case jump instruction
+ */
+void gen_jump_case(void) {
+ output_with_tab ("jmp \tcccase");
+ newline ();
+}
+
+/**
+ * add the primary and secondary registers
+ * if lval2 is int pointer and lval is not, scale lval
+ * @param lval
+ * @param lval2
+ */
+void gen_add(LVALUE *lval, LVALUE *lval2) {
+ gen_pop ();
+ if (dbltest (lval2, lval)) {
+ gen_swap ();
+ gen_multiply_by_two ();
+ gen_swap ();
+ }
+ output_line ("dad \td");
+}
+
+/**
+ * subtract the primary register from the secondary
+ */
+void gen_sub(void) {
+ gen_pop ();
+ gen_call ("ccsub");
+}
+
+/**
+ * multiply the primary and secondary registers (result in primary)
+ */
+void gen_mult(void) {
+ gen_pop();
+ gen_call ("ccmul");
+}
+
+/**
+ * divide the secondary register by the primary
+ * (quotient in primary, remainder in secondary)
+ */
+void gen_div(void) {
+ gen_pop();
+ gen_call ("ccdiv");
+}
+
+/**
+ * unsigned divide the secondary register by the primary
+ * (quotient in primary, remainder in secondary)
+ */
+void gen_udiv(void) {
+ gen_pop();
+ gen_call ("ccudiv");
+}
+
+/**
+ * compute the remainder (mod) of the secondary register
+ * divided by the primary register
+ * (remainder in primary, quotient in secondary)
+ */
+void gen_mod(void) {
+ gen_div ();
+ gen_swap ();
+}
+
+/**
+ * compute the remainder (mod) of the secondary register
+ * divided by the primary register
+ * (remainder in primary, quotient in secondary)
+ */
+void gen_umod(void) {
+ gen_udiv ();
+ gen_swap ();
+}
+
+/**
+ * inclusive 'or' the primary and secondary registers
+ */
+void gen_or(void) {
+ gen_pop();
+ gen_call ("ccor");
+}
+
+/**
+ * exclusive 'or' the primary and secondary registers
+ */
+void gen_xor(void) {
+ gen_pop();
+ gen_call ("ccxor");
+}
+
+/**
+ * 'and' the primary and secondary registers
+ */
+void gen_and(void) {
+ gen_pop();
+ gen_call ("ccand");
+}
+
+/**
+ * arithmetic shift right the secondary register the number of
+ * times in the primary register (results in primary register)
+ */
+void gen_arithm_shift_right(void) {
+ gen_pop();
+ gen_call ("ccasr");
+}
+
+/**
+ * logically shift right the secondary register the number of
+ * times in the primary register (results in primary register)
+ */
+void gen_logical_shift_right(void) {
+ gen_pop();
+ gen_call ("cclsr");
+}
+
+/**
+ * arithmetic shift left the secondary register the number of
+ * times in the primary register (results in primary register)
+ */
+void gen_arithm_shift_left(void) {
+ gen_pop ();
+ gen_call ("ccasl");
+}
+
+/**
+ * two's complement of primary register
+ */
+void gen_twos_complement(void) {
+ gen_call ("ccneg");
+}
+
+/**
+ * logical complement of primary register
+ */
+void gen_logical_negation(void) {
+ gen_call ("cclneg");
+}
+
+/**
+ * one's complement of primary register
+ */
+void gen_complement(void) {
+ gen_call ("cccom");
+}
+
+/**
+ * Convert primary value into logical value (0 if 0, 1 otherwise)
+ */
+void gen_convert_primary_reg_value_to_bool(void) {
+ gen_call ("ccbool");
+}
+
+/**
+ * increment the primary register by 1 if char, INTSIZE if int
+ */
+void gen_increment_primary_reg(LVALUE *lval) {
+ switch (lval->ptr_type) {
+ case STRUCT:
+ gen_immediate2();
+ output_number(lval->tagsym->size);
+ newline();
+ output_line("dad \td");
+ break ;
+ case CINT:
+ case UINT:
+ output_line("inx \th");
+ default:
+ output_line("inx \th");
+ break;
+ }
+}
+
+/**
+ * decrement the primary register by one if char, INTSIZE if int
+ */
+void gen_decrement_primary_reg(LVALUE *lval) {
+ output_line("dcx \th");
+ switch (lval->ptr_type) {
+ case CINT:
+ case UINT:
+ output_line("dcx \th");
+ break;
+ case STRUCT:
+ gen_immediate2();
+ output_number(lval->tagsym->size - 1);
+ newline();
+ // two's complement
+ output_line("mov \ta,d");
+ output_line("cma");
+ output_line("mov \td,a");
+ output_line("mov \ta,e");
+ output_line("cma");
+ output_line("mov \te,a");
+ output_line("inx \td");
+ // substract
+ output_line("dad \td");
+ break ;
+ default:
+ break;
+ }
+}
+
+/**
+ * following are the conditional operators.
+ * they compare the secondary register against the primary register
+ * and put a literal 1 in the primary if the condition is true,
+ * otherwise they clear the primary register
+ */
+
+/**
+ * equal
+ */
+void gen_equal(void) {
+ gen_pop();
+ gen_call ("cceq");
+}
+
+/**
+ * not equal
+ */
+void gen_not_equal(void) {
+ gen_pop();
+ gen_call ("ccne");
+}
+
+/**
+ * less than (signed)
+ */
+void gen_less_than(void) {
+ gen_pop();
+ gen_call ("cclt");
+}
+
+/**
+ * less than or equal (signed)
+ */
+void gen_less_or_equal(void) {
+ gen_pop();
+ gen_call ("ccle");
+}
+
+/**
+ * greater than (signed)
+ */
+void gen_greater_than(void) {
+ gen_pop();
+ gen_call ("ccgt");
+}
+
+/**
+ * greater than or equal (signed)
+ */
+void gen_greater_or_equal(void) {
+ gen_pop();
+ gen_call ("ccge");
+}
+
+/**
+ * less than (unsigned)
+ */
+void gen_unsigned_less_than(void) {
+ gen_pop();
+ gen_call ("ccult");
+}
+
+/**
+ * less than or equal (unsigned)
+ */
+void gen_unsigned_less_or_equal(void) {
+ gen_pop();
+ gen_call ("ccule");
+}
+
+/**
+ * greater than (unsigned)
+ */
+void gen_usigned_greater_than(void) {
+ gen_pop();
+ gen_call ("ccugt");
+}
+
+/**
+ * greater than or equal (unsigned)
+ */
+void gen_unsigned_greater_or_equal(void) {
+ gen_pop();
+ gen_call ("ccuge");
+}
+
+char *inclib(void) {
+#ifdef cpm
+ return("B:");
+#endif
+#ifdef unix
+#ifdef INCDIR
+ return(INCDIR);
+#else
+ return "";
+#endif
+#endif
+}
+
+/**
+ * Squirrel away argument count in a register that modstk doesn't touch.
+ * @param d
+ */
+void gnargs(int d)
+{
+ output_with_tab ("mvi \ta,");
+ output_number(d);
+ newline ();
+}
+
+/**
+ * print partial instruction to get an immediate value into
+ * the secondary register
+ */
+void gen_immediate2(void) {
+ output_with_tab ("lxi \td,");
+}
+
+/**
+ * add offset to primary register
+ * @param val the value
+ */
+void add_offset(int val) {
+ gen_immediate2();
+ output_number(val);
+ newline();
+ output_line ("dad \td");
+}
+
+/**
+ * multiply the primary register by the length of some variable
+ * @param type
+ * @param size
+ */
+void gen_multiply(int type, int size) {
+ switch (type) {
+ case CINT:
+ case UINT:
+ gen_multiply_by_two();
+ break;
+ case STRUCT:
+ gen_immediate2();
+ output_number(size);
+ newline();
+ gen_call("ccmul");
+ break ;
+ default:
+ break;
+ }
+}
+
+#endif
--- /dev/null
+/* File data.c: 2.2 (84/11/27,16:26:13) */
+/*% cc -O -c %
+ *
+ */
+
+#include <stdio.h>
+#include "defs.h"
+
+/* storage words */
+SYMBOL symbol_table[NUMBER_OF_GLOBALS + NUMBER_OF_LOCALS];
+int global_table_index, rglobal_table_index;
+int local_table_index;
+
+WHILE ws[WSTABSZ];
+int while_table_index;
+
+int swstcase[SWSTSZ];
+int swstlab[SWSTSZ];
+int swstp;
+char litq[LITABSZ];
+int litptr;
+char macq[MACQSIZE];
+int macptr;
+char line[LINESIZE];
+char mline[LINESIZE];
+int lptr, mptr;
+
+TAG_SYMBOL tag_table[NUMTAG]; // start of structure tag table
+int tag_table_index; // ptr to next entry
+
+SYMBOL member_table[NUMMEMB]; // structure member table
+int member_table_index; // ptr to next member
+
+/* miscellaneous storage */
+int nxtlab,
+ litlab,
+ stkp,
+ argstk,
+ ncmp,
+ errcnt,
+ glbflag,
+ ctext,
+ cmode,
+ lastst;
+
+int input, input2, output;
+int inclstk[INCLSIZ] = {-1, -1, -1 };
+int inclsp;
+char fname[20];
+char input_eof;
+
+//char quote[2];
+int current_symbol_table_idx; //char *cptr;
+int *iptr;
+int fexitlab;
+int iflevel, skiplevel;
+int errfile;
+int cflag;
+int errs;
+int aflag;
+int uflag; // undocumented 8085 instructions
+
+INITIALS initials_table[NUMBER_OF_GLOBALS];
+char initials_data_table[INITIALS_SIZE]; // 5kB space for initialisation data
+int initials_idx = 0, initials_data_idx = 0;
--- /dev/null
+/* File data.h: 2.2 (84/11/27,16:26:11) */
+
+/* storage words */
+extern SYMBOL symbol_table[NUMBER_OF_GLOBALS + NUMBER_OF_LOCALS];
+extern int global_table_index, rglobal_table_index;
+extern int local_table_index;
+extern WHILE ws[];
+extern int while_table_index;
+extern int swstcase[];
+extern int swstlab[];
+extern int swstp;
+extern char litq[];
+extern int litptr;
+extern char macq[];
+extern int macptr;
+extern char line[];
+extern char mline[];
+extern int lptr, mptr;
+
+extern TAG_SYMBOL tag_table[NUMTAG]; // start of structure tag table
+extern int tag_table_index; // ptr to next entry
+
+extern SYMBOL member_table[NUMMEMB]; // structure member table
+extern int member_table_index; // ptr to next member<
+
+/* miscellaneous storage */
+extern int nxtlab,
+ litlab,
+ stkp,
+ argstk,
+ ncmp,
+ errcnt,
+ glbflag,
+ ctext,
+ cmode,
+ lastst;
+
+extern int input, input2, output;
+extern int inclstk[];
+extern int inclsp;
+extern char fname[];
+extern char input_eof;
+
+extern char quote[];
+extern int current_symbol_table_idx; //extern char *cptr;
+extern int *iptr;
+extern int fexitlab;
+extern int iflevel, skiplevel;
+extern int errfile;
+extern int cflag;
+extern int errs;
+extern int aflag;
+extern int uflag; // undocumented 8085 instructions
+
+extern INITIALS initials_table[NUMBER_OF_GLOBALS];
+extern char initials_data_table[INITIALS_SIZE]; // 5kB space for initialisation data
+extern int initials_idx, initials_data_idx;
--- /dev/null
+/*
+ * File defs.h: 2.1 (83/03/21,02:07:20)
+ */
+
+// Intel 8080 architecture defs
+#if defined(M6809) || defined(M8080)
+#define INTSIZE 2
+#endif
+
+// miscellaneous
+#define FOREVER for(;;)
+#define FALSE 0
+#define TRUE 1
+#define NO 0
+#define YES 1
+
+#define EOS 0
+#define LF 10
+#define BKSP 8
+#define CR 13
+#define FFEED 12
+#define TAB 9
+
+#ifdef TINY
+#define NAMESIZE 17
+#define NAMEMAX 16
+#else
+// system-wide name size (for symbols)
+#define NAMESIZE 33
+#define NAMEMAX 32
+#endif
+
+struct symbol {
+ char name[NAMESIZE]; // symbol name
+ unsigned char identity; // variable, array, pointer, function
+ unsigned char storage; // public, auto, extern, static, lstatic, defauto
+ int type; // char, int, uchar, unit
+ int offset; // offset
+ int tagidx; // index of struct in tag table
+};
+#define SYMBOL struct symbol
+
+#define NUMBER_OF_GLOBALS 100
+#define NUMBER_OF_LOCALS 20
+
+// Define the structure tag table parameters
+#define NUMTAG 10
+
+struct tag_symbol {
+ char name[NAMESIZE]; // structure tag name
+ int size; // size of struct in bytes
+ int member_idx; // index of first member
+ int number_of_members; // number of tag members
+};
+#define TAG_SYMBOL struct tag_symbol
+
+#ifdef SMALL_C
+#define NULL_TAG 0
+#else
+#define NULL_TAG (TAG_SYMBOL *)0
+#endif
+
+// Define the structure member table parameters
+#define NUMMEMB 30
+
+// possible entries for "ident"
+#define VARIABLE 1
+#define ARRAY 2
+#define POINTER 3
+#define FUNCTION 4
+
+/**
+ * possible entries for "type"
+ * high order 14 bits give length of object
+ * low order 2 bits make type unique within length
+ */
+#define UNSIGNED 1
+#define STRUCT 2
+#define CCHAR (1 << 2)
+#define UCHAR ((1 << 2) + 1)
+#define CINT (2 << 2)
+#define UINT ((2 << 2) + 1)
+
+// possible entries for storage
+#define PUBLIC 1
+#define AUTO 2
+#define EXTERN 3
+
+#define STATIC 4
+#define LSTATIC 5
+#define DEFAUTO 6
+
+// "do"/"for"/"while"/"switch" statement stack
+#define WSTABSZ 20
+
+struct while_rec {
+ int symbol_idx; // symbol table address
+ int stack_pointer; // stack pointer
+ int type; // type
+ int case_test; // case or test
+ int incr_def; // continue label ?
+ int body_tab; // body of loop, switch ?
+ int while_exit; // exit label
+};
+#define WHILE struct while_rec
+
+/* possible entries for "wstyp" */
+#define WSWHILE 0
+#define WSFOR 1
+#define WSDO 2
+#define WSSWITCH 3
+
+/* "switch" label stack */
+#define SWSTSZ 100
+
+/* literal pool */
+#ifdef TINY
+#define LITABSZ 2500
+#else
+#define LITABSZ 5000
+#endif
+#define LITMAX LITABSZ-1
+
+/* input line */
+#define LINESIZE 150
+#define LINEMAX (LINESIZE-1)
+#define MPMAX LINEMAX
+
+#ifdef TINY
+#define MACQSIZE 500
+#define MACMAX (MACQSIZE-1)
+#else
+/* macro (define) pool */
+#define MACQSIZE 1500
+#define MACMAX (MACQSIZE-1)
+#endif
+
+/* "include" stack */
+#define INCLSIZ 3
+
+/* statement types (tokens) */
+#define STIF 1
+#define STWHILE 2
+#define STRETURN 3
+#define STBREAK 4
+#define STCONT 5
+#define STASM 6
+#define STEXP 7
+#define STDO 8
+#define STFOR 9
+#define STSWITCH 10
+
+#define DEFLIB inclib()
+
+#define FETCH 1
+#define HL_REG 1<<1
+#define DE_REG 1<<2
+
+struct lvalue {
+ SYMBOL *symbol; // symbol table address, or 0 for constant
+ int indirect; // type of indirect object, 0 for static object
+ int ptr_type; // type of pointer or array, 0 for other idents
+ TAG_SYMBOL *tagsym; // tag symbol address, 0 if not struct
+};
+#define LVALUE struct lvalue
+
+/**
+ * path to include directories. set at compile time on host machine
+ * @return
+ */
+char *inclib(void);
+
+/**
+ * Output the variable symbol at scptr as an extrn or a public
+ * @param scptr
+ */
+void ppubext(SYMBOL *scptr);
+
+/**
+ * Output the function symbol at scptr as an extrn or a public
+ * @param scptr
+ */
+void fpubext(SYMBOL *scptr);
+
+/**
+ * fetch a static memory cell into the primary register
+ * @param sym
+ */
+void gen_get_memory(SYMBOL *sym);
+
+/**
+ * fetch the specified object type indirect through the primary
+ * register into the primary register
+ * @param typeobj object type
+ */
+void gen_get_indirect(char typeobj, int reg);
+
+/**
+ * asm - store the primary register into the specified static memory cell
+ * @param sym
+ */
+void gen_put_memory(SYMBOL *sym);
+
+// initialisation of global variables
+#define INIT_TYPE NAMESIZE
+#define INIT_LENGTH NAMESIZE+1
+#define INITIALS_SIZE 5*1024
+
+struct initials_table {
+ char name[NAMESIZE]; // symbol name
+ int type; // type
+ int dim; // length of data (possibly an array)
+ int data_len; // index of tag or zero
+};
+#define INITIALS struct initials_table
+
+/**
+ * determine if 'sname' is a member of the struct with tag 'tag'
+ * @param tag
+ * @param sname
+ * @return pointer to member symbol if it is, else 0
+ */
+SYMBOL *find_member(TAG_SYMBOL *tag, char *sname);
+
+#include "prototype.h"
--- /dev/null
+/* File error.c: 2.1 (83/03/20,16:02:00) */
+/*% cc -O -c %
+ *
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+void error (char *ptr)
+{
+ int tempfile;
+
+ tempfile = output;
+ output = 1;
+ doerror(ptr);
+ output = tempfile;
+ doerror(ptr);
+ errcnt++;
+}
+
+void doerror(char *ptr)
+{
+ int k;
+ gen_comment ();
+ output_string (line);
+ newline ();
+ gen_comment ();
+ k = 0;
+ while (k < lptr) {
+ if (line[k] == 9)
+ print_tab ();
+ else
+ output_byte (' ');
+ k++;
+ }
+ output_byte ('^');
+ newline ();
+ gen_comment ();
+ output_string ("****** ");
+ output_string (ptr);
+ output_string (" ******");
+ newline ();
+}
+
--- /dev/null
+/*
+ * File expr.c: 2.2 (83/06/21,11:24:26)
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+/**
+ * unsigned operand ?
+ */
+int nosign(LVALUE *is) {
+ SYMBOL *ptr;
+
+ if((is->ptr_type) ||
+ ((ptr = is->symbol) && (ptr->type & UNSIGNED))) {
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * lval.symbol - symbol table address, else 0 for constant
+ * lval.indirect - type indirect object to fetch, else 0 for static object
+ * lval.ptr_type - type pointer or array, else 0
+ * @param comma
+ * @return
+ */
+void expression(int comma) {
+ LVALUE lval;
+ int k;
+
+ do {
+ k = hier1 (&lval);
+ if (k & FETCH)
+ rvalue(&lval, k);
+ if (!comma)
+ return;
+ } while (match (","));
+}
+
+/**
+ * assignment operators
+ * @param lval
+ * @return
+ */
+int hier1 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+ char fc;
+
+ k = hier1a (lval);
+ if (match ("=")) {
+ if ((k & FETCH) == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval->indirect)
+ gen_push(k);
+ k = hier1 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ store (lval);
+ return (0);
+ } else {
+ fc = ch();
+ if (match ("-=") ||
+ match ("+=") ||
+ match ("*=") ||
+ match ("/=") ||
+ match ("%=") ||
+ match (">>=") ||
+ match ("<<=") ||
+ match ("&=") ||
+ match ("^=") ||
+ match ("|=")) {
+ if ((k & FETCH) == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval->indirect)
+ gen_push(k);
+ k = rvalue(lval, k);
+ gen_push(k);
+ k = hier1 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ switch (fc) {
+ case '-': {
+ if (dbltest(lval,lval2)) {
+ gen_multiply(lval->ptr_type, lval->tagsym ? lval->tagsym->size : INTSIZE);
+ }
+ gen_sub();
+ result (lval, lval2);
+ break;
+ }
+ case '+': {
+ if (dbltest(lval,lval2)) {
+ gen_multiply(lval->ptr_type, lval->tagsym ? lval->tagsym->size : INTSIZE);
+ }
+ gen_add (lval,lval2);
+ result(lval,lval2);
+ break;
+ }
+ case '*': gen_mult (); break;
+ case '/':
+ if(nosign(lval) || nosign(lval2)) {
+ gen_udiv();
+ } else {
+ gen_div();
+ }
+ break;
+ case '%':
+ if(nosign(lval) || nosign(lval2)) {
+ gen_umod();
+ } else {
+ gen_mod();
+ }
+ break;
+ case '>':
+ if (nosign(lval)) {
+ gen_logical_shift_right();
+ } else {
+ gen_arithm_shift_right();
+ }
+ break;
+ case '<': gen_arithm_shift_left(); break;
+ case '&': gen_and (); break;
+ case '^': gen_xor (); break;
+ case '|': gen_or (); break;
+ }
+ store (lval);
+ return (0);
+ } else
+ return (k);
+ }
+}
+
+/**
+ * processes ? : expression
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier1a (LVALUE *lval) {
+ int k, lab1, lab2;
+ LVALUE lval2[1];
+
+ k = hier1b (lval);
+ blanks ();
+ if (ch () != '?')
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER
+ if (match ("?")) {
+ gen_test_jump (lab1 = getlabel (), FALSE);
+ k = hier1b (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ gen_jump (lab2 = getlabel ());
+ print_label (lab1);
+ output_label_terminator ();
+ newline ();
+ blanks ();
+ if (!match (":")) {
+ error ("missing colon");
+ return (0);
+ }
+ k = hier1b (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ print_label (lab2);
+ output_label_terminator ();
+ newline ();
+ } else
+ return (0);
+}
+
+/**
+ * processes logical or ||
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier1b (LVALUE *lval) {
+ int k, lab;
+ LVALUE lval2[1];
+
+ k = hier1c (lval);
+ blanks ();
+ if (!sstreq ("||"))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER
+ if (match ("||")) {
+ gen_test_jump (lab = getlabel (), TRUE);
+ k = hier1c (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ print_label (lab);
+ output_label_terminator ();
+ newline ();
+ gen_convert_primary_reg_value_to_bool();
+ } else
+ return (0);
+}
+
+/**
+ * processes logical and &&
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier1c (LVALUE *lval) {
+ int k, lab;
+ LVALUE lval2[1];
+
+ k = hier2 (lval);
+ blanks ();
+ if (!sstreq ("&&"))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER
+ if (match ("&&")) {
+ gen_test_jump (lab = getlabel (), FALSE);
+ k = hier2 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ print_label (lab);
+ output_label_terminator ();
+ newline ();
+ gen_convert_primary_reg_value_to_bool();
+ } else
+ return (0);
+}
+
+/**
+ * processes bitwise or |
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier2 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+
+ k = hier3 (lval);
+ blanks ();
+ if ((ch() != '|') | (nch() == '|') | (nch() == '='))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER {
+ if ((ch() == '|') & (nch() != '|') & (nch() != '=')) {
+ inbyte ();
+ gen_push(k);
+ k = hier3 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ gen_or ();
+ blanks();
+ } else
+ return (0);
+ }
+}
+
+/**
+ * processes bitwise exclusive or
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier3 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+
+ k = hier4 (lval);
+ blanks ();
+ if ((ch () != '^') | (nch() == '='))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER {
+ if ((ch() == '^') & (nch() != '=')){
+ inbyte ();
+ gen_push(k);
+ k = hier4 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ gen_xor ();
+ blanks();
+ } else
+ return (0);
+ }
+}
+
+/**
+ * processes bitwise and &
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier4 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+
+ k = hier5 (lval);
+ blanks ();
+ if ((ch() != '&') | (nch() == '|') | (nch() == '='))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER {
+ if ((ch() == '&') & (nch() != '&') & (nch() != '=')) {
+ inbyte ();
+ gen_push(k);
+ k = hier5 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ gen_and ();
+ blanks();
+ } else
+ return (0);
+ }
+
+}
+
+/**
+ * processes equal and not equal operators
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier5 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+
+ k = hier6 (lval);
+ blanks ();
+ if (!sstreq ("==") &
+ !sstreq ("!="))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER {
+ if (match ("==")) {
+ gen_push(k);
+ k = hier6 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ gen_equal ();
+ } else if (match ("!=")) {
+ gen_push(k);
+ k = hier6 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ gen_not_equal ();
+ } else
+ return (0);
+ }
+
+}
+
+/**
+ * comparison operators
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier6 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+
+ k = hier7 (lval);
+ blanks ();
+ if (!sstreq ("<") &&
+ !sstreq ("<=") &&
+ !sstreq (">=") &&
+ !sstreq (">"))
+ return (k);
+ if (sstreq ("<<") || sstreq (">>"))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER {
+ if (match ("<=")) {
+ gen_push(k);
+ k = hier7 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ if (nosign(lval) || nosign(lval2)) {
+ gen_unsigned_less_or_equal ();
+ continue;
+ }
+ gen_less_or_equal ();
+ } else if (match (">=")) {
+ gen_push(k);
+ k = hier7 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ if (nosign(lval) || nosign(lval2)) {
+ gen_unsigned_greater_or_equal ();
+ continue;
+ }
+ gen_greater_or_equal();
+ } else if ((sstreq ("<")) &&
+ !sstreq ("<<")) {
+ inbyte ();
+ gen_push(k);
+ k = hier7 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ if (nosign(lval) || nosign(lval2)) {
+ gen_unsigned_less_than ();
+ continue;
+ }
+ gen_less_than ();
+ } else if ((sstreq (">")) &&
+ !sstreq (">>")) {
+ inbyte ();
+ gen_push(k);
+ k = hier7 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ if (nosign(lval) || nosign(lval2)) {
+ gen_usigned_greater_than ();
+ continue;
+ }
+ gen_greater_than();
+ } else
+ return (0);
+ blanks ();
+ }
+
+}
+
+/**
+ * bitwise left, right shift
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier7 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+
+ k = hier8(lval);
+ blanks();
+ if ((!sstreq (">>") &&
+ !sstreq ("<<")) || sstreq(">>=") || sstreq("<<="))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER {
+ if (sstreq(">>") && ! sstreq(">>=")) {
+ inbyte(); inbyte();
+ gen_push(k);
+ k = hier8 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ if (nosign(lval)) {
+ gen_logical_shift_right();
+ } else {
+ gen_arithm_shift_right();
+ }
+ } else if (sstreq("<<") && ! sstreq("<<=")) {
+ inbyte(); inbyte();
+ gen_push(k);
+ k = hier8 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ gen_arithm_shift_left();
+ } else
+ return (0);
+ blanks();
+ }
+
+}
+
+/**
+ * addition, subtraction
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier8 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+
+ k = hier9 (lval);
+ blanks ();
+ if ((ch () != '+') & (ch () != '-') | nch() == '=')
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER {
+ if (match ("+")) {
+ gen_push(k);
+ k = hier9 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ // if left is pointer and right is int, scale right
+ if (dbltest(lval,lval2)) {
+ gen_multiply(lval->ptr_type, lval->tagsym ? lval->tagsym->size : INTSIZE);
+ }
+ // will scale left if right int pointer and left int
+ gen_add (lval,lval2);
+ result (lval, lval2);
+ } else if (match ("-")) {
+ gen_push(k);
+ k = hier9 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ /* if dbl, can only be: pointer - int, or
+ pointer - pointer, thus,
+ in first case, int is scaled up,
+ in second, result is scaled down. */
+ if (dbltest(lval,lval2)) {
+ gen_multiply(lval->ptr_type, lval->tagsym ? lval->tagsym->size : INTSIZE);
+ }
+ gen_sub ();
+ /* if both pointers, scale result */
+ if ((lval->ptr_type & CINT) && (lval2->ptr_type & CINT)) {
+ gen_divide_by_two(); /* divide by intsize */
+ }
+ result (lval, lval2);
+ } else
+ return (0);
+ }
+}
+
+/**
+ * multiplication, division, modulus
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier9 (LVALUE *lval) {
+ int k;
+ LVALUE lval2[1];
+
+ k = hier10 (lval);
+ blanks ();
+ if (((ch () != '*') && (ch () != '/') &&
+ (ch () != '%')) || (nch() == '='))
+ return (k);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ FOREVER {
+ if (match ("*")) {
+ gen_push(k);
+ k = hier10 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ gen_mult ();
+ } else if (match ("/")) {
+ gen_push(k);
+ k = hier10 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ if(nosign(lval) || nosign(lval2)) {
+ gen_udiv();
+ } else {
+ gen_div ();
+ }
+ } else if (match ("%")) {
+ gen_push(k);
+ k = hier10 (lval2);
+ if (k & FETCH)
+ k = rvalue(lval2, k);
+ if(nosign(lval) || nosign(lval2)) {
+ gen_umod();
+ } else {
+ gen_mod ();
+ }
+ } else
+ return (0);
+ }
+
+}
+
+/**
+ * increment, decrement, negation operators
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier10 (LVALUE *lval) {
+ int k;
+ SYMBOL *ptr;
+
+ if (match ("++")) {
+ if (((k = hier10 (lval)) & FETCH) == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval->indirect)
+ gen_push(k);
+ k = rvalue(lval, k);
+ gen_increment_primary_reg (lval);
+ store (lval);
+ return (HL_REG);
+ } else if (match ("--")) {
+ if (((k = hier10 (lval)) & FETCH) == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval->indirect)
+ gen_push(k);
+ k = rvalue(lval, k);
+ gen_decrement_primary_reg (lval);
+ store (lval);
+ return (HL_REG);
+ } else if (match ("-")) {
+ k = hier10 (lval);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ gen_twos_complement();
+ return (HL_REG);
+ } else if (match ("~")) {
+ k = hier10 (lval);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ gen_complement ();
+ return (HL_REG);
+ } else if (match ("!")) {
+ k = hier10 (lval);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ gen_logical_negation();
+ return (HL_REG);
+ } else if (ch()=='*' && nch() != '=') {
+ inbyte();
+ k = hier10 (lval);
+ if (k & FETCH)
+ k = rvalue(lval, k);
+ if ((ptr = lval->symbol) != 0)
+ lval->indirect = ptr->type;
+ else
+ lval->indirect = CINT;
+ lval->ptr_type = 0; // flag as not pointer or array
+ return FETCH | k;
+ } else if (ch()=='&' && nch()!='&' && nch()!='=') {
+ inbyte();
+ k = hier10 (lval);
+ if ((k & FETCH) == 0) {
+ error ("illegal address");
+ return (0);
+ }
+ ptr = lval->symbol;
+ lval->ptr_type = ptr->type;
+ if (lval->indirect) {
+ if (k & DE_REG) {
+ gen_swap();
+ }
+ return (HL_REG);
+ }
+ // global and non-array
+ gen_immediate ();
+ output_string ((ptr = lval->symbol)->name);
+ newline ();
+ lval->indirect = ptr->type;
+ return (HL_REG);
+ } else {
+ k = hier11 (lval);
+ if (match ("++")) {
+ if ((k & FETCH) == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval->indirect)
+ gen_push(k);
+ k = rvalue(lval, k);
+ gen_increment_primary_reg (lval);
+ store (lval);
+ gen_decrement_primary_reg (lval);
+ return (HL_REG);
+ } else if (match ("--")) {
+ if ((k & FETCH) == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval->indirect)
+ gen_push(k);
+ k = rvalue(lval, k);
+ gen_decrement_primary_reg (lval);
+ store (lval);
+ gen_increment_primary_reg (lval);
+ return (HL_REG);
+ } else
+ return (k);
+ }
+
+}
+
+/**
+ * array subscripting
+ * @param lval
+ * @return 0 or 1, fetch or no fetch
+ */
+int hier11(LVALUE *lval) {
+ int direct, k;
+ SYMBOL *ptr;
+ char sname[NAMESIZE];
+
+ k = primary(lval);
+ ptr = lval->symbol;
+ blanks();
+ if ((ch () == '[') || (ch () == '(') || (ch () == '.') || ((ch () == '-') && (nch() == '>')))
+ FOREVER {
+ if (match("[")) {
+ if (ptr == 0) {
+ error("can't subscript");
+ junk();
+ needbrack("]");
+ return (0);
+ } else if (ptr->identity == POINTER) {
+ k = rvalue(lval, k);
+ } else if (ptr->identity != ARRAY) {
+ error("can't subscript");
+ k = 0;
+ }
+ gen_push(k);
+ expression (YES);
+ needbrack ("]");
+ gen_multiply(ptr->type, tag_table[ptr->tagidx].size);
+ gen_add (NULL,NULL);
+ //lval->symbol = 0;
+ lval->indirect = ptr->type;
+ lval->ptr_type = 0;
+ k = FETCH | HL_REG;
+ } else if (match ("(")) {
+ if (ptr == 0) {
+ callfunction(0);
+ } else if (ptr->identity != FUNCTION) {
+ k = rvalue(lval, k);
+ callfunction(0);
+ } else {
+ callfunction(ptr->name);
+ }
+ lval->symbol = 0;
+ k = 0;
+ } else if ((direct=match(".")) || match("->")) {
+ if (lval->tagsym == 0) {
+ error("can't take member");
+ junk();
+ return 0;
+ }
+ if (symname(sname) == 0 ||
+ ((ptr=find_member(lval->tagsym, sname)) == 0)) {
+ error("unknown member");
+ junk();
+ return 0;
+ }
+ if ((k & FETCH) && direct == 0) {
+ k = rvalue(lval, k);
+ }
+ if (k == DE_REG) {
+ gen_swap();
+ }
+ add_offset(ptr->offset); // move pointer from struct begin to struct member
+ lval->symbol = ptr;
+ lval->indirect = ptr->type; // lval->indirect = lval->val_type = ptr->type
+ lval->ptr_type = 0;
+ lval->tagsym = NULL_TAG;
+ if (ptr->type == STRUCT) {
+ lval->tagsym = &tag_table[ptr->tagidx];
+ }
+ if (ptr->identity == POINTER) {
+ lval->indirect = CINT;
+ lval->ptr_type = ptr->type;
+ //lval->val_type = CINT;
+ }
+ if (ptr->identity==ARRAY ||
+ (ptr->type==STRUCT && ptr->identity==VARIABLE)) {
+ // array or struct
+ lval->ptr_type = ptr->type;
+ //lval->val_type = CINT;
+ k = 0;
+ } else {
+ k = FETCH | HL_REG;
+ }
+ }
+ else return k;
+ }
+ if (ptr == 0)
+ return k;
+ if (ptr->identity == FUNCTION) {
+ gen_immediate();
+ output_string(ptr->name);
+ newline();
+ return 0;
+ }
+ return k;
+}
+
--- /dev/null
+/*
+ * File function.c: 2.1 (83/03/20,16:02:04)
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+int argtop;
+
+/**
+ * begin a function
+ * called from "parse", this routine tries to make a function out
+ * of what follows
+ * modified version. p.l. woods
+ */
+void newfunc(void) {
+ char n[NAMESIZE];
+ int idx, type;
+ fexitlab = getlabel();
+
+ if (!symname(n)) {
+ error("illegal function or declaration");
+ do_kill();
+ return;
+ }
+ if ((idx = find_global(n)) > -1) {
+ if (symbol_table[idx].identity != FUNCTION)
+ multidef(n);
+ else if (symbol_table[idx].offset == FUNCTION)
+ multidef(n);
+ else
+ symbol_table[idx].offset = FUNCTION;
+ } else
+ add_global(n, FUNCTION, CINT, FUNCTION, PUBLIC);
+ if (!match("("))
+ error("missing open paren");
+ output_string(n);
+ output_label_terminator();
+ newline();
+ local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC;
+ argstk = 0;
+ // ANSI style argument declaration
+ if (doAnsiArguments() == 0) {
+ // K&R style argument declaration
+ while (!match(")")) {
+ if (symname(n)) {
+ if (find_locale(n) > -1)
+ multidef(n);
+ else {
+ add_local(n, 0, 0, argstk, AUTO);
+ argstk = argstk + INTSIZE;
+ }
+ } else {
+ error("illegal argument name");
+ junk();
+ }
+ blanks();
+ if (!streq(line + lptr, ")")) {
+ if (!match(","))
+ error("expected comma");
+ }
+ if (endst())
+ break;
+ }
+ stkp = 0;
+ argtop = argstk;
+ while (argstk) {
+ if ((type = get_type()) != 0) {
+ getarg(type);
+ need_semicolon();
+ } else {
+ error("wrong number args");
+ break;
+ }
+ }
+ }
+ statement(YES);
+ print_label(fexitlab);
+ output_label_terminator();
+ newline();
+ gen_modify_stack(0);
+ gen_ret();
+ stkp = 0;
+ local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC;
+}
+
+/**
+ * declare argument types
+ * called from "newfunc", this routine adds an entry in the local
+ * symbol table for each named argument
+ * completely rewritten version. p.l. woods
+ * @param t argument type (char, int)
+ * @return
+ */
+void getarg(int t) {
+ int j, legalname, address, argptr;
+ char n[NAMESIZE];
+
+ FOREVER
+ {
+ if (argstk == 0)
+ return;
+ if (match("*"))
+ j = POINTER;
+ else
+ j = VARIABLE;
+ if (!(legalname = symname(n)))
+ illname();
+ if (match("[")) {
+ while (inbyte() != ']')
+ if (endst())
+ break;
+ j = POINTER;
+ }
+ if (legalname) {
+ if ((argptr = find_locale(n)) > -1) {
+ symbol_table[argptr].identity = j;
+ symbol_table[argptr].type = t;
+ address = argtop - symbol_table[argptr].offset;
+ symbol_table[argptr].offset = address;
+ } else
+ error("expecting argument name");
+ }
+ argstk = argstk - INTSIZE;
+ if (endst())
+ return;
+ if (!match(","))
+ error("expected comma");
+ }
+}
+
+int doAnsiArguments(void) {
+ int type;
+ type = get_type();
+ if (type == 0) {
+ return 0; // no type detected, revert back to K&R style
+ }
+ argtop = argstk;
+ argstk = 0;
+ FOREVER
+ {
+ if (type) {
+ doLocalAnsiArgument(type);
+ } else {
+ error("wrong number args");
+ break;
+ }
+ if (match(",")) {
+ type = get_type();
+ continue;
+ }
+ if (match(")")) {
+ break;
+ }
+ }
+ return 1;
+}
+
+void doLocalAnsiArgument(int type) {
+ char symbol_name[NAMESIZE];
+ int identity, address, argptr, ptr;
+
+ if (match("*")) {
+ identity = POINTER;
+ } else {
+ identity = VARIABLE;
+ }
+ if (symname(symbol_name)) {
+ if (find_locale(symbol_name) > -1) {
+ multidef(symbol_name);
+ } else {
+ argptr = add_local (symbol_name, identity, type, 0, AUTO);
+ argstk = argstk + INTSIZE;
+ ptr = local_table_index;
+ while (ptr != NUMBER_OF_GLOBALS) { // modify stack offset as we push more params
+ ptr = ptr - 1;
+ address = symbol_table[ptr].offset;
+ symbol_table[ptr].offset = address + INTSIZE;
+ }
+ }
+ } else {
+ error("illegal argument name");
+ junk();
+ }
+ if (match("[")) {
+ while (inbyte() != ']') {
+ if (endst()) {
+ break;
+ }
+ }
+ identity = POINTER;
+ symbol_table[argptr].identity = identity;
+ }
+}
+
--- /dev/null
+/* File gen.c: 2.1 (83/03/20,16:02:06) */
+/*% cc -O -c %
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "defs.h"
+#include "data.h"
+
+static char obuf[512];
+static char *optr = obuf;
+
+void oflush(void)
+{
+ if (write(output, obuf, optr-obuf) != optr-obuf)
+ error("I/O error");
+ optr = obuf;
+}
+
+/**
+ * return next available internal label number
+ */
+int getlabel(void) {
+ return (nxtlab++);
+}
+
+/**
+ * print specified number as label
+ * @param label
+ */
+void print_label(int label) {
+ output_label_prefix ();
+ output_decimal (label);
+}
+
+/**
+ * glabel - generate label
+ * not used ?
+ * @param lab label number
+ */
+void glabel(char *lab) {
+ output_string (lab);
+ output_label_terminator ();
+ newline ();
+}
+
+/**
+ * gnlabel - generate numeric label
+ * @param nlab label number
+ * @return
+ */
+void generate_label(int nlab) {
+ print_label (nlab);
+ output_label_terminator ();
+ newline ();
+}
+
+/**
+ * outputs one byte
+ * @param c
+ * @return
+ */
+int output_byte(char c) {
+ if (c == 0)
+ return (0);
+ if (optr == obuf + sizeof(obuf))
+ oflush();
+ *optr++ = c;
+//FIX
+ oflush();
+ return (c);
+}
+
+/**
+ * outputs a string
+ * @param ptr the string
+ * @return
+ */
+void output_string(char ptr[]) {
+ int k;
+ k = 0;
+ while (output_byte (ptr[k++]));
+}
+
+/**
+ * outputs a tab
+ * @return
+ */
+void print_tab(void) {
+ output_byte ('\t');
+}
+
+/**
+ * output line
+ * @param ptr
+ * @return
+ */
+void output_line(char ptr[])
+{
+ output_with_tab (ptr);
+ newline ();
+}
+
+/**
+ * tabbed output
+ * @param ptr
+ * @return
+ */
+void output_with_tab(char ptr[]) {
+ print_tab ();
+ output_string (ptr);
+}
+
+#ifdef __linux__
+char *_itoa(int n)
+{
+ static char buf[32];
+ snprintf(buf, 32, "%d", n);
+ return buf;
+}
+#endif
+
+/**
+ * output decimal number
+ * @param number
+ * @return
+ */
+void output_decimal(int number) {
+ char *p = _itoa(number);
+ output_string(p);
+}
+
+/**
+ * stores values into memory
+ * @param lval
+ * @return
+ */
+void store(LVALUE *lval) {
+ if (lval->indirect == 0)
+ gen_put_memory (lval->symbol);
+ else
+ gen_put_indirect (lval->indirect);
+}
+
+int rvalue(LVALUE *lval, int reg) {
+ if ((lval->symbol != 0) && (lval->indirect == 0))
+ gen_get_memory (lval->symbol);
+ else
+ gen_get_indirect (lval->indirect, reg);
+ return HL_REG;
+}
+
+/**
+ * parses test part "(expression)" input and generates assembly for jump
+ * @param label
+ * @param ft : false - test jz, true test jnz
+ * @return
+ */
+void test(int label, int ft) {
+ needbrack ("(");
+ expression (YES);
+ needbrack (")");
+ gen_test_jump (label, ft);
+}
+
+/**
+ * scale constant depending on type
+ * @param type
+ * @param otag
+ * @param size
+ * @return
+ */
+void scale_const(int type, int otag, int *size) {
+ switch (type) {
+ case CINT:
+ case UINT:
+ *size += *size;
+ break;
+ case STRUCT:
+ *size *= tag_table[otag].size;
+ break;
+ default:
+ break;
+ }
+}
--- /dev/null
+/* Nothing needed in this file */
--- /dev/null
+#define stdin 0
+#define stdout 1
+#define stderr 2
+#define NULL 0
+#define EOF (-1)
+#define FILE char
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "data.h"
+
+/**
+ * erase the data storage
+ */
+void create_initials(void) {
+ /*int i;
+ for (i=0; i<INITIALS_SIZE; i++) {
+ initials_data_table[i] = 0;
+ }
+ for (i=0; i<NUMBER_OF_GLOBALS; i++) {
+ initials_table[i].type = 0;
+ initials_table[i].name[0] = 0;
+ initials_table[i].dim = 0;
+ initials_table[i].data_len = 0;
+ }*/
+}
+
+/**
+ * add new symbol to table, initialise begin position in data array
+ * @param symbol_name
+ * @param type
+ */
+void add_symbol_initials(char *symbol_name, char type) {
+ strcpy(initials_table[initials_idx].name, symbol_name);
+ initials_table[initials_idx].type = type;
+}
+
+/**
+ * find symbol in table, count position in data array
+ * @param symbol_name
+ * @return
+ */
+int find_symbol_initials(char *symbol_name) {
+ int result = 0;
+ initials_data_idx = 0;
+ for (initials_idx=0; initials_table[initials_idx].type != 0; initials_idx++) {
+ if (initials_idx >= NUMBER_OF_GLOBALS) {
+ error("initials table overrun");
+ }
+ if (astreq (symbol_name, initials_table[initials_idx].name, NAMEMAX) != 0) {
+ result = 1;
+ break;
+ } else { // move to next symbol
+ // count position in data array
+ initials_data_idx += initials_table[initials_idx].data_len;
+ }
+ }
+ return result;
+}
+
+/**
+ * add data to table for given symbol
+ * @param symbol_name
+ * @param type
+ * @param value
+ * @param tag
+ */
+void add_data_initials(char *symbol_name, int type, int value, TAG_SYMBOL *tag) {
+ int position;
+ if (find_symbol_initials(symbol_name) == 0) {
+ add_symbol_initials(symbol_name, tag == 0 ? type : STRUCT);
+ }
+ if (tag != 0) {
+ // find number of members, dim is total number of values added
+ int index = initials_table[initials_idx].dim % tag->number_of_members;
+ int member_type = member_table[tag->member_idx + index].type;
+ // add it recursively
+ add_data_initials(symbol_name, member_type, value, 0);
+ } else {
+ position = initials_table[initials_idx].data_len;
+ if (type & CCHAR) {
+ initials_data_table[initials_data_idx + position] = 0xff & value;
+ initials_table[initials_idx].data_len += 1;
+ } else if (type & CINT) {
+ initials_data_table[initials_data_idx + position] = (0xff00 & value) >> 8;
+ initials_data_table[initials_data_idx + position + 1] = 0xff & value;
+ initials_table[initials_idx].data_len += INTSIZE;
+ }
+ initials_table[initials_idx].dim += 1;
+ }
+}
+
+/**
+ * get number of data items for given symbol
+ * @param symbol_name
+ * @return
+ */
+int get_size(char *symbol_name) {
+ int result = 0;
+ if (find_symbol_initials(symbol_name) != 0) {
+ result = initials_table[initials_idx].dim;
+ }
+ return result;
+}
+
+/**
+ * get item at position
+ * @param symbol_name
+ * @param position
+ * @param itag index of tag in tag table
+ * @return
+ */
+int get_item_at(char *symbol_name, int position, TAG_SYMBOL *tag) {
+ int result = 0, i, type;
+ if (find_symbol_initials(symbol_name) != 0) {
+ if (initials_table[initials_idx].type & CCHAR) {
+ result = initials_data_table[initials_data_idx + position];
+ } else if (initials_table[initials_idx].type & CINT) {
+ position *= INTSIZE;
+ result = (initials_data_table[initials_data_idx + position] << 8) +
+ (unsigned char)initials_data_table[initials_data_idx + position+1];
+ } else if (initials_table[initials_idx].type == STRUCT) {
+ // find number of members
+ int number_of_members = tag->number_of_members;
+ // point behind the last full struct
+ int index = (position / number_of_members) * tag->size;
+ // move to required member
+ for (i=0; i < (position % number_of_members); i++) {
+ type = member_table[tag->member_idx + i].type;
+ if (type & CCHAR) {
+ index += 1;
+ } else {
+ index += INTSIZE;
+ }
+ }
+ // get value
+ type = member_table[tag->member_idx + i].type;
+ if (type & CCHAR) {
+ result = initials_data_table[initials_data_idx + index];
+ } else {
+ result = (initials_data_table[initials_data_idx + index] << 8) +
+ (unsigned char)initials_data_table[initials_data_idx + index+1];
+ }
+ }
+ }
+ return result;
+}
--- /dev/null
+/* File io.c: 2.1 (83/03/20,16:02:07) */
+/*% cc -O -c %
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "defs.h"
+#include "data.h"
+
+/*
+ * open input file
+ */
+int openin(char *p)
+{
+ strcpy(fname, p);
+ fixname (fname);
+ if (!checkname (fname))
+ return (NO);
+ if ((input = open(fname, O_RDONLY)) == -1) {
+ pl ("Open failure\n");
+ return (NO);
+ }
+ do_kill();
+ return (YES);
+
+}
+
+/*
+ * open output file
+ */
+int openout(void)
+{
+ outfname (fname);
+ if ((output = open (fname, O_WRONLY|O_TRUNC|O_CREAT, 0644)) == -1) {
+ pl ("Open failure");
+ return (NO);
+ }
+ do_kill();
+ return (YES);
+
+}
+
+/*
+ * change input filename to output filename
+ */
+void outfname(char *s)
+{
+ while (*s)
+ s++;
+ *--s = 's';
+
+}
+
+/**
+ * remove NL from filenames
+ */
+void fixname(char *s)
+{
+ while (*s && *s++ != LF);
+ if (!*s) return;
+ *(--s) = 0;
+
+}
+
+/**
+ * check that filename is "*.c"
+ */
+int checkname(char *s)
+{
+ while (*s)
+ s++;
+ if (*--s != 'c')
+ return (NO);
+ if (*--s != '.')
+ return (NO);
+ return (YES);
+
+}
+
+void do_kill(void) {
+ lptr = 0;
+ line[lptr] = 0;
+}
+
+int igetc(int unit)
+{
+ unsigned char c;
+ int err;
+ err = read(unit, &c, 1);
+ if (err == 1)
+ return (int)c;
+ if (err == 0) {
+ if (unit == input)
+ input_eof = 1;
+ return -1;
+ }
+ writee("I/O error");
+ exit(1);
+}
+
+void readline(void) {
+ int k;
+ int unit;
+
+ FOREVER {
+ if (input_eof)
+ return;
+ if ((unit = input2) == -1)
+ unit = input;
+ do_kill();
+ while ((k = igetc(unit)) != EOF) {
+ if ((k == CR) || (k == LF) | (lptr >= LINEMAX))
+ break;
+ line[lptr++] = k;
+ }
+ line[lptr] = 0;
+ if (k <= 0)
+ if (input2 != -1) {
+ input2 = inclstk[--inclsp];
+ close (unit);
+ }
+ if (lptr) {
+ if ((ctext) & (cmode)) {
+ gen_comment ();
+ output_string (line);
+ newline ();
+ }
+ lptr = 0;
+ return;
+ }
+ }
+}
+
+int inbyte(void) {
+ while (ch () == 0) {
+ if (input_eof)
+ return (0);
+ preprocess ();
+ }
+ return (gch ());
+}
+
+int inchar(void) {
+ if (ch () == 0)
+ readline ();
+ if (input_eof)
+ return (0);
+ return (gch ());
+}
+
+/**
+ * gets current char from input line and moves to the next one
+ * @return current char
+ */
+int gch(void) {
+ if (ch () == 0)
+ return (0);
+ else
+ return (line[lptr++] & 127);
+}
+
+/**
+ * returns next char
+ * @return next char
+ */
+int nch (void) {
+ if (ch () == 0)
+ return (0);
+ else
+ return (line[lptr + 1] & 127);
+}
+
+/**
+ * returns current char
+ * @return current char
+ */
+int ch (void) {
+ return (line[lptr] & 127);
+}
+
+/*
+ * print a carriage return and a string only to console
+ *
+ */
+void pl (char *str)
+{
+ write(1, "\n", 1);
+ write(1, str, strlen(str));
+}
+
+
+void writee(char *str)
+{
+ write(2, str, strlen(str));
+}
--- /dev/null
+/* File lex.c: 2.1 (83/03/20,16:02:09) */
+/*% cc -O -c %
+ *
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+/**
+ * test if given character is alpha
+ * @param c
+ * @return
+ */
+
+int alpha(char c) {
+ c = c & 127;
+ return (((c >= 'a') && (c <= 'z')) ||
+ ((c >= 'A') && (c <= 'Z')) ||
+ (c == '_'));
+}
+
+/**
+ * test if given character is numeric
+ * @param c
+ * @return
+ */
+int numeric(char c) {
+ c = c & 127;
+ return ((c >= '0') && (c <= '9'));
+}
+
+/**
+ * test if given character is alphanumeric
+ * @param c
+ * @return
+ */
+int alphanumeric(char c) {
+ return ((alpha (c)) || (numeric (c)));
+}
+
+/**
+ * semicolon enforcer
+ * called whenever syntax requires a semicolon
+ */
+void need_semicolon(void) {
+ if (!match (";"))
+ error ("missing semicolon");
+}
+
+void junk(void) {
+ if (alphanumeric (inbyte ()))
+ while (alphanumeric (ch ()))
+ gch ();
+ else
+ while (alphanumeric (ch ())) {
+ if (ch () == 0)
+ break;
+ gch ();
+ }
+ blanks ();
+}
+
+int endst(void) {
+ blanks ();
+ return ((streq (line + lptr, ";") | (ch () == 0)));
+}
+
+/**
+ * enforces bracket
+ * @param str
+ * @return
+ */
+void needbrack(char *str) {
+ if (!match (str)) {
+ error ("missing bracket");
+ gen_comment ();
+ output_string (str);
+ newline ();
+ }
+}
+
+/**
+ *
+ * @param str1
+ * @return
+ */
+int sstreq(char *str1) {
+ return (streq(line + lptr, str1));
+}
+
+/**
+ * indicates whether or not the current substring in the source line matches a
+ * literal string
+ * accepts the address of the current character in the source
+ * line and the address of the a literal string, and returns the substring length
+ * if a match occurs and zero otherwise
+ * @param str1 address1
+ * @param str2 address2
+ * @return
+ */
+int streq(char str1[], char str2[]) {
+ int k;
+ k = 0;
+ while (str2[k]) {
+ if ((str1[k] != str2[k]))
+ return (0);
+ k++;
+ }
+ return (k);
+}
+
+/**
+ * compares two string both must be zero ended, otherwise no match found
+ * ensures that the entire token is examined
+ * @param str1
+ * @param str2
+ * @param len
+ * @return
+ */
+int astreq(char str1[], char str2[], int len) {
+ int k;
+ k = 0;
+ while (k < len) {
+ if ((str1[k] != str2[k]))
+ break;
+ if (str1[k] == 0)
+ break;
+ if (str2[k] == 0)
+ break;
+ k++;
+ }
+ if (alphanumeric (str1[k]))
+ return (0);
+ if (alphanumeric (str2[k]))
+ return (0);
+ return (k);
+}
+
+/**
+ * looks for a match between a literal string and the current token in
+ * the input line. It skips over the token and returns true if a match occurs
+ * otherwise it retains the current position in the input line and returns false
+ * there is no verification that all of the token was matched
+ * @param lit
+ * @return
+ */
+int match(char *lit) {
+ int k;
+ blanks();
+ if ((k = streq (line + lptr, lit)) != 0) {
+ lptr = lptr + k;
+ return (1);
+ }
+ return (0);
+}
+
+/**
+ * compares two string both must be zero ended, otherwise no match found
+ * advances line pointer only if match found
+ * it assumes that an alphanumeric (including underscore) comparison
+ * is being made and guarantees that all of the token in the source line is
+ * scanned in the process
+ * @param lit
+ * @param len
+ * @return
+ */
+int amatch(char *lit, int len) {
+ int k;
+
+ blanks();
+ if ((k = astreq (line + lptr, lit, len)) != 0) {
+ lptr = lptr + k;
+ while (alphanumeric (ch ()))
+ inbyte ();
+ return (1);
+ }
+ return (0);
+}
+
+void blanks(void) {
+ FOREVER {
+ while (ch () == 0) {
+ preprocess ();
+ if (input_eof)
+ break;
+ }
+ if (ch () == ' ')
+ gch ();
+ else if (ch () == 9)
+ gch ();
+ else
+ return;
+ }
+}
+
+/**
+ * returns declaration type
+ * @return CCHAR, CINT, UCHAR, UINT
+ */
+int get_type(void) {
+ if (amatch ("register", 8)) {
+ if (amatch("char", 4))
+ return CCHAR;
+ else if (amatch ("int", 3))
+ return CINT;
+ else
+ return CINT;
+ } else if(amatch("unsigned", 8)) {
+ if (amatch("char", 4)) {
+ return UCHAR;
+ } else if (amatch("int", 3)) {
+ return UINT;
+ }
+ } else if(amatch("signed", 8)) {
+ if (amatch("char", 4)) {
+ return CCHAR;
+ } else if (amatch("int", 3)) {
+ return CINT;
+ }
+ } else if (amatch ("char", 4)) {
+ return CCHAR;
+ } else if (amatch ("int", 3)) {
+ return CINT;
+ }
+ return 0;
+}
+
--- /dev/null
+/* abs (num) return absolute value */
+abs(num) int num;{
+ if (num < 0) return (-num);
+ else return (num);
+ }
--- /dev/null
+#include <stdio.h>
+#define EOL 10
+atoi(s) char s[];{
+ int i,n,sign;
+ for (i=0;
+ (s[i] == ' ') | (s[i] == EOL) | (s[i] == '\t');
+ ++i) ;
+ sign = 1;
+ switch(s[i]){
+ case '-': sign = -1; /* and fall through */
+ case '+': ++i;
+ break;
+ }
+ for(n = 0;
+ isdigit(s[i]);
+ ++i)
+ n = 10 * n + s[i] - '0';
+ return (sign * n);
+
+}
+
--- /dev/null
+/* binary search for string word in table[0] .. table[n-1]
+ * reference CPL pg. 125
+ */
+#include <stdio.h>
+binary(word, table, n)
+char *word;
+int table[];
+int n;{
+ int low, high, mid, cond;
+ low = 0;
+ high = n - 1;
+ while (low <= high){
+ mid = (low + high) / 2;
+ if ((cond = strcmp(word, table[mid])) < 0)
+ high = mid - 1;
+ else if (cond > 0)
+ low = mid + 1;
+ else
+ return (mid);
+ }
+ return (-1);
+ }
--- /dev/null
+isalpha(c) char c;{
+ if ((c >= 'a' & c <= 'z') |
+ (c >= 'A' & c <= 'Z')) return(1);
+ else return(0);
+ }
+
+isupper(c) char c;{
+ if (c >= 'A' & c <= 'Z') return(1);
+ else return(0);
+ }
+
+islower(c) char c;{
+ if (c >= 'a' & c <= 'z') return(1);
+ else return(0);
+ }
+
+isdigit(c) char c;{
+ if (c >= '0' & c <= '9') return(1);
+ else return(0);
+ }
+
+isspace(c) char c;{
+ if (c == ' ' | c == '\t' | c == '\n') return(1);
+ else return(0);
+ }
+
+toupper(c) char c;{
+ return ((c >= 'a' && c <= 'z') ? c - 32: c);
+ }
+
+tolower(c) char c;{
+ return((c >= 'A' && c <= 'Z') ? c + 32: c);
+ }
--- /dev/null
+/*
+#include <stdio.h>
+*/
+#define NULL 0
+#define FILE char
+
+fgets(s, n, iop)
+int n;
+char *s;
+register FILE *iop;
+{
+ register c;
+ register char *cs;
+
+ cs = s;
+ while (--n>0 && (c = fgetc(iop))>=0) {
+ *cs++ = c;
+ if (c=='\n')
+ break;
+ }
+ if (c<0 && cs==s)
+ return(NULL);
+ *cs++ = '\0';
+ return(s);
+
+}
+
--- /dev/null
+#include <stdio.h>
+
+fputs(str, fp) FILE *fp; char *str; {
+ while(*str) fputc(*str++, fp);
+
+}
+
--- /dev/null
+#include <stdio.h>
+getchar() {
+ return(fgetc(stdin));
+}
+
--- /dev/null
+#include <stdio.h>
+#define EOL 10
+#define BKSP 8
+#define CTRLU 0x15
+gets(s) char *s; {
+ char c, *ts;
+ ts = s;
+ while ((c = getchar()) != EOL && (c != EOF)) {
+ if (c == BKSP) {
+ if (ts > s) {
+ --ts;
+ /* CPM already echoed */
+ putchar(' ');
+ putchar(BKSP);
+ }
+ }
+ else if (c == CTRLU) {
+ ts = s;
+ putchar(EOL);
+ putchar('#');
+ }
+ else (*ts++) = c;
+ }
+ if ((c == EOF) && (ts == s)) return NULL;
+ (*ts) = NULL;
+ return s;
+}
+
--- /dev/null
+/* index - find index of string t in s
+ * reference CPL 67.
+ */
+#include <stdio.h>
+#define EOS 0
+index(s, t)
+char s[], t[];{
+ int i, j, k;
+ for (i = 0; s[i] != EOS; i++){
+ k=0;
+ for (j=i;t[k]!=EOS & s[j]==t[k]; i++)
+ j++;
+ ;
+ if (t[k] == EOS)
+ return(i);
+ }
+ return(-1);
+ }
--- /dev/null
+#include <stdio.h>
+#define EOS 0
+itoa(n,s) char s[];int n;{
+ int i,sign;
+ if((sign = n) < 0) n = -n;
+ i = 0;
+ do {
+ s[i++] = n % 10 + '0';
+ }while ((n = n/10) > 0);
+ if (sign < 0) s[i++] = '-';
+ s[i] = EOS;
+ reverse(s);
+}
+
--- /dev/null
+#include <stdio.h>
+/* print a number in any radish */
+#define DIGARR "0123456789ABCDEF"
+printn(number, radix, file)
+int number, radix; FILE *file;{
+ int i;
+ char *digitreps;
+ if (number < 0 & radix == 10){
+ fputc('-', file);
+ number = -number;
+ }
+ if ((i = number / radix) != 0)
+ printn(i, radix, file);
+ digitreps=DIGARR;
+ fputc(digitreps[number % radix], file);
+ }
--- /dev/null
+#include <stdio.h>
+putchar(c) char c; {
+ return fputc(c, stdout);
+}
+
--- /dev/null
+#include <stdio.h>
+#define EOL 10
+puts(str) char *str;{
+ while (*str) putchar(*str++);
+ putchar(EOL);
+ }
--- /dev/null
+
+int xxseed;
+
+srand (x) int x; {
+ xxseed = x;
+
+}
+
+rand () {
+ xxseed = xxseed * 251 + 123;
+ if (xxseed < 0) xxseed = - xxseed;
+ return (xxseed);
+
+}
+
+getrand () {
+ puts ("Type a character");
+ return (getchar() * 123);
+}
+
--- /dev/null
+#include <stdio.h>
+/* Reverse a character string, reference CPL p 59 */
+reverse(s)
+char *s;{
+ int i, j;
+ char c;
+ i = 0;
+ j = strlen(s) - 1;
+ while (i < j){
+ c = s[i];
+ s[i] = s[j];
+ s[j] = c;
+ i++;
+ j--;
+ }
+ return(s);
+ }
--- /dev/null
+extern char *brkend;
+sbrk (incr) char *incr; {
+ char *stktop;
+
+ stktop = Xstktop() - 200;
+
+ /* do we have enough space? */
+ if (brkend + incr < stktop) {
+ stktop = brkend;
+ brkend = brkend + incr;
+ return (stktop);
+ }
+ else
+ return (-1);
+
+}
+
--- /dev/null
+/* Shell sort of string v[0] .... v[n-1] into increasing
+ * order.
+ * Reference CPL pg. 108.
+ */
+
+shellsort(v, n)
+int v[];
+int n;
+ {
+ int gap, i, j;
+ char *temp;
+ for (gap = n/2; gap > 0; gap = gap / 2)
+ for (i = gap; i < n; i++)
+ for (j = i - gap; j >= 0; j = j - gap){
+ if (strcmp(v[j], v[j+gap]) <= 0)
+ break;
+ temp = v[j];
+ v[j] = v[j + gap];
+ v[j + gap] = temp;
+ }
+ }
--- /dev/null
+/*
+ * Concatenate s2 on the end of s1. S1's space must be large enough.
+ * Return s1.
+ */
+
+strcat(s1, s2)
+char *s1, *s2;
+{
+ char *os1;
+
+ os1 = s1;
+ while (*s1++)
+ ;
+ *--s1;
+ while (*s1++ = *s2++)
+ ;
+ return(os1);
+
+}
+
--- /dev/null
+/*
+ * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
+ */
+
+strcmp(s1, s2)
+char *s1, *s2;
+{
+
+ while (*s1 == *s2++)
+ if (*s1++=='\0')
+ return(0);
+ return(*s1 - *--s2);
+ }
--- /dev/null
+#include <stdio.h>
+/*
+ * Copy string s2 to s1. s1 must be large enough.
+ * return s1
+ */
+
+strcpy(s1, s2)
+char *s1, *s2;
+{
+ char *os1;
+
+ os1 = s1;
+ while (*s1++ = *s2++)
+ ;
+ return(os1);
+
+}
+
--- /dev/null
+#include <stdio.h>
+/* return length of string, reference CPL p 36 */
+strlen(s) char *s;{
+ int i;
+ i = 0;
+ while (*s++) i++;
+ return (i);
+ }
--- /dev/null
+/*
+ * Concatenate s2 on the end of s1. S1's space must be large enough.
+ * At most n characters are moved.
+ * Return s1.
+ */
+
+strncat(s1, s2, n)
+register char *s1, *s2;
+register n;
+{
+ register char *os1;
+
+ os1 = s1;
+ while (*s1++)
+ ;
+ --s1;
+ while (*s1++ = *s2++)
+ if (--n < 0) {
+ *--s1 = '\0';
+ break;
+ }
+ return(os1);
+
+}
+
--- /dev/null
+/*
+ * Compare strings (at most n bytes): s1>s2: >0 s1==s2: 0 s1<s2: <0
+ */
+
+strncmp(s1, s2, n)
+char *s1, *s2;
+int n;
+{
+
+ while (--n >= 0 && *s1 == *s2++)
+ if (*s1++ == '\0')
+ return(0);
+ return(n<0 ? 0 : *s1 - *--s2);
+
+}
+
--- /dev/null
+/*
+ * Copy s2 to s1, truncating or null-padding to always copy n bytes
+ * return s1
+ */
+
+strncpy(s1, s2, n)
+char *s1, *s2;
+int n;
+{
+ register i;
+ register char *os1;
+
+ os1 = s1;
+ for (i = 0; i < n; i++)
+ if ((*s1++ = *s2++) == '\0') {
+ while (++i < n)
+ *s1++ = '\0';
+ return(os1);
+ }
+ return(os1);
+
+}
+
--- /dev/null
+/*
+ * File main.c: 2.7 (84/11/28,10:14:56)
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "defs.h"
+#include "data.h"
+
+int main(int argc, char *argv[]) {
+ char *param = NULL, *bp;
+ int i;
+ macptr = 0;
+ ctext = 0;
+ errs = 0;
+ aflag = 1;
+ uflag = 0;
+
+ for (i=1; i<argc; i++) {
+ param = argv[i];
+ if (*param == '-') {
+ while (*++param) {
+ switch (*param) {
+ case 't': case 'T': // output c source as asm comments
+ ctext = 1;
+ break;
+ case 'a': case 'A': // no argument count in A to function calls
+ aflag = 0;
+ break;
+ case 'u': case 'U': // use undocumented 8085 instructions
+ uflag = 1;
+ break;
+ case 'd': case 'D': // define macro
+ bp = ++param;
+ if (!*param) usage();
+ while (*param && *param != '=') param++;
+ if (*param == '=') *param = '\t';
+ while (*param) param++;
+ param--;
+ defmac(bp);
+ break;
+ default:
+ usage();
+ }
+ }
+ } else {
+ usage();
+ break;
+ }
+ }
+
+ if (i == argc) {
+ compile(NULL); // training mode - read code from stdin
+ exit(errs != 0);
+ }
+ usage();
+}
+
+/**
+ * compile one file if filename is NULL redirect do to stdin/stdout
+ * @param file filename
+ * @return
+ */
+void compile(char *file) {
+ if (file == NULL || filename_typeof(file) == 'c') {
+ global_table_index = 0;
+ local_table_index = NUMBER_OF_GLOBALS;
+ while_table_index = 0;
+ tag_table_index = 0;
+ inclsp =
+ iflevel =
+ skiplevel =
+ swstp =
+ litptr =
+ stkp =
+ errcnt =
+ ncmp =
+ lastst =
+ //quote[1] =
+ 0;
+ input2 = -1;
+ //quote[0] = '"';
+ cmode = 1;
+ glbflag = 1;
+ nxtlab = 0;
+ litlab = getlabel();
+ defmac("end\tmemory");
+ //add_global("memory", ARRAY, CCHAR, 0, EXTERN);
+ //add_global("stack", ARRAY, CCHAR, 0, EXTERN);
+ rglobal_table_index = global_table_index; //rglbptr = glbptr;
+ //add_global("etext", ARRAY, CCHAR, 0, EXTERN);
+ //add_global("edata", ARRAY, CCHAR, 0, EXTERN);
+ defmac("short\tint");
+ initmac();
+ // compiler body
+ if (file == NULL) {
+ input = 0;
+ } else if (!openin(file))
+ return;
+ if (file == NULL) {
+ output = 1;
+ } else if (!openout())
+ return;
+ header();
+ code_segment_gtext();
+ parse();
+ close(input);
+ data_segment_gdata();
+ dumplits();
+ dumpglbs();
+ errorsummary();
+ trailer();
+ oflush();
+ close(output);
+ pl("");
+ errs = errs || errfile;
+ } else {
+ writee("Don't understand file ");
+ writee(file);
+ errs = 1;
+ }
+}
+
+void frontend_version(void) {
+ output_string("\tFront End (2.7,84/11/28)");
+ output_string("\n;\tFront End for ASXXXX (2.8,13/01/20)");
+}
+
+/**
+ * prints usage
+ * @return exits the execution
+ */
+void usage(void) {
+ writee("unknown argument.\n");
+ exit(1);
+}
+
+/**
+ * process all input text
+ * at this level, only static declarations, defines, includes,
+ * and function definitions are legal.
+ */
+void parse(void) {
+ while (!input_eof) {
+ if (amatch("extern", 6))
+ do_declarations(EXTERN, NULL_TAG, 0);
+ else if (amatch("static", 6))
+ do_declarations(STATIC, NULL_TAG, 0);
+ else if (do_declarations(PUBLIC, NULL_TAG, 0));
+ else if (match("#asm"))
+ doasm();
+ else if (match("#include"))
+ doinclude();
+ else if (match("#define")) {
+ dodefine();
+ }
+ else if (match("#undef"))
+ doundef();
+ else {
+ newfunc();
+ }
+ blanks();
+ }
+}
+
+/**
+ * parse top level declarations
+ * @param stclass storage
+ * @param mtag
+ * @param is_struct
+ * @return
+ */
+int do_declarations(int stclass, TAG_SYMBOL *mtag, int is_struct) {
+ int type;
+ int otag; // tag of struct object being declared
+ int sflag; // TRUE for struct definition, zero for union
+ char sname[NAMESIZE];
+
+ blanks();
+ if ((sflag=amatch("struct", 6)) || amatch("union", 5)) {
+ if (symname(sname) == 0) { // legal name ?
+ illname();
+ }
+ if ((otag=find_tag(sname)) == -1) { // structure not previously defined
+ otag = define_struct(sname, stclass, sflag);
+ }
+ declare_global(STRUCT, stclass, mtag, otag, is_struct);
+ } else if ((type = get_type()) != 0) {
+ declare_global(type, stclass, mtag, 0, is_struct);
+ } else if (stclass == PUBLIC) {
+ return (0);
+ } else {
+ declare_global(CINT, stclass, mtag, 0, is_struct);
+ }
+ need_semicolon();
+ return (1);
+}
+
+/**
+ * dump the literal pool
+ */
+void dumplits(void) {
+ int j, k;
+
+#ifndef TINY
+ if (litptr == 0)
+ return;
+ print_label(litlab);
+ output_label_terminator();
+ k = 0;
+ while (k < litptr) {
+ gen_def_byte();
+ j = 8;
+ while (j--) {
+ output_number(litq[k++] & 127);
+ if ((j == 0) | (k >= litptr)) {
+ newline();
+ break;
+ }
+ output_byte(',');
+ }
+ }
+#endif
+}
+
+/**
+ * dump all static variables
+ */
+void dumpglbs(void) {
+#ifndef TINY
+ int dim, i, list_size, line_count, value;
+ if (!glbflag)
+ return;
+ current_symbol_table_idx = rglobal_table_index;
+ while (current_symbol_table_idx < global_table_index) {
+ SYMBOL *symbol = &symbol_table[current_symbol_table_idx];
+ if (symbol->identity != FUNCTION) {
+ ppubext(symbol);
+ if (symbol->storage != EXTERN) {
+ output_string(symbol->name);
+ output_label_terminator();
+ dim = symbol->offset;
+ list_size = 0;
+ line_count = 0;
+ if (find_symbol_initials(symbol->name)) { // has initials
+ list_size = get_size(symbol->name);
+ if (dim == -1) {
+ dim = list_size;
+ }
+ }
+ for (i=0; i<dim; i++) {
+ if (symbol->type == STRUCT) {
+ dump_struct(symbol, i);
+ } else {
+ if (line_count % 10 == 0) {
+ newline();
+ if ((symbol->type & CINT) || (symbol->identity == POINTER)) {
+ gen_def_word();
+ } else {
+ gen_def_byte();
+ }
+ }
+ if (i < list_size) {
+ // dump data
+ value = get_item_at(symbol->name, i, &tag_table[symbol->tagidx]);
+ output_number(value);
+ } else {
+ // dump zero, no more data available
+ output_number(0);
+ }
+ line_count++;
+ if (line_count % 10 == 0) {
+ line_count = 0;
+ } else {
+ if (i < dim-1) {
+ output_byte( ',' );
+ }
+ }
+ }
+ }
+ newline();
+ }
+ } else {
+ fpubext(symbol);
+ }
+ current_symbol_table_idx++;
+ }
+#endif
+}
+
+#ifndef TINY
+/**
+ * dump struct data
+ * @param symbol struct variable
+ * @param position position of the struct in the array, or zero
+ */
+void dump_struct(SYMBOL *symbol, int position) {
+ int i, number_of_members, value;
+ number_of_members = tag_table[symbol->tagidx].number_of_members;
+ newline();
+ for (i=0; i<number_of_members; i++) {
+ // i is the index of current member, get type
+ int member_type = member_table[tag_table[symbol->tagidx].member_idx + i].type;
+ if (member_type & CINT) {
+ gen_def_word();
+ } else {
+ gen_def_byte();
+ }
+ if (position < get_size(symbol->name)) {
+ // dump data
+ value = get_item_at(symbol->name, position*number_of_members+i, &tag_table[symbol->tagidx]);
+ output_number(value);
+ } else {
+ // dump zero, no more data available
+ output_number(0);
+ }
+ newline();
+ }
+}
+#endif
+
+/**
+ * report errors
+ */
+void errorsummary(void) {
+ if (ncmp)
+ error("missing closing bracket");
+ newline();
+ gen_comment();
+ output_decimal(errcnt);
+ if (errcnt) errfile = YES;
+ output_string(" error(s) in compilation");
+ newline();
+ gen_comment();
+ output_with_tab("literal pool:");
+ output_decimal(litptr);
+ newline();
+ gen_comment();
+ output_with_tab("global pool:");
+ output_decimal(global_table_index - rglobal_table_index);
+ newline();
+ gen_comment();
+ output_with_tab("Macro pool:");
+ output_decimal(macptr);
+ newline();
+ if (errcnt > 0)
+ pl("Error(s)");
+}
+
+/**
+ * test for C or similar filename, e.g. xxxxx.x, tests the dot at end-1 postion
+ * @param s the filename
+ * @return the last char if it contains dot, space otherwise
+ */
+int filename_typeof(char *s) {
+ s += strlen(s) - 2;
+ if (*s == '.')
+ return (*(s + 1));
+ return (' ');
+}
+
--- /dev/null
+/* File preproc.c: 2.3 (84/11/27,11:47:40) */
+/*% cc -O -c %
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "defs.h"
+#include "data.h"
+
+/**
+ * remove "brackets" surrounding include file name
+ * @see DEFLIB
+ */
+int fix_include_name (void) {
+ char c1, c2, *p, *ibp;
+ char buf[20];
+ int fp;
+ char buf2[100];
+
+ ibp = &buf[0];
+
+ if ((c1 = gch ()) != '"' && c1 != '<')
+ return -1;
+ for (p = line + lptr; *p ;)
+ *ibp++ = *p++;
+ c2 = *(--p);
+ if (c1 == '"' ? (c2 != '"') : (c2 != '>')) {
+ error ("incorrect delimiter");
+ return -1;
+ }
+ *(--ibp) = 0;
+ fp = -1;
+ if (c1 == '<' || ((fp = open(buf, O_RDONLY)) != -1)) {
+ strcpy(buf2, DEFLIB);
+ strlcat(buf2, buf, sizeof(buf2));
+ fp = open(buf2, O_RDONLY);
+ }
+ return (fp);
+}
+
+/**
+ * open an include file
+ */
+void doinclude(void)
+{
+ int inp2;
+
+ blanks ();
+ if ((inp2 = fix_include_name ()) != -1)
+ if (inclsp < INCLSIZ) {
+ inclstk[inclsp++] = input2;
+ input2 = inp2;
+ } else {
+ close (inp2);
+ error ("too many nested includes");
+ }
+ else {
+ error ("Could not open include file");
+ }
+ do_kill();
+
+}
+
+/**
+ * "asm" pseudo-statement
+ * enters mode where assembly language statements are passed
+ * intact through parser
+ */
+void doasm(void)
+{
+ cmode = 0;
+ FOREVER {
+ readline ();
+ if (match ("#endasm"))
+ break;
+ if (input_eof)
+ break;
+ output_string (line);
+ newline ();
+ }
+ do_kill();
+ cmode = 1;
+
+}
+
+void dodefine(void)
+{
+ addmac();
+}
+
+void doundef(void)
+{
+ int mp;
+ char sname[NAMESIZE];
+
+ if (!symname(sname)) {
+ illname();
+ do_kill();
+ return;
+ }
+
+ if ((mp = findmac(sname)) != 0)
+ delmac(mp);
+ do_kill();
+
+}
+
+void preprocess(void)
+{
+ if (ifline()) return;
+ while (cpp());
+}
+
+void doifdef(int ifdef)
+{
+ char sname[NAMESIZE];
+ int k;
+
+ blanks();
+ ++iflevel;
+ if (skiplevel) return;
+ k = symname(sname) && findmac(sname);
+ if (k != ifdef) skiplevel = iflevel;
+
+}
+
+int ifline(void)
+{
+ FOREVER {
+ readline();
+ if (input_eof) return(1);
+ if (match("#ifdef")) {
+ doifdef(YES);
+ continue;
+ } else if (match("#ifndef")) {
+ doifdef(NO);
+ continue;
+ } else if (match("#else")) {
+ if (iflevel) {
+ if (skiplevel == iflevel) skiplevel = 0;
+ else if (skiplevel == 0) skiplevel = iflevel;
+ } else noiferr();
+ continue;
+ } else if (match("#endif")) {
+ if (iflevel) {
+ if (skiplevel == iflevel) skiplevel = 0;
+ --iflevel;
+ } else noiferr();
+ continue;
+ }
+ if (!skiplevel) return(0);
+ }
+
+}
+
+void noiferr(void)
+{
+ error("no matching #if...");
+
+}
+
+/**
+ * preprocess - copies mline to line with special treatment of preprocess cmds
+ * @return
+ */
+int cpp(void)
+{
+ int k;
+ char c, sname[NAMESIZE];
+ int tog;
+ int cpped; /* non-zero if something expanded */
+
+ cpped = 0;
+ /* don't expand lines with preprocessor commands in them */
+ if (!cmode || line[0] == '#') return(0);
+
+ mptr = lptr = 0;
+ while (ch ()) {
+ if ((ch () == ' ') | (ch () == 9)) {
+ keepch (' ');
+ while ((ch () == ' ') | (ch () == 9))
+ gch ();
+ } else if (ch () == '"') {
+ keepch (ch ());
+ gch ();
+ while (ch () != '"') {
+ if (ch () == 0) {
+ error ("missing quote");
+ break;
+ }
+ if (ch() == '\\') keepch(gch());
+ keepch (gch ());
+ }
+ gch ();
+ keepch ('"');
+ } else if (ch () == '\'') {
+ keepch ('\'');
+ gch ();
+ while (ch () != '\'') {
+ if (ch () == 0) {
+ error ("missing apostrophe");
+ break;
+ }
+ if (ch() == '\\') keepch(gch());
+ keepch (gch ());
+ }
+ gch ();
+ keepch ('\'');
+ } else if ((ch () == '/') & (nch () == '*')) {
+ inchar ();
+ inchar ();
+ while ((((c = ch ()) == '*') & (nch () == '/')) == 0)
+ if (c == '$') {
+ inchar ();
+ tog = TRUE;
+ if (ch () == '-') {
+ tog = FALSE;
+ inchar ();
+ }
+ if (alpha (c = ch ())) {
+ inchar ();
+ toggle (c, tog);
+ }
+ } else {
+ if (ch () == 0)
+ readline ();
+ else
+ inchar ();
+ if (input_eof)
+ break;
+ }
+ inchar ();
+ inchar ();
+ } else if ((ch () == '/') & (nch () == '/')) { // one line comment
+ while(gch());
+ } else if (alphanumeric(ch ())) {
+ k = 0;
+ while (alphanumeric(ch ())) {
+ if (k < NAMEMAX)
+ sname[k++] = ch ();
+ gch ();
+ }
+ sname[k] = 0;
+ if ((k = findmac (sname)) != 0) {
+ cpped = 1;
+ while ((c = macq[k++]) != 0)
+ keepch (c);
+ } else {
+ k = 0;
+ while ((c = sname[k++]) != 0)
+ keepch (c);
+ }
+ } else
+ keepch (gch ());
+ }
+ keepch (0);
+ if (mptr >= MPMAX)
+ error ("line too long");
+ lptr = mptr = 0;
+ while((line[lptr++] = mline[mptr++]) != 0);
+ lptr = 0;
+ return(cpped);
+
+}
+
+int keepch(char c)
+{
+ mline[mptr] = c;
+ if (mptr < MPMAX)
+ mptr++;
+ return (c);
+
+}
+
+void defmac(char *s)
+{
+ do_kill();
+ strcpy(line, s);
+ addmac();
+}
+
+void addmac(void)
+{
+ char sname[NAMESIZE];
+ int k;
+ int mp;
+
+ if (!symname (sname)) {
+ illname();
+ do_kill();
+ return;
+ }
+ if ((mp = findmac(sname)) != 0) {
+ error("Duplicate define");
+ delmac(mp);
+ }
+ k = 0;
+ while (putmac (sname[k++]));
+ while (ch () == ' ' || ch () == 9)
+ gch ();
+ //while (putmac (gch ()));
+ while (putmac(remove_one_line_comment(gch ())));
+ if (macptr >= MACMAX)
+ error ("macro table full");
+
+}
+
+/**
+ * removes one line comments from defines
+ * @param c
+ * @return
+ */
+int remove_one_line_comment(char c) {
+ if ((c == '/') && (ch() == '/')) {
+ while(gch());
+ return 0;
+ } else {
+ return c;
+ }
+}
+
+void delmac(int mp) {
+ --mp; --mp; /* step over previous null */
+ while (mp >= 0 && macq[mp]) macq[mp--] = '%';
+
+}
+
+int putmac(char c)
+{
+ macq[macptr] = c;
+ if (macptr < MACMAX)
+ macptr++;
+ return (c);
+
+}
+
+int findmac(char *sname)
+{
+ int k;
+
+ k = 0;
+ while (k < macptr) {
+ if (astreq (sname, macq + k, NAMEMAX)) {
+ while (macq[k++]);
+ return (k);
+ }
+ while (macq[k++]);
+ while (macq[k++]);
+ }
+ return (0);
+
+}
+
+void toggle(char name, int onoff) {
+ switch (name) {
+ case 'C':
+ ctext = onoff;
+ break;
+ }
+}
+
--- /dev/null
+/*
+ * File primary.c: 2.4 (84/11/27,16:26:07)
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+int primary(LVALUE *lval) {
+ char sname[NAMESIZE];
+ int num[1], k, symbol_table_idx, offset, reg;
+ SYMBOL *symbol;
+
+ lval->ptr_type = 0; // clear pointer/array type
+ lval->tagsym = 0;
+ if (match ("(")) {
+ k = hier1 (lval);
+ needbrack (")");
+ return (k);
+ }
+ if (amatch("sizeof", 6)) {
+ needbrack("(");
+ gen_immediate();
+ if (amatch("int", 3)) output_number(INTSIZE);
+ else if (amatch("char", 4)) output_number(1);
+ else if (symname(sname)) {
+ if (((symbol_table_idx = find_locale(sname)) > -1) ||
+ ((symbol_table_idx = find_global(sname)) > -1)) {
+ symbol = &symbol_table[symbol_table_idx];
+ if (symbol->storage == LSTATIC)
+ error("sizeof local static");
+ offset = symbol->offset;
+ if ((symbol->type & CINT) ||
+ (symbol->identity == POINTER))
+ offset *= INTSIZE;
+ else if (symbol->type == STRUCT)
+ offset *= tag_table[symbol->tagidx].size;
+ output_number(offset);
+ } else {
+ error("sizeof undeclared variable");
+ output_number(0);
+ }
+ } else {
+ error("sizeof only on type or variable");
+ }
+ needbrack(")");
+ newline();
+ lval->symbol = 0;
+ lval->indirect = 0;
+ return(0);
+ }
+ if (symname (sname)) {
+ if ((symbol_table_idx = find_locale(sname)) > -1) {
+ symbol = &symbol_table[symbol_table_idx];
+ reg = gen_get_locale(symbol);
+ lval->symbol = symbol;
+ lval->indirect = symbol->type;
+ if (symbol->type == STRUCT) {
+ lval->tagsym = &tag_table[symbol->tagidx];
+ }
+ if (symbol->identity == ARRAY ||
+ (symbol->identity == VARIABLE && symbol->type == STRUCT)) {
+ lval->ptr_type = symbol->type;
+ return reg;
+ }
+ if (symbol->identity == POINTER) {
+ lval->indirect = CINT;
+ lval->ptr_type = symbol->type;
+ }
+ return FETCH | reg;
+ }
+ if ((symbol_table_idx = find_global(sname)) > -1) {
+ symbol = &symbol_table[symbol_table_idx];
+ if (symbol->identity != FUNCTION) {
+ lval->symbol = symbol;
+ lval->indirect = 0;
+ if (symbol->type == STRUCT) {
+ lval->tagsym = &tag_table[symbol->tagidx];
+ }
+ if (symbol->identity != ARRAY &&
+ (symbol->identity != VARIABLE || symbol->type != STRUCT)) {
+ if (symbol->identity == POINTER) {
+ lval->ptr_type = symbol->type;
+ }
+ return FETCH | HL_REG;
+ }
+ gen_immediate();
+ output_string(symbol->name);
+ newline();
+ lval->indirect = symbol->type;
+ lval->ptr_type = symbol->type;
+ return 0;
+ }
+ }
+ blanks();
+ if (ch() != '(')
+ error("undeclared variable");
+ symbol_table_idx = add_global(sname, FUNCTION, CINT, 0, PUBLIC);
+ symbol = &symbol_table[symbol_table_idx];
+ lval->symbol = symbol;
+ lval->indirect = 0;
+ return 0;
+ }
+ lval->symbol = 0;
+ lval->indirect = 0;
+ if (constant(num))
+ return 0;
+ else {
+ error("invalid expression");
+ gen_immediate();
+ output_number(0);
+ newline();
+ junk();
+ return 0;
+ }
+}
+
+/**
+ * true if val1 -> int pointer or int array and val2 not pointer or array
+ * @param val1
+ * @param val2
+ * @return
+ */
+int dbltest(LVALUE *val1, LVALUE *val2) {
+ if (val1 == NULL)
+ return (FALSE);
+ if (val1->ptr_type) {
+ if (val1->ptr_type & CCHAR)
+ return (FALSE);
+ if (val2->ptr_type)
+ return (FALSE);
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ * determine type of binary operation
+ * @param lval
+ * @param lval2
+ * @return
+ */
+void result(LVALUE *lval, LVALUE *lval2) {
+ if (lval->ptr_type && lval2->ptr_type)
+ lval->ptr_type = 0;
+ else if (lval2->ptr_type) {
+ lval->symbol = lval2->symbol;
+ lval->indirect = lval2->indirect;
+ lval->ptr_type = lval2->ptr_type;
+ }
+}
+
+int constant(int val[]) {
+ if (number (val))
+ gen_immediate ();
+ else if (quoted_char (val))
+ gen_immediate ();
+ else if (quoted_string (val)) {
+ gen_immediate ();
+ print_label (litlab);
+ output_byte ('+');
+ } else
+ return (0);
+ output_number (val[0]);
+ newline ();
+ return (1);
+}
+
+int number(int val[]) {
+ int k, minus, base;
+ char c;
+
+ k = minus = 1;
+ while (k) {
+ k = 0;
+ if (match("+"))
+ k = 1;
+ if (match("-")) {
+ minus = (-minus);
+ k = 1;
+ }
+ }
+ if (!numeric(c = ch ()))
+ return (0);
+ if (match("0x") || match ("0X"))
+ while (numeric(c = ch ()) ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F')) {
+ inbyte ();
+ k = k * 16 + (numeric (c) ? (c - '0') : ((c & 07) + 9));
+ }
+ else {
+ base = (c == '0') ? 8 : 10;
+ while (numeric(ch())) {
+ c = inbyte ();
+ k = k * base + (c - '0');
+ }
+ }
+ if (minus < 0)
+ k = (-k);
+ val[0] = k;
+ if(k < 0) {
+ return (UINT);
+ } else {
+ return (CINT);
+ }
+}
+
+/**
+ * Test if we have one char enclosed in single quotes
+ * @param value returns the char found
+ * @return 1 if we have, 0 otherwise
+ */
+int quoted_char(int *value) {
+ int k;
+ char c;
+
+ k = 0;
+ if (!match ("'"))
+ return (0);
+ while ((c = gch ()) != '\'') {
+ c = (c == '\\') ? spechar(): c;
+ k = (k & 255) * 256 + (c & 255);
+ }
+ *value = k;
+ return (1);
+}
+
+/**
+ * Test if we have string enclosed in double quotes. e.g. "abc".
+ * Load the string into literal pool.
+ * @param position returns beginning of the string
+ * @return 1 if such string found, 0 otherwise
+ */
+int quoted_string(int *position) {
+ char c;
+
+ if (!match ("\""))
+ return (0);
+ *position = litptr;
+ while (ch () != '"') {
+ if (ch () == 0)
+ break;
+ if (litptr >= LITMAX) {
+ error ("string space exhausted");
+ while (!match ("\""))
+ if (gch () == 0)
+ break;
+ return (1);
+ }
+ c = gch();
+ litq[litptr++] = (c == '\\') ? spechar(): c;
+ }
+ gch ();
+ litq[litptr++] = 0;
+ return (1);
+}
+
+/**
+ * decode special characters (preceeded by back slashes)
+ */
+int spechar(void) {
+ char c;
+ c = ch();
+
+ if (c == 'n') c = LF;
+ else if (c == 't') c = TAB;
+ else if (c == 'r') c = CR;
+ else if (c == 'f') c = FFEED;
+ else if (c == 'b') c = BKSP;
+ else if (c == '0') c = EOS;
+ else if (c == EOS) return 0;
+
+ gch();
+ return (c);
+}
+
+/**
+ * perform a function call
+ * called from "hier11", this routine will either call the named
+ * function, or if the supplied ptr is zero, will call the contents
+ * of HL
+ * @param ptr name of the function
+ */
+void callfunction(char *ptr) {
+ int nargs;
+
+ nargs = 0;
+ blanks ();
+ if (ptr == 0)
+ gen_push (HL_REG);
+ while (!streq (line + lptr, ")")) {
+ if (endst ())
+ break;
+ expression (NO);
+ if (ptr == 0)
+ gen_swap_stack ();
+ gen_push (HL_REG);
+ nargs = nargs + INTSIZE;
+ if (!match (","))
+ break;
+ }
+ needbrack (")");
+ if (aflag)
+ gnargs(nargs / INTSIZE);
+ if (ptr)
+ gen_call (ptr);
+ else
+ callstk ();
+ stkp = gen_modify_stack (stkp + nargs);
+}
+
+void needlval(void) {
+ error ("must be lvalue");
+}
+
--- /dev/null
+extern void header(void);
+extern void newline(void);
+extern void initmac(void);
+extern void output_label_prefix(void);
+extern void output_label_terminator (void);
+extern void gen_comment(void);
+extern void trailer(void);
+extern void code_segment_gtext(void);
+extern void data_segment_gdata(void);
+extern void ppubext(SYMBOL *scptr);
+extern void fpubext(SYMBOL *scptr);
+extern void output_number(int num);
+extern void gen_get_memory(SYMBOL *sym);
+extern int gen_get_locale(SYMBOL *sym);
+extern void gen_put_memory(SYMBOL *sym);
+extern void gen_put_indirect(char typeobj);
+extern void gen_get_indirect(char typeobj, int reg);
+extern void gen_swap(void);
+extern void gen_immediate(void);
+extern void gen_push(int reg);
+extern void gen_pop(void);
+extern void gen_swap_stack(void);
+extern void gen_call(char *sname);
+extern void declare_entry_point(char *symbol_name);
+extern void gen_ret(void);
+extern void callstk(void);
+extern void gen_jump(int label);
+extern void gen_test_jump(int label, int ft);
+extern void gen_def_byte(void);
+extern void gen_def_storage(void);
+extern void gen_def_word(void);
+extern int gen_modify_stack(int newstkp);
+extern void gen_multiply_by_two(void);
+extern void gen_divide_by_two(void);
+extern void gen_jump_case(void);
+extern void gen_add(LVALUE *lval, LVALUE *lval2);
+extern void gen_sub(void);
+extern void gen_mult(void);
+extern void gen_div(void);
+extern void gen_udiv(void);
+extern void gen_mod(void);
+extern void gen_umod(void);
+extern void gen_or(void);
+extern void gen_xor(void);
+extern void gen_and(void);
+extern void gen_arithm_shift_right(void);
+extern void gen_logical_shift_right(void);
+extern void gen_arithm_shift_left(void);
+extern void gen_twos_complement(void);
+extern void gen_logical_negation(void);
+extern void gen_complement(void);
+extern void gen_convert_primary_reg_value_to_bool(void);
+extern void gen_increment_primary_reg(LVALUE *lval);
+extern void gen_decrement_primary_reg(LVALUE *lval);
+extern void gen_equal(void);
+extern void gen_not_equal(void);
+extern void gen_less_than(void);
+extern void gen_less_or_equal(void);
+extern void gen_greater_than(void);
+extern void gen_greater_or_equal(void);
+extern void gen_unsigned_less_than(void);
+extern void gen_unsigned_less_or_equal(void);
+extern void gen_usigned_greater_than(void);
+extern void gen_unsigned_greater_or_equal(void);
+extern char *inclib(void);
+extern void gnargs(int d);
+extern int assemble(char *s);
+extern void gen_immediate2(void);
+extern void add_offset(int val);
+extern void gen_multiply(int type, int size);
+extern void error(char *ptr);
+extern void doerror(char *ptr);
+extern int nosign(LVALUE *is);
+extern void expression(int comma);
+extern int hier1(LVALUE *lval);
+extern int hier1a(LVALUE *lval);
+extern int hier1b(LVALUE *lval);
+extern int hier1c(LVALUE *lval);
+extern int hier2(LVALUE *lval);
+extern int hier3(LVALUE *lval);
+extern int hier4(LVALUE *lval);
+extern int hier5(LVALUE *lval);
+extern int hier6(LVALUE *lval);
+extern int hier7(LVALUE *lval);
+extern int hier8(LVALUE *lval);
+extern int hier9(LVALUE *lval);
+extern int hier10(LVALUE *lval);
+extern int hier11(LVALUE *lval);
+extern void newfunc(void);
+extern void getarg(int t);
+extern int doAnsiArguments(void);
+extern void doLocalAnsiArgument(int type);
+extern void oflush(void);
+extern int getlabel(void);
+extern void print_label(int label);
+extern void glabel(char *lab);
+extern void generate_label(int nlab);
+extern int output_byte(char c);
+extern void output_string(char ptr[]);
+extern void print_tab(void);
+extern void output_line(char ptr[]);
+extern void output_with_tab(char ptr[]);
+extern void output_decimal(int number);
+extern void store(LVALUE *lval);
+extern int rvalue(LVALUE *lval, int reg);
+extern void test(int label, int ft);
+extern void scale_const(int type, int otag, int *size);
+extern void create_initials(void);
+extern void add_symbol_initials(char *symbol_name, char type);
+extern int find_symbol_initials(char *symbol_name);
+extern void add_data_initials(char *symbol_name, int type, int value, TAG_SYMBOL *tag);
+extern int get_size(char *symbol_name);
+extern int get_item_at(char *symbol_name, int position, TAG_SYMBOL *tag);
+extern int openin(char *p);
+extern int openout(void);
+extern void outfname(char *s);
+extern void fixname(char *s);
+extern int checkname(char *s);
+extern void do_kill(void);
+extern int igetc(int unit);
+extern void readline(void);
+extern int inbyte(void);
+extern int inchar(void);
+extern int gch(void);
+extern int nch(void);
+extern int ch(void);
+extern void pl(char *str);
+extern void writee(char *str);
+extern int alpha(char c);
+extern int numeric(char c);
+extern int alphanumeric(char c);
+extern void need_semicolon(void);
+extern void junk(void);
+extern int endst(void);
+extern void needbrack(char *str);
+extern int sstreq(char *str1);
+extern int streq(char str1[], char str2[]);
+extern int astreq(char str1[], char str2[], int len);
+extern int match(char *lit);
+extern int amatch(char *lit, int len);
+extern void blanks(void);
+extern int get_type(void);
+extern void compile(char *file);
+extern void frontend_version(void);
+extern void usage(void);
+extern void parse(void);
+extern int do_declarations(int stclass, TAG_SYMBOL *mtag, int is_struct);
+extern void dumplits(void);
+extern void dumpglbs(void);
+extern void dump_struct(SYMBOL *symbol, int position);
+extern void errorsummary(void);
+extern int filename_typeof(char *s);
+extern int fix_include_name (void);
+extern void doinclude(void);
+extern void doasm(void);
+extern void dodefine(void);
+extern void doundef(void);
+extern void preprocess(void);
+extern void doifdef(int ifdef);
+extern int ifline(void);
+extern void noiferr(void);
+extern int cpp(void);
+extern int keepch(char c);
+extern void defmac(char *s);
+extern void addmac(void);
+extern int remove_one_line_comment(char c);
+extern void delmac(int mp);
+extern int putmac(char c);
+extern int findmac(char *sname);
+extern void toggle(char name, int onoff);
+extern int primary(LVALUE *lval);
+extern int dbltest(LVALUE *val1, LVALUE *val2);
+extern void result(LVALUE *lval, LVALUE *lval2);
+extern int constant(int val[]);
+extern int number(int val[]);
+extern int quoted_char(int *value);
+extern int quoted_string(int *position);
+extern int spechar(void);
+extern void callfunction(char *ptr);
+extern void needlval(void);
+extern int statement(int func);
+extern int statement_declare(void);
+extern int do_local_declares(int stclass);
+extern void do_statement(void);
+extern void do_compound(int func);
+extern void doif(void);
+extern void dowhile(void);
+extern void dodo(void);
+extern void dofor(void);
+extern void doswitch(void);
+extern void docase(void);
+extern void dodefault(void);
+extern void doreturn(void);
+extern void dobreak(void);
+extern void docont(void);
+extern void dumpsw(WHILE *ws);
+extern int find_tag(char *sname);
+extern SYMBOL *find_member(TAG_SYMBOL *tag, char *sname);
+extern void add_member(char *sname, char identity, char type, int offset, int storage_class);
+extern int define_struct(char *sname, int storage, int is_struct);
+extern void declare_global(int type, int storage, TAG_SYMBOL *mtag, int otag, int is_struct);
+extern int initials(char *symbol_name, int type, int identity, int dim, int otag);
+extern void struct_init(TAG_SYMBOL *tag, char *symbol_name);
+extern int init(char *symbol_name, int type, int identity, int *dim, TAG_SYMBOL *tag);
+extern void declare_local(int typ, int stclass, int otag);
+extern int needsub(void);
+extern int find_global (char *sname);
+extern int find_locale (char *sname);
+extern int add_global (char *sname, int identity, int type, int offset, int storage);
+extern int add_local (char *sname, int identity, int type, int offset, int storage_class);
+extern int symname(char *sname);
+extern void illname(void);
+extern void multidef(char *symbol_name);
+extern void addwhile(WHILE *ptr);
+extern void delwhile(void);
+extern WHILE *readwhile(void);
+extern WHILE *findwhile(void);
+extern WHILE *readswitch(void);
+extern void addcase(int val);
--- /dev/null
+\r
+There've been quite a few requests for this via net.micro.cpm, so's I\r
+thought I'd post it thru mod.sources. This is Ron Cain's original Small\r
+C compiler, but highly extended. Included are code generators for 8080,\r
+6809, 68000, and VAX, as well as run-time support for 8080 CPM, VAX BSD4.1,\r
+and a FLEX 6809 environment. See the README for a description of Small C's\r
+limitations.\r
--- /dev/null
+/*
+ * File stmt.c: 2.1 (83/03/20,16:02:17)
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+/**
+ * statement parser
+ * called whenever syntax requires a statement. this routine
+ * performs that statement and returns a number telling which one
+ * @param func func is true if we require a "function_statement", which
+ * must be compound, and must contain "statement_list" (even if
+ * "declaration_list" is omitted)
+ * @return statement type
+ */
+int statement(int func) {
+ if ((ch () == 0) && input_eof)
+ return (0);
+ lastst = 0;
+ if (func) {
+ if (match ("{")) {
+ do_compound (YES);
+ return (lastst);
+ } else
+ error ("function requires compound statement");
+ }
+ if (match ("{"))
+ do_compound (NO);
+ else
+ do_statement ();
+ return (lastst);
+}
+
+/**
+ * declaration
+ */
+int statement_declare(void) {
+ if (amatch("register", 8))
+ do_local_declares(DEFAUTO);
+ else if (amatch("auto", 4))
+ do_local_declares(DEFAUTO);
+ else if (amatch("static", 6))
+ do_local_declares(LSTATIC);
+ else if (do_local_declares(AUTO)) ;
+ else
+ return (NO);
+ return (YES);
+}
+
+/**
+ * local declarations
+ * @param stclass
+ * @return
+ */
+int do_local_declares(int stclass) {
+ int type = 0;
+ int otag; // tag of struct object being declared
+ int sflag; // TRUE for struct definition, zero for union
+ char sname[NAMESIZE];
+ blanks();
+ if ((sflag=amatch("struct", 6)) || amatch("union", 5)) {
+ if (symname(sname) == 0) { // legal name ?
+ illname();
+ }
+ if ((otag=find_tag(sname)) == -1) { // structure not previously defined
+ otag = define_struct(sname, stclass, sflag);
+ }
+ declare_local(STRUCT, stclass, otag);
+ } else if ((type = get_type()) != 0) {
+ declare_local(type, stclass, -1);
+ } else if (stclass == LSTATIC || stclass == DEFAUTO) {
+ declare_local(CINT, stclass, -1);
+ } else {
+ return(0);
+ }
+ need_semicolon();
+ return(1);
+}
+
+/**
+ * non-declaration statement
+ */
+void do_statement(void) {
+ if (amatch ("if", 2)) {
+ doif ();
+ lastst = STIF;
+ } else if (amatch ("while", 5)) {
+ dowhile ();
+ lastst = STWHILE;
+ } else if (amatch ("switch", 6)) {
+ doswitch ();
+ lastst = STSWITCH;
+ } else if (amatch ("do", 2)) {
+ dodo ();
+ need_semicolon ();
+ lastst = STDO;
+ } else if (amatch ("for", 3)) {
+ dofor ();
+ lastst = STFOR;
+ } else if (amatch ("return", 6)) {
+ doreturn ();
+ need_semicolon ();
+ lastst = STRETURN;
+ } else if (amatch ("break", 5)) {
+ dobreak ();
+ need_semicolon ();
+ lastst = STBREAK;
+ } else if (amatch ("continue", 8)) {
+ docont();
+ need_semicolon ();
+ lastst = STCONT;
+ } else if (match (";"))
+ ;
+ else if (amatch ("case", 4)) {
+ docase ();
+ lastst = statement (NO);
+ } else if (amatch ("default", 7)) {
+ dodefault ();
+ lastst = statement (NO);
+ } else if (match ("#asm")) {
+ doasm ();
+ lastst = STASM;
+ } else if (match ("{"))
+ do_compound (NO);
+ else {
+ expression (YES);
+/* if (match (":")) {
+ dolabel ();
+ lastst = statement (NO);
+ } else {
+*/ need_semicolon ();
+ lastst = STEXP;
+/* }
+*/ }
+}
+
+/**
+ * compound statement
+ * allow any number of statements to fall between "{" and "}"
+ * 'func' is true if we are in a "function_statement", which
+ * must contain "statement_list"
+ */
+void do_compound(int func) {
+ int decls;
+
+ decls = YES;
+ ncmp++;
+ while (!match ("}")) {
+ if (input_eof)
+ return;
+ if (decls) {
+ if (!statement_declare ())
+ decls = NO;
+ } else
+ do_statement ();
+ }
+ ncmp--;
+}
+
+/**
+ * "if" statement
+ */
+void doif(void) {
+ int fstkp, flab1, flab2;
+ int flev;
+
+ flev = local_table_index;
+ fstkp = stkp;
+ flab1 = getlabel ();
+ test (flab1, FALSE);
+ statement (NO);
+ stkp = gen_modify_stack (fstkp);
+ local_table_index = flev;
+ if (!amatch ("else", 4)) {
+ generate_label (flab1);
+ return;
+ }
+ gen_jump (flab2 = getlabel ());
+ generate_label (flab1);
+ statement (NO);
+ stkp = gen_modify_stack (fstkp);
+ local_table_index = flev;
+ generate_label (flab2);
+}
+
+/**
+ * "while" statement
+ */
+void dowhile(void) {
+ WHILE ws;
+
+ ws.symbol_idx = local_table_index;
+ ws.stack_pointer = stkp;
+ ws.type = WSWHILE;
+ ws.case_test = getlabel ();
+ ws.while_exit = getlabel ();
+ addwhile (&ws);
+ generate_label (ws.case_test);
+ test (ws.while_exit, FALSE);
+ statement (NO);
+ gen_jump (ws.case_test);
+ generate_label (ws.while_exit);
+ local_table_index = ws.symbol_idx;
+ stkp = gen_modify_stack (ws.stack_pointer);
+ delwhile ();
+}
+
+/**
+ * "do" statement
+ */
+void dodo(void) {
+ WHILE ws;
+
+ ws.symbol_idx = local_table_index;
+ ws.stack_pointer = stkp;
+ ws.type = WSDO;
+ ws.body_tab = getlabel ();
+ ws.case_test = getlabel ();
+ ws.while_exit = getlabel ();
+ addwhile (&ws);
+ generate_label (ws.body_tab);
+ statement (NO);
+ if (!match ("while")) {
+ error ("missing while");
+ return;
+ }
+ generate_label (ws.case_test);
+ test (ws.body_tab, TRUE);
+ generate_label (ws.while_exit);
+ local_table_index = ws.symbol_idx;
+ stkp = gen_modify_stack (ws.stack_pointer);
+ delwhile ();
+}
+
+/**
+ * "for" statement
+ */
+void dofor(void) {
+ WHILE ws;
+ WHILE *pws;
+
+ ws.symbol_idx = local_table_index;
+ ws.stack_pointer = stkp;
+ ws.type = WSFOR;
+ ws.case_test = getlabel ();
+ ws.incr_def = getlabel ();
+ ws.body_tab = getlabel ();
+ ws.while_exit = getlabel ();
+ addwhile (&ws);
+ pws = readwhile ();
+ needbrack ("(");
+ if (!match (";")) {
+ expression (YES);
+ need_semicolon ();
+ }
+ generate_label (pws->case_test);
+ if (!match (";")) {
+ expression (YES);
+ gen_test_jump (pws->body_tab, TRUE);
+ gen_jump (pws->while_exit);
+ need_semicolon ();
+ } else
+ pws->case_test = pws->body_tab;
+ generate_label (pws->incr_def);
+ if (!match (")")) {
+ expression (YES);
+ needbrack (")");
+ gen_jump (pws->case_test);
+ } else
+ pws->incr_def = pws->case_test;
+ generate_label (pws->body_tab);
+ statement (NO);
+ gen_jump (pws->incr_def);
+ generate_label (pws->while_exit);
+ local_table_index = pws->symbol_idx;
+ stkp = gen_modify_stack (pws->stack_pointer);
+ delwhile ();
+}
+
+/**
+ * "switch" statement
+ */
+void doswitch(void) {
+ WHILE ws;
+ WHILE *ptr;
+
+ ws.symbol_idx = local_table_index;
+ ws.stack_pointer = stkp;
+ ws.type = WSSWITCH;
+ ws.case_test = swstp;
+ ws.body_tab = getlabel ();
+ ws.incr_def = ws.while_exit = getlabel ();
+ addwhile (&ws);
+ gen_immediate ();
+ print_label (ws.body_tab);
+ newline ();
+ gen_push (HL_REG);
+ needbrack ("(");
+ expression (YES);
+ needbrack (")");
+ stkp = stkp + INTSIZE; // '?case' will adjust the stack
+ gen_jump_case ();
+ statement (NO);
+ ptr = readswitch ();
+ gen_jump (ptr->while_exit);
+ dumpsw (ptr);
+ generate_label (ptr->while_exit);
+ local_table_index = ptr->symbol_idx;
+ stkp = gen_modify_stack (ptr->stack_pointer);
+ swstp = ptr->case_test;
+ delwhile ();
+}
+
+/**
+ * "case" label
+ */
+void docase(void) {
+ int val;
+
+ val = 0;
+ if (readswitch ()) {
+ if (!number (&val))
+ if (!quoted_char (&val))
+ error ("bad case label");
+ addcase (val);
+ if (!match (":"))
+ error ("missing colon");
+ } else
+ error ("no active switch");
+}
+
+/**
+ * "default" label
+ */
+void dodefault(void) {
+ WHILE *ptr;
+ int lab;
+
+ if ((ptr = readswitch ()) != 0) {
+ ptr->incr_def = lab = getlabel ();
+ generate_label (lab);
+ if (!match (":"))
+ error ("missing colon");
+ } else
+ error ("no active switch");
+}
+
+/**
+ * "return" statement
+ */
+void doreturn(void) {
+ if (endst () == 0)
+ expression (YES);
+ gen_jump(fexitlab);
+}
+
+/**
+ * "break" statement
+ */
+void dobreak(void) {
+ WHILE *ptr;
+
+ if ((ptr = readwhile ()) == 0)
+ return;
+ gen_modify_stack (ptr->stack_pointer);
+ gen_jump (ptr->while_exit);
+}
+
+/**
+ * "continue" statement
+ */
+void docont(void) {
+ WHILE *ptr; //int *ptr;
+
+ if ((ptr = findwhile ()) == 0)
+ return;
+ gen_modify_stack (ptr->stack_pointer);
+ if (ptr->type == WSFOR)
+ gen_jump (ptr->incr_def);
+ else
+ gen_jump (ptr->case_test);
+}
+
+/**
+ * dump switch table
+ */
+void dumpsw(WHILE *ws) {
+ int i,j;
+
+ data_segment_gdata ();
+ generate_label (ws->body_tab);
+ if (ws->case_test != swstp) {
+ j = ws->case_test;
+ while (j < swstp) {
+ gen_def_word ();
+ i = 4;
+ while (i--) {
+ output_number (swstcase[j]);
+ output_byte (',');
+ print_label (swstlab[j++]);
+ if ((i == 0) | (j >= swstp)) {
+ newline ();
+ break;
+ }
+ output_byte (',');
+ }
+ }
+ }
+ gen_def_word ();
+ print_label (ws->incr_def);
+ output_string (",0");
+ newline ();
+ code_segment_gtext ();
+}
--- /dev/null
+/*
+ * File struct.c: (12/12/12,21:31:33)
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "data.h"
+
+/**
+ * look up a tag in tag table by name
+ * @param sname
+ * @return index
+ */
+int find_tag(char *sname) {
+ int index;
+
+ index = 0;
+ while (index < tag_table_index) {
+ if (astreq (sname, tag_table[index].name, NAMEMAX)) {
+ return index;
+ }
+ ++index;
+ }
+ return -1;
+}
+
+/**
+ * determine if 'sname' is a member of the struct with tag 'tag'
+ * @param tag
+ * @param sname
+ * @return pointer to member symbol if it is, else 0
+ */
+SYMBOL *find_member(TAG_SYMBOL *tag, char *sname) {
+ int member_idx;
+
+ member_idx = tag->member_idx;
+
+ while (member_idx < tag->member_idx + tag->number_of_members) {
+ if (strcmp(member_table[member_idx].name, sname) == 0)
+ return &member_table[member_idx];
+ ++member_idx;
+ }
+ return 0;
+}
+
+/**
+ * add new structure member to table
+ * @param sname
+ * @param identity - variable, array, pointer, function
+ * @param typ
+ * @param offset
+ * @param storage
+ * @return
+ */
+void add_member(char *sname, char identity, char type, int offset, int storage_class) {
+ char *buffer_ptr;
+ SYMBOL *symbol;
+ if (member_table_index >= NUMMEMB) {
+ error("symbol table overflow");
+ return;
+ }
+ symbol = &member_table[member_table_index];
+ buffer_ptr = symbol->name;
+ while (alphanumeric(*buffer_ptr++ = *sname++));
+ symbol->identity = identity;
+ symbol->type = type;
+ symbol->storage = storage_class;
+ symbol->offset = offset;
+
+ member_table_index++;
+}
+
+int define_struct(char *sname, int storage, int is_struct) {
+ TAG_SYMBOL *symbol;
+ char *buffer_ptr;
+
+ //tag_table_index++;
+ if (tag_table_index >= NUMTAG) {
+ error("struct table overflow");
+ return 0;
+ }
+ symbol = &tag_table[tag_table_index];
+ buffer_ptr = symbol->name;
+ while (alphanumeric(*buffer_ptr++ = *sname++));
+ symbol->size = 0;
+ symbol->member_idx = member_table_index;
+
+ needbrack("{");
+ do {
+ do_declarations(storage, &tag_table[tag_table_index], is_struct);
+ } while (!match ("}"));
+ symbol->number_of_members = member_table_index - symbol->member_idx;
+ return tag_table_index++;
+}
--- /dev/null
+/*
+ * File sym.c: 2.1 (83/03/20,16:02:19)
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "data.h"
+
+/**
+ * declare a static variable
+ * @param type
+ * @param storage
+ * @param mtag tag of struct whose members are being declared, or zero
+ * @param otag tag of struct object being declared. only matters if mtag is non-zero
+ * @param is_struct struct or union or no meaning
+ * @return
+ */
+void declare_global(int type, int storage, TAG_SYMBOL *mtag, int otag, int is_struct) {
+ int dim, identity;
+ char sname[NAMESIZE];
+
+ FOREVER {
+ FOREVER {
+ if (endst ())
+ return;
+ dim = 1;
+ if (match ("*")) {
+ identity = POINTER;
+ } else {
+ identity = VARIABLE;
+ }
+ if (!symname (sname))
+ illname ();
+ if (find_global (sname) > -1)
+ multidef (sname);
+ if (match ("[")) {
+ dim = needsub ();
+ //if (dim || storage == EXTERN) {
+ identity = ARRAY;
+ //} else {
+ // identity = POINTER;
+ //}
+ }
+ // add symbol
+ if (mtag == 0) { // real variable, not a struct/union member
+ identity = initials(sname, type, identity, dim, otag);
+ add_global (sname, identity, type, (dim == 0 ? -1 : dim), storage);
+ if (type == STRUCT) {
+ symbol_table[current_symbol_table_idx].tagidx = otag;
+ }
+ break;
+ } else if (is_struct) {
+ // structure member, mtag->size is offset
+ add_member(sname, identity, type, mtag->size, storage);
+ // store (correctly scaled) size of member in tag table entry
+ if (identity == POINTER)
+ type = CINT;
+ scale_const(type, otag, &dim);
+ mtag->size += dim;
+ }
+ else {
+ // union member, offset is always zero
+ add_member(sname, identity, type, 0, storage);
+ // store maximum member size in tag table entry
+ if (identity == POINTER)
+ type = CINT;
+ scale_const(type, otag, &dim);
+ if (mtag->size < dim)
+ mtag->size = dim;
+ }
+ }
+ if (!match (","))
+ return;
+ }
+}
+
+/**
+ * initialize global objects
+ * @param symbol_name
+ * @param type char or integer or struct
+ * @param identity
+ * @param dim
+ * @return 1 if variable is initialized
+ */
+int initials(char *symbol_name, int type, int identity, int dim, int otag) {
+ int dim_unknown = 0;
+ litptr = 0;
+ if(dim == 0) { // allow for xx[] = {..}; declaration
+ dim_unknown = 1;
+ }
+ if (!(type & CCHAR) && !(type & CINT) && !(type == STRUCT)) {
+ error("unsupported storage size");
+ }
+ if(match("=")) {
+ // an array or struct
+ if(match("{")) {
+ // aggregate initialiser
+ if ((identity == POINTER || identity == VARIABLE) && type == STRUCT) {
+ // aggregate is structure or pointer to structure
+ dim = 0;
+ struct_init(&tag_table[otag], symbol_name);
+ }
+ else {
+ while((dim > 0) || (dim_unknown)) {
+ if (identity == ARRAY && type == STRUCT) {
+ // array of struct
+ needbrack("{");
+ struct_init(&tag_table[otag], symbol_name);
+ --dim;
+ needbrack("}");
+ }
+ else {
+ if (init(symbol_name, type, identity, &dim, 0)) {
+ dim_unknown++;
+ }
+ }
+ if(match(",") == 0) {
+ break;
+ }
+ }
+ if(--dim_unknown == 0)
+ identity = POINTER;
+ }
+ needbrack("}");
+ // single constant
+ } else {
+ init(symbol_name, type, identity, &dim, 0);
+ }
+ }
+ return identity;
+}
+
+/**
+ * initialise structure
+ * @param tag
+ */
+void struct_init(TAG_SYMBOL *tag, char *symbol_name) {
+ int dim ;
+ int member_idx;
+
+ member_idx = tag->member_idx;
+ while (member_idx < tag->member_idx + tag->number_of_members) {
+ init(symbol_name, member_table[tag->member_idx + member_idx].type,
+ member_table[tag->member_idx + member_idx].identity, &dim, tag);
+ ++member_idx;
+ if ((match(",") == 0) && (member_idx != (tag->member_idx + tag->number_of_members))) {
+ error("struct initialisaton out of data");
+ break ;
+ }
+ }
+}
+
+/**
+ * evaluate one initializer, add data to table
+ * @param symbol_name
+ * @param type
+ * @param identity
+ * @param dim
+ * @param tag
+ * @return
+ */
+int init(char *symbol_name, int type, int identity, int *dim, TAG_SYMBOL *tag) {
+ int value, number_of_chars;
+ if(identity == POINTER) {
+ error("cannot assign to pointer");
+ }
+ if(quoted_string(&value)) {
+ if((identity == VARIABLE) || !(type & CCHAR))
+ error("found string: must assign to char pointer or array");
+ number_of_chars = litptr - value;
+ *dim = *dim - number_of_chars;
+ while (number_of_chars > 0) {
+ add_data_initials(symbol_name, CCHAR, litq[value++], tag);
+ number_of_chars = number_of_chars - 1;
+ }
+ } else if (number(&value)) {
+ add_data_initials(symbol_name, CINT, value, tag);
+ *dim = *dim - 1;
+ } else if(quoted_char(&value)) {
+ add_data_initials(symbol_name, CCHAR, value, tag);
+ *dim = *dim - 1;
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * declare local variables
+ * works just like "declglb", but modifies machine stack and adds
+ * symbol table entry with appropriate stack offset to find it again
+ * @param typ
+ * @param stclass
+ * @param otag index of tag in tag_table
+ */
+void declare_local(int typ, int stclass, int otag) {
+ int k, j;
+ char sname[NAMESIZE];
+
+ FOREVER {
+ FOREVER {
+ if (endst())
+ return;
+ if (match("*"))
+ j = POINTER;
+ else
+ j = VARIABLE;
+ if (!symname(sname))
+ illname();
+ if (-1 != find_locale(sname))
+ multidef (sname);
+ if (match("[")) {
+ k = needsub();
+ if (k) {
+ j = ARRAY;
+ if (typ & CINT) {
+ k = k * INTSIZE;
+ } else if (typ == STRUCT) {
+ k = k * tag_table[otag].size;
+ }
+ } else {
+ j = POINTER;
+ k = INTSIZE;
+ }
+ } else {
+ if (j == POINTER) {
+ k = INTSIZE;
+ } else {
+ switch (typ) {
+ case CCHAR:
+ case UCHAR:
+ k = 1;
+ break;
+ case STRUCT:
+ k = tag_table[otag].size;
+ break;
+ default:
+ k = INTSIZE;
+ }
+ }
+ }
+ if (stclass != LSTATIC) {
+ stkp = gen_modify_stack(stkp - k);
+ add_local(sname, j, typ, stkp, AUTO);
+ } else
+ add_local(sname, j, typ, k, LSTATIC);
+ break;
+ }
+ if (!match(","))
+ return;
+ }
+}
+
+/**
+ * get required array size. [xx]
+ * @return array size
+ */
+int needsub(void) {
+ int num[1];
+
+ if (match ("]"))
+ return (0);
+ if (!number (num)) {
+ error ("must be constant");
+ num[0] = 1;
+ }
+ if (num[0] < 0) {
+ error ("negative size illegal");
+ num[0] = (-num[0]);
+ }
+ needbrack ("]");
+ return (num[0]);
+}
+
+/**
+ * search global table for given symbol name
+ * @param sname
+ * @return table index
+ */
+int find_global (char *sname) {
+ int idx;
+
+ idx = 0;
+ while (idx < global_table_index) {
+ if (astreq (sname, symbol_table[idx].name, NAMEMAX))
+ return (idx);
+ idx++;
+ }
+ return (-1);
+}
+
+/**
+ * search local table for given symbol name
+ * @param sname
+ * @return table index
+ */
+int find_locale (char *sname) {
+ int idx;
+
+ idx = local_table_index;
+ while (idx >= NUMBER_OF_GLOBALS) {
+ idx--;
+ if (astreq (sname, symbol_table[idx].name, NAMEMAX))
+ return (idx);
+ }
+ return (-1);
+}
+
+/**
+ * add new symbol to global table
+ * @param sname
+ * @param identity
+ * @param type
+ * @param offset size in bytes
+ * @param storage
+ * @return new index
+ */
+int add_global (char *sname, int identity, int type, int offset, int storage) {
+ SYMBOL *symbol;
+ char *buffer_ptr;
+ if ((current_symbol_table_idx = find_global(sname)) > -1) {
+ return (current_symbol_table_idx);
+ }
+ if (global_table_index >= NUMBER_OF_GLOBALS) {
+ error ("global symbol table overflow");
+ return (0);
+ }
+ current_symbol_table_idx = global_table_index;
+ symbol = &symbol_table[current_symbol_table_idx];
+ buffer_ptr = symbol->name;
+ while (alphanumeric(*buffer_ptr++ = *sname++));
+ symbol->identity = identity;
+ symbol->type = type;
+ symbol->storage = storage;
+ symbol->offset = offset;
+ global_table_index++;
+ return (current_symbol_table_idx);
+}
+
+/**
+ * add new symbol to local table
+ * @param sname
+ * @param identity
+ * @param type
+ * @param offset size in bytes
+ * @param storage_class
+ * @return
+ */
+int add_local (char *sname, int identity, int type, int offset, int storage_class) {
+ int k;
+ SYMBOL *symbol;
+ char *buffer_ptr;
+
+ if ((current_symbol_table_idx = find_locale (sname)) > -1) {
+ return (current_symbol_table_idx);
+ }
+ if (local_table_index >= NUMBER_OF_GLOBALS + NUMBER_OF_LOCALS) {
+ error ("local symbol table overflow");
+ return (0);
+ }
+ current_symbol_table_idx = local_table_index;
+ symbol = &symbol_table[current_symbol_table_idx];
+ buffer_ptr = symbol->name;
+ while (alphanumeric(*buffer_ptr++ = *sname++));
+ symbol->identity = identity;
+ symbol->type = type;
+ symbol->storage = storage_class;
+ if (storage_class == LSTATIC) {
+ data_segment_gdata();
+ print_label(k = getlabel());
+ output_label_terminator();
+ gen_def_storage();
+ output_number(offset);
+ newline();
+ code_segment_gtext();
+ offset = k;
+ }
+ symbol->offset = offset;
+ local_table_index++;
+ return (current_symbol_table_idx);
+}
+
+/**
+ * test if next input string is legal symbol name
+ */
+int symname(char *sname) {
+ int k;
+
+ blanks();
+ if (!alpha (ch ()))
+ return (0);
+ k = 0;
+ while (alphanumeric(ch ()))
+ if (k < NAMEMAX)
+ sname[k++] = gch ();
+ sname[k] = 0;
+ return (1);
+}
+
+/**
+ * print error message
+ */
+void illname(void) {
+ error ("illegal symbol name");
+}
+
+/**
+ * print error message
+ * @param symbol_name
+ * @return
+ */
+void multidef(char *symbol_name) {
+ error ("already defined");
+ gen_comment ();
+ output_string (symbol_name);
+ newline ();
+}
+
--- /dev/null
+/* File while.c: 2.1 (83/03/20,16:02:22) */
+/*% cc -O -c %
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "data.h"
+
+void addwhile(WHILE *ptr) {
+//int ptr[];
+ //int k;
+
+ //if (wsptr == WSMAX) {
+ if (while_table_index == WSTABSZ) {
+ error ("too many active whiles");
+ return;
+ }
+ //k = 0;
+ //while (k < WSSIZ)
+ // *wsptr++ = ptr[k++];
+ memcpy(&ws[while_table_index++], ptr, sizeof(WHILE));
+}
+
+void delwhile(void) {
+ if (readwhile ()) {
+ //wsptr = wsptr - WSSIZ;
+ while_table_index--;
+ }
+}
+
+WHILE *readwhile(void) {
+ if (while_table_index == 0) {
+ //if (wsptr == ws) {
+ error ("no active do/for/while/switch");
+ return (0);
+ } else {
+ //return (wsptr-WSSIZ);
+ return &ws[while_table_index - 1];
+ }
+}
+
+WHILE *findwhile(void) {
+ //int *ptr;
+ int while_table_idx;
+
+ //for (ptr = wsptr; ptr != ws;) {
+ while_table_idx = while_table_index;
+ for (; while_table_idx != 0;) {
+ //ptr = ptr - WSSIZ;
+ while_table_idx--;
+ //if (ptr[WSTYP] != WSSWITCH)
+ // return (ptr);
+ if (ws[while_table_idx].type != WSSWITCH)
+ return &ws[while_table_idx];
+ }
+ error ("no active do/for/while");
+ return (0);
+}
+
+WHILE *readswitch(void) {
+ WHILE *ptr; //int *ptr;
+
+ if ((ptr = readwhile ()) != 0) {
+ //if (ptr[WSTYP] == WSSWITCH)
+ if (ptr->type == WSSWITCH) {
+ return (ptr);
+ }
+ }
+ return (0);
+}
+
+void addcase(int val) {
+ int lab;
+
+ if (swstp == SWSTSZ)
+ error ("too many case labels");
+ else {
+ swstcase[swstp] = val;
+ swstlab[swstp++] = lab = getlabel ();
+ print_label (lab);
+ output_label_terminator ();
+ newline ();
+ }
+}