├── LICENSE ├── README └── smallC ├── 8080 ├── Makefile ├── arglist.c ├── bdos.c ├── bdos1.c ├── chio8080.c ├── cret.asm ├── crun.asm ├── exit.c ├── inout.c └── io8080.c ├── M_README ├── Makefile ├── Makefile.bsd ├── README ├── c8080lib.asm ├── code8080.c ├── crun8080lib.asm ├── crun8085lib.asm ├── data.c ├── data.h ├── defs.h ├── error.c ├── expr.c ├── function.c ├── gen.c ├── includes ├── ctype.h └── stdio.h ├── initials.c ├── io.c ├── lex.c ├── lib ├── Makefile ├── abs.c ├── atoi.c ├── binary.c ├── charclass.c ├── fgets.c ├── fputs.c ├── getchar.c ├── gets.c ├── index.c ├── itoa.c ├── lorder8080 ├── printn.c ├── putchar.c ├── puts.c ├── rand.c ├── reverse.c ├── sbrk.c ├── shell.c ├── strcat.c ├── strcmp.c ├── strcpy.c ├── strlen.c ├── strncat.c ├── strncmp.c └── strncpy.c ├── main.c ├── preproc.c ├── primary.c ├── readme.txt ├── smallc1of3.sh ├── smallc2of3.sh ├── smallc3of3.sh ├── stmt.c ├── struct.c ├── sym.c └── while.c /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | Except as contained in this notice, the names of the authors above 25 | shall not be used in advertising or otherwise to promote the sale, 26 | use or other dealings in this Software without prior written 27 | authorization from those authors. 28 | 29 | For more information, please refer to 30 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Revived version of SmallC based on Chris Lewis' port to UNIX V. I have 2 | mainly rewritten code to use structures and to make it compile using GCC 3 | silently without warnigns. 4 | 5 | Support for one line comments from C99 specification was added as well 6 | as capability to handle Windows EOLs. 7 | 8 | Initialisation of global variables is also possible. When not initialised 9 | global var is assigned zero at compile time. 10 | 11 | Furthermore support for ANSI style method declaration, support for unsigned types, 12 | support for undocumented 8085 istructions LHLX, SHLX, LDSI, ARHL and support 13 | for structs and unions have been added. 14 | 15 | Generated code is suitable for ASXXXX assembler/linker. 16 | 17 | 18 | SmallC compiled for win32 can be downloaded here: 19 | https://drive.google.com/file/d/0B2TmWnRjWCj2alRqZHM1VEgwNFE/edit?usp=sharing 20 | 21 | -------------------------- original posting ------------------------------ 22 | 23 | Small C version C3.0R1.1 24 | (SCC3) 25 | 26 | Chris Lewis 27 | 28 | This directory contains the source for a version of Ron Cain's Small C 29 | compiler that I have heavily modified - beyond the Small-C V2.0 later 30 | published in Dr. Dobbs. This compiler generates assembler source code that 31 | needs to be assembled and linked to make a running program. 32 | 33 | Small C is a public domain compiler for a subset of C. The main things 34 | lacking are "#if", structs/unions, doubles/floats/longs and more than 35 | one level of indirection. Even so, it's powerful enough to be able to 36 | compile itself. It's also lots of fun to play around with. It could 37 | use lots of more work (eg: a real scanner), but what the heck... 38 | Retargetting the compiler requires only relinking the frontend with a new 39 | code generator. 40 | 41 | Code generators for 6809 (MIT UNIX-like assembler), M68K (Motorola V/68 42 | UNIX 43 | assembler), VAX (BSD 4.1 assembler), and 8080 (RMAC assembler) are 44 | provided. 45 | 46 | Users having access to System V make should be able to use the Makefile 47 | without any modification except for INCDIR and LIBDIR (where you'd like 48 | to put the compiler itself). 49 | 50 | Users not having access to System V will probably have to rewrite the 51 | Makefile. 52 | [ I have provided a Makefile that seems to work with bsd systems - mod] 53 | 54 | WARNING: you will probably see a great deal of compilation warnings when 55 | you compile this compiler with a "real" UNIX C. Don't worry - this is 56 | *perfectly* normal - Small C is a subset of real C, and in order to 57 | keep the compiler in this subset you have to bend the rules somewhat. 58 | The only time where this might cause a problem is where pointers are 59 | "different" from ints (ie: different length or on non-byte-addressible 60 | machines). Small C assumes that ints are the same as pointers. 61 | 62 | Invocation: 63 | scc<6809|vax|m68k|8080> filename 64 | 65 | There are other options available - see main.c for details. 66 | 67 | The code generated by these compilers need a run-time support library 68 | for two things: operations that are "hard" on a particular processor 69 | (eg: 16 bit multiply on an 8080), or O/S interface (vax is BSD 4.1, 70 | 6809 is FLEX, 8080 is CPM, never had one for M68k). 71 | 72 | Status: the 6809, VAX and 8080 versions work last I checked - a problem or 73 | two may have crept in during the implementation of the compile/assemble/and 74 | link code for machines that support it. The M68k version has never been 75 | tested. I don't have a Pyramid version because Pyrcorp seems reluctant 76 | to publish instruction set information. 77 | 78 | So you want to write a new coder do you? Well, it's easy - read the 79 | comments in one of the coders. You should not have to modify *any* of 80 | the existing files, just write a new codexxx.c file. Please contact 81 | me if you run into trouble. I would be greatly interested in any new 82 | coders or bug reports in the compilers. As far as I am aware, the 83 | major restriction on porting this thing for different targets is that 84 | pointers and integers *must* be the same length, alignment, and be 85 | interchangeable. 86 | -------------------------------------------------------------------------------- /smallC/8080/Makefile: -------------------------------------------------------------------------------- 1 | .SUFFIXES: .o .c .asm 2 | 3 | ASSEMS = bdos.asm bdos1.asm chio8080.asm exit.asm io8080.asm sbrk.asm 4 | 5 | .c.asm: 6 | tscc $*.c 7 | 8 | all: $(ASSEMS) 9 | -------------------------------------------------------------------------------- /smallC/8080/arglist.c: -------------------------------------------------------------------------------- 1 | /* Interpret CPM argument list to produce C style 2 | argc/argv 3 | default dma buffer has it, form: 4 | --------------------------------- 5 | |count|characters ... | 6 | --------------------------------- 7 | */ 8 | int Xargc; 9 | int Xargv[30]; 10 | Xarglist(ap) char *ap; { 11 | char qc; 12 | Xargc = 0; 13 | ap[(*ap)+1 ] = '\0'; 14 | ap++; 15 | while (isspace(*ap)) ap++; 16 | Xargv[Xargc++] = "arg0"; 17 | if (*ap) 18 | do { 19 | if (*ap == '\'' || *ap == '\"') { 20 | qc = *ap; 21 | Xargv[Xargc++] = ++ap; 22 | while (*ap&&*ap != qc) ap++; 23 | } else { 24 | Xargv[Xargc++] = ap; 25 | while (*ap&&!isspace(*ap)) ap++; 26 | } 27 | if (!*ap) break; 28 | *ap++='\0'; 29 | while (isspace(*ap)) ap++; 30 | } while(*ap); 31 | Xargv[Xargc] = 0; 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /smallC/8080/bdos.c: -------------------------------------------------------------------------------- 1 | bdos (c, de) int c, de; { 2 | #asm 3 | ; CP/M support routine 4 | ; bdos(C,DE); 5 | ; char *DE; int C; 6 | ; returns H=B,L=A per CPM standard 7 | pop h ; hold return address 8 | pop d ; get bdos function number 9 | pop b ; get DE register argument 10 | push d 11 | push b 12 | push h 13 | call 5 14 | mov h,b 15 | mov l,a 16 | #endasm 17 | } 18 | 19 | -------------------------------------------------------------------------------- /smallC/8080/bdos1.c: -------------------------------------------------------------------------------- 1 | bdos1(c, de) int c, de; { 2 | /* returns only single byte (top half is 0) */ 3 | return (255 & bdos(c, de)); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /smallC/8080/chio8080.c: -------------------------------------------------------------------------------- 1 | #define EOL 10 2 | getchar() { 3 | return (bdos(1,1)); 4 | 5 | } 6 | 7 | putchar (c) char c; { 8 | if (c == EOL) bdos(2,13); 9 | bdos(2,c); 10 | return c; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /smallC/8080/cret.asm: -------------------------------------------------------------------------------- 1 | ; Run time start off for Small C. 2 | cseg 3 | sphl ; save the stack pointer 4 | shld ?stksav 5 | lhld 6 ; pick up core top 6 | lxi d,-10 ; decrease by 10 for safety 7 | dad d 8 | sphl ; set stack pointer 9 | call stdioinit ; initialize stdio 10 | call Xarglist 11 | lhld Xargc 12 | push h 13 | lxi h,Xargv 14 | push h 15 | call main ; call main program 16 | pop d 17 | pop d 18 | lhld ?stksav ; restore stack pointer 19 | ret ; go back to CCP 20 | dseg 21 | ?stksav ds 2 22 | extrn stdioinit 23 | extrn Xarglist 24 | extrn Xargc 25 | extrn Xargv 26 | extrn main 27 | end 28 | -------------------------------------------------------------------------------- /smallC/8080/crun.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ;***************************************************** 3 | ; * 4 | ; runtime library for small C compiler * 5 | ; * 6 | ; c.s - runtime routine for basic C code * 7 | ; * 8 | ; Ron Cain * 9 | ; * 10 | ;***************************************************** 11 | ; 12 | cseg 13 | ; 14 | public ?gchar,?gint,?pchar,?pint 15 | public ?sxt 16 | public ?or,?and,?xor 17 | public ?eq,?ne,?gt,?le,?ge,?lt,?uge,?ult,?ugt,?ule 18 | public ?asr,?asl 19 | public ?sub,?neg,?com,?lneg,?bool,?mul,?div 20 | public ?case,brkend,Xstktop 21 | public etext 22 | public edata 23 | ; 24 | ; fetch char from (HL) and sign extend into HL 25 | ?gchar: mov a,m 26 | ?sxt: mov l,a 27 | rlc 28 | sbb a 29 | mov h,a 30 | ret 31 | ; fetch int from (HL) 32 | ?gint: mov a,m 33 | inx h 34 | mov h,m 35 | mov l,a 36 | ret 37 | ; store char from HL into (DE) 38 | ?pchar: mov a,l 39 | stax d 40 | ret 41 | ; store int from HL into (DE) 42 | ?pint: mov a,l 43 | stax d 44 | inx d 45 | mov a,h 46 | stax d 47 | ret 48 | ; "or" HL and DE into HL 49 | ?or: mov a,l 50 | ora e 51 | mov l,a 52 | mov a,h 53 | ora d 54 | mov h,a 55 | ret 56 | ; "xor" HL and DE into HL 57 | ?xor: mov a,l 58 | xra e 59 | mov l,a 60 | mov a,h 61 | xra d 62 | mov h,a 63 | ret 64 | ; "and" HL and DE into HL 65 | ?and: mov a,l 66 | ana e 67 | mov l,a 68 | mov a,h 69 | ana d 70 | mov h,a 71 | ret 72 | ; 73 | ;......logical operations: HL set to 0 (false) or 1 (true) 74 | ; 75 | ; DE == HL 76 | ?eq: call ?cmp 77 | rz 78 | dcx h 79 | ret 80 | ; DE != HL 81 | ?ne: call ?cmp 82 | rnz 83 | dcx h 84 | ret 85 | ; DE > HL [signed] 86 | ?gt: xchg 87 | call ?cmp 88 | rc 89 | dcx h 90 | ret 91 | ; DE <= HL [signed] 92 | ?le: call ?cmp 93 | rz 94 | rc 95 | dcx h 96 | ret 97 | ; DE >= HL [signed] 98 | ?ge: call ?cmp 99 | rnc 100 | dcx h 101 | ret 102 | ; DE < HL [signed] 103 | ?lt: call ?cmp 104 | rc 105 | dcx h 106 | ret 107 | ; DE >= HL [unsigned] 108 | ?uge: call ?ucmp 109 | rnc 110 | dcx h 111 | ret 112 | ; DE < HL [unsigned] 113 | ?ult: call ?ucmp 114 | rc 115 | dcx h 116 | ret 117 | ; DE > HL [unsigned] 118 | ?ugt: xchg 119 | call ?ucmp 120 | rc 121 | dcx h 122 | ret 123 | ; DE <= HL [unsigned] 124 | ?ule: call ?ucmp 125 | rz 126 | rc 127 | dcx h 128 | ret 129 | ; signed compare of DE and HL 130 | ; carry is sign of difference [set => DE < HL] 131 | ; zero is zero/non-zero 132 | ?cmp: mov a,e 133 | sub l 134 | mov e,a 135 | mov a,d 136 | sbb h 137 | lxi h,1 ;preset true 138 | jm ?cmp1 139 | ora e ;resets carry 140 | ret 141 | ?cmp1: ora e 142 | stc 143 | ret 144 | ; unsigned compare of DE and HL 145 | ; carry is sign of difference [set => DE < HL] 146 | ; zero is zero/non-zero 147 | ?ucmp: mov a,d 148 | cmp h 149 | jnz ?ucmp1 150 | mov a,e 151 | cmp l 152 | ?ucmp1: lxi h,1 ;preset true 153 | ret 154 | ; shift DE right arithmetically by HL, move to HL 155 | ?asr: xchg 156 | ?asr1: dcr e 157 | rm 158 | mov a,h 159 | ral 160 | mov a,h 161 | rar 162 | mov h,a 163 | mov a,l 164 | rar 165 | mov l,a 166 | jmp ?asr1 167 | ; shift DE left arithmetically by HL, move to HL 168 | ?asl: xchg 169 | ?asl1: dcr e 170 | rm 171 | dad h 172 | jmp ?asl1 173 | ; HL = DE - HL 174 | ?sub: mov a,e 175 | sub l 176 | mov l,a 177 | mov a,d 178 | sbb h 179 | mov h,a 180 | ret 181 | ; HL = -HL 182 | ?neg: call ?com 183 | inx h 184 | ret 185 | ; HL = ~HL 186 | ?com: mov a,h 187 | cma 188 | mov h,a 189 | mov a,l 190 | cma 191 | mov l,a 192 | ret 193 | ; HL = !HL 194 | ?lneg: mov a,h 195 | ora l 196 | jz ?lneg1 197 | lxi h,0 198 | ret 199 | ?lneg1: inx h 200 | ret 201 | ; HL = !!HL 202 | ?bool: call ?lneg 203 | jmp ?lneg 204 | ; 205 | ; HL = DE * HL [signed] 206 | ?mul: mov b,h 207 | mov c,l 208 | lxi h,0 209 | ?mul1: mov a,c 210 | rrc 211 | jnc ?mul2 212 | dad d 213 | ?mul2: xra a 214 | mov a,b 215 | rar 216 | mov b,a 217 | mov a,c 218 | rar 219 | mov c,a 220 | ora b 221 | rz 222 | xra a 223 | mov a,e 224 | ral 225 | mov e,a 226 | mov a,d 227 | ral 228 | mov d,a 229 | ora e 230 | rz 231 | jmp ?mul1 232 | ; HL = DE / HL, DE = DE % HL 233 | ?div: mov b,h 234 | mov c,l 235 | mov a,d 236 | xra b 237 | push psw 238 | mov a,d 239 | ora a 240 | cm ?deneg 241 | mov a,b 242 | ora a 243 | cm ?bcneg 244 | mvi a,16 245 | push psw 246 | xchg 247 | lxi d,0 248 | ?div1: dad h 249 | call ?rdel 250 | jz ?div2 251 | call ?cmpbd 252 | jm ?div2 253 | mov a,l 254 | ori 1 255 | mov l,a 256 | mov a,e 257 | sub c 258 | mov e,a 259 | mov a,d 260 | sbb b 261 | mov d,a 262 | ?div2: pop psw 263 | dcr a 264 | jz ?div3 265 | push psw 266 | jmp ?div1 267 | ?div3: pop psw 268 | rp 269 | call ?deneg 270 | xchg 271 | call ?deneg 272 | xchg 273 | ret 274 | ; {DE = -DE} 275 | ?deneg: mov a,d 276 | cma 277 | mov d,a 278 | mov a,e 279 | cma 280 | mov e,a 281 | inx d 282 | ret 283 | ; {BC = -BC} 284 | ?bcneg: mov a,b 285 | cma 286 | mov b,a 287 | mov a,c 288 | cma 289 | mov c,a 290 | inx b 291 | ret 292 | ; {DE 6 | ininst in 0 ; self modifying code... 7 | mov l,a 8 | xra a 9 | mov h,a 10 | ret 11 | #endasm 12 | 13 | } 14 | 15 | outp(pno, val) char pno, val; { 16 | pno; 17 | #asm 18 | mov a,l 19 | sta outinst+1 20 | #endasm 21 | val; 22 | #asm 23 | mov a,l 24 | outinst out 0 25 | ret 26 | #endasm 27 | } 28 | 29 | -------------------------------------------------------------------------------- /smallC/8080/io8080.c: -------------------------------------------------------------------------------- 1 | /* Basic CP/M file I/O: 2 | fopen,fclose,fgetc,fputc,feof 3 | 4 | Original: Paul Tarvydas 5 | Fixed by: Chris Lewis 6 | */ 7 | #include 8 | 9 | #define EOL 10 10 | #define EOL2 13 11 | #define CPMEOF 26 12 | #define CPMERR 255 13 | #define UNIT_OFFSET 3 14 | #define CPMCIN 1 15 | #define CPMCOUT 2 16 | #define READ_EOF 3 17 | #define SETDMA 26 18 | #define DEFAULT_DMA 128 19 | #define CPMREAD 20 20 | #define CPMWR 21 21 | #define WRITE 2 22 | #define READ 1 23 | #define FREE 0 24 | #define NBUFFS 4 25 | #define BUFSIZ 512 26 | #define FCBSIZ 33 27 | #define ALLBUFFS 2048 28 | #define ALLFCBS 132 29 | #define CPMERA 19 30 | #define CPMCREAT 22 31 | #define CPMOPEN 15 32 | #define NBLOCKS 4 33 | #define BLKSIZ 128 34 | #define BKSP 8 35 | #define CTRLU 21 36 | #define FWSP ' ' 37 | #define CPMCLOSE 16 38 | 39 | char buffs[ALLBUFFS], /* disk buffers */ 40 | fcbs[ALLFCBS]; /* fcbs for buffers */ 41 | int bptr[NBUFFS]; /* ptrs into buffers */ 42 | int modes[NBUFFS]; /* mode for each open file */ 43 | int eptr[NBUFFS]; /* buffers' ends */ 44 | char eofstdin; /* flag end of file on stdin */ 45 | 46 | fgetc(unit) int unit; 47 | { 48 | int c; 49 | while ((c = Xfgetc(unit)) == EOL2); 50 | return c; 51 | 52 | } 53 | 54 | Xfgetc(unit) int unit; 55 | { 56 | int i; 57 | int c; 58 | char *buff; 59 | char *fcba; 60 | if ((unit == stdin) & !eofstdin) { 61 | c = bdos1(CPMCIN, 0); 62 | if (c == 4) { 63 | eofstdin = 1; 64 | return (EOF); 65 | } 66 | else if (c == 3) 67 | exit (1); 68 | else { 69 | if (c == EOL2) { 70 | c = EOL; 71 | bdos (CPMCOUT, EOL); 72 | } 73 | return (c); 74 | } 75 | } 76 | if (modes[unit = unit - UNIT_OFFSET] == READ) { 77 | if (bptr[unit] >= eptr[unit]) { 78 | fcba = fcbaddr(unit); 79 | /* fill da buffer again */ 80 | i = 0; /* block counter */ 81 | buff = buffaddr(unit); /* dma ptr */ 82 | /* if buffer wasn't totally 83 | filled last time, we already 84 | eof */ 85 | if (eptr[unit] == buffaddr(unit + 1)) 86 | do { 87 | bdos(SETDMA, buff); 88 | if (0!=bdos1(CPMREAD, fcba)) 89 | break; 90 | buff = buff + BLKSIZ; 91 | } 92 | while (++ieof*/ 95 | if (i==0) { 96 | modes[unit] = READ_EOF; 97 | return EOF; 98 | } 99 | /* o.k. set start & end ptrs */ 100 | eptr[unit] = 101 | (bptr[unit]=buffaddr(unit)) 102 | + (i * BLKSIZ); 103 | } 104 | c = (*(bptr[unit]++)) & 0xff; 105 | if (c == CPMEOF) { 106 | c = EOF; 107 | modes[unit] = READ_EOF; 108 | } 109 | return c; 110 | } 111 | return EOF; 112 | 113 | } 114 | 115 | fclose(unit) int unit; 116 | { 117 | int i; 118 | if ((unit==stdin)|(unit==stdout)|(unit==stderr)) 119 | return NULL; 120 | if (modes[unit = unit - UNIT_OFFSET] != FREE) { 121 | if (modes[unit] == WRITE) 122 | fflush(unit + UNIT_OFFSET); 123 | modes[unit] = FREE; 124 | return bdos1(CPMCLOSE, fcbaddr(unit)); 125 | } 126 | return EOF; 127 | 128 | } 129 | 130 | fflush(unit) int unit; 131 | { 132 | char *buffa; 133 | char *fcba; 134 | if ((unit!=stdin)|(unit!=stdout)|(unit!=stderr)) { 135 | /* put an eof at end of file */ 136 | fputc(CPMEOF, unit); 137 | if (bptr[unit = unit - UNIT_OFFSET] != 138 | (buffa = buffaddr(unit))) { 139 | /* some chars in buffer - flush them */ 140 | fcba = fcbaddr(unit); 141 | do { 142 | bdos(SETDMA, buffa); 143 | if (0 != bdos1(CPMWR, fcba)) 144 | return (EOF); 145 | } 146 | while (bptr[unit] > 147 | (buffa=buffa+BLKSIZ)); 148 | bdos(SETDMA, DEFAULT_DMA); 149 | } 150 | } 151 | return NULL; 152 | 153 | } 154 | 155 | fputc(c, unit) char c; 156 | int unit; 157 | { 158 | char *buffa; 159 | char *fcba; 160 | if (c == EOL) fputc(EOL2, unit); 161 | if ((unit == stdout) | (unit == stderr)) { 162 | bdos(CPMCOUT, c); 163 | return c; 164 | } 165 | if (WRITE == modes[unit = unit - UNIT_OFFSET]) { 166 | if (bptr[unit] >= eptr[unit]) { 167 | /* no room - dump buffer */ 168 | fcba = fcbaddr(unit); 169 | buffa=buffaddr(unit); 170 | while (buffa < eptr[unit]) { 171 | bdos(SETDMA, buffa); 172 | if (0 != bdos1(CPMWR, fcba)) break; 173 | buffa = buffa + BLKSIZ; 174 | } 175 | bdos(SETDMA, DEFAULT_DMA); 176 | bptr[unit] = buffaddr(unit); 177 | if (buffa < eptr[unit]) return EOF; 178 | } 179 | *(bptr[unit]++) = c; 180 | return c; 181 | } 182 | return EOF; 183 | 184 | } 185 | 186 | allocunitno() { 187 | int i; 188 | /* returns # of first free buffer, EOF if none */ 189 | /* buffer is not reserved (ie. mode remains FREE) */ 190 | for (i = 0; i < NBUFFS; ++i) 191 | if (modes[i] == FREE) break; 192 | if (i >= NBUFFS) return EOF; 193 | else return (i + UNIT_OFFSET); 194 | 195 | } 196 | 197 | fopen(name, mode) char *name, *mode; 198 | { 199 | int fileno, fno2; 200 | if (EOF != (fileno = allocunitno())) { 201 | /* internal file # excludes units 0,1 & 2 202 | since there's no buffers associated with 203 | these units */ 204 | movname(clearfcb(fcbaddr(fno2 = fileno 205 | - UNIT_OFFSET)), name); 206 | if ('r' == *mode) { 207 | if (bdos1(CPMOPEN, fcbaddr(fno2)) != CPMERR) 208 | { 209 | modes[fno2] = READ; 210 | /* ptr>bufsiz => buffer empty*/ 211 | eptr[fno2] = 212 | bptr[fno2] = buffaddr(fno2+1 ); 213 | return fileno; 214 | } 215 | } 216 | else if ('w' == *mode) { 217 | bdos(CPMERA, fcbaddr(fno2)); 218 | if (bdos1(CPMCREAT, fcbaddr(fno2)) != CPMERR){ 219 | modes[fno2] = WRITE; 220 | bptr[fno2] = buffaddr(fno2); 221 | eptr[fno2] = buffaddr(fno2+1 ); 222 | return fileno; 223 | } 224 | } 225 | } 226 | return NULL; 227 | 228 | } 229 | 230 | clearfcb(fcb) char fcb[]; 231 | { 232 | int i; 233 | for (i=0; i= c)) { 249 | *fcb = (c - 'A' + 1); 250 | str++; 251 | str++; 252 | } 253 | } 254 | while ((NULL != *str) & (i<9)) { 255 | /* up to 8 chars into file name field */ 256 | if ('.' == *str) break; 257 | fcb[i++] = toupper(*str++); 258 | } 259 | /* strip off excess chars - up to '.' (beginning of 260 | extension name ) */ 261 | while ((NULL != *str) & ((*str) != '.')) ++str; 262 | if (*str) 263 | /* '.' is first char of *str now */ 264 | /* copy 3 chars of ext. if there */ 265 | for ( /* first char of ext @ pos 9 (8+1 )*/ 266 | i = 8; 267 | /* '.' is stripped by ++ 1st time */ 268 | /* around */ 269 | (NULL != *++str) & (12 > ++i); 270 | fcb[i] = toupper(*str) 271 | ); 272 | return fcb; 273 | 274 | } 275 | 276 | stdioinit() { 277 | int i; 278 | eofstdin = 0; 279 | for (i=0; i .. 8 | TARGDIR = /home/notebook/Public/work/smallCextended/lib 9 | #INCDIR = "/usr/shared/smallC/src/scc/include/" 10 | INCDIR = "./include/" 11 | 12 | INSTFLAGS = -DINCDIR=$(INCDIR) 13 | CFLAGS = '$(INSTFLAGS)' -ggdb -g 14 | 15 | ifdef SystemRoot 16 | # windows 17 | CFLAGS = '$(INSTFLAGS)' 18 | else 19 | ifeq ($(shell uname), Linux) 20 | CFLAGS = '$(INSTFLAGS)' 21 | endif 22 | endif 23 | 24 | SRC = initials.c data.c error.c expr.c function.c gen.c io.c lex.c main.c preproc.c \ 25 | primary.c stmt.c sym.c while.c code8080.c struct.c 26 | 27 | OBJ = $(addsuffix .o, $(basename $(SRC))) 28 | 29 | all: scc8080 30 | 31 | scc8080: $(OBJ) 32 | $(CC) -o scc8080 $(CFLAGS) $(OBJ) 33 | 34 | clean: 35 | rm -f $(OBJ) scc8080.exe scc8080 36 | 37 | %.o : %.c 38 | $(CC) $(CFLAGS) -c $< -o $@ 39 | -------------------------------------------------------------------------------- /smallC/Makefile.bsd: -------------------------------------------------------------------------------- 1 | # I couldn't get the supplied makefile to work, so I wrote one for 2 | # BSD systems - John Nelson, moderator, mod.sources 3 | # 4 | # You'll probabably want to change these. These are used by the 5 | compilers# to figure out where the include files should go. 6 | TARGDIR = /u/clewis/lib 7 | INCDIR = "/u/clewis/src/scc/include/" 8 | 9 | INSTFLAGS = -DINCDIR=$(INCDIR) 10 | CFLAGS = '$(INSTFLAGS)' -O 11 | AR = ar 12 | ARFLAGS = rv 13 | 14 | LIB = scclib.a 15 | 16 | FE = data.o \ 17 | error.o \ 18 | expr.o \ 19 | function.o \ 20 | gen.o \ 21 | io.o \ 22 | lex.o \ 23 | main.o \ 24 | preproc.o \ 25 | primary.o \ 26 | stmt.o \ 27 | sym.o \ 28 | while.o 29 | 30 | all: scc8080 sccas09 sccvax sccm68k 31 | 32 | $(FE) code8080.o codeas09.o codevax.o codem68k.o: defs.h data.h 33 | 34 | install: all 35 | mv sccvax scc8080 sccas09 sccm68k $(TARGDIR) 36 | 37 | #Alternately, you may have to do an lorder 38 | $(LIB): $(FE) 39 | -rm $@ 40 | ar q $@ $(FE) 41 | -ranlib $(LIB) 42 | 43 | scc8080: code8080.o $(LIB) 44 | $(CC) -o scc8080 $(CFLAGS) $(LIB) code8080.o 45 | 46 | sccas09: codeas09.o $(LIB) 47 | $(CC) -o sccas09 $(CFLAGS) $(LIB) codeas09.o 48 | 49 | sccvax: codevax.o $(LIB) 50 | $(CC) -o sccvax $(CFLAGS) $(LIB) codevax.o 51 | 52 | sccm68k: codem68k.o $(LIB) 53 | $(CC) -o sccm68k $(CFLAGS) $(LIB) codem68k.o 54 | 55 | print: 56 | pr -n defs.h data.h data.c error.c expr.c function.c gen.c \ 57 | io.c lex.c main.c preproc.c primary.c stmt.c \ 58 | sym.c while.c code*.c | lp 59 | clean: 60 | rm -f $(LIB) code8080.o codeas09.o codevax.o codem68k.o \ 61 | sccvax scc8080 sccas09 sccm68k 62 | -------------------------------------------------------------------------------- /smallC/README: -------------------------------------------------------------------------------- 1 | Small C version C3.0R1.1 2 | (SCC3) 3 | 4 | Chris Lewis 5 | 6 | This directory contains the source for a version of Ron Cain's Small C 7 | compiler that I have heavily modified - beyond the Small-C V2.0 later 8 | published in Dr. Dobbs. This compiler generates assembler source code that 9 | needs to be assembled and linked to make a running program. 10 | 11 | Small C is a public domain compiler for a subset of C. The main things 12 | lacking are "#if", structs/unions, doubles/floats/longs and more than 13 | one level of indirection. Even so, it's powerful enough to be able to 14 | compile itself. It's also lots of fun to play around with. It could 15 | use lots of more work (eg: a real scanner), but what the heck... 16 | Retargetting the compiler requires only relinking the frontend with a new 17 | code generator. 18 | 19 | Code generators for 6809 (MIT UNIX-like assembler), M68K (Motorola V/68 20 | UNIX 21 | assembler), VAX (BSD 4.1 assembler), and 8080 (RMAC assembler) are 22 | provided. 23 | 24 | Users having access to System V make should be able to use the Makefile 25 | without any modification except for INCDIR and LIBDIR (where you'd like 26 | to put the compiler itself). 27 | 28 | Users not having access to System V will probably have to rewrite the 29 | Makefile. 30 | [ I have provided a Makefile that seems to work with bsd systems - mod] 31 | 32 | WARNING: you will probably see a great deal of compilation warnings when 33 | you compile this compiler with a "real" UNIX C. Don't worry - this is 34 | *perfectly* normal - Small C is a subset of real C, and in order to 35 | keep the compiler in this subset you have to bend the rules somewhat. 36 | The only time where this might cause a problem is where pointers are 37 | "different" from ints (ie: different length or on non-byte-addressible 38 | machines). Small C assumes that ints are the same as pointers. 39 | 40 | Invocation: 41 | scc<6809|vax|m68k|8080> filename 42 | 43 | There are other options available - see main.c for details. 44 | 45 | The code generated by these compilers need a run-time support library 46 | for two things: operations that are "hard" on a particular processor 47 | (eg: 16 bit multiply on an 8080), or O/S interface (vax is BSD 4.1, 48 | 6809 is FLEX, 8080 is CPM, never had one for M68k). 49 | 50 | Status: the 6809, VAX and 8080 versions work last I checked - a problem or 51 | two may have crept in during the implementation of the compile/assemble/and 52 | link code for machines that support it. The M68k version has never been 53 | tested. I don't have a Pyramid version because Pyrcorp seems reluctant 54 | to publish instruction set information. 55 | 56 | So you want to write a new coder do you? Well, it's easy - read the 57 | comments in one of the coders. You should not have to modify *any* of 58 | the existing files, just write a new codexxx.c file. Please contact 59 | me if you run into trouble. I would be greatly interested in any new 60 | coders or bug reports in the compilers. As far as I am aware, the 61 | major restriction on porting this thing for different targets is that 62 | pointers and integers *must* be the same length, alignment, and be 63 | interchangeable. 64 | -------------------------------------------------------------------------------- /smallC/c8080lib.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ;------------------------------------------------------------------ 3 | ; Small-C Run-time Library 4 | ; 5 | ; V4d As of July 16, 1980 (gtf) 6 | ; Added EXIT() function 7 | ;------------------------------------------------------------------ 8 | ; 9 | ;Fetch a single byte from the address in HL and sign extend into HL 10 | CCGCHAR: MOV A,M 11 | CCSXT: MOV L,A 12 | RLC 13 | SBB A 14 | MOV H,A 15 | RET 16 | ;Fetch a full 16-bit integer from the address in HL 17 | CCGINT: MOV A,M 18 | INX H 19 | MOV H,M 20 | MOV L,A 21 | RET 22 | ;Store a single byte from HL at the address in DE 23 | CCPCHAR: MOV A,L 24 | STAX D 25 | RET 26 | ;Store a 16-bit integer in HL at the address in DE 27 | CCPINT: MOV A,L 28 | STAX D 29 | INX D 30 | MOV A,H 31 | STAX D 32 | RET 33 | ;Inclusive "or" HL and DE into HL 34 | CCOR: MOV A,L 35 | ORA E 36 | MOV L,A 37 | MOV A,H 38 | ORA D 39 | MOV H,A 40 | RET 41 | ;Exclusive "or" HL and DE into HL 42 | CCXOR: MOV A,L 43 | XRA E 44 | MOV L,A 45 | MOV A,H 46 | XRA D 47 | MOV H,A 48 | RET 49 | ;"And" HL and DE into HL 50 | CCAND: MOV A,L 51 | ANA E 52 | MOV L,A 53 | MOV A,H 54 | ANA D 55 | MOV H,A 56 | RET 57 | ;Test if HL = DE and set HL = 1 if true else 0 58 | CCEQ: CALL CCCMP 59 | RZ 60 | DCX H 61 | RET 62 | ;Test if DE ~= HL 63 | CCNE: CALL CCCMP 64 | RNZ 65 | DCX H 66 | RET 67 | ;Test if DE > HL (signed) 68 | CCGT: XCHG 69 | CALL CCCMP 70 | RC 71 | DCX H 72 | RET 73 | ;Test if DE <= HL (signed) 74 | CCLE: CALL CCCMP 75 | RZ 76 | RC 77 | DCX H 78 | RET 79 | ;Test if DE >= HL (signed) 80 | CCGE: CALL CCCMP 81 | RNC 82 | DCX H 83 | RET 84 | ;Test if DE < HL (signed) 85 | CCLT: CALL CCCMP 86 | RC 87 | DCX H 88 | RET 89 | ; Signed compare of DE and HL 90 | ; Performs DE - HL and sets the conditions: 91 | ; Carry reflects sign of difference (set means DE < HL) 92 | ; Zero/non-zero set according to equality. 93 | CCCMP: MOV A,E 94 | SUB L 95 | MOV E,A 96 | MOV A,D 97 | SBB H 98 | LXI H,1 99 | JM CCCMP1 100 | ORA E ;"OR" resets carry 101 | RET 102 | CCCMP1: ORA E 103 | STC ;set carry to signal minus 104 | RET 105 | ;Test if DE >= HL (unsigned) 106 | CCUGE: CALL CCUCMP 107 | RNC 108 | DCX H 109 | RET 110 | ;Test if DE < HL (unsigned) 111 | CCULT: CALL CCUCMP 112 | RC 113 | DCX H 114 | RET 115 | ;Test if DE > HL (unsigned) 116 | CCUGT: XCHG 117 | CALL CCUCMP 118 | RC 119 | DCX H 120 | RET 121 | ;Test if DE <= HL (unsigned) 122 | CCULE: CALL CCUCMP 123 | RZ 124 | RC 125 | DCX H 126 | RET 127 | ;Routine to perform unsigned compare 128 | ;carry set if DE < HL 129 | ;zero/nonzero set accordingly 130 | CCUCMP: MOV A,D 131 | CMP H 132 | JNZ .+5 133 | MOV A,E 134 | CMP L 135 | LXI H,1 136 | RET 137 | ;Shift DE arithmetically right by HL and return in HL 138 | CCASR: XCHG 139 | MOV A,H 140 | RAL 141 | MOV A,H 142 | RAR 143 | MOV H,A 144 | MOV A,L 145 | RAR 146 | MOV L,A 147 | DCR E 148 | JNZ CCASR+1 149 | RET 150 | ;Shift DE arithmetically left by HL and return in HL 151 | CCASL: XCHG 152 | DAD H 153 | DCR E 154 | JNZ CCASL+1 155 | RET 156 | ;Subtract HL from DE and return in HL 157 | CCSUB: MOV A,E 158 | SUB L 159 | MOV L,A 160 | MOV A,D 161 | SBB H 162 | MOV H,A 163 | RET 164 | ;Form the two's complement of HL 165 | CCNEG: CALL CCCOM 166 | INX H 167 | RET 168 | ;Form the one's complement of HL 169 | CCCOM: MOV A,H 170 | CMA 171 | MOV H,A 172 | MOV A,L 173 | CMA 174 | MOV L,A 175 | RET 176 | ;Multiply DE by HL and return in HL 177 | CCMULT: MOV B,H 178 | MOV C,L 179 | LXI H,0 180 | CCMULT1: MOV A,C 181 | RRC 182 | JNC .+4 183 | DAD D 184 | XRA A 185 | MOV A,B 186 | RAR 187 | MOV B,A 188 | MOV A,C 189 | RAR 190 | MOV C,A 191 | ORA B 192 | RZ 193 | XRA A 194 | MOV A,E 195 | RAL 196 | MOV E,A 197 | MOV A,D 198 | RAL 199 | MOV D,A 200 | ORA E 201 | RZ 202 | JMP CCMULT1 203 | ;Divide DE by HL and return quotient in HL, remainder in DE 204 | CCDIV: MOV B,H 205 | MOV C,L 206 | MOV A,D 207 | XRA B 208 | PUSH PSW 209 | MOV A,D 210 | ORA A 211 | CM CCDENEG 212 | MOV A,B 213 | ORA A 214 | CM CCBCNEG 215 | MVI A,16 216 | PUSH PSW 217 | XCHG 218 | LXI D,0 219 | CCDIV1: DAD H 220 | CALL CCRDEL 221 | JZ CCDIV2 222 | CALL CCCMPBCDE 223 | JM CCDIV2 224 | MOV A,L 225 | ORI 1 226 | MOV L,A 227 | MOV A,E 228 | SUB C 229 | MOV E,A 230 | MOV A,D 231 | SBB B 232 | MOV D,A 233 | CCDIV2: POP PSW 234 | DCR A 235 | JZ CCDIV3 236 | PUSH PSW 237 | JMP CCDIV1 238 | CCDIV3: POP PSW 239 | RP 240 | CALL CCDENEG 241 | XCHG 242 | CALL CCDENEG 243 | XCHG 244 | RET 245 | CCDENEG: MOV A,D 246 | CMA 247 | MOV D,A 248 | MOV A,E 249 | CMA 250 | MOV E,A 251 | INX D 252 | RET 253 | CCBCNEG: MOV A,B 254 | CMA 255 | MOV B,A 256 | MOV A,C 257 | CMA 258 | MOV C,A 259 | INX B 260 | RET 261 | CCRDEL: MOV A,E 262 | RAL 263 | MOV E,A 264 | MOV A,D 265 | RAL 266 | MOV D,A 267 | ORA E 268 | RET 269 | CCCMPBCDE: MOV A,E 270 | SUB C 271 | MOV A,D 272 | SBB B 273 | RET 274 | ; -------------------------------------------------------------------------------- /smallC/code8080.c: -------------------------------------------------------------------------------- 1 | /* File code8080.c: 2.2 (84/08/31,10:05:09) */ 2 | /*% cc -O -c % 3 | * 4 | */ 5 | 6 | #include 7 | #include "defs.h" 8 | #include "data.h" 9 | 10 | /* Define ASNM and LDNM to the names of the assembler and linker 11 | respectively */ 12 | 13 | /* 14 | * Some predefinitions: 15 | * 16 | * INTSIZE is the size of an integer in the target machine 17 | * BYTEOFF is the offset of an byte within an integer on the 18 | * target machine. (ie: 8080,pdp11 = 0, 6809 = 1, 19 | * 360 = 3) 20 | * This compiler assumes that an integer is the SAME length as 21 | * a pointer - in fact, the compiler uses INTSIZE for both. 22 | */ 23 | 24 | /** 25 | * print all assembler info before any code is generated 26 | */ 27 | void header () { 28 | output_string ("; Small C 8080\n;\tCoder (2.4,84/11/27)\n;"); 29 | frontend_version(); 30 | newline (); 31 | output_line ("\t;program area SMALLC_GENERATED is RELOCATABLE"); 32 | output_line ("\t.module SMALLC_GENERATED"); 33 | output_line ("\t.list (err, loc, bin, eqt, cyc, lin, src, lst, md)"); 34 | output_line ("\t.nlist (pag)"); 35 | } 36 | 37 | /** 38 | * prints new line 39 | * @return 40 | */ 41 | newline () { 42 | #if __CYGWIN__ == 1 43 | output_byte (CR); 44 | #endif 45 | output_byte (LF); 46 | } 47 | 48 | void initmac() { 49 | defmac("cpm\t1"); 50 | defmac("I8080\t1"); 51 | defmac("RMAC\t1"); 52 | defmac("smallc\t1"); 53 | } 54 | 55 | /** 56 | * Output internal generated label prefix 57 | */ 58 | void output_label_prefix() { 59 | output_byte('$'); 60 | } 61 | 62 | /** 63 | * Output a label definition terminator 64 | */ 65 | void output_label_terminator () { 66 | output_byte (':'); 67 | } 68 | 69 | /** 70 | * begin a comment line for the assembler 71 | */ 72 | void gen_comment() { 73 | output_byte (';'); 74 | } 75 | 76 | /** 77 | * print any assembler stuff needed after all code 78 | */ 79 | void trailer() { 80 | output_line (";\t.end"); 81 | } 82 | 83 | /** 84 | * text (code) segment 85 | */ 86 | void code_segment_gtext() { 87 | output_line ("\t.area SMALLC_GENERATED (REL,CON,CSEG)"); 88 | } 89 | 90 | /** 91 | * data segment 92 | */ 93 | void data_segment_gdata() { 94 | output_line ("\t.area SMALLC_GENERATED_DATA (REL,CON,DSEG)"); 95 | } 96 | 97 | /** 98 | * Output the variable symbol at scptr as an extrn or a public 99 | * @param scptr 100 | */ 101 | void ppubext(SYMBOL *scptr) { 102 | if (symbol_table[current_symbol_table_idx].storage == STATIC) return; 103 | output_with_tab (scptr->storage == EXTERN ? ";extrn\t" : ".globl\t"); 104 | output_string (scptr->name); 105 | newline(); 106 | } 107 | 108 | /** 109 | * Output the function symbol at scptr as an extrn or a public 110 | * @param scptr 111 | */ 112 | void fpubext(SYMBOL *scptr) { 113 | if (scptr->storage == STATIC) return; 114 | output_with_tab (scptr->offset == FUNCTION ? ".globl\t" : ";extrn\t"); 115 | output_string (scptr->name); 116 | newline (); 117 | } 118 | 119 | /** 120 | * Output a decimal number to the assembler file, with # prefix 121 | * @param num 122 | */ 123 | void output_number(num) int num; { 124 | output_byte('#'); 125 | output_decimal(num); 126 | } 127 | 128 | /** 129 | * fetch a static memory cell into the primary register 130 | * @param sym 131 | */ 132 | void gen_get_memory(SYMBOL *sym) { 133 | if ((sym->identity != POINTER) && (sym->type == CCHAR)) { 134 | output_with_tab ("lda\t"); 135 | output_string (sym->name); 136 | newline (); 137 | gen_call ("ccsxt"); 138 | } else if ((sym->identity != POINTER) && (sym->type == UCHAR)) { 139 | output_with_tab("lda\t"); 140 | output_string(sym->name); 141 | newline(); 142 | output_line("mov \tl,a"); 143 | output_line("mvi \th,#0"); 144 | } else { 145 | output_with_tab ("lhld\t"); 146 | output_string (sym->name); 147 | newline (); 148 | } 149 | } 150 | 151 | /** 152 | * asm - fetch the address of the specified symbol into the primary register 153 | * @param sym the symbol name 154 | * @return which register pair contains result 155 | */ 156 | int gen_get_locale(SYMBOL *sym) { 157 | if (sym->storage == LSTATIC) { 158 | gen_immediate(); 159 | print_label(sym->offset); 160 | newline(); 161 | return HL_REG; 162 | } else { 163 | if (uflag && !(sym->identity == ARRAY)) {/* || 164 | (sym->identity == VARIABLE && sym->type == STRUCT))) {*/ 165 | output_with_tab("ldsi\t"); 166 | output_number(sym->offset - stkp); 167 | newline (); 168 | return DE_REG; 169 | } else { 170 | gen_immediate(); 171 | output_number(sym->offset - stkp); 172 | newline (); 173 | output_line ("dad \tsp"); 174 | return HL_REG; 175 | } 176 | } 177 | } 178 | 179 | /** 180 | * asm - store the primary register into the specified static memory cell 181 | * @param sym 182 | */ 183 | void gen_put_memory(SYMBOL *sym) { 184 | if ((sym->identity != POINTER) && (sym->type & CCHAR)) { 185 | output_line ("mov \ta,l"); 186 | output_with_tab ("sta \t"); 187 | } else { 188 | output_with_tab ("shld\t"); 189 | } 190 | output_string (sym->name); 191 | newline (); 192 | } 193 | 194 | /** 195 | * store the specified object type in the primary register 196 | * at the address in secondary register (on the top of the stack) 197 | * @param typeobj 198 | */ 199 | void gen_put_indirect(char typeobj) { 200 | gen_pop (); 201 | if (typeobj & CCHAR) { 202 | /*gen_call("ccpchar");*/ 203 | output_line("mov \ta,l"); 204 | output_line("stax\td"); 205 | } else { 206 | if (uflag) { 207 | output_line("shlx"); 208 | } else { 209 | gen_call("ccpint"); 210 | } 211 | } 212 | } 213 | 214 | /** 215 | * fetch the specified object type indirect through the primary 216 | * register into the primary register 217 | * @param typeobj object type 218 | */ 219 | void gen_get_indirect(char typeobj, int reg) { 220 | if (typeobj == CCHAR) { 221 | if (reg & DE_REG) { 222 | gen_swap(); 223 | } 224 | gen_call("ccgchar"); 225 | } else if (typeobj == UCHAR) { 226 | if (reg & DE_REG) { 227 | gen_swap(); 228 | } 229 | /*gen_call("cguchar");*/ 230 | output_line("mov \tl,m"); 231 | output_line("mvi \th,0"); 232 | } else { /*int*/ 233 | if (uflag) { 234 | if (reg & HL_REG) { 235 | gen_swap(); 236 | } 237 | output_line("lhlx"); 238 | } else { 239 | gen_call("ccgint"); 240 | } 241 | } 242 | } 243 | 244 | /** 245 | * swap the primary and secondary registers 246 | */ 247 | gen_swap() { 248 | output_line("xchg"); 249 | } 250 | 251 | /** 252 | * print partial instruction to get an immediate value into 253 | * the primary register 254 | */ 255 | gen_immediate() { 256 | output_with_tab ("lxi \th,"); 257 | } 258 | 259 | /** 260 | * push the primary register onto the stack 261 | */ 262 | gen_push(int reg) { 263 | if (reg & DE_REG) { 264 | output_line ("push\td"); 265 | stkp = stkp - INTSIZE; 266 | } else { 267 | output_line ("push\th"); 268 | stkp = stkp - INTSIZE; 269 | } 270 | } 271 | 272 | /** 273 | * pop the top of the stack into the secondary register 274 | */ 275 | gen_pop() { 276 | output_line ("pop \td"); 277 | stkp = stkp + INTSIZE; 278 | } 279 | 280 | /** 281 | * swap the primary register and the top of the stack 282 | */ 283 | gen_swap_stack() { 284 | output_line ("xthl"); 285 | } 286 | 287 | /** 288 | * call the specified subroutine name 289 | * @param sname subroutine name 290 | */ 291 | gen_call(char *sname) { 292 | output_with_tab ("call\t"); 293 | output_string (sname); 294 | newline (); 295 | } 296 | 297 | /** 298 | * declare entry point 299 | */ 300 | declare_entry_point(char *symbol_name) { 301 | output_string(symbol_name); 302 | output_label_terminator(); 303 | /*newline();*/ 304 | } 305 | 306 | /** 307 | * return from subroutine 308 | */ 309 | gen_ret() { 310 | output_line ("ret"); 311 | } 312 | 313 | /** 314 | * perform subroutine call to value on top of stack 315 | */ 316 | callstk() { 317 | gen_immediate (); 318 | output_string ("#.+5"); 319 | newline (); 320 | gen_swap_stack (); 321 | output_line ("pchl"); 322 | stkp = stkp + INTSIZE; 323 | } 324 | 325 | /** 326 | * jump to specified internal label number 327 | * @param label the label 328 | */ 329 | gen_jump(label) 330 | int label; 331 | { 332 | output_with_tab ("jmp \t"); 333 | print_label (label); 334 | newline (); 335 | } 336 | 337 | /** 338 | * test the primary register and jump if false to label 339 | * @param label the label 340 | * @param ft if true jnz is generated, jz otherwise 341 | */ 342 | gen_test_jump(label, ft) 343 | int label, 344 | ft; 345 | { 346 | output_line ("mov \ta,h"); 347 | output_line ("ora \tl"); 348 | if (ft) 349 | output_with_tab ("jnz \t"); 350 | else 351 | output_with_tab ("jz \t"); 352 | print_label (label); 353 | newline (); 354 | } 355 | 356 | /** 357 | * print pseudo-op to define a byte 358 | */ 359 | gen_def_byte() { 360 | output_with_tab (".db\t"); 361 | } 362 | 363 | /** 364 | * print pseudo-op to define storage 365 | */ 366 | gen_def_storage() { 367 | output_with_tab (".ds\t"); 368 | } 369 | 370 | /** 371 | * print pseudo-op to define a word 372 | */ 373 | gen_def_word() { 374 | output_with_tab (".dw\t"); 375 | } 376 | 377 | /** 378 | * modify the stack pointer to the new value indicated 379 | * @param newstkp new value 380 | */ 381 | gen_modify_stack(int newstkp) { 382 | int k; 383 | 384 | k = newstkp - stkp; 385 | if (k == 0) 386 | return (newstkp); 387 | if (k > 0) { 388 | if (k < 7) { 389 | if (k & 1) { 390 | output_line ("inx \tsp"); 391 | k--; 392 | } 393 | while (k) { 394 | output_line ("pop \tb"); 395 | k = k - INTSIZE; 396 | } 397 | return (newstkp); 398 | } 399 | } else { 400 | if (k > -7) { 401 | if (k & 1) { 402 | output_line ("dcx \tsp"); 403 | k++; 404 | } 405 | while (k) { 406 | output_line ("push\tb"); 407 | k = k + INTSIZE; 408 | } 409 | return (newstkp); 410 | } 411 | } 412 | gen_swap (); 413 | gen_immediate (); 414 | output_number (k); 415 | newline (); 416 | output_line ("dad \tsp"); 417 | output_line ("sphl"); 418 | gen_swap (); 419 | return (newstkp); 420 | } 421 | 422 | /** 423 | * multiply the primary register by INTSIZE 424 | */ 425 | gen_multiply_by_two() { 426 | output_line ("dad \th"); 427 | } 428 | 429 | /** 430 | * divide the primary register by INTSIZE, never used 431 | */ 432 | gen_divide_by_two() { 433 | gen_push(HL_REG); /* push primary in prep for gasr */ 434 | gen_immediate (); 435 | output_number (1); 436 | newline (); 437 | gen_arithm_shift_right (); /* divide by two */ 438 | } 439 | 440 | /** 441 | * Case jump instruction 442 | */ 443 | gen_jump_case() { 444 | output_with_tab ("jmp \tcccase"); 445 | newline (); 446 | } 447 | 448 | /** 449 | * add the primary and secondary registers 450 | * if lval2 is int pointer and lval is not, scale lval 451 | * @param lval 452 | * @param lval2 453 | */ 454 | gen_add(lval,lval2) int *lval,*lval2; { 455 | gen_pop (); 456 | if (dbltest (lval2, lval)) { 457 | gen_swap (); 458 | gen_multiply_by_two (); 459 | gen_swap (); 460 | } 461 | output_line ("dad \td"); 462 | } 463 | 464 | /** 465 | * subtract the primary register from the secondary 466 | */ 467 | gen_sub() { 468 | gen_pop (); 469 | gen_call ("ccsub"); 470 | } 471 | 472 | /** 473 | * multiply the primary and secondary registers (result in primary) 474 | */ 475 | gen_mult() { 476 | gen_pop(); 477 | gen_call ("ccmul"); 478 | } 479 | 480 | /** 481 | * divide the secondary register by the primary 482 | * (quotient in primary, remainder in secondary) 483 | */ 484 | gen_div() { 485 | gen_pop(); 486 | gen_call ("ccdiv"); 487 | } 488 | 489 | /** 490 | * unsigned divide the secondary register by the primary 491 | * (quotient in primary, remainder in secondary) 492 | */ 493 | gen_udiv() { 494 | gen_pop(); 495 | gen_call ("ccudiv"); 496 | } 497 | 498 | /** 499 | * compute the remainder (mod) of the secondary register 500 | * divided by the primary register 501 | * (remainder in primary, quotient in secondary) 502 | */ 503 | gen_mod() { 504 | gen_div (); 505 | gen_swap (); 506 | } 507 | 508 | /** 509 | * compute the remainder (mod) of the secondary register 510 | * divided by the primary register 511 | * (remainder in primary, quotient in secondary) 512 | */ 513 | gen_umod() { 514 | gen_udiv (); 515 | gen_swap (); 516 | } 517 | 518 | /** 519 | * inclusive 'or' the primary and secondary registers 520 | */ 521 | gen_or() { 522 | gen_pop(); 523 | gen_call ("ccor"); 524 | } 525 | 526 | /** 527 | * exclusive 'or' the primary and secondary registers 528 | */ 529 | gen_xor() { 530 | gen_pop(); 531 | gen_call ("ccxor"); 532 | } 533 | 534 | /** 535 | * 'and' the primary and secondary registers 536 | */ 537 | gen_and() { 538 | gen_pop(); 539 | gen_call ("ccand"); 540 | } 541 | 542 | /** 543 | * arithmetic shift right the secondary register the number of 544 | * times in the primary register (results in primary register) 545 | */ 546 | gen_arithm_shift_right() { 547 | gen_pop(); 548 | gen_call ("ccasr"); 549 | } 550 | 551 | /** 552 | * logically shift right the secondary register the number of 553 | * times in the primary register (results in primary register) 554 | */ 555 | gen_logical_shift_right() { 556 | gen_pop(); 557 | gen_call ("cclsr"); 558 | } 559 | 560 | /** 561 | * arithmetic shift left the secondary register the number of 562 | * times in the primary register (results in primary register) 563 | */ 564 | gen_arithm_shift_left() { 565 | gen_pop (); 566 | gen_call ("ccasl"); 567 | } 568 | 569 | /** 570 | * two's complement of primary register 571 | */ 572 | gen_twos_complement() { 573 | gen_call ("ccneg"); 574 | } 575 | 576 | /** 577 | * logical complement of primary register 578 | */ 579 | gen_logical_negation() { 580 | gen_call ("cclneg"); 581 | } 582 | 583 | /** 584 | * one's complement of primary register 585 | */ 586 | gen_complement() { 587 | gen_call ("cccom"); 588 | } 589 | 590 | /** 591 | * Convert primary value into logical value (0 if 0, 1 otherwise) 592 | */ 593 | gen_convert_primary_reg_value_to_bool() { 594 | gen_call ("ccbool"); 595 | } 596 | 597 | /** 598 | * increment the primary register by 1 if char, INTSIZE if int 599 | */ 600 | gen_increment_primary_reg(LVALUE *lval) { 601 | switch (lval->ptr_type) { 602 | case STRUCT: 603 | gen_immediate2(); 604 | output_number(lval->tagsym->size); 605 | newline(); 606 | output_line("dad \td"); 607 | break ; 608 | case CINT: 609 | case UINT: 610 | output_line("inx \th"); 611 | default: 612 | output_line("inx \th"); 613 | break; 614 | } 615 | } 616 | 617 | /** 618 | * decrement the primary register by one if char, INTSIZE if int 619 | */ 620 | gen_decrement_primary_reg(LVALUE *lval) { 621 | output_line("dcx \th"); 622 | switch (lval->ptr_type) { 623 | case CINT: 624 | case UINT: 625 | output_line("dcx \th"); 626 | break; 627 | case STRUCT: 628 | gen_immediate2(); 629 | output_number(lval->tagsym->size - 1); 630 | newline(); 631 | /* two's complement */ 632 | output_line("mov \ta,d"); 633 | output_line("cma"); 634 | output_line("mov \td,a"); 635 | output_line("mov \ta,e"); 636 | output_line("cma"); 637 | output_line("mov \te,a"); 638 | output_line("inx \td"); 639 | /* subtract */ 640 | output_line("dad \td"); 641 | break ; 642 | default: 643 | break; 644 | } 645 | } 646 | 647 | /** 648 | * following are the conditional operators. 649 | * they compare the secondary register against the primary register 650 | * and put a literal 1 in the primary if the condition is true, 651 | * otherwise they clear the primary register 652 | */ 653 | 654 | /** 655 | * equal 656 | */ 657 | gen_equal() { 658 | gen_pop(); 659 | gen_call ("cceq"); 660 | } 661 | 662 | /** 663 | * not equal 664 | */ 665 | gen_not_equal() { 666 | gen_pop(); 667 | gen_call ("ccne"); 668 | } 669 | 670 | /** 671 | * less than (signed) 672 | */ 673 | gen_less_than() { 674 | gen_pop(); 675 | gen_call ("cclt"); 676 | } 677 | 678 | /** 679 | * less than or equal (signed) 680 | */ 681 | gen_less_or_equal() { 682 | gen_pop(); 683 | gen_call ("ccle"); 684 | } 685 | 686 | /** 687 | * greater than (signed) 688 | */ 689 | gen_greater_than() { 690 | gen_pop(); 691 | gen_call ("ccgt"); 692 | } 693 | 694 | /** 695 | * greater than or equal (signed) 696 | */ 697 | gen_greater_or_equal() { 698 | gen_pop(); 699 | gen_call ("ccge"); 700 | } 701 | 702 | /** 703 | * less than (unsigned) 704 | */ 705 | gen_unsigned_less_than() { 706 | gen_pop(); 707 | gen_call ("ccult"); 708 | } 709 | 710 | /** 711 | * less than or equal (unsigned) 712 | */ 713 | gen_unsigned_less_or_equal() { 714 | gen_pop(); 715 | gen_call ("ccule"); 716 | } 717 | 718 | /** 719 | * greater than (unsigned) 720 | */ 721 | gen_usigned_greater_than() { 722 | gen_pop(); 723 | gen_call ("ccugt"); 724 | } 725 | 726 | /** 727 | * greater than or equal (unsigned) 728 | */ 729 | gen_unsigned_greater_or_equal() { 730 | gen_pop(); 731 | gen_call ("ccuge"); 732 | } 733 | 734 | char *inclib() { 735 | #ifdef cpm 736 | return("B:"); 737 | #endif 738 | #ifdef unix 739 | #ifdef INCDIR 740 | return(INCDIR); 741 | #else 742 | return ""; 743 | #endif 744 | #endif 745 | } 746 | 747 | /** 748 | * Squirrel away argument count in a register that modstk doesn't touch. 749 | * @param d 750 | */ 751 | gnargs(d) 752 | int d; { 753 | output_with_tab ("mvi \ta,"); 754 | output_number(d); 755 | newline (); 756 | } 757 | 758 | int assemble(s) 759 | char *s; { 760 | #ifdef ASNM 761 | char buf[100]; 762 | strcpy(buf, ASNM); 763 | strcat(buf, " "); 764 | strcat(buf, s); 765 | buf[strlen(buf)-1] = 's'; 766 | return(system(buf)); 767 | #else 768 | return(0); 769 | #endif 770 | 771 | } 772 | 773 | int link() { 774 | #ifdef LDNM 775 | fputs("I don't know how to link files yet\n", stderr); 776 | #else 777 | return(0); 778 | #endif 779 | } 780 | 781 | /** 782 | * print partial instruction to get an immediate value into 783 | * the secondary register 784 | */ 785 | gen_immediate2() { 786 | output_with_tab ("lxi \td,"); 787 | } 788 | 789 | /** 790 | * add offset to primary register 791 | * @param val the value 792 | */ 793 | add_offset(int val) { 794 | gen_immediate2(); 795 | output_number(val); 796 | newline(); 797 | output_line ("dad \td"); 798 | } 799 | 800 | /** 801 | * multiply the primary register by the length of some variable 802 | * @param type 803 | * @param size 804 | */ 805 | gen_multiply(int type, int size) { 806 | switch (type) { 807 | case CINT: 808 | case UINT: 809 | gen_multiply_by_two(); 810 | break; 811 | case STRUCT: 812 | gen_immediate2(); 813 | output_number(size); 814 | newline(); 815 | gen_call("ccmul"); 816 | break ; 817 | default: 818 | break; 819 | } 820 | } 821 | 822 | -------------------------------------------------------------------------------- /smallC/crun8080lib.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ;***************************************************** 3 | ; * 4 | ; runtime library for small C compiler * 5 | ; * 6 | ; c.s - runtime routine for basic C code * 7 | ; * 8 | ; Ron Cain * 9 | ; * 10 | ;***************************************************** 11 | ; 12 | .module LIB8080 13 | .area LIB8080 (REL,CON) ;program area CODE1 is RELOCATABLE 14 | .list (err, loc, bin, eqt, cyc, lin, src, lst, md) 15 | .nlist (pag) 16 | ; cseg 17 | ; 18 | .globl ccgchar,ccgint,ccpchar,ccpint 19 | .globl ccsxt 20 | .globl ccor,ccand,ccxor 21 | .globl cceq,ccne,ccgt,ccle,ccge,cclt,ccuge,ccult,ccugt,ccule 22 | .globl cclsr,ccasr,ccasl 23 | .globl ccsub,ccneg,cccom,cclneg,ccbool,ccmul,ccdiv 24 | .globl cccase 25 | ; .globl brkend,Xstktop 26 | .globl cguchar,ccudiv 27 | .globl crun8080_end 28 | ; .globl etext,edata 29 | 30 | ; fetch char from (HL) and sign extend into HL 31 | ccgchar: mov a,m 32 | ccsxt: mov l,a 33 | rlc 34 | sbb a 35 | mov h,a 36 | ret 37 | ; fetch int from (HL) 38 | ccgint: mov a,m 39 | inx h 40 | mov h,m 41 | mov l,a 42 | ret 43 | ; store char from HL into (DE) 44 | ccpchar: mov a,l 45 | stax d 46 | ret 47 | ; store int from HL into (DE) 48 | ccpint: mov a,l 49 | stax d 50 | inx d 51 | mov a,h 52 | stax d 53 | ret 54 | ; "or" HL and DE into HL 55 | ccor: mov a,l 56 | ora e 57 | mov l,a 58 | mov a,h 59 | ora d 60 | mov h,a 61 | ret 62 | ; "xor" HL and DE into HL 63 | ccxor: mov a,l 64 | xra e 65 | mov l,a 66 | mov a,h 67 | xra d 68 | mov h,a 69 | ret 70 | ; "and" HL and DE into HL 71 | ccand: mov a,l 72 | ana e 73 | mov l,a 74 | mov a,h 75 | ana d 76 | mov h,a 77 | ret 78 | ; 79 | ;......logical operations: HL set to 0 (false) or 1 (true) 80 | ; 81 | ; DE == HL 82 | cceq: call cccmp 83 | rz 84 | dcx h 85 | ret 86 | ; DE != HL 87 | ccne: call cccmp 88 | rnz 89 | dcx h 90 | ret 91 | ; DE > HL [signed] 92 | ccgt: xchg 93 | call cccmp 94 | rc 95 | dcx h 96 | ret 97 | ; DE <= HL [signed] 98 | ccle: call cccmp 99 | rz 100 | rc 101 | dcx h 102 | ret 103 | ; DE >= HL [signed] 104 | ccge: call cccmp 105 | rnc 106 | dcx h 107 | ret 108 | ; DE < HL [signed] 109 | cclt: call cccmp 110 | rc 111 | dcx h 112 | ret 113 | ; DE >= HL [unsigned] 114 | ccuge: call ccucmp 115 | rnc 116 | dcx h 117 | ret 118 | ; DE < HL [unsigned] 119 | ccult: call ccucmp 120 | rc 121 | dcx h 122 | ret 123 | ; DE > HL [unsigned] 124 | ccugt: xchg 125 | call ccucmp 126 | rc 127 | dcx h 128 | ret 129 | ; DE <= HL [unsigned] 130 | ccule: call ccucmp 131 | rz 132 | rc 133 | dcx h 134 | ret 135 | ; signed compare of DE and HL 136 | ; carry is sign of difference [set => DE < HL] 137 | ; zero is zero/non-zero 138 | cccmp: mov a,e 139 | sub l 140 | mov e,a 141 | mov a,d 142 | sbb h 143 | lxi h,1 ;preset true 144 | jm cccmp1 145 | ora e ;resets carry 146 | ret 147 | cccmp1: ora e 148 | stc 149 | ret 150 | ; unsigned compare of DE and HL 151 | ; carry is sign of difference [set => DE < HL] 152 | ; zero is zero/non-zero 153 | ccucmp: mov a,d 154 | cmp h 155 | jnz ccucmp1 156 | mov a,e 157 | cmp l 158 | ccucmp1: lxi h,1 ;preset true 159 | ret 160 | ; shift DE right logically by HL, move to HL 161 | cclsr: xchg 162 | cclsr1: dcr e 163 | rm 164 | stc 165 | cmc 166 | mov a,h 167 | rar 168 | mov h,a 169 | mov a,l 170 | rar 171 | mov l,a 172 | stc 173 | cmc 174 | jmp cclsr1 175 | ; shift DE right arithmetically by HL, move to HL 176 | ccasr: xchg 177 | ccasr1: dcr e 178 | rm 179 | mov a,h 180 | ral 181 | mov a,h 182 | rar 183 | mov h,a 184 | mov a,l 185 | rar 186 | mov l,a 187 | jmp ccasr1 188 | ; shift DE left arithmetically by HL, move to HL 189 | ccasl: xchg 190 | ccasl1: dcr e 191 | rm 192 | dad h 193 | jmp ccasl1 194 | ; HL = DE - HL 195 | ccsub: mov a,e 196 | sub l 197 | mov l,a 198 | mov a,d 199 | sbb h 200 | mov h,a 201 | ret 202 | ; HL = -HL 203 | ccneg: call cccom 204 | inx h 205 | ret 206 | ; HL = ~HL 207 | cccom: mov a,h 208 | cma 209 | mov h,a 210 | mov a,l 211 | cma 212 | mov l,a 213 | ret 214 | ; HL = !HL 215 | cclneg: mov a,h 216 | ora l 217 | jz cclneg1 218 | lxi h,0 219 | ret 220 | cclneg1: inx h 221 | ret 222 | ; HL = !!HL 223 | ccbool: call cclneg 224 | jmp cclneg 225 | ; 226 | ; HL = DE * HL [signed] 227 | ccmul: mov b,h 228 | mov c,l 229 | lxi h,0 230 | ccmul1: mov a,c 231 | rrc 232 | jnc ccmul2 233 | dad d 234 | ccmul2: xra a 235 | mov a,b 236 | rar 237 | mov b,a 238 | mov a,c 239 | rar 240 | mov c,a 241 | ora b 242 | rz 243 | xra a 244 | mov a,e 245 | ral 246 | mov e,a 247 | mov a,d 248 | ral 249 | mov d,a 250 | ora e 251 | rz 252 | jmp ccmul1 253 | ; HL = DE / HL, DE = DE % HL 254 | ccdiv: mov b,h 255 | mov c,l 256 | mov a,d 257 | xra b 258 | push psw 259 | mov a,d 260 | ora a 261 | cm ccdeneg 262 | mov a,b 263 | ora a 264 | cm ccbcneg 265 | mvi a,16 266 | push psw 267 | xchg 268 | lxi d,0 269 | ccdiv1: dad h 270 | call ccrdel 271 | jz ccdiv2 272 | call cccmpbd 273 | jm ccdiv2 274 | mov a,l 275 | ori 1 276 | mov l,a 277 | mov a,e 278 | sub c 279 | mov e,a 280 | mov a,d 281 | sbb b 282 | mov d,a 283 | ccdiv2: pop psw 284 | dcr a 285 | jz ccdiv3 286 | push psw 287 | jmp ccdiv1 288 | ccdiv3: pop psw 289 | rp 290 | call ccdeneg 291 | xchg 292 | call ccdeneg 293 | xchg 294 | ret 295 | ; {DE = -DE} 296 | ccdeneg: 297 | mov a,d 298 | cma 299 | mov d,a 300 | mov a,e 301 | cma 302 | mov e,a 303 | inx d 304 | ret 305 | ; {BC = -BC} 306 | ccbcneg: 307 | mov a,b 308 | cma 309 | mov b,a 310 | mov a,c 311 | cma 312 | mov c,a 313 | inx b 314 | ret 315 | ; {DE calling else branch 397 | pop psw ; decrement loop counter 398 | dcr a 399 | jz ccduv5 400 | push psw 401 | xra a ; clear carry 402 | jmp ccduv3 403 | ccduv2: pop psw ; decrement loop counter 404 | dcr a 405 | jz ccduv5 406 | push psw 407 | stc ; set carry 408 | ccduv3: mov a,l ; left shift carry into remainder 409 | ral 410 | mov l,a 411 | mov a,h 412 | ral 413 | mov h,a 414 | mov a,l ; substract divisor from remainder 415 | sub c 416 | mov l,a 417 | mov a,h 418 | sbb b 419 | mov h,a 420 | jnc ccduv4 ; if result negative, add back divisor, clear carry 421 | mov a,l ; add back divisor 422 | add c 423 | mov l,a 424 | mov a,h 425 | adc b 426 | mov h,a 427 | xra a ; clear carry 428 | jmp ccduv1 429 | ccduv4: stc ; set carry 430 | jmp ccduv1 431 | ccduv5: xchg 432 | ret 433 | ; 434 | crun8080_end: 435 | -------------------------------------------------------------------------------- /smallC/crun8085lib.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ;***************************************************** 3 | ; * 4 | ; runtime library for small C compiler * 5 | ; * 6 | ; c.s - runtime routine for basic C code * 7 | ; * 8 | ; Ron Cain * 9 | ; * 10 | ;***************************************************** 11 | ; 12 | .module LIB8080 13 | .area LIB8080 (REL,CON) ;program area CODE1 is RELOCATABLE 14 | .list (err, loc, bin, eqt, cyc, lin, src, lst, md) 15 | .nlist (pag) 16 | ; cseg 17 | ; 18 | ;.globl ccgchar,ccgint,ccpchar,ccpint 19 | .globl ccgchar 20 | .globl ccsxt 21 | .globl ccor,ccand,ccxor 22 | .globl cceq,ccne,ccgt,ccle,ccge,cclt,ccuge,ccult,ccugt,ccule 23 | .globl cclsr,ccasr,ccasl 24 | .globl ccsub,ccneg,cccom,cclneg,ccbool,ccmul,ccdiv 25 | .globl cccase 26 | ; .globl brkend,Xstktop 27 | ;.globl cguchar,ccudiv 28 | .globl ccudiv 29 | .globl crun8080_end 30 | ; .globl etext,edata 31 | 32 | ; fetch char from (HL) and sign extend into HL 33 | ccgchar: mov a,m 34 | ccsxt: mov l,a 35 | rlc 36 | sbb a 37 | mov h,a 38 | ret 39 | ; fetch int from (HL) 40 | ;ccgint: mov a,m 41 | ; inx h 42 | ; mov h,m 43 | ; mov l,a 44 | ; ret 45 | ; fetch int from (HL) - 8085 undocumented instructions 46 | ;ccgint: xchg 47 | ; lhlx 48 | ; xchg 49 | ; ret 50 | ; store char from HL into (DE) 51 | ;ccpchar: mov a,l 52 | ; stax d 53 | ; ret 54 | ; store int from HL into (DE) 55 | ;ccpint: mov a,l 56 | ; stax d 57 | ; inx d 58 | ; mov a,h 59 | ; stax d 60 | ; ret 61 | ; store int from HL into (DE) - 8085 undocumented instructions 62 | ;ccpint: shlx 63 | ; ret 64 | ; "or" HL and DE into HL 65 | ccor: mov a,l 66 | ora e 67 | mov l,a 68 | mov a,h 69 | ora d 70 | mov h,a 71 | ret 72 | ; "xor" HL and DE into HL 73 | ccxor: mov a,l 74 | xra e 75 | mov l,a 76 | mov a,h 77 | xra d 78 | mov h,a 79 | ret 80 | ; "and" HL and DE into HL 81 | ccand: mov a,l 82 | ana e 83 | mov l,a 84 | mov a,h 85 | ana d 86 | mov h,a 87 | ret 88 | ; 89 | ;......logical operations: HL set to 0 (false) or 1 (true) 90 | ; 91 | ; DE == HL 92 | cceq: call cccmp 93 | rz 94 | dcx h 95 | ret 96 | ; DE != HL 97 | ccne: call cccmp 98 | rnz 99 | dcx h 100 | ret 101 | ; DE > HL [signed] 102 | ccgt: xchg 103 | call cccmp 104 | rc 105 | dcx h 106 | ret 107 | ; DE <= HL [signed] 108 | ccle: call cccmp 109 | rz 110 | rc 111 | dcx h 112 | ret 113 | ; DE >= HL [signed] 114 | ccge: call cccmp 115 | rnc 116 | dcx h 117 | ret 118 | ; DE < HL [signed] 119 | cclt: call cccmp 120 | rc 121 | dcx h 122 | ret 123 | ; DE >= HL [unsigned] 124 | ccuge: call ccucmp 125 | rnc 126 | dcx h 127 | ret 128 | ; DE < HL [unsigned] 129 | ccult: call ccucmp 130 | rc 131 | dcx h 132 | ret 133 | ; DE > HL [unsigned] 134 | ccugt: xchg 135 | call ccucmp 136 | rc 137 | dcx h 138 | ret 139 | ; DE <= HL [unsigned] 140 | ccule: call ccucmp 141 | rz 142 | rc 143 | dcx h 144 | ret 145 | ; signed compare of DE and HL 146 | ; carry is sign of difference [set => DE < HL] 147 | ; zero is zero/non-zero 148 | cccmp: mov a,e 149 | sub l 150 | mov e,a 151 | mov a,d 152 | sbb h 153 | lxi h,1 ;preset true 154 | jm cccmp1 155 | ora e ;resets carry 156 | ret 157 | cccmp1: ora e 158 | stc 159 | ret 160 | ; unsigned compare of DE and HL 161 | ; carry is sign of difference [set => DE < HL] 162 | ; zero is zero/non-zero 163 | ccucmp: mov a,d 164 | cmp h 165 | jnz ccucmp1 166 | mov a,e 167 | cmp l 168 | ccucmp1: lxi h,1 ;preset true 169 | ret 170 | ; shift DE right logically by HL, move to HL 171 | cclsr: xchg 172 | cclsr1: dcr e 173 | rm 174 | stc 175 | cmc 176 | mov a,h 177 | rar 178 | mov h,a 179 | mov a,l 180 | rar 181 | mov l,a 182 | jmp cclsr1 183 | ; shift DE right arithmetically by HL, move to HL - 8085 undocumented instructions 184 | ccasr: 185 | xchg 186 | ccasr1: dcr e 187 | rm 188 | arhl 189 | jmp ccasr1 190 | ; shift DE left arithmetically by HL, move to HL 191 | ccasl: xchg 192 | ccasl1: dcr e 193 | rm 194 | dad h 195 | jmp ccasl1 196 | ; HL = DE - HL 197 | ccsub: mov a,e 198 | sub l 199 | mov l,a 200 | mov a,d 201 | sbb h 202 | mov h,a 203 | ret 204 | ; HL = -HL 205 | ccneg: call cccom 206 | inx h 207 | ret 208 | ; HL = ~HL 209 | cccom: mov a,h 210 | cma 211 | mov h,a 212 | mov a,l 213 | cma 214 | mov l,a 215 | ret 216 | ; HL = !HL 217 | cclneg: mov a,h 218 | ora l 219 | jz cclneg1 220 | lxi h,0 221 | ret 222 | cclneg1: inx h 223 | ret 224 | ; HL = !!HL 225 | ccbool: call cclneg 226 | jmp cclneg 227 | ; 228 | ; HL = DE * HL [signed] 229 | ccmul: mov b,h 230 | mov c,l 231 | lxi h,0 232 | ccmul1: mov a,c 233 | rrc 234 | jnc ccmul2 235 | dad d 236 | ccmul2: xra a 237 | mov a,b 238 | rar 239 | mov b,a 240 | mov a,c 241 | rar 242 | mov c,a 243 | ora b 244 | rz 245 | xra a 246 | mov a,e 247 | ral 248 | mov e,a 249 | mov a,d 250 | ral 251 | mov d,a 252 | ora e 253 | rz 254 | jmp ccmul1 255 | ; HL = DE / HL, DE = DE % HL 256 | ccdiv: mov b,h 257 | mov c,l 258 | mov a,d 259 | xra b 260 | push psw 261 | mov a,d 262 | ora a 263 | cm ccdeneg 264 | mov a,b 265 | ora a 266 | cm ccbcneg 267 | mvi a,16 268 | push psw 269 | xchg 270 | lxi d,0 271 | ccdiv1: dad h 272 | call ccrdel 273 | jz ccdiv2 274 | call cccmpbd 275 | jm ccdiv2 276 | mov a,l 277 | ori 1 278 | mov l,a 279 | mov a,e 280 | sub c 281 | mov e,a 282 | mov a,d 283 | sbb b 284 | mov d,a 285 | ccdiv2: pop psw 286 | dcr a 287 | jz ccdiv3 288 | push psw 289 | jmp ccdiv1 290 | ccdiv3: pop psw 291 | rp 292 | call ccdeneg 293 | xchg 294 | call ccdeneg 295 | xchg 296 | ret 297 | ; {DE = -DE} 298 | ccdeneg: 299 | mov a,d 300 | cma 301 | mov d,a 302 | mov a,e 303 | cma 304 | mov e,a 305 | inx d 306 | ret 307 | ; {BC = -BC} 308 | ccbcneg: 309 | mov a,b 310 | cma 311 | mov b,a 312 | mov a,c 313 | cma 314 | mov c,a 315 | inx b 316 | ret 317 | ; {DE calling else branch 399 | pop psw ; decrement loop counter 400 | dcr a 401 | jz ccduv5 402 | push psw 403 | xra a ; clear carry 404 | jmp ccduv3 405 | ccduv2: pop psw ; decrement loop counter 406 | dcr a 407 | jz ccduv5 408 | push psw 409 | stc ; set carry 410 | ccduv3: mov a,l ; left shift carry into remainder 411 | ral 412 | mov l,a 413 | mov a,h 414 | ral 415 | mov h,a 416 | mov a,l ; substract divisor from remainder 417 | sub c 418 | mov l,a 419 | mov a,h 420 | sbb b 421 | mov h,a 422 | jnc ccduv4 ; if result negative, add back divisor, clear carry 423 | mov a,l ; add back divisor 424 | add c 425 | mov l,a 426 | mov a,h 427 | adc b 428 | mov h,a 429 | xra a ; clear carry 430 | jmp ccduv1 431 | ccduv4: stc ; set carry 432 | jmp ccduv1 433 | ccduv5: xchg 434 | ret 435 | ; 436 | crun8080_end: 437 | -------------------------------------------------------------------------------- /smallC/data.c: -------------------------------------------------------------------------------- 1 | /* File data.c: 2.2 (84/11/27,16:26:13) */ 2 | /*% cc -O -c % 3 | * 4 | */ 5 | 6 | #include 7 | #include "defs.h" 8 | 9 | /* storage words */ 10 | SYMBOL symbol_table[NUMBER_OF_GLOBALS + NUMBER_OF_LOCALS]; 11 | int global_table_index, rglobal_table_index; 12 | int local_table_index; 13 | 14 | WHILE ws[WSTABSZ]; 15 | int while_table_index; 16 | 17 | int swstcase[SWSTSZ]; 18 | int swstlab[SWSTSZ]; 19 | int swstp; 20 | char litq[LITABSZ]; 21 | int litptr; 22 | char macq[MACQSIZE]; 23 | int macptr; 24 | char line[LINESIZE]; 25 | char mline[LINESIZE]; 26 | int lptr, mptr; 27 | 28 | TAG_SYMBOL tag_table[NUMTAG]; /* start of structure tag table */ 29 | int tag_table_index; /* ptr to next entry */ 30 | 31 | SYMBOL member_table[NUMMEMB]; /* structure member table */ 32 | int member_table_index; /* ptr to next member */ 33 | 34 | /* miscellaneous storage */ 35 | int nxtlab, 36 | litlab, 37 | stkp, 38 | argstk, 39 | ncmp, 40 | errcnt, 41 | glbflag, 42 | ctext, 43 | cmode, 44 | lastst; 45 | 46 | FILE *input, *input2, *output; 47 | FILE *inclstk[INCLSIZ]; 48 | int inclsp; 49 | char fname[20]; 50 | 51 | /*char quote[2]; 52 | char *cptr;*/ 53 | int current_symbol_table_idx; 54 | int *iptr; 55 | int fexitlab; 56 | int iflevel, skiplevel; 57 | int errfile; 58 | int sflag; 59 | int cflag; 60 | int errs; 61 | int aflag; 62 | int uflag; /* undocumented 8085 instructions */ 63 | 64 | INITIALS initials_table[NUMBER_OF_GLOBALS]; 65 | char initials_data_table[INITIALS_SIZE]; /* 5kB space for initialisation data */ 66 | int initials_idx = 0, initials_data_idx = 0; 67 | -------------------------------------------------------------------------------- /smallC/data.h: -------------------------------------------------------------------------------- 1 | /* File data.h: 2.2 (84/11/27,16:26:11) */ 2 | 3 | /* storage words */ 4 | extern SYMBOL symbol_table[NUMBER_OF_GLOBALS + NUMBER_OF_LOCALS]; 5 | extern int global_table_index, rglobal_table_index; 6 | extern int local_table_index; 7 | extern WHILE ws[]; 8 | extern int while_table_index; 9 | extern int swstcase[]; 10 | extern int swstlab[]; 11 | extern int swstp; 12 | extern char litq[]; 13 | extern int litptr; 14 | extern char macq[]; 15 | extern int macptr; 16 | extern char line[]; 17 | extern char mline[]; 18 | extern int lptr, mptr; 19 | extern char finame[INCLSIZ+1][20]; /* global input filenames for error messages */ 20 | extern int srcln[]; /* source file line counters for error messages */ 21 | 22 | extern TAG_SYMBOL tag_table[NUMTAG]; /* start of structure tag table */ 23 | extern int tag_table_index; /* ptr to next entry */ 24 | 25 | extern SYMBOL member_table[NUMMEMB]; /* structure member table */ 26 | extern int member_table_index; /* ptr to next member< */ 27 | 28 | /* miscellaneous storage */ 29 | extern int nxtlab, 30 | litlab, 31 | stkp, 32 | argstk, 33 | ncmp, 34 | errcnt, 35 | glbflag, 36 | ctext, 37 | cmode, 38 | lastst; 39 | 40 | extern FILE *input, *input2, *output; 41 | extern FILE *inclstk[]; 42 | extern int inclsp; 43 | extern char fname[]; 44 | 45 | extern char quote[]; 46 | extern int current_symbol_table_idx; /*extern char *cptr; */ 47 | extern int *iptr; 48 | extern int fexitlab; 49 | extern int iflevel, skiplevel; 50 | extern int errfile; 51 | extern int sflag; 52 | extern int cflag; 53 | extern int errs; 54 | extern int aflag; 55 | extern int uflag; /* undocumented 8085 instructions */ 56 | 57 | extern INITIALS initials_table[NUMBER_OF_GLOBALS]; 58 | /* 5kB space for initialisation data*/ 59 | extern char initials_data_table[INITIALS_SIZE]; 60 | extern int initials_idx, initials_data_idx; 61 | -------------------------------------------------------------------------------- /smallC/defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File defs.h: 2.1 (83/03/21,02:07:20) 3 | */ 4 | 5 | /* Intel 8080 architecture defs */ 6 | #define INTSIZE 2 7 | 8 | /* miscellaneous */ 9 | #define FOREVER for(;;) 10 | #define FALSE 0 11 | #define TRUE 1 12 | #define NO 0 13 | #define YES 1 14 | 15 | #define EOS 0 16 | #define LF 10 17 | #define BKSP 8 18 | #define CR 13 19 | #define FFEED 12 20 | #define TAB 9 21 | 22 | /* system-wide name size (for symbols) */ 23 | #define NAMESIZE 33 24 | #define NAMEMAX 32 25 | 26 | struct symbol { 27 | char name[NAMESIZE]; /* symbol name */ 28 | int identity; /* variable, array, pointer, function */ 29 | int type; /* char, int, uchar, unit */ 30 | int storage; /* public, auto, extern, static, lstatic, defauto*/ 31 | int offset; /* offset*/ 32 | int tagidx; /* index of struct in tag table*/ 33 | int struct_size; /* the size, in bytes, of a member of a struct - only used for member declarations */ 34 | }; 35 | #define SYMBOL struct symbol 36 | 37 | #define NUMBER_OF_GLOBALS 100 38 | #define NUMBER_OF_LOCALS 20 39 | 40 | /* Define the structure tag table parameters */ 41 | #define NUMTAG 10 42 | 43 | struct tag_symbol { 44 | char name[NAMESIZE]; /* structure tag name */ 45 | int size; /* size of struct in bytes */ 46 | int member_idx; /* index of first member */ 47 | int number_of_members; /* number of tag members */ 48 | }; 49 | #define TAG_SYMBOL struct tag_symbol 50 | 51 | #ifdef SMALL_C 52 | #define NULL_TAG 0 53 | #else 54 | #define NULL_TAG (TAG_SYMBOL *)0 55 | #endif 56 | 57 | /* Define the structure member table parameters */ 58 | #define NUMMEMB 30 59 | 60 | /* possible entries for "ident" */ 61 | #define VARIABLE 1 62 | #define ARRAY 2 63 | #define POINTER 3 64 | #define FUNCTION 4 65 | 66 | /** 67 | * possible entries for "type" 68 | * high order 14 bits give length of object 69 | * low order 2 bits make type unique within length 70 | */ 71 | #define UNSIGNED 1 72 | #define STRUCT 2 73 | #define CCHAR (1 << 2) 74 | #define UCHAR ((1 << 2) + 1) 75 | #define CINT (2 << 2) 76 | #define UINT ((2 << 2) + 1) 77 | 78 | /* possible entries for storage */ 79 | #define PUBLIC 1 80 | #define AUTO 2 81 | #define EXTERN 3 82 | 83 | #define STATIC 4 84 | #define LSTATIC 5 85 | #define DEFAUTO 6 86 | 87 | /* "do"/"for"/"while"/"switch" statement stack */ 88 | #define WSTABSZ 20 89 | 90 | struct while_rec { 91 | int symbol_idx; /* symbol table address */ 92 | int stack_pointer; /* stack pointer */ 93 | int type; /* type */ 94 | int case_test; /* case or test */ 95 | int incr_def; /* continue label ? */ 96 | int body_tab; /* body of loop, switch ? */ 97 | int while_exit; /* exit label */ 98 | }; 99 | #define WHILE struct while_rec 100 | 101 | /* possible entries for "wstyp" */ 102 | #define WSWHILE 0 103 | #define WSFOR 1 104 | #define WSDO 2 105 | #define WSSWITCH 3 106 | 107 | /* "switch" label stack */ 108 | #define SWSTSZ 100 109 | 110 | /* literal pool */ 111 | #define LITABSZ 5000 112 | #define LITMAX LITABSZ-1 113 | 114 | /* input line */ 115 | #define LINESIZE 150 116 | #define LINEMAX (LINESIZE-1) 117 | #define MPMAX LINEMAX 118 | 119 | /* macro (define) pool */ 120 | #define MACQSIZE 1500 121 | #define MACMAX (MACQSIZE-1) 122 | 123 | /* "include" stack */ 124 | #define INCLSIZ 3 125 | 126 | /* statement types (tokens) */ 127 | #define STIF 1 128 | #define STWHILE 2 129 | #define STRETURN 3 130 | #define STBREAK 4 131 | #define STCONT 5 132 | #define STASM 6 133 | #define STEXP 7 134 | #define STDO 8 135 | #define STFOR 9 136 | #define STSWITCH 10 137 | 138 | #define DEFLIB inclib() 139 | 140 | #define FETCH 1 141 | #define HL_REG 1<<1 142 | #define DE_REG 1<<2 143 | 144 | struct lvalue { 145 | SYMBOL *symbol; /* symbol table address, or 0 for constant */ 146 | int indirect; /* type of indirect object, 0 for static object */ 147 | int ptr_type; /* type of pointer or array, 0 for other idents */ 148 | TAG_SYMBOL *tagsym; /* tag symbol address, 0 if not struct */ 149 | }; 150 | #define LVALUE struct lvalue 151 | 152 | /** 153 | * path to include directories. set at compile time on host machine 154 | * @return 155 | */ 156 | char *inclib(); 157 | 158 | WHILE *readwhile(); 159 | WHILE *findwhile(); 160 | WHILE *readswitch(); 161 | 162 | /** 163 | * Output the variable symbol at scptr as an extrn or a public 164 | * @param scptr 165 | */ 166 | void ppubext(SYMBOL *scptr); 167 | 168 | /** 169 | * Output the function symbol at scptr as an extrn or a public 170 | * @param scptr 171 | */ 172 | void fpubext(SYMBOL *scptr); 173 | 174 | /** 175 | * fetch a static memory cell into the primary register 176 | * @param sym 177 | */ 178 | void gen_get_memory (SYMBOL *sym); 179 | 180 | /** 181 | * fetch the specified object type indirect through the primary 182 | * register into the primary register 183 | * @param typeobj object type 184 | */ 185 | void gen_get_indirect(char typeobj, int reg); 186 | 187 | /** 188 | * asm - store the primary register into the specified static memory cell 189 | * @param sym 190 | */ 191 | void gen_put_memory (SYMBOL *sym); 192 | 193 | /* initialisation of global variables */ 194 | #define INIT_TYPE NAMESIZE 195 | #define INIT_LENGTH NAMESIZE+1 196 | #define INITIALS_SIZE 5*1024 197 | 198 | struct initials_table { 199 | char name[NAMESIZE]; /* symbol name */ 200 | int type; /* type */ 201 | int dim; /* length of data (possibly an array) */ 202 | int data_len; /* index of tag or zero */ 203 | }; 204 | #define INITIALS struct initials_table 205 | 206 | /** 207 | * determine if 'sname' is a member of the struct with tag 'tag' 208 | * @param tag 209 | * @param sname 210 | * @return pointer to member symbol if it is, else 0 211 | */ 212 | SYMBOL *find_member(TAG_SYMBOL *tag, char *sname); 213 | 214 | -------------------------------------------------------------------------------- /smallC/error.c: -------------------------------------------------------------------------------- 1 | /* File error.c: 2.1 (83/03/20,16:02:00) */ 2 | /*% cc -O -c % 3 | * 4 | */ 5 | 6 | #include 7 | #include "defs.h" 8 | #include "data.h" 9 | 10 | 11 | error (ptr) 12 | char ptr[]; 13 | { 14 | FILE *tempfile; 15 | 16 | tempfile = output; 17 | output = stdout; 18 | doerror(ptr); 19 | output = tempfile; 20 | doerror(ptr); 21 | errcnt++; 22 | } 23 | 24 | doerror(ptr) char *ptr; { 25 | int k; 26 | if(finame[inclsp]) {/* print actual source filename */ 27 | output_string (finame[inclsp]); 28 | } 29 | output_string (":"); 30 | output_decimal(srcln[inclsp]); /* print source line number*/ 31 | output_string (":"); 32 | output_decimal(lptr); /* print column number */ 33 | output_string (": error: "); 34 | output_string (ptr); 35 | newline (); 36 | output_string (line); 37 | newline (); 38 | k = 0; 39 | while (k < lptr) { 40 | if (line[k] == 9) 41 | print_tab (); 42 | else 43 | output_byte (' '); 44 | k++; 45 | } 46 | output_byte ('^'); 47 | newline (); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /smallC/expr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File expr.c: 2.2 (83/06/21,11:24:26) 3 | */ 4 | 5 | #include 6 | #include "defs.h" 7 | #include "data.h" 8 | 9 | /** 10 | * unsigned operand ? 11 | */ 12 | nosign(LVALUE *is) { 13 | SYMBOL *ptr; 14 | 15 | if((is->ptr_type) || 16 | ((ptr = is->symbol) && (ptr->type & UNSIGNED))) { 17 | return 1; 18 | } 19 | return 0; 20 | } 21 | 22 | /** 23 | * lval.symbol - symbol table address, else 0 for constant 24 | * lval.indirect - type indirect object to fetch, else 0 for static object 25 | * lval.ptr_type - type pointer or array, else 0 26 | * @param comma 27 | * @return 28 | */ 29 | expression(int comma) { 30 | LVALUE lval; 31 | int k; 32 | 33 | do { 34 | k = hier1 (&lval); 35 | if (k & FETCH) 36 | rvalue(&lval, k); 37 | if (!comma) 38 | return; 39 | } while (match (",")); 40 | } 41 | 42 | /** 43 | * assignment operators 44 | * @param lval 45 | * @return 46 | */ 47 | hier1 (LVALUE *lval) { 48 | int k; 49 | LVALUE lval2[1]; 50 | char fc; 51 | 52 | k = hier1a (lval); 53 | if (match ("=")) { 54 | if ((k & FETCH) == 0) { 55 | needlval (); 56 | return (0); 57 | } 58 | if (lval->indirect) 59 | gen_push(k); 60 | k = hier1 (lval2); 61 | if (k & FETCH) 62 | k = rvalue(lval2, k); 63 | store (lval); 64 | return (0); 65 | } else { 66 | fc = ch(); 67 | if (match ("-=") || 68 | match ("+=") || 69 | match ("*=") || 70 | match ("/=") || 71 | match ("%=") || 72 | match (">>=") || 73 | match ("<<=") || 74 | match ("&=") || 75 | match ("^=") || 76 | match ("|=")) { 77 | if ((k & FETCH) == 0) { 78 | needlval (); 79 | return (0); 80 | } 81 | if (lval->indirect) 82 | gen_push(k); 83 | k = rvalue(lval, k); 84 | gen_push(k); 85 | k = hier1 (lval2); 86 | if (k & FETCH) 87 | k = rvalue(lval2); 88 | switch (fc) { 89 | case '-': { 90 | if (dbltest(lval,lval2)) { 91 | gen_multiply(lval->ptr_type, lval->tagsym ? lval->tagsym->size : INTSIZE); 92 | } 93 | gen_sub(); 94 | result (lval, lval2); 95 | break; 96 | } 97 | case '+': { 98 | if (dbltest(lval,lval2)) { 99 | gen_multiply(lval->ptr_type, lval->tagsym ? lval->tagsym->size : INTSIZE); 100 | } 101 | gen_add (lval,lval2); 102 | result(lval,lval2); 103 | break; 104 | } 105 | case '*': gen_mult (); break; 106 | case '/': 107 | if(nosign(lval) || nosign(lval2)) { 108 | gen_udiv(); 109 | } else { 110 | gen_div(); 111 | } 112 | break; 113 | case '%': 114 | if(nosign(lval) || nosign(lval2)) { 115 | gen_umod(); 116 | } else { 117 | gen_mod(); 118 | } 119 | break; 120 | case '>': 121 | if (nosign(lval)) { 122 | gen_logical_shift_right(); 123 | } else { 124 | gen_arithm_shift_right(); 125 | } 126 | break; 127 | case '<': gen_arithm_shift_left(); break; 128 | case '&': gen_and (); break; 129 | case '^': gen_xor (); break; 130 | case '|': gen_or (); break; 131 | } 132 | store (lval); 133 | return (0); 134 | } else 135 | return (k); 136 | } 137 | } 138 | 139 | /** 140 | * processes ? : expression 141 | * @param lval 142 | * @return 0 or 1, fetch or no fetch 143 | */ 144 | hier1a (LVALUE *lval) { 145 | int k, lab1, lab2; 146 | LVALUE lval2[1]; 147 | 148 | k = hier1b (lval); 149 | blanks (); 150 | if (ch () != '?') 151 | return (k); 152 | if (k & FETCH) 153 | k = rvalue(lval, k); 154 | FOREVER 155 | if (match ("?")) { 156 | gen_test_jump (lab1 = getlabel (), FALSE); 157 | k = hier1b (lval2); 158 | if (k & FETCH) 159 | k = rvalue(lval2, k); 160 | gen_jump (lab2 = getlabel ()); 161 | print_label (lab1); 162 | output_label_terminator (); 163 | newline (); 164 | blanks (); 165 | if (!match (":")) { 166 | error ("missing colon"); 167 | return (0); 168 | } 169 | k = hier1b (lval2); 170 | if (k & FETCH) 171 | k = rvalue(lval2, k); 172 | print_label (lab2); 173 | output_label_terminator (); 174 | newline (); 175 | } else 176 | return (0); 177 | } 178 | 179 | /** 180 | * processes logical or || 181 | * @param lval 182 | * @return 0 or 1, fetch or no fetch 183 | */ 184 | hier1b (LVALUE *lval) { 185 | int k, lab; 186 | LVALUE lval2[1]; 187 | 188 | k = hier1c (lval); 189 | blanks (); 190 | if (!sstreq ("||")) 191 | return (k); 192 | if (k & FETCH) 193 | k = rvalue(lval, k); 194 | FOREVER 195 | if (match ("||")) { 196 | gen_test_jump (lab = getlabel (), TRUE); 197 | k = hier1c (lval2); 198 | if (k & FETCH) 199 | k = rvalue(lval2, k); 200 | print_label (lab); 201 | output_label_terminator (); 202 | newline (); 203 | gen_convert_primary_reg_value_to_bool(); 204 | } else 205 | return (0); 206 | } 207 | 208 | /** 209 | * processes logical and && 210 | * @param lval 211 | * @return 0 or 1, fetch or no fetch 212 | */ 213 | hier1c (LVALUE *lval) { 214 | int k, lab; 215 | LVALUE lval2[1]; 216 | 217 | k = hier2 (lval); 218 | blanks (); 219 | if (!sstreq ("&&")) 220 | return (k); 221 | if (k & FETCH) 222 | k = rvalue(lval, k); 223 | FOREVER 224 | if (match ("&&")) { 225 | gen_test_jump (lab = getlabel (), FALSE); 226 | k = hier2 (lval2); 227 | if (k & FETCH) 228 | k = rvalue(lval2, k); 229 | print_label (lab); 230 | output_label_terminator (); 231 | newline (); 232 | gen_convert_primary_reg_value_to_bool(); 233 | } else 234 | return (0); 235 | } 236 | 237 | /** 238 | * processes bitwise or | 239 | * @param lval 240 | * @return 0 or 1, fetch or no fetch 241 | */ 242 | hier2 (LVALUE *lval) { 243 | int k; 244 | LVALUE lval2[1]; 245 | 246 | k = hier3 (lval); 247 | blanks (); 248 | if ((ch() != '|') | (nch() == '|') | (nch() == '=')) 249 | return (k); 250 | if (k & FETCH) 251 | k = rvalue(lval, k); 252 | FOREVER { 253 | if ((ch() == '|') & (nch() != '|') & (nch() != '=')) { 254 | inbyte (); 255 | gen_push(k); 256 | k = hier3 (lval2); 257 | if (k & FETCH) 258 | k = rvalue(lval2, k); 259 | gen_or (); 260 | blanks(); 261 | } else 262 | return (0); 263 | } 264 | } 265 | 266 | /** 267 | * processes bitwise exclusive or 268 | * @param lval 269 | * @return 0 or 1, fetch or no fetch 270 | */ 271 | hier3 (LVALUE *lval) { 272 | int k; 273 | LVALUE lval2[1]; 274 | 275 | k = hier4 (lval); 276 | blanks (); 277 | if ((ch () != '^') | (nch() == '=')) 278 | return (k); 279 | if (k & FETCH) 280 | k = rvalue(lval, k); 281 | FOREVER { 282 | if ((ch() == '^') & (nch() != '=')){ 283 | inbyte (); 284 | gen_push(k); 285 | k = hier4 (lval2); 286 | if (k & FETCH) 287 | k = rvalue(lval2, k); 288 | gen_xor (); 289 | blanks(); 290 | } else 291 | return (0); 292 | } 293 | } 294 | 295 | /** 296 | * processes bitwise and & 297 | * @param lval 298 | * @return 0 or 1, fetch or no fetch 299 | */ 300 | hier4 (LVALUE *lval) { 301 | int k; 302 | LVALUE lval2[1]; 303 | 304 | k = hier5 (lval); 305 | blanks (); 306 | if ((ch() != '&') | (nch() == '|') | (nch() == '=')) 307 | return (k); 308 | if (k & FETCH) 309 | k = rvalue(lval, k); 310 | FOREVER { 311 | if ((ch() == '&') & (nch() != '&') & (nch() != '=')) { 312 | inbyte (); 313 | gen_push(k); 314 | k = hier5 (lval2); 315 | if (k & FETCH) 316 | k = rvalue(lval2, k); 317 | gen_and (); 318 | blanks(); 319 | } else 320 | return (0); 321 | } 322 | 323 | } 324 | 325 | /** 326 | * processes equal and not equal operators 327 | * @param lval 328 | * @return 0 or 1, fetch or no fetch 329 | */ 330 | hier5 (LVALUE *lval) { 331 | int k; 332 | LVALUE lval2[1]; 333 | 334 | k = hier6 (lval); 335 | blanks (); 336 | if (!sstreq ("==") & 337 | !sstreq ("!=")) 338 | return (k); 339 | if (k & FETCH) 340 | k = rvalue(lval, k); 341 | FOREVER { 342 | if (match ("==")) { 343 | gen_push(k); 344 | k = hier6 (lval2); 345 | if (k & FETCH) 346 | k = rvalue(lval2, k); 347 | gen_equal (); 348 | } else if (match ("!=")) { 349 | gen_push(k); 350 | k = hier6 (lval2); 351 | if (k & FETCH) 352 | k = rvalue(lval2, k); 353 | gen_not_equal (); 354 | } else 355 | return (0); 356 | } 357 | 358 | } 359 | 360 | /** 361 | * comparison operators 362 | * @param lval 363 | * @return 0 or 1, fetch or no fetch 364 | */ 365 | hier6 (LVALUE *lval) { 366 | int k; 367 | LVALUE lval2[1]; 368 | 369 | k = hier7 (lval); 370 | blanks (); 371 | if (!sstreq ("<") && 372 | !sstreq ("<=") && 373 | !sstreq (">=") && 374 | !sstreq (">")) 375 | return (k); 376 | if (sstreq ("<<") || sstreq (">>")) 377 | return (k); 378 | if (k & FETCH) 379 | k = rvalue(lval, k); 380 | FOREVER { 381 | if (match ("<=")) { 382 | gen_push(k); 383 | k = hier7 (lval2); 384 | if (k & FETCH) 385 | k = rvalue(lval2, k); 386 | if (nosign(lval) || nosign(lval2)) { 387 | gen_unsigned_less_or_equal (); 388 | continue; 389 | } 390 | gen_less_or_equal (); 391 | } else if (match (">=")) { 392 | gen_push(k); 393 | k = hier7 (lval2); 394 | if (k & FETCH) 395 | k = rvalue(lval2, k); 396 | if (nosign(lval) || nosign(lval2)) { 397 | gen_unsigned_greater_or_equal (); 398 | continue; 399 | } 400 | gen_greater_or_equal(); 401 | } else if ((sstreq ("<")) && 402 | !sstreq ("<<")) { 403 | inbyte (); 404 | gen_push(k); 405 | k = hier7 (lval2); 406 | if (k & FETCH) 407 | k = rvalue(lval2, k); 408 | if (nosign(lval) || nosign(lval2)) { 409 | gen_unsigned_less_than (); 410 | continue; 411 | } 412 | gen_less_than (); 413 | } else if ((sstreq (">")) && 414 | !sstreq (">>")) { 415 | inbyte (); 416 | gen_push(k); 417 | k = hier7 (lval2); 418 | if (k & FETCH) 419 | k = rvalue(lval2, k); 420 | if (nosign(lval) || nosign(lval2)) { 421 | gen_usigned_greater_than (); 422 | continue; 423 | } 424 | gen_greater_than(); 425 | } else 426 | return (0); 427 | blanks (); 428 | } 429 | 430 | } 431 | 432 | /** 433 | * bitwise left, right shift 434 | * @param lval 435 | * @return 0 or 1, fetch or no fetch 436 | */ 437 | hier7 (LVALUE *lval) { 438 | int k; 439 | LVALUE lval2[1]; 440 | 441 | k = hier8(lval); 442 | blanks(); 443 | if (!sstreq (">>") && 444 | !sstreq ("<<") || sstreq(">>=") || sstreq("<<=")) 445 | return (k); 446 | if (k & FETCH) 447 | k = rvalue(lval, k); 448 | FOREVER { 449 | if (sstreq(">>") && ! sstreq(">>=")) { 450 | inbyte(); inbyte(); 451 | gen_push(k); 452 | k = hier8 (lval2); 453 | if (k & FETCH) 454 | k = rvalue(lval2, k); 455 | if (nosign(lval)) { 456 | gen_logical_shift_right(); 457 | } else { 458 | gen_arithm_shift_right(); 459 | } 460 | } else if (sstreq("<<") && ! sstreq("<<=")) { 461 | inbyte(); inbyte(); 462 | gen_push(k); 463 | k = hier8 (lval2); 464 | if (k & FETCH) 465 | k = rvalue(lval2, k); 466 | gen_arithm_shift_left(); 467 | } else 468 | return (0); 469 | blanks(); 470 | } 471 | 472 | } 473 | 474 | /** 475 | * addition, subtraction 476 | * @param lval 477 | * @return 0 or 1, fetch or no fetch 478 | */ 479 | hier8 (LVALUE *lval) { 480 | int k; 481 | LVALUE lval2[1]; 482 | 483 | k = hier9 (lval); 484 | blanks (); 485 | if ((ch () != '+') & (ch () != '-') | nch() == '=') 486 | return (k); 487 | if (k & FETCH) 488 | k = rvalue(lval, k); 489 | FOREVER { 490 | if (match ("+")) { 491 | gen_push(k); 492 | k = hier9 (lval2); 493 | if (k & FETCH) 494 | k = rvalue(lval2, k); 495 | /* if left is pointer and right is int, scale right */ 496 | if (dbltest(lval,lval2)) { 497 | gen_multiply(lval->ptr_type, lval->tagsym ? lval->tagsym->size : INTSIZE); 498 | } 499 | /* will scale left if right int pointer and left int */ 500 | gen_add (lval,lval2); 501 | result (lval, lval2); 502 | } else if (match ("-")) { 503 | gen_push(k); 504 | k = hier9 (lval2); 505 | if (k & FETCH) 506 | k = rvalue(lval2, k); 507 | /* if dbl, can only be: pointer - int, or 508 | pointer - pointer, thus, 509 | in first case, int is scaled up, 510 | in second, result is scaled down. */ 511 | if (dbltest(lval,lval2)) { 512 | gen_multiply(lval->ptr_type, lval->tagsym ? lval->tagsym->size : INTSIZE); 513 | } 514 | gen_sub (); 515 | /* if both pointers, scale result */ 516 | if ((lval->ptr_type & CINT) && (lval2->ptr_type & CINT)) { 517 | gen_divide_by_two(); /* divide by intsize */ 518 | } 519 | result (lval, lval2); 520 | } else 521 | return (0); 522 | } 523 | } 524 | 525 | /** 526 | * multiplication, division, modulus 527 | * @param lval 528 | * @return 0 or 1, fetch or no fetch 529 | */ 530 | hier9 (LVALUE *lval) { 531 | int k; 532 | LVALUE lval2[1]; 533 | 534 | k = hier10 (lval); 535 | blanks (); 536 | if (((ch () != '*') && (ch () != '/') && 537 | (ch () != '%')) || (nch() == '=')) 538 | return (k); 539 | if (k & FETCH) 540 | k = rvalue(lval, k); 541 | FOREVER { 542 | if (match ("*")) { 543 | gen_push(k); 544 | k = hier10 (lval2); 545 | if (k & FETCH) 546 | k = rvalue(lval2, k); 547 | gen_mult (); 548 | } else if (match ("/")) { 549 | gen_push(k); 550 | k = hier10 (lval2); 551 | if (k & FETCH) 552 | k = rvalue(lval2, k); 553 | if(nosign(lval) || nosign(lval2)) { 554 | gen_udiv(); 555 | } else { 556 | gen_div (); 557 | } 558 | } else if (match ("%")) { 559 | gen_push(k); 560 | k = hier10 (lval2); 561 | if (k & FETCH) 562 | k = rvalue(lval2, k); 563 | if(nosign(lval) || nosign(lval2)) { 564 | gen_umod(); 565 | } else { 566 | gen_mod (); 567 | } 568 | } else 569 | return (0); 570 | } 571 | 572 | } 573 | 574 | /** 575 | * increment, decrement, negation operators 576 | * @param lval 577 | * @return 0 or 1, fetch or no fetch 578 | */ 579 | hier10 (LVALUE *lval) { 580 | int k; 581 | SYMBOL *ptr; 582 | 583 | if (match ("++")) { 584 | if (((k = hier10 (lval)) & FETCH) == 0) { 585 | needlval (); 586 | return (0); 587 | } 588 | if (lval->indirect) 589 | gen_push(k); 590 | k = rvalue(lval, k); 591 | gen_increment_primary_reg (lval); 592 | store (lval); 593 | return (HL_REG); 594 | } else if (match ("--")) { 595 | if (((k = hier10 (lval)) & FETCH) == 0) { 596 | needlval (); 597 | return (0); 598 | } 599 | if (lval->indirect) 600 | gen_push(k); 601 | k = rvalue(lval, k); 602 | gen_decrement_primary_reg (lval); 603 | store (lval); 604 | return (HL_REG); 605 | } else if (match ("-")) { 606 | k = hier10 (lval); 607 | if (k & FETCH) 608 | k = rvalue(lval, k); 609 | gen_twos_complement(); 610 | return (HL_REG); 611 | } else if (match ("~")) { 612 | k = hier10 (lval); 613 | if (k & FETCH) 614 | k = rvalue(lval, k); 615 | gen_complement (); 616 | return (HL_REG); 617 | } else if (match ("!")) { 618 | k = hier10 (lval); 619 | if (k & FETCH) 620 | k = rvalue(lval, k); 621 | gen_logical_negation(); 622 | return (HL_REG); 623 | } else if (ch()=='*' && nch() != '=') { 624 | inbyte(); 625 | k = hier10 (lval); 626 | if (k & FETCH) 627 | k = rvalue(lval, k); 628 | if (ptr = lval->symbol) 629 | lval->indirect = ptr->type; 630 | else 631 | lval->indirect = CINT; 632 | lval->ptr_type = 0; /* flag as not pointer or array */ 633 | return FETCH | k; 634 | } else if (ch()=='&' && nch()!='&' && nch()!='=') { 635 | inbyte(); 636 | k = hier10 (lval); 637 | if ((k & FETCH) == 0) { 638 | /* Without this check, this error triggers when trying to 639 | * evaluate a struct's address (a legal operation). Because 640 | * structs are stored as an address, nothing more than not 641 | * erroring is needed to load their address. */ 642 | if (lval->symbol->type != STRUCT){ 643 | error ("illegal address"); 644 | } 645 | return (0); 646 | } 647 | ptr = lval->symbol; 648 | lval->ptr_type = ptr->type; 649 | if (lval->indirect) { 650 | if (k & DE_REG) { 651 | gen_swap(); 652 | } 653 | return (HL_REG); 654 | } 655 | /* global and non-array */ 656 | gen_immediate (); 657 | output_string ((ptr = lval->symbol)->name); 658 | newline (); 659 | lval->indirect = ptr->type; 660 | return (HL_REG); 661 | } else { 662 | k = hier11 (lval); 663 | if (match ("++")) { 664 | if ((k & FETCH) == 0) { 665 | needlval (); 666 | return (0); 667 | } 668 | if (lval->indirect) 669 | gen_push(k); 670 | k = rvalue(lval, k); 671 | gen_increment_primary_reg (lval); 672 | store (lval); 673 | gen_decrement_primary_reg (lval); 674 | return (HL_REG); 675 | } else if (match ("--")) { 676 | if ((k & FETCH) == 0) { 677 | needlval (); 678 | return (0); 679 | } 680 | if (lval->indirect) 681 | gen_push(k); 682 | k = rvalue(lval, k); 683 | gen_decrement_primary_reg (lval); 684 | store (lval); 685 | gen_increment_primary_reg (lval); 686 | return (HL_REG); 687 | } else 688 | return (k); 689 | } 690 | 691 | } 692 | 693 | /** 694 | * array subscripting 695 | * @param lval 696 | * @return 0 or 1, fetch or no fetch 697 | */ 698 | hier11(LVALUE *lval) { 699 | int direct, k; 700 | SYMBOL *ptr; 701 | char sname[NAMESIZE]; 702 | 703 | k = primary(lval); 704 | ptr = lval->symbol; 705 | blanks(); 706 | if ((ch () == '[') || (ch () == '(') || (ch () == '.') || ((ch () == '-') && (nch() == '>'))) 707 | FOREVER { 708 | if (match("[")) { 709 | if (ptr == 0) { 710 | error("can't subscript"); 711 | junk(); 712 | needbrack("]"); 713 | return (0); 714 | } else if (ptr->identity == POINTER) { 715 | k = rvalue(lval, k); 716 | } else if (ptr->identity != ARRAY) { 717 | error("can't subscript"); 718 | k = 0; 719 | } 720 | gen_push(k); 721 | expression (YES); 722 | needbrack ("]"); 723 | gen_multiply(ptr->type, tag_table[ptr->tagidx].size); 724 | gen_add (NULL,NULL); 725 | /*lval->symbol = 0;*/ 726 | lval->indirect = ptr->type; 727 | lval->ptr_type = 0; 728 | k = FETCH | HL_REG; 729 | } else if (match ("(")) { 730 | if (ptr == 0) { 731 | callfunction(0); 732 | } else if (ptr->identity != FUNCTION) { 733 | k = rvalue(lval, k); 734 | callfunction(0); 735 | } else { 736 | callfunction(ptr); 737 | } 738 | lval->symbol = 0; 739 | k = 0; 740 | } else if ((direct=match(".")) || match("->")) { 741 | if (lval->tagsym == 0) { 742 | error("can't take member"); 743 | junk(); 744 | return 0; 745 | } 746 | if (symname(sname) == 0 || 747 | ((ptr=find_member(lval->tagsym, sname)) == 0)) { 748 | error("unknown member"); 749 | junk(); 750 | return 0; 751 | } 752 | if ((k & FETCH) && direct == 0) { 753 | k = rvalue(lval, k); 754 | } 755 | if (k == DE_REG) { 756 | gen_swap(); 757 | } 758 | 759 | /* move pointer from struct begin to struct member */ 760 | 761 | add_offset(ptr->offset); 762 | lval->symbol = ptr; 763 | /* lval->indirect = lval->val_type = ptr->type */ 764 | lval->indirect = ptr->type; 765 | lval->ptr_type = 0; 766 | lval->tagsym = NULL_TAG; 767 | if (ptr->type == STRUCT) { 768 | lval->tagsym = &tag_table[ptr->tagidx]; 769 | } 770 | if (ptr->identity == POINTER) { 771 | lval->indirect = CINT; 772 | lval->ptr_type = ptr->type; 773 | /*lval->val_type = CINT;*/ 774 | } 775 | if (ptr->identity==ARRAY || 776 | (ptr->type==STRUCT && ptr->identity==VARIABLE)) { 777 | /* array or struct*/ 778 | lval->ptr_type = ptr->type; 779 | /*lval->val_type = CINT;*/ 780 | k = 0; 781 | } else { 782 | k = FETCH | HL_REG; 783 | } 784 | } 785 | else return k; 786 | } 787 | if (ptr == 0) 788 | return k; 789 | if (ptr->identity == FUNCTION) { 790 | gen_immediate(); 791 | output_string(ptr); 792 | newline(); 793 | return 0; 794 | } 795 | return k; 796 | } 797 | 798 | -------------------------------------------------------------------------------- /smallC/function.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File function.c: 2.1 (83/03/20,16:02:04) 3 | */ 4 | 5 | #include 6 | #include "defs.h" 7 | #include "data.h" 8 | 9 | int argtop; 10 | 11 | /** 12 | * begin a function 13 | * called from "parse", this routine tries to make a function out 14 | * of what follows 15 | * modified version. p.l. woods 16 | */ 17 | newfunc() { 18 | char n[NAMESIZE]; 19 | int idx, type; 20 | fexitlab = getlabel(); 21 | 22 | if (!symname(n)) { 23 | error("illegal function or declaration"); 24 | kill(); 25 | return; 26 | } 27 | if ((idx = find_global(n)) > -1) { 28 | if (symbol_table[idx].identity != FUNCTION) 29 | multidef(n); 30 | else if (symbol_table[idx].offset == FUNCTION) 31 | multidef(n); 32 | else 33 | symbol_table[idx].offset = FUNCTION; 34 | } else 35 | add_global(n, FUNCTION, CINT, FUNCTION, PUBLIC); 36 | if (!match("(")) 37 | error("missing open paren"); 38 | output_string(n); 39 | output_label_terminator(); 40 | newline(); 41 | local_table_index = NUMBER_OF_GLOBALS; /*locptr = STARTLOC;*/ 42 | argstk = 0; 43 | /* ANSI style argument declaration*/ 44 | if (doAnsiArguments() == 0) { 45 | /* K&R style argument declaration*/ 46 | while (!match(")")) { 47 | if (symname(n)) { 48 | if (find_locale(n) > -1) 49 | multidef(n); 50 | else { 51 | add_local(n, 0, 0, argstk, AUTO); 52 | argstk = argstk + INTSIZE; 53 | } 54 | } else { 55 | error("illegal argument name"); 56 | junk(); 57 | } 58 | blanks(); 59 | if (!streq(line + lptr, ")")) { 60 | if (!match(",")) 61 | error("expected comma"); 62 | } 63 | if (endst()) 64 | break; 65 | } 66 | stkp = 0; 67 | argtop = argstk; 68 | while (argstk) { 69 | if (type = get_type()) { 70 | getarg(type); 71 | need_semicolon(); 72 | } else { 73 | error("wrong number args"); 74 | break; 75 | } 76 | } 77 | } 78 | statement(YES); 79 | print_label(fexitlab); 80 | output_label_terminator(); 81 | newline(); 82 | gen_modify_stack(0); 83 | gen_ret(); 84 | stkp = 0; 85 | local_table_index = NUMBER_OF_GLOBALS; /*locptr = STARTLOC;*/ 86 | } 87 | 88 | /** 89 | * declare argument types 90 | * called from "newfunc", this routine adds an entry in the local 91 | * symbol table for each named argument 92 | * completely rewritten version. p.l. woods 93 | * @param t argument type (char, int) 94 | * @return 95 | */ 96 | getarg(int t) { 97 | int j, legalname, address, argptr, otag; 98 | char n[NAMESIZE]; 99 | 100 | FOREVER 101 | { 102 | if (argstk == 0) 103 | return; 104 | /* if a struct is being passed, its tag must be read in before checking 105 | * if it is a pointer */ 106 | if (t == STRUCT) { 107 | if (symname(n) == 0) { 108 | /* make sure tag doesn't contain odd symbols, etc */ 109 | illname(); 110 | } 111 | if ((otag=find_tag(n)) == -1) { /* struct tag undefined */ 112 | error("struct tag undefined"); 113 | } 114 | } 115 | if (match("*")) 116 | j = POINTER; 117 | else 118 | j = VARIABLE; 119 | if (!(legalname = symname(n))) 120 | illname(); 121 | if (match("[")) { 122 | while (inbyte() != ']') 123 | if (endst()) 124 | break; 125 | j = POINTER; 126 | } 127 | if (legalname) { 128 | if ((argptr = find_locale(n)) > -1) { 129 | symbol_table[argptr].identity = j; 130 | symbol_table[argptr].type = t; 131 | address = argtop - symbol_table[argptr].offset; 132 | symbol_table[argptr].offset = address; 133 | /* set tagidx for struct arguments */ 134 | if (t == STRUCT){ 135 | if (j != POINTER){ 136 | /* because each argument takes exactly two bytes on the 137 | * stack, whole structs can't be passed to functions */ 138 | error("only struct pointers, not structs, can be passed to functions"); 139 | } 140 | symbol_table[argptr].tagidx = otag; 141 | } 142 | } else 143 | error("expecting argument name"); 144 | } 145 | argstk = argstk - INTSIZE; 146 | if (endst()) 147 | return; 148 | if (!match(",")) 149 | error("expected comma"); 150 | } 151 | } 152 | 153 | doAnsiArguments() { 154 | int type; 155 | type = get_type(); 156 | if (type == 0) { 157 | return 0; /* no type detected, revert back to K&R style */ 158 | } 159 | argtop = argstk; 160 | argstk = 0; 161 | FOREVER 162 | { 163 | if (type) { 164 | doLocalAnsiArgument(type); 165 | } else { 166 | error("wrong number args"); 167 | break; 168 | } 169 | if (match(",")) { 170 | type = get_type(); 171 | continue; 172 | } 173 | if (match(")")) { 174 | break; 175 | } 176 | } 177 | } 178 | 179 | doLocalAnsiArgument(int type) { 180 | char symbol_name[NAMESIZE]; 181 | int identity, address, argptr, ptr, otag; 182 | /* if a struct is being passed, its tag must be read in before checking if 183 | * it is a pointer */ 184 | if (type == STRUCT) { 185 | if (symname(symbol_name) == 0) { 186 | /* make sure tag doesn't contain odd symbols, etc */ 187 | illname(); 188 | } 189 | if ((otag=find_tag(symbol_name)) == -1) { /* struct tag undefined */ 190 | error("struct tag undefined"); 191 | } 192 | } 193 | if (match("*")) { 194 | identity = POINTER; 195 | } else { 196 | identity = VARIABLE; 197 | } 198 | if (symname(symbol_name)) { 199 | if (find_locale(symbol_name) > -1) { 200 | multidef(symbol_name); 201 | } else { 202 | argptr = add_local (symbol_name, identity, type, 0, AUTO); 203 | argstk = argstk + INTSIZE; 204 | ptr = local_table_index; 205 | /* if argument is a struct, properly set the argument's tagidx */ 206 | if (type == STRUCT) { 207 | if (identity != POINTER){ 208 | /* because each argument takes exactly two bytes on the stack, whole structs can't be passed to functions */ 209 | error("only struct pointers, not structs, can be passed to functions"); 210 | } 211 | symbol_table[argptr].tagidx = otag; 212 | } 213 | /* modify stack offset as we push more params */ 214 | while (ptr != NUMBER_OF_GLOBALS) { 215 | ptr = ptr - 1; 216 | address = symbol_table[ptr].offset; 217 | symbol_table[ptr].offset = address + INTSIZE; 218 | } 219 | } 220 | } else { 221 | error("illegal argument name"); 222 | junk(); 223 | } 224 | if (match("[")) { 225 | while (inbyte() != ']') { 226 | if (endst()) { 227 | break; 228 | } 229 | } 230 | identity = POINTER; 231 | symbol_table[argptr].identity = identity; 232 | } 233 | } 234 | 235 | -------------------------------------------------------------------------------- /smallC/gen.c: -------------------------------------------------------------------------------- 1 | /* File gen.c: 2.1 (83/03/20,16:02:06) */ 2 | /*% cc -O -c % 3 | * 4 | */ 5 | 6 | #include 7 | #include "defs.h" 8 | #include "data.h" 9 | 10 | /** 11 | * return next available internal label number 12 | */ 13 | getlabel() { 14 | return (nxtlab++); 15 | } 16 | 17 | /** 18 | * print specified number as label 19 | * @param label 20 | */ 21 | print_label(int label) { 22 | output_label_prefix (); 23 | output_decimal (label); 24 | } 25 | 26 | /** 27 | * glabel - generate label 28 | * not used ? 29 | * @param lab label number 30 | */ 31 | glabel(char *lab) { 32 | output_string (lab); 33 | output_label_terminator (); 34 | newline (); 35 | } 36 | 37 | /** 38 | * gnlabel - generate numeric label 39 | * @param nlab label number 40 | * @return 41 | */ 42 | generate_label(int nlab) { 43 | print_label (nlab); 44 | output_label_terminator (); 45 | newline (); 46 | } 47 | 48 | /** 49 | * outputs one byte 50 | * @param c 51 | * @return 52 | */ 53 | output_byte(char c) { 54 | if (c == 0) 55 | return (0); 56 | fputc (c, output); 57 | return (c); 58 | } 59 | 60 | /** 61 | * outputs a string 62 | * @param ptr the string 63 | * @return 64 | */ 65 | output_string(char ptr[]) { 66 | int k; 67 | k = 0; 68 | while (output_byte (ptr[k++])); 69 | } 70 | 71 | /** 72 | * outputs a tab 73 | * @return 74 | */ 75 | print_tab() { 76 | output_byte ('\t'); 77 | } 78 | 79 | /** 80 | * output line 81 | * @param ptr 82 | * @return 83 | */ 84 | output_line(char ptr[]) 85 | { 86 | output_with_tab (ptr); 87 | newline (); 88 | } 89 | 90 | /** 91 | * tabbed output 92 | * @param ptr 93 | * @return 94 | */ 95 | output_with_tab(char ptr[]) { 96 | print_tab (); 97 | output_string (ptr); 98 | } 99 | 100 | /** 101 | * output decimal number 102 | * @param number 103 | * @return 104 | */ 105 | output_decimal(int number) { 106 | fprintf(output, "%d", number); 107 | } 108 | 109 | /** 110 | * stores values into memory 111 | * @param lval 112 | * @return 113 | */ 114 | store(LVALUE *lval) { 115 | if (lval->indirect == 0) 116 | gen_put_memory (lval->symbol); 117 | else 118 | gen_put_indirect (lval->indirect); 119 | } 120 | 121 | rvalue(LVALUE *lval, int reg) { 122 | if ((lval->symbol != 0) & (lval->indirect == 0)) 123 | gen_get_memory (lval->symbol); 124 | else 125 | gen_get_indirect (lval->indirect, reg); 126 | return HL_REG; 127 | } 128 | 129 | /** 130 | * parses test part "(expression)" input and generates assembly for jump 131 | * @param label 132 | * @param ft : false - test jz, true test jnz 133 | * @return 134 | */ 135 | test(int label, int ft) { 136 | needbrack ("("); 137 | expression (YES); 138 | needbrack (")"); 139 | gen_test_jump (label, ft); 140 | } 141 | 142 | /** 143 | * scale constant depending on type 144 | * @param type 145 | * @param otag 146 | * @param size 147 | * @return 148 | */ 149 | scale_const(int type, int otag, int *size) { 150 | switch (type) { 151 | case CINT: 152 | case UINT: 153 | *size += *size; 154 | break; 155 | case STRUCT: 156 | *size *= tag_table[otag].size; 157 | break; 158 | default: 159 | break; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /smallC/includes/ctype.h: -------------------------------------------------------------------------------- 1 | /* Nothing needed in this file */ 2 | -------------------------------------------------------------------------------- /smallC/includes/stdio.h: -------------------------------------------------------------------------------- 1 | #define stdin 0 2 | #define stdout 1 3 | #define stderr 2 4 | #define NULL 0 5 | #define EOF (-1) 6 | #define FILE char 7 | -------------------------------------------------------------------------------- /smallC/initials.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "defs.h" 4 | #include "data.h" 5 | 6 | /** 7 | * erase the data storage 8 | */ 9 | create_initials() { 10 | /*int i; 11 | for (i=0; i= NUMBER_OF_GLOBALS) { 42 | error("initials table overrun"); 43 | } 44 | 45 | if(astreq(symbol_name, &initials_table[initials_idx].name, NAMEMAX)) 46 | { 47 | result = 1; 48 | break; 49 | } else { /* move to next symbol 50 | count position in data array */ 51 | initials_data_idx += initials_table[initials_idx].data_len; 52 | } 53 | } 54 | return result; 55 | } 56 | 57 | /** 58 | * add data to table for given symbol 59 | * @param symbol_name 60 | * @param type 61 | * @param value 62 | * @param tag 63 | */ 64 | add_data_initials(char *symbol_name, int type, int value, TAG_SYMBOL *tag) { 65 | int position; 66 | if (find_symbol_initials(symbol_name) == 0) { 67 | add_symbol_initials(symbol_name, tag == 0 ? type : STRUCT); 68 | } 69 | if (tag != 0) { 70 | /* find number of members, dim is total number of values added */ 71 | int index = initials_table[initials_idx].dim % tag->number_of_members; 72 | int member_type = member_table[tag->member_idx + index].type; 73 | /* add it recursively */ 74 | add_data_initials(symbol_name, member_type, value, 0); 75 | } else { 76 | position = initials_table[initials_idx].data_len; 77 | if (type & CCHAR) { 78 | initials_data_table[initials_data_idx + position] = 0xff & value; 79 | initials_table[initials_idx].data_len += 1; 80 | } else if (type & CINT) { 81 | 82 | initials_data_table[initials_data_idx + position] = 83 | (0xff00 & value) >> 8; 84 | 85 | initials_data_table[initials_data_idx + position + 1] = 86 | 0xff & value; 87 | initials_table[initials_idx].data_len += INTSIZE; 88 | } 89 | initials_table[initials_idx].dim += 1; 90 | } 91 | } 92 | 93 | /** 94 | * get number of data items for given symbol 95 | * @param symbol_name 96 | * @return 97 | */ 98 | int get_size(char *symbol_name) { 99 | int result = 0; 100 | if (find_symbol_initials(symbol_name) != 0) { 101 | result = initials_table[initials_idx].dim; 102 | } 103 | return result; 104 | } 105 | 106 | /** 107 | * get item at position 108 | * @param symbol_name 109 | * @param position 110 | * @param itag index of tag in tag table 111 | * @return 112 | */ 113 | int get_item_at(char *symbol_name, int position, TAG_SYMBOL *tag) { 114 | int result = 0, i, type; 115 | if (find_symbol_initials(symbol_name) != 0) { 116 | if (initials_table[initials_idx].type & CCHAR) { 117 | result = initials_data_table[initials_data_idx + position]; 118 | } else if (initials_table[initials_idx].type & CINT) { 119 | position *= INTSIZE; 120 | result = (initials_data_table[initials_data_idx + position] << 8) + 121 | (unsigned char)initials_data_table[ 122 | initials_data_idx + position+1]; 123 | } else if (initials_table[initials_idx].type == STRUCT) { 124 | /* find number of members */ 125 | int number_of_members = tag->number_of_members; 126 | /* point behind the last full struct */ 127 | int index = (position / number_of_members) * tag->size; 128 | /* move to required member */ 129 | for (i=0; i < (position % number_of_members); i++) { 130 | type = member_table[tag->member_idx + i].type; 131 | if (type & CCHAR) { 132 | index += 1; 133 | } else { 134 | index += INTSIZE; 135 | } 136 | } 137 | /* get value */ 138 | type = member_table[tag->member_idx + i].type; 139 | if (type & CCHAR) { 140 | result = initials_data_table[initials_data_idx + index]; 141 | } else { 142 | result = (initials_data_table[initials_data_idx + index] << 8) + 143 | (unsigned char)initials_data_table[ 144 | initials_data_idx + index+ 1]; 145 | } 146 | } 147 | } 148 | return result; 149 | } 150 | -------------------------------------------------------------------------------- /smallC/io.c: -------------------------------------------------------------------------------- 1 | /* File io.c: 2.1 (83/03/20,16:02:07) */ 2 | /*% cc -O -c % 3 | * 4 | */ 5 | 6 | #include 7 | #include 8 | #include "defs.h" 9 | #include "data.h" 10 | 11 | /* 12 | * open input file 13 | */ 14 | openin (p) char *p; 15 | { 16 | strcpy(fname, p); 17 | fixname (fname); 18 | if (!checkname (fname)) 19 | return (NO); 20 | if ((input = fopen (fname, "r")) == NULL) { 21 | pl ("Open failure\n"); 22 | return (NO); 23 | } 24 | kill (); 25 | return (YES); 26 | 27 | } 28 | 29 | /* 30 | * open output file 31 | */ 32 | openout () 33 | { 34 | outfname (fname); 35 | if ((output = fopen (fname, "w")) == NULL) { 36 | pl ("Open failure"); 37 | return (NO); 38 | } 39 | kill (); 40 | return (YES); 41 | 42 | } 43 | 44 | /* 45 | * change input filename to output filename 46 | */ 47 | outfname (s) 48 | char *s; 49 | { 50 | while (*s) 51 | s++; 52 | *--s = 's'; 53 | 54 | } 55 | 56 | /** 57 | * remove NL from filenames 58 | */ 59 | fixname (s) 60 | char *s; 61 | { 62 | while (*s && *s++ != LF); 63 | if (!*s) return; 64 | *(--s) = 0; 65 | 66 | } 67 | 68 | /** 69 | * check that filename is "*.c" 70 | */ 71 | checkname (s) 72 | char *s; 73 | { 74 | while (*s) 75 | s++; 76 | if (*--s != 'c') 77 | return (NO); 78 | if (*--s != '.') 79 | return (NO); 80 | return (YES); 81 | 82 | } 83 | 84 | kill () { 85 | lptr = 0; 86 | line[lptr] = 0; 87 | } 88 | 89 | readline () { 90 | int k; 91 | FILE *unit; 92 | 93 | FOREVER { 94 | if (feof (input)) 95 | return; 96 | if ((unit = input2) == NULL) 97 | unit = input; 98 | kill (); 99 | while ((k = fgetc (unit)) != EOF) { 100 | if ((k == CR) || (k == LF) || (lptr >= LINEMAX)) 101 | break; 102 | line[lptr++] = k; 103 | } 104 | line[lptr] = 0; 105 | srcln[inclsp]++; /* increment source line number of actual file */ 106 | if (k <= 0) 107 | if (input2 != NULL) { 108 | input2 = inclstk[--inclsp]; 109 | fclose (unit); 110 | } 111 | if (lptr) { 112 | if ((ctext) & (cmode)) { 113 | gen_comment (); 114 | output_string (line); 115 | newline (); 116 | } 117 | lptr = 0; 118 | return; 119 | } 120 | } 121 | } 122 | 123 | inbyte () { 124 | while (ch () == 0) { 125 | if (feof (input)) 126 | return (0); 127 | preprocess (); 128 | } 129 | return (gch ()); 130 | } 131 | 132 | inchar () { 133 | if (ch () == 0) 134 | readline (); 135 | if (feof (input)) 136 | return (0); 137 | return (gch ()); 138 | } 139 | 140 | /** 141 | * gets current char from input line and moves to the next one 142 | * @return current char 143 | */ 144 | gch () { 145 | if (ch () == 0) 146 | return (0); 147 | else 148 | return (line[lptr++] & 127); 149 | } 150 | 151 | /** 152 | * returns next char 153 | * @return next char 154 | */ 155 | nch () { 156 | if (ch () == 0) 157 | return (0); 158 | else 159 | return (line[lptr + 1] & 127); 160 | } 161 | 162 | /** 163 | * returns current char 164 | * @return current char 165 | */ 166 | ch () { 167 | return (line[lptr] & 127); 168 | } 169 | 170 | /* 171 | * print a carriage return and a string only to console 172 | * 173 | */ 174 | pl (str) 175 | char *str; 176 | { 177 | int k; 178 | 179 | k = 0; 180 | #if __CYGWIN__ == 1 181 | putchar (CR); 182 | #endif 183 | putchar (LF); 184 | while (str[k]) 185 | putchar (str[k++]); 186 | } 187 | 188 | -------------------------------------------------------------------------------- /smallC/lex.c: -------------------------------------------------------------------------------- 1 | /* File lex.c: 2.1 (83/03/20,16:02:09) */ 2 | /*% cc -O -c % 3 | * 4 | */ 5 | 6 | #include 7 | #include "defs.h" 8 | #include "data.h" 9 | 10 | /** 11 | * test if given character is alpha 12 | * @param c 13 | * @return 14 | */ 15 | alpha(char c) { 16 | c = c & 127; 17 | return (((c >= 'a') && (c <= 'z')) || 18 | ((c >= 'A') && (c <= 'Z')) || 19 | (c == '_')); 20 | } 21 | 22 | /** 23 | * test if given character is numeric 24 | * @param c 25 | * @return 26 | */ 27 | numeric(char c) { 28 | c = c & 127; 29 | return ((c >= '0') && (c <= '9')); 30 | } 31 | 32 | /** 33 | * test if given character is alphanumeric 34 | * @param c 35 | * @return 36 | */ 37 | alphanumeric(char c) { 38 | return ((alpha (c)) || (numeric (c))); 39 | } 40 | 41 | /** 42 | * semicolon enforcer 43 | * called whenever syntax requires a semicolon 44 | */ 45 | need_semicolon() { 46 | if (!match (";")) 47 | error ("missing semicolon"); 48 | } 49 | 50 | junk() { 51 | if (alphanumeric (inbyte ())) 52 | while (alphanumeric (ch ())) 53 | gch (); 54 | else 55 | while (alphanumeric (ch ())) { 56 | if (ch () == 0) 57 | break; 58 | gch (); 59 | } 60 | blanks (); 61 | } 62 | 63 | endst() { 64 | blanks (); 65 | return ((streq (line + lptr, ";") | (ch () == 0))); 66 | } 67 | 68 | /** 69 | * enforces bracket 70 | * @param str 71 | * @return 72 | */ 73 | needbrack(char *str) { 74 | if (!match (str)) { 75 | error ("missing bracket"); 76 | gen_comment (); 77 | output_string (str); 78 | newline (); 79 | } 80 | } 81 | 82 | /** 83 | * 84 | * @param str1 85 | * @return 86 | */ 87 | sstreq(str1) char *str1; { 88 | return (streq(line + lptr, str1)); 89 | } 90 | 91 | /** 92 | * indicates whether or not the current substring in the source line matches a 93 | * literal string 94 | * accepts the address of the current character in the source 95 | * line and the address of the a literal string, and returns the substring 96 | * length if a match occurs and zero otherwise 97 | * @param str1 address1 98 | * @param str2 address2 99 | * @return 100 | */ 101 | streq(char str1[], char str2[]) { 102 | int k; 103 | k = 0; 104 | while (str2[k]) { 105 | if ((str1[k] != str2[k])) 106 | return (0); 107 | k++; 108 | } 109 | return (k); 110 | } 111 | 112 | /** 113 | * compares two string both must be zero ended, otherwise no match found 114 | * ensures that the entire token is examined 115 | * @param str1 116 | * @param str2 117 | * @param len 118 | * @return 119 | */ 120 | astreq (char str1[], char str2[], int len) { 121 | int k; 122 | k = 0; 123 | while (k < len) { 124 | if ((str1[k] != str2[k])) 125 | break; 126 | if (str1[k] == 0) 127 | break; 128 | if (str2[k] == 0) 129 | break; 130 | k++; 131 | } 132 | if (alphanumeric (str1[k])) 133 | return (0); 134 | if (alphanumeric (str2[k])) 135 | return (0); 136 | return (k); 137 | } 138 | 139 | /** 140 | * looks for a match between a literal string and the current token in 141 | * the input line. It skips over the token and returns true if a match occurs 142 | * otherwise it retains the current position in the input line and returns false 143 | * there is no verification that all of the token was matched 144 | * @param lit 145 | * @return 146 | */ 147 | match (char *lit) { 148 | int k; 149 | blanks(); 150 | if (k = streq (line + lptr, lit)) { 151 | lptr = lptr + k; 152 | return (1); 153 | } 154 | return (0); 155 | } 156 | 157 | /** 158 | * compares two string both must be zero ended, otherwise no match found 159 | * advances line pointer only if match found 160 | * it assumes that an alphanumeric (including underscore) comparison 161 | * is being made and guarantees that all of the token in the source line is 162 | * scanned in the process 163 | * @param lit 164 | * @param len 165 | * @return 166 | */ 167 | amatch(char *lit, int len) { 168 | int k; 169 | 170 | blanks(); 171 | if (k = astreq (line + lptr, lit, len)) { 172 | lptr = lptr + k; 173 | while (alphanumeric (ch ())) 174 | inbyte (); 175 | return (1); 176 | } 177 | return (0); 178 | } 179 | 180 | blanks() { 181 | FOREVER { 182 | while (ch () == 0) { 183 | preprocess (); 184 | if (feof (input)) 185 | break; 186 | } 187 | if (ch () == ' ') 188 | gch (); 189 | else if (ch () == 9) 190 | gch (); 191 | else 192 | return; 193 | } 194 | } 195 | 196 | /** 197 | * returns declaration type 198 | * @return CCHAR, CINT, UCHAR, UINT 199 | */ 200 | int get_type() { 201 | if (amatch ("register", 8)) { 202 | if (amatch("char", 4)) 203 | return CCHAR; 204 | else if (amatch ("int", 3)) 205 | return CINT; 206 | else 207 | return CINT; 208 | } else if(amatch("unsigned", 8)) { 209 | if (amatch("char", 4)) { 210 | return UCHAR; 211 | } else if (amatch("int", 3)) { 212 | return UINT; 213 | } 214 | } else if(amatch("signed", 8)) { 215 | if (amatch("char", 4)) { 216 | return CCHAR; 217 | } else if (amatch("int", 3)) { 218 | return CINT; 219 | } 220 | } else if (amatch ("char", 4)) { 221 | return CCHAR; 222 | } else if (amatch ("int", 3)) { 223 | return CINT; 224 | /* recognize structs being passed as a proper type */ 225 | } else if (amatch ("struct", 6)) { 226 | return STRUCT; 227 | } 228 | return 0; 229 | } 230 | 231 | -------------------------------------------------------------------------------- /smallC/lib/Makefile: -------------------------------------------------------------------------------- 1 | .SUFFIXES: .o .obj .c .asm 2 | 3 | .c.o: 4 | ../src/sccvax $*.c 5 | as -o $*.o $*.s 6 | rm $*.s 7 | ASSEMS =\ 8 | abs.asm atoi.asm binary.asm\ 9 | charclass.asm fgets.asm fputs.asm\ 10 | getchar.asm gets.asm index.asm\ 11 | itoa.asm printn.asm putchar.asm\ 12 | puts.asm reverse.asm shell.asm\ 13 | strcat.asm strcmp.asm strcpy.asm\ 14 | strlen.asm rand.asm \ 15 | strncat.asm strncmp.asm strncpy.asm 16 | 17 | OBJ =\ 18 | abs.o atoi.o binary.o\ 19 | charclass.o fgets.o fputs.o\ 20 | getchar.o gets.o index.o\ 21 | itoa.o printn.o putchar.o\ 22 | puts.o reverse.o shell.o\ 23 | strcat.o strcmp.o strcpy.o\ 24 | strlen.o rand.o \ 25 | strncat.o strncmp.o strncpy.o 26 | .c.asm: 27 | ../src/scc8080 $*.c 28 | mv $*.s $*.asm 29 | 30 | all: $(ASSEMS) 31 | 32 | vaxlibc.a: $(OBJ) 33 | ar ur vaxlibc.a $(OBJ) 34 | ranlib vaxlibc.a 35 | -------------------------------------------------------------------------------- /smallC/lib/abs.c: -------------------------------------------------------------------------------- 1 | /* abs (num) return absolute value */ 2 | abs(num) int num;{ 3 | if (num < 0) return (-num); 4 | else return (num); 5 | } 6 | -------------------------------------------------------------------------------- /smallC/lib/atoi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define EOL 10 3 | atoi(s) char s[];{ 4 | int i,n,sign; 5 | for (i=0; 6 | (s[i] == ' ') | (s[i] == EOL) | (s[i] == '\t'); 7 | ++i) ; 8 | sign = 1; 9 | switch(s[i]){ 10 | case '-': sign = -1; /* and fall through */ 11 | case '+': ++i; 12 | break; 13 | } 14 | for(n = 0; 15 | isdigit(s[i]); 16 | ++i) 17 | n = 10 * n + s[i] - '0'; 18 | return (sign * n); 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /smallC/lib/binary.c: -------------------------------------------------------------------------------- 1 | /* binary search for string word in table[0] .. table[n-1] 2 | * reference CPL pg. 125 3 | */ 4 | #include 5 | binary(word, table, n) 6 | char *word; 7 | int table[]; 8 | int n;{ 9 | int low, high, mid, cond; 10 | low = 0; 11 | high = n - 1; 12 | while (low <= high){ 13 | mid = (low + high) / 2; 14 | if ((cond = strcmp(word, table[mid])) < 0) 15 | high = mid - 1; 16 | else if (cond > 0) 17 | low = mid + 1; 18 | else 19 | return (mid); 20 | } 21 | return (-1); 22 | } 23 | -------------------------------------------------------------------------------- /smallC/lib/charclass.c: -------------------------------------------------------------------------------- 1 | isalpha(c) char c;{ 2 | if ((c >= 'a' & c <= 'z') | 3 | (c >= 'A' & c <= 'Z')) return(1); 4 | else return(0); 5 | } 6 | 7 | isupper(c) char c;{ 8 | if (c >= 'A' & c <= 'Z') return(1); 9 | else return(0); 10 | } 11 | 12 | islower(c) char c;{ 13 | if (c >= 'a' & c <= 'z') return(1); 14 | else return(0); 15 | } 16 | 17 | isdigit(c) char c;{ 18 | if (c >= '0' & c <= '9') return(1); 19 | else return(0); 20 | } 21 | 22 | isspace(c) char c;{ 23 | if (c == ' ' | c == '\t' | c == '\n') return(1); 24 | else return(0); 25 | } 26 | 27 | toupper(c) char c;{ 28 | return ((c >= 'a' && c <= 'z') ? c - 32: c); 29 | } 30 | 31 | tolower(c) char c;{ 32 | return((c >= 'A' && c <= 'Z') ? c + 32: c); 33 | } 34 | -------------------------------------------------------------------------------- /smallC/lib/fgets.c: -------------------------------------------------------------------------------- 1 | /* 2 | #include 3 | */ 4 | #define NULL 0 5 | #define FILE char 6 | 7 | fgets(s, n, iop) 8 | int n; 9 | char *s; 10 | register FILE *iop; 11 | { 12 | register c; 13 | register char *cs; 14 | 15 | cs = s; 16 | while (--n>0 && (c = fgetc(iop))>=0) { 17 | *cs++ = c; 18 | if (c=='\n') 19 | break; 20 | } 21 | if (c<0 && cs==s) 22 | return(NULL); 23 | *cs++ = '\0'; 24 | return(s); 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /smallC/lib/fputs.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | fputs(str, fp) FILE *fp; char *str; { 4 | while(*str) fputc(*str++, fp); 5 | 6 | } 7 | 8 | -------------------------------------------------------------------------------- /smallC/lib/getchar.c: -------------------------------------------------------------------------------- 1 | #include 2 | getchar() { 3 | return(fgetc(stdin)); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /smallC/lib/gets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define EOL 10 3 | #define BKSP 8 4 | #define CTRLU 0x15 5 | gets(s) char *s; { 6 | char c, *ts; 7 | ts = s; 8 | while ((c = getchar()) != EOL && (c != EOF)) { 9 | if (c == BKSP) { 10 | if (ts > s) { 11 | --ts; 12 | /* CPM already echoed */ 13 | putchar(' '); 14 | putchar(BKSP); 15 | } 16 | } 17 | else if (c == CTRLU) { 18 | ts = s; 19 | putchar(EOL); 20 | putchar('#'); 21 | } 22 | else (*ts++) = c; 23 | } 24 | if ((c == EOF) && (ts == s)) return NULL; 25 | (*ts) = NULL; 26 | return s; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /smallC/lib/index.c: -------------------------------------------------------------------------------- 1 | /* index - find index of string t in s 2 | * reference CPL 67. 3 | */ 4 | #include 5 | #define EOS 0 6 | index(s, t) 7 | char s[], t[];{ 8 | int i, j, k; 9 | for (i = 0; s[i] != EOS; i++){ 10 | k=0; 11 | for (j=i;t[k]!=EOS & s[j]==t[k]; i++) 12 | j++; 13 | ; 14 | if (t[k] == EOS) 15 | return(i); 16 | } 17 | return(-1); 18 | } 19 | -------------------------------------------------------------------------------- /smallC/lib/itoa.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define EOS 0 3 | itoa(n,s) char s[];int n;{ 4 | int i,sign; 5 | if((sign = n) < 0) n = -n; 6 | i = 0; 7 | do { 8 | s[i++] = n % 10 + '0'; 9 | }while ((n = n/10) > 0); 10 | if (sign < 0) s[i++] = '-'; 11 | s[i] = EOS; 12 | reverse(s); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /smallC/lib/lorder8080: -------------------------------------------------------------------------------- 1 | grep public $* | sed 's/: public// 2 | /?/d 3 | s?\([^ ]*\)[ ]*\(.*\)?\2 \1? 4 | s/\.asm//'> /tmp/symdef$$ 5 | grep extrn $* | sed 's/: extrn// 6 | s/\.asm// 7 | s?\([^ ]*\)[ ]*\(.*\)?\2 \1? 8 | /?/d' > /tmp/symref$$ 9 | sort /tmp/symdef$$ -o /tmp/symdef$$ 10 | sort /tmp/symref$$ -o /tmp/symref$$ 11 | join /tmp/symref$$ /tmp/symdef$$ | sed 's/[^ ]* *//' 12 | rm /tmp/symdef$$ /tmp/symref$$ 13 | -------------------------------------------------------------------------------- /smallC/lib/printn.c: -------------------------------------------------------------------------------- 1 | #include 2 | /* print a number in any radish */ 3 | #define DIGARR "0123456789ABCDEF" 4 | printn(number, radix, file) 5 | int number, radix; FILE *file;{ 6 | int i; 7 | char *digitreps; 8 | if (number < 0 & radix == 10){ 9 | fputc('-', file); 10 | number = -number; 11 | } 12 | if ((i = number / radix) != 0) 13 | printn(i, radix, file); 14 | digitreps=DIGARR; 15 | fputc(digitreps[number % radix], file); 16 | } 17 | -------------------------------------------------------------------------------- /smallC/lib/putchar.c: -------------------------------------------------------------------------------- 1 | #include 2 | putchar(c) char c; { 3 | return fputc(c, stdout); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /smallC/lib/puts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define EOL 10 3 | puts(str) char *str;{ 4 | while (*str) putchar(*str++); 5 | putchar(EOL); 6 | } 7 | -------------------------------------------------------------------------------- /smallC/lib/rand.c: -------------------------------------------------------------------------------- 1 | 2 | int xxseed; 3 | 4 | srand (x) int x; { 5 | xxseed = x; 6 | 7 | } 8 | 9 | rand () { 10 | xxseed = xxseed * 251 + 123; 11 | if (xxseed < 0) xxseed = - xxseed; 12 | return (xxseed); 13 | 14 | } 15 | 16 | getrand () { 17 | puts ("Type a character"); 18 | return (getchar() * 123); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /smallC/lib/reverse.c: -------------------------------------------------------------------------------- 1 | #include 2 | /* Reverse a character string, reference CPL p 59 */ 3 | reverse(s) 4 | char *s;{ 5 | int i, j; 6 | char c; 7 | i = 0; 8 | j = strlen(s) - 1; 9 | while (i < j){ 10 | c = s[i]; 11 | s[i] = s[j]; 12 | s[j] = c; 13 | i++; 14 | j--; 15 | } 16 | return(s); 17 | } 18 | -------------------------------------------------------------------------------- /smallC/lib/sbrk.c: -------------------------------------------------------------------------------- 1 | extern char *brkend; 2 | sbrk (incr) char *incr; { 3 | char *stktop; 4 | 5 | stktop = Xstktop() - 200; 6 | 7 | /* do we have enough space? */ 8 | if (brkend + incr < stktop) { 9 | stktop = brkend; 10 | brkend = brkend + incr; 11 | return (stktop); 12 | } 13 | else 14 | return (-1); 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /smallC/lib/shell.c: -------------------------------------------------------------------------------- 1 | /* Shell sort of string v[0] .... v[n-1] into increasing 2 | * order. 3 | * Reference CPL pg. 108. 4 | */ 5 | 6 | shellsort(v, n) 7 | int v[]; 8 | int n; 9 | { 10 | int gap, i, j; 11 | char *temp; 12 | for (gap = n/2; gap > 0; gap = gap / 2) 13 | for (i = gap; i < n; i++) 14 | for (j = i - gap; j >= 0; j = j - gap){ 15 | if (strcmp(v[j], v[j+gap]) <= 0) 16 | break; 17 | temp = v[j]; 18 | v[j] = v[j + gap]; 19 | v[j + gap] = temp; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smallC/lib/strcat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Concatenate s2 on the end of s1. S1's space must be large enough. 3 | * Return s1. 4 | */ 5 | 6 | strcat(s1, s2) 7 | char *s1, *s2; 8 | { 9 | char *os1; 10 | 11 | os1 = s1; 12 | while (*s1++) 13 | ; 14 | *--s1; 15 | while (*s1++ = *s2++) 16 | ; 17 | return(os1); 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /smallC/lib/strcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compare strings: s1>s2: >0 s1==s2: 0 s1 2 | /* 3 | * Copy string s2 to s1. s1 must be large enough. 4 | * return s1 5 | */ 6 | 7 | strcpy(s1, s2) 8 | char *s1, *s2; 9 | { 10 | char *os1; 11 | 12 | os1 = s1; 13 | while (*s1++ = *s2++) 14 | ; 15 | return(os1); 16 | 17 | } 18 | 19 | -------------------------------------------------------------------------------- /smallC/lib/strlen.c: -------------------------------------------------------------------------------- 1 | #include 2 | /* return length of string, reference CPL p 36 */ 3 | strlen(s) char *s;{ 4 | int i; 5 | i = 0; 6 | while (*s++) i++; 7 | return (i); 8 | } 9 | -------------------------------------------------------------------------------- /smallC/lib/strncat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Concatenate s2 on the end of s1. S1's space must be large enough. 3 | * At most n characters are moved. 4 | * Return s1. 5 | */ 6 | 7 | strncat(s1, s2, n) 8 | register char *s1, *s2; 9 | register n; 10 | { 11 | register char *os1; 12 | 13 | os1 = s1; 14 | while (*s1++) 15 | ; 16 | --s1; 17 | while (*s1++ = *s2++) 18 | if (--n < 0) { 19 | *--s1 = '\0'; 20 | break; 21 | } 22 | return(os1); 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /smallC/lib/strncmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compare strings (at most n bytes): s1>s2: >0 s1==s2: 0 s1= 0 && *s1 == *s2++) 11 | if (*s1++ == '\0') 12 | return(0); 13 | return(n<0 ? 0 : *s1 - *--s2); 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /smallC/lib/strncpy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copy s2 to s1, truncating or null-padding to always copy n bytes 3 | * return s1 4 | */ 5 | 6 | strncpy(s1, s2, n) 7 | char *s1, *s2; 8 | int n; 9 | { 10 | register i; 11 | register char *os1; 12 | 13 | os1 = s1; 14 | for (i = 0; i < n; i++) 15 | if ((*s1++ = *s2++) == '\0') { 16 | while (++i < n) 17 | *s1++ = '\0'; 18 | return(os1); 19 | } 20 | return(os1); 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /smallC/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File main.c: 2.7 (Rev.1) (17/5/21,1:38:54) 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "defs.h" 9 | #include "data.h" 10 | 11 | FILE *logFile = NULL; 12 | 13 | char finame [INCLSIZ+1][20]; /* global input filenames for error messages */ 14 | 15 | int srcln[INCLSIZ+1]={0,0,0,0}; /* source file line counters for error messages */ 16 | 17 | /* Simple oputs function to replace the ugly fputs(foo, stdout) */ 18 | 19 | void oputs(char *str) 20 | { 21 | if(logFile) fputs(str, logFile); 22 | fputs(str, stderr); 23 | } 24 | 25 | main(int argc, char *argv[]) { 26 | char *param = NULL, *bp; 27 | int smacptr, i; 28 | macptr = 0; 29 | ctext = 0; 30 | errs = 0; 31 | aflag = 1; 32 | uflag = 0; 33 | 34 | setbuf(stdout, NULL); /* disable stdout buffering */ /* why exactly? */ 35 | 36 | for (i=1; i= litptr)) { 304 | newline(); 305 | break; 306 | } 307 | output_byte(','); 308 | } 309 | } 310 | } 311 | 312 | /** 313 | * dump all static variables 314 | */ 315 | dumpglbs() { 316 | int dim, i, list_size, line_count, value; 317 | 318 | if (!glbflag) 319 | return; 320 | current_symbol_table_idx = rglobal_table_index; 321 | while (current_symbol_table_idx < global_table_index) { 322 | SYMBOL *symbol = &symbol_table[current_symbol_table_idx]; 323 | if (symbol->identity != FUNCTION) { 324 | ppubext(symbol); 325 | if (symbol->storage != EXTERN) { 326 | output_string(symbol->name); 327 | output_label_terminator(); 328 | dim = symbol->offset; 329 | list_size = 0; 330 | line_count = 0; 331 | if (find_symbol_initials(symbol->name)) { /* has initials */ 332 | list_size = get_size(symbol->name); 333 | if (dim == -1) { 334 | dim = list_size; 335 | } 336 | } 337 | for (i=0; itype == STRUCT) { 339 | dump_struct(symbol, i); 340 | } else { 341 | if (line_count % 10 == 0) { 342 | newline(); 343 | if((symbol->type & CINT) || 344 | (symbol->identity == POINTER)) 345 | { 346 | gen_def_word(); 347 | } else { 348 | gen_def_byte(); 349 | } 350 | } 351 | if (i < list_size) { 352 | /* dump data */ 353 | value = get_item_at(symbol->name, i, 354 | &tag_table[symbol->tagidx]); 355 | output_number(value); 356 | } else { 357 | /* dump zero, no more data available */ 358 | output_number(0); 359 | } 360 | line_count++; 361 | if (line_count % 10 == 0) { 362 | line_count = 0; 363 | } else { 364 | if (i < dim-1) { 365 | output_byte( ',' ); 366 | } 367 | } 368 | } 369 | } 370 | newline(); 371 | } 372 | } else { 373 | fpubext(symbol); 374 | } 375 | current_symbol_table_idx++; 376 | } 377 | } 378 | 379 | /** 380 | * dump struct data 381 | * @param symbol struct variable 382 | * @param position position of the struct in the array, or zero 383 | */ 384 | dump_struct(SYMBOL *symbol, int position) { 385 | int i, number_of_members, value; 386 | number_of_members = tag_table[symbol->tagidx].number_of_members; 387 | newline(); 388 | for (i=0; itagidx].member_idx + i]; 392 | /* array members need proper storage space (the compiler currently 393 | * doesn't allow arrays in structs to be initilized */ 394 | if(member.identity == ARRAY){ 395 | gen_def_storage(); 396 | output_number(member.struct_size); 397 | newline(); 398 | } 399 | else{ 400 | /* both pointers and ints take two bytes */ 401 | if (member.type & CINT || member.identity == POINTER) { 402 | gen_def_word(); 403 | } else { 404 | gen_def_byte(); 405 | } 406 | if (position < get_size(symbol->name)) { 407 | /* dump data */ 408 | value = get_item_at(symbol->name, position*number_of_members+i, 409 | &tag_table[symbol->tagidx]); 410 | output_number(value); 411 | } else { 412 | /* dump zero, no more data available */ 413 | output_number(0); 414 | } 415 | newline(); 416 | } 417 | } 418 | } 419 | 420 | /** 421 | * report errors 422 | */ 423 | errorsummary() { 424 | if (ncmp) 425 | error("missing closing bracket"); 426 | newline(); 427 | gen_comment(); 428 | output_decimal(errcnt); 429 | if (errcnt) errfile = YES; 430 | output_string(" error(s) in compilation"); 431 | newline(); 432 | gen_comment(); 433 | output_with_tab("literal pool:"); 434 | output_decimal(litptr); 435 | newline(); 436 | gen_comment(); 437 | output_with_tab("global pool:"); 438 | output_decimal(global_table_index - rglobal_table_index); 439 | newline(); 440 | gen_comment(); 441 | output_with_tab("Macro pool:"); 442 | output_decimal(macptr); 443 | newline(); 444 | if (errcnt > 0) 445 | pl("Error(s)"); 446 | } 447 | 448 | /** 449 | * test for C or similar filename, e.g. xxxxx.x, tests the dot at end-1 postion 450 | * @param s the filename 451 | * @return the last char if it contains dot, space otherwise 452 | */ 453 | filename_typeof(char *s) { 454 | s += strlen(s) - 2; 455 | if (*s == '.') 456 | return (*(s + 1)); 457 | return (' '); 458 | } 459 | -------------------------------------------------------------------------------- /smallC/preproc.c: -------------------------------------------------------------------------------- 1 | /* File preproc.c: 2.3 (84/11/27,11:47:40) */ 2 | /*% cc -O -c % 3 | * 4 | */ 5 | 6 | #include 7 | #include 8 | #include "defs.h" 9 | #include "data.h" 10 | 11 | /** 12 | * remove "brackets" surrounding include file name 13 | * @see DEFLIB 14 | */ 15 | FILE* fix_include_name () { 16 | char c1, c2, *p, *ibp; 17 | char buf[20]; 18 | FILE *fp; 19 | char buf2[100]; 20 | 21 | ibp = &buf[0]; 22 | 23 | if ((c1 = gch ()) != '"' && c1 != '<') 24 | return (NULL); 25 | for (p = line + lptr; *p ;) 26 | *ibp++ = *p++; 27 | c2 = *(--p); 28 | if (c1 == '"' ? (c2 != '"') : (c2 != '>')) { 29 | error ("incorrect delimiter"); 30 | return (NULL); 31 | } 32 | *(--ibp) = 0; 33 | fp = NULL; 34 | if (c1 == '<' || !(fp = fopen(buf, "r"))) { 35 | strcpy(buf2, DEFLIB); 36 | strcat(buf2, buf); 37 | fp = fopen(buf2, "r"); 38 | strcpy(finame[inclsp+1],buf2); /* copy include filename to filename array*/ 39 | srcln[inclsp+1]=0; /* reset source line counter*/ 40 | } 41 | return (fp); 42 | } 43 | 44 | /** 45 | * open an include file 46 | */ 47 | doinclude () 48 | { 49 | char *p; 50 | FILE *inp2; 51 | 52 | blanks (); 53 | if (inp2 = fix_include_name ()) 54 | if (inclsp < INCLSIZ) { 55 | inclstk[inclsp++] = input2; 56 | input2 = inp2; 57 | } else { 58 | fclose (inp2); 59 | error ("too many nested includes"); 60 | } 61 | else { 62 | error ("Could not open include file"); 63 | } 64 | kill (); 65 | 66 | } 67 | 68 | /** 69 | * "asm" pseudo-statement 70 | * enters mode where assembly language statements are passed 71 | * intact through parser 72 | */ 73 | doasm () 74 | { 75 | cmode = 0; 76 | FOREVER { 77 | readline (); 78 | if (match ("#endasm")) 79 | break; 80 | if (feof (input)) 81 | break; 82 | output_string (line); 83 | newline (); 84 | } 85 | kill (); 86 | cmode = 1; 87 | 88 | } 89 | 90 | dodefine () 91 | { 92 | addmac(); 93 | } 94 | 95 | doundef () 96 | { 97 | int mp; 98 | char sname[NAMESIZE]; 99 | 100 | if (!symname(sname)) { 101 | illname(); 102 | kill(); 103 | return; 104 | } 105 | 106 | if (mp = findmac(sname)) 107 | delmac(mp); 108 | kill(); 109 | 110 | } 111 | 112 | preprocess () 113 | { 114 | if (ifline()) return; 115 | while (cpp()); 116 | } 117 | 118 | doifdef (ifdef) 119 | int ifdef; 120 | { 121 | char sname[NAMESIZE]; 122 | int k; 123 | 124 | blanks(); 125 | ++iflevel; 126 | if (skiplevel) return; 127 | k = symname(sname) && findmac(sname); 128 | if (k != ifdef) skiplevel = iflevel; 129 | 130 | } 131 | 132 | ifline() 133 | { 134 | FOREVER { 135 | readline(); 136 | if (feof(input)) return(1); 137 | if (match("#ifdef")) { 138 | doifdef(YES); 139 | continue; 140 | } else if (match("#ifndef")) { 141 | doifdef(NO); 142 | continue; 143 | } else if (match("#else")) { 144 | if (iflevel) { 145 | if (skiplevel == iflevel) skiplevel = 0; 146 | else if (skiplevel == 0) skiplevel = iflevel; 147 | } else noiferr(); 148 | continue; 149 | } else if (match("#endif")) { 150 | if (iflevel) { 151 | if (skiplevel == iflevel) skiplevel = 0; 152 | --iflevel; 153 | } else noiferr(); 154 | continue; 155 | } 156 | if (!skiplevel) return(0); 157 | } 158 | 159 | } 160 | 161 | noiferr() 162 | { 163 | error("no matching #if..."); 164 | 165 | } 166 | 167 | /** 168 | * preprocess - copies mline to line with special treatment of preprocess cmds 169 | * @return 170 | */ 171 | cpp () 172 | { 173 | int k; 174 | char c, sname[NAMESIZE]; 175 | int tog; 176 | int cpped; /* non-zero if something expanded */ 177 | 178 | cpped = 0; 179 | /* don't expand lines with preprocessor commands in them */ 180 | if (!cmode || line[0] == '#') return(0); 181 | 182 | mptr = lptr = 0; 183 | while (ch ()) { 184 | if ((ch () == ' ') | (ch () == 9)) { 185 | keepch (' '); 186 | while ((ch () == ' ') | (ch () == 9)) 187 | gch (); 188 | } else if (ch () == '"') { 189 | keepch (ch ()); 190 | gch (); 191 | while (ch () != '"') { 192 | if (ch () == 0) { 193 | error ("missing quote"); 194 | break; 195 | } 196 | if (ch() == '\\') keepch(gch()); 197 | keepch (gch ()); 198 | } 199 | gch (); 200 | keepch ('"'); 201 | } else if (ch () == '\'') { 202 | keepch ('\''); 203 | gch (); 204 | while (ch () != '\'') { 205 | if (ch () == 0) { 206 | error ("missing apostrophe"); 207 | break; 208 | } 209 | if (ch() == '\\') keepch(gch()); 210 | keepch (gch ()); 211 | } 212 | gch (); 213 | keepch ('\''); 214 | } else if ((ch () == '/') & (nch () == '*')) { 215 | inchar (); 216 | inchar (); 217 | while ((((c = ch ()) == '*') & (nch () == '/')) == 0) 218 | if (c == '$') { 219 | inchar (); 220 | tog = TRUE; 221 | if (ch () == '-') { 222 | tog = FALSE; 223 | inchar (); 224 | } 225 | if (alpha (c = ch ())) { 226 | inchar (); 227 | toggle (c, tog); 228 | } 229 | } else { 230 | if (ch () == 0) 231 | readline (); 232 | else 233 | inchar (); 234 | if (feof (input)) 235 | break; 236 | } 237 | inchar (); 238 | inchar (); 239 | /* one line comment */ 240 | } else if ((ch () == '/') & (nch () == '/')) { 241 | while(gch()); 242 | } else if (alphanumeric(ch ())) { 243 | k = 0; 244 | while (alphanumeric(ch ())) { 245 | if (k < NAMEMAX) 246 | sname[k++] = ch (); 247 | gch (); 248 | } 249 | sname[k] = 0; 250 | if (k = findmac (sname)) { 251 | cpped = 1; 252 | while (c = macq[k++]) 253 | keepch (c); 254 | } else { 255 | k = 0; 256 | while (c = sname[k++]) 257 | keepch (c); 258 | } 259 | } else 260 | keepch (gch ()); 261 | } 262 | keepch (0); 263 | if (mptr >= MPMAX) 264 | error ("line too long"); 265 | lptr = mptr = 0; 266 | while (line[lptr++] = mline[mptr++]); 267 | lptr = 0; 268 | return(cpped); 269 | 270 | } 271 | 272 | keepch (c) 273 | char c; 274 | { 275 | mline[mptr] = c; 276 | if (mptr < MPMAX) 277 | mptr++; 278 | return (c); 279 | 280 | } 281 | 282 | defmac(s) 283 | char *s; 284 | { 285 | kill(); 286 | strcpy(line, s); 287 | addmac(); 288 | } 289 | 290 | addmac () 291 | { 292 | char sname[NAMESIZE]; 293 | int k; 294 | int mp; 295 | 296 | if (!symname (sname)) { 297 | illname (); 298 | kill (); 299 | return; 300 | } 301 | if (mp = findmac(sname)) { 302 | error("Duplicate define"); 303 | delmac(mp); 304 | } 305 | k = 0; 306 | while (putmac (sname[k++])); 307 | while (ch () == ' ' | ch () == 9) 308 | gch (); 309 | /*while (putmac (gch ()));*/ 310 | while (putmac(remove_one_line_comment(gch ()))); 311 | if (macptr >= MACMAX) 312 | error ("macro table full"); 313 | 314 | } 315 | 316 | /** 317 | * removes one line comments from defines 318 | * @param c 319 | * @return 320 | */ 321 | remove_one_line_comment(c) char c; { 322 | if ((c == '/') && (ch() == '/')) { 323 | while(gch()); 324 | return 0; 325 | } else { 326 | return c; 327 | } 328 | } 329 | 330 | delmac(mp) int mp; { 331 | --mp; --mp; /* step over previous null */ 332 | while (mp >= 0 && macq[mp]) macq[mp--] = '%'; 333 | 334 | } 335 | 336 | putmac (c) 337 | char c; 338 | { 339 | macq[macptr] = c; 340 | if (macptr < MACMAX) 341 | macptr++; 342 | return (c); 343 | 344 | } 345 | 346 | findmac (sname) 347 | char *sname; 348 | { 349 | int k; 350 | 351 | k = 0; 352 | while (k < macptr) { 353 | if (astreq (sname, macq + k, NAMEMAX)) { 354 | while (macq[k++]); 355 | return (k); 356 | } 357 | while (macq[k++]); 358 | while (macq[k++]); 359 | } 360 | return (0); 361 | 362 | } 363 | 364 | toggle (name, onoff) 365 | char name; 366 | int onoff; 367 | { 368 | switch (name) { 369 | case 'C': 370 | ctext = onoff; 371 | break; 372 | } 373 | } 374 | 375 | -------------------------------------------------------------------------------- /smallC/primary.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File primary.c: 2.4 (84/11/27,16:26:07) 3 | */ 4 | 5 | #include 6 | #include "defs.h" 7 | #include "data.h" 8 | 9 | primary (LVALUE *lval) { 10 | char sname[NAMESIZE]; 11 | int num[1], k, symbol_table_idx, offset, reg, otag; 12 | SYMBOL *symbol; 13 | 14 | lval->ptr_type = 0; /* clear pointer/array type */ 15 | lval->tagsym = 0; 16 | if (match ("(")) { 17 | k = hier1 (lval); 18 | needbrack (")"); 19 | return (k); 20 | } 21 | if (amatch("sizeof", 6)) { 22 | needbrack("("); 23 | gen_immediate(); 24 | if (amatch("int", 3) || amatch("unsigned int", 12)){ 25 | blanks(); 26 | /* pointers and ints are both INTSIZE */ 27 | match("*"); 28 | output_number(INTSIZE); 29 | } 30 | else if (amatch("char", 4) || amatch("unsigned char", 13)){ 31 | /* if sizeof a char pointer, output INTSIZE */ 32 | if(match("*")) 33 | output_number(INTSIZE); 34 | else 35 | output_number(1); 36 | } 37 | else if (amatch("struct", 6)){ 38 | if(symname(sname) == 0){ 39 | illname(); 40 | } 41 | if((otag = find_tag(sname)) == -1){ 42 | error("struct tag undefined"); 43 | } 44 | /* Write out struct size, or INTSIZE if struct pointer */ 45 | if(match("*")) 46 | output_number(INTSIZE); 47 | else 48 | output_number(tag_table[otag].size); 49 | } else if (symname(sname)) { 50 | if (((symbol_table_idx = find_locale(sname)) > -1) || 51 | ((symbol_table_idx = find_global(sname)) > -1)) { 52 | symbol = &symbol_table[symbol_table_idx]; 53 | if (symbol->storage == LSTATIC) 54 | error("sizeof local static"); 55 | offset = symbol->offset; 56 | if ((symbol->type & CINT) || 57 | (symbol->identity == POINTER)) 58 | offset *= INTSIZE; 59 | else if (symbol->type == STRUCT) 60 | offset *= tag_table[symbol->tagidx].size; 61 | output_number(offset); 62 | } else { 63 | error("sizeof undeclared variable"); 64 | output_number(0); 65 | } 66 | } else { 67 | error("sizeof only on type or variable"); 68 | } 69 | needbrack(")"); 70 | newline(); 71 | lval->symbol = 0; 72 | lval->indirect = 0; 73 | return(0); 74 | } 75 | if (symname (sname)) { 76 | if ((symbol_table_idx = find_locale(sname)) > -1) { 77 | symbol = &symbol_table[symbol_table_idx]; 78 | reg = gen_get_locale(symbol); 79 | lval->symbol = symbol; 80 | lval->indirect = symbol->type; 81 | if (symbol->type == STRUCT) { 82 | lval->tagsym = &tag_table[symbol->tagidx]; 83 | } 84 | if (symbol->identity == ARRAY || 85 | (symbol->identity == VARIABLE && symbol->type == STRUCT)) { 86 | lval->ptr_type = symbol->type; 87 | return reg; 88 | } 89 | if (symbol->identity == POINTER) { 90 | lval->indirect = CINT; 91 | lval->ptr_type = symbol->type; 92 | } 93 | return FETCH | reg; 94 | } 95 | if ((symbol_table_idx = find_global(sname)) > -1) { 96 | symbol = &symbol_table[symbol_table_idx]; 97 | if (symbol->identity != FUNCTION) { 98 | lval->symbol = symbol; 99 | lval->indirect = 0; 100 | if (symbol->type == STRUCT) { 101 | lval->tagsym = &tag_table[symbol->tagidx]; 102 | } 103 | if (symbol->identity != ARRAY && 104 | (symbol->identity != VARIABLE || symbol->type != STRUCT)) { 105 | if (symbol->identity == POINTER) { 106 | lval->ptr_type = symbol->type; 107 | } 108 | return FETCH | HL_REG; 109 | } 110 | gen_immediate(); 111 | output_string(symbol->name); 112 | newline(); 113 | lval->indirect = symbol->type; 114 | lval->ptr_type = symbol->type; 115 | return 0; 116 | } 117 | } 118 | blanks(); 119 | if (ch() != '(') 120 | error("undeclared variable"); 121 | symbol_table_idx = add_global(sname, FUNCTION, CINT, 0, PUBLIC); 122 | symbol = &symbol_table[symbol_table_idx]; 123 | lval->symbol = symbol; 124 | lval->indirect = 0; 125 | return 0; 126 | } 127 | if (constant(num)) { 128 | lval->symbol = 0; 129 | lval->indirect = 0; 130 | return 0; 131 | } 132 | else { 133 | error("invalid expression"); 134 | gen_immediate(); 135 | output_number(0); 136 | newline(); 137 | junk(); 138 | return 0; 139 | } 140 | 141 | } 142 | 143 | /** 144 | * true if val1 -> int pointer or int array and val2 not pointer or array 145 | * @param val1 146 | * @param val2 147 | * @return 148 | */ 149 | dbltest (LVALUE *val1, LVALUE *val2) { 150 | if (val1 == NULL) 151 | return (FALSE); 152 | if (val1->ptr_type) { 153 | if (val1->ptr_type & CCHAR) 154 | return (FALSE); 155 | if (val2->ptr_type) 156 | return (FALSE); 157 | return (TRUE); 158 | } 159 | return (FALSE); 160 | } 161 | 162 | /** 163 | * determine type of binary operation 164 | * @param lval 165 | * @param lval2 166 | * @return 167 | */ 168 | result (LVALUE *lval, LVALUE *lval2) { 169 | if (lval->ptr_type && lval2->ptr_type) 170 | lval->ptr_type = 0; 171 | else if (lval2->ptr_type) { 172 | lval->symbol = lval2->symbol; 173 | lval->indirect = lval2->indirect; 174 | lval->ptr_type = lval2->ptr_type; 175 | } 176 | } 177 | 178 | constant (int val[]) { 179 | if (number (val)) 180 | gen_immediate (); 181 | else if (quoted_char (val)) 182 | gen_immediate (); 183 | else if (quoted_string (val)) { 184 | gen_immediate (); 185 | print_label (litlab); 186 | output_byte ('+'); 187 | } else 188 | return (0); 189 | output_number (val[0]); 190 | newline (); 191 | return (1); 192 | } 193 | 194 | number (int val[]) { 195 | int k, minus, base; 196 | char c; 197 | 198 | k = minus = 1; 199 | while (k) { 200 | k = 0; 201 | if (match("+")) 202 | k = 1; 203 | if (match("-")) { 204 | minus = (-minus); 205 | k = 1; 206 | } 207 | } 208 | if (!numeric(c = ch ())) 209 | return (0); 210 | if (match("0x") || match ("0X")) 211 | while (numeric(c = ch ()) || 212 | (c >= 'a' && c <= 'f') || 213 | (c >= 'A' && c <= 'F')) { 214 | inbyte (); 215 | k = k * 16 + (numeric (c) ? (c - '0') : ((c & 07) + 9)); 216 | } 217 | else { 218 | base = (c == '0') ? 8 : 10; 219 | while (numeric(ch())) { 220 | c = inbyte (); 221 | k = k * base + (c - '0'); 222 | } 223 | } 224 | if (minus < 0) 225 | k = (-k); 226 | val[0] = k; 227 | if(k < 0) { 228 | return (UINT); 229 | } else { 230 | return (CINT); 231 | } 232 | } 233 | 234 | /** 235 | * Test if we have one char enclosed in single quotes 236 | * @param value returns the char found 237 | * @return 1 if we have, 0 otherwise 238 | */ 239 | quoted_char (int *value) { 240 | int k; 241 | char c; 242 | 243 | k = 0; 244 | if (!match ("'")) 245 | return (0); 246 | while ((c = gch ()) != '\'') { 247 | c = (c == '\\') ? spechar(): c; 248 | k = (k & 255) * 256 + (c & 255); 249 | } 250 | *value = k; 251 | return (1); 252 | } 253 | 254 | /** 255 | * Test if we have string enclosed in double quotes. e.g. "abc". 256 | * Load the string into literal pool. 257 | * @param position returns beginning of the string 258 | * @return 1 if such string found, 0 otherwise 259 | */ 260 | quoted_string (int *position) { 261 | char c; 262 | 263 | if (!match ("\"")) 264 | return (0); 265 | *position = litptr; 266 | while (ch () != '"') { 267 | if (ch () == 0) 268 | break; 269 | if (litptr >= LITMAX) { 270 | error ("string space exhausted"); 271 | while (!match ("\"")) 272 | if (gch () == 0) 273 | break; 274 | return (1); 275 | } 276 | c = gch(); 277 | litq[litptr++] = (c == '\\') ? spechar(): c; 278 | } 279 | gch (); 280 | litq[litptr++] = 0; 281 | return (1); 282 | } 283 | 284 | /** 285 | * decode special characters (preceeded by back slashes) 286 | */ 287 | spechar() { 288 | char c; 289 | c = ch(); 290 | 291 | if (c == 'n') c = LF; 292 | else if (c == 't') c = TAB; 293 | else if (c == 'r') c = CR; 294 | else if (c == 'f') c = FFEED; 295 | else if (c == 'b') c = BKSP; 296 | else if (c == '0') c = EOS; 297 | else if (c == EOS) return 0; 298 | 299 | gch(); 300 | return (c); 301 | } 302 | 303 | /** 304 | * perform a function call 305 | * called from "hier11", this routine will either call the named 306 | * function, or if the supplied ptr is zero, will call the contents 307 | * of HL 308 | * @param ptr name of the function 309 | */ 310 | void callfunction (char *ptr) { 311 | int nargs; 312 | 313 | nargs = 0; 314 | blanks (); 315 | if (ptr == 0) 316 | gen_push (HL_REG); 317 | while (!streq (line + lptr, ")")) { 318 | if (endst ()) 319 | break; 320 | expression (NO); 321 | if (ptr == 0) 322 | gen_swap_stack (); 323 | gen_push (HL_REG); 324 | nargs = nargs + INTSIZE; 325 | if (!match (",")) 326 | break; 327 | } 328 | needbrack (")"); 329 | if (aflag) 330 | gnargs(nargs / INTSIZE); 331 | if (ptr) 332 | gen_call (ptr); 333 | else 334 | callstk (); 335 | stkp = gen_modify_stack (stkp + nargs); 336 | } 337 | 338 | needlval () { 339 | error ("must be lvalue"); 340 | } 341 | 342 | -------------------------------------------------------------------------------- /smallC/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | There've been quite a few requests for this via net.micro.cpm, so's I 3 | thought I'd post it thru mod.sources. This is Ron Cain's original Small 4 | C compiler, but highly extended. Included are code generators for 8080, 5 | 6809, 68000, and VAX, as well as run-time support for 8080 CPM, VAX BSD4.1, 6 | and a FLEX 6809 environment. See the README for a description of Small C's 7 | limitations. 8 | -------------------------------------------------------------------------------- /smallC/stmt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File stmt.c: 2.1 (83/03/20,16:02:17) 3 | */ 4 | 5 | #include 6 | #include "defs.h" 7 | #include "data.h" 8 | 9 | /** 10 | * statement parser 11 | * called whenever syntax requires a statement. this routine 12 | * performs that statement and returns a number telling which one 13 | * @param func func is true if we require a "function_statement", which 14 | * must be compound, and must contain "statement_list" (even if 15 | * "declaration_list" is omitted) 16 | * @return statement type 17 | */ 18 | statement (int func) { 19 | if ((ch () == 0) & feof (input)) 20 | return (0); 21 | lastst = 0; 22 | if (func) 23 | if (match ("{")) { 24 | do_compound (YES); 25 | return (lastst); 26 | } else 27 | error ("function requires compound statement"); 28 | if (match ("{")) 29 | do_compound (NO); 30 | else 31 | do_statement (); 32 | return (lastst); 33 | } 34 | 35 | /** 36 | * declaration 37 | */ 38 | statement_declare() { 39 | if (amatch("register", 8)) 40 | do_local_declares(DEFAUTO); 41 | else if (amatch("auto", 4)) 42 | do_local_declares(DEFAUTO); 43 | else if (amatch("static", 6)) 44 | do_local_declares(LSTATIC); 45 | else if (do_local_declares(AUTO)) ; 46 | else 47 | return (NO); 48 | return (YES); 49 | } 50 | 51 | /** 52 | * local declarations 53 | * @param stclass 54 | * @return 55 | */ 56 | do_local_declares(int stclass) { 57 | int type = 0; 58 | int otag; /* tag of struct object being declared */ 59 | int sflag; /* TRUE for struct definition, zero for union */ 60 | char sname[NAMESIZE]; 61 | blanks(); 62 | if ((sflag=amatch("struct", 6)) || amatch("union", 5)) { 63 | if (symname(sname) == 0) { /* legal name ? */ 64 | illname(); 65 | } 66 | if ((otag=find_tag(sname)) == -1) /* structure not previously defined */ 67 | { 68 | otag = define_struct(sname, stclass, sflag); 69 | } 70 | declare_local(STRUCT, stclass, otag); 71 | } else if (type = get_type()) { 72 | declare_local(type, stclass, -1); 73 | } else if (stclass == LSTATIC || stclass == DEFAUTO) { 74 | declare_local(CINT, stclass, -1); 75 | } else { 76 | return(0); 77 | } 78 | need_semicolon(); 79 | return(1); 80 | } 81 | 82 | /** 83 | * non-declaration statement 84 | */ 85 | do_statement () { 86 | if (amatch ("if", 2)) { 87 | doif (); 88 | lastst = STIF; 89 | } else if (amatch ("while", 5)) { 90 | dowhile (); 91 | lastst = STWHILE; 92 | } else if (amatch ("switch", 6)) { 93 | doswitch (); 94 | lastst = STSWITCH; 95 | } else if (amatch ("do", 2)) { 96 | dodo (); 97 | need_semicolon (); 98 | lastst = STDO; 99 | } else if (amatch ("for", 3)) { 100 | dofor (); 101 | lastst = STFOR; 102 | } else if (amatch ("return", 6)) { 103 | doreturn (); 104 | need_semicolon (); 105 | lastst = STRETURN; 106 | } else if (amatch ("break", 5)) { 107 | dobreak (); 108 | need_semicolon (); 109 | lastst = STBREAK; 110 | } else if (amatch ("continue", 8)) { 111 | docont (); 112 | need_semicolon (); 113 | lastst = STCONT; 114 | } else if (match (";")) 115 | ; 116 | else if (amatch ("case", 4)) { 117 | docase (); 118 | lastst = statement (NO); 119 | } else if (amatch ("default", 7)) { 120 | dodefault (); 121 | lastst = statement (NO); 122 | } else if (match ("#asm")) { 123 | doasm (); 124 | lastst = STASM; 125 | } else if (match ("{")) 126 | do_compound (NO); 127 | else { 128 | expression (YES); 129 | /* if (match (":")) { 130 | dolabel (); 131 | lastst = statement (NO); 132 | } else { 133 | */ need_semicolon (); 134 | lastst = STEXP; 135 | /* } 136 | */ } 137 | } 138 | 139 | /** 140 | * compound statement 141 | * allow any number of statements to fall between "{" and "}" 142 | * 'func' is true if we are in a "function_statement", which 143 | * must contain "statement_list" 144 | */ 145 | do_compound(int func) { 146 | int decls; 147 | 148 | decls = YES; 149 | ncmp++; 150 | while (!match ("}")) { 151 | if (feof (input)) 152 | return; 153 | if (decls) { 154 | if (!statement_declare ()) 155 | decls = NO; 156 | } else 157 | do_statement (); 158 | } 159 | ncmp--; 160 | } 161 | 162 | /** 163 | * "if" statement 164 | */ 165 | doif() { 166 | int fstkp, flab1, flab2; 167 | int flev; 168 | 169 | flev = local_table_index; 170 | fstkp = stkp; 171 | flab1 = getlabel (); 172 | test (flab1, FALSE); 173 | statement (NO); 174 | stkp = gen_modify_stack (fstkp); 175 | local_table_index = flev; 176 | if (!amatch ("else", 4)) { 177 | generate_label (flab1); 178 | return; 179 | } 180 | gen_jump (flab2 = getlabel ()); 181 | generate_label (flab1); 182 | statement (NO); 183 | stkp = gen_modify_stack (fstkp); 184 | local_table_index = flev; 185 | generate_label (flab2); 186 | } 187 | 188 | /** 189 | * "while" statement 190 | */ 191 | dowhile() { 192 | WHILE ws; 193 | 194 | ws.symbol_idx = local_table_index; 195 | ws.stack_pointer = stkp; 196 | ws.type = WSWHILE; 197 | ws.case_test = getlabel (); 198 | ws.while_exit = getlabel (); 199 | addwhile (&ws); 200 | generate_label (ws.case_test); 201 | test (ws.while_exit, FALSE); 202 | statement (NO); 203 | gen_jump (ws.case_test); 204 | generate_label (ws.while_exit); 205 | local_table_index = ws.symbol_idx; 206 | stkp = gen_modify_stack (ws.stack_pointer); 207 | delwhile (); 208 | } 209 | 210 | /** 211 | * "do" statement 212 | */ 213 | dodo() { 214 | WHILE ws; 215 | 216 | ws.symbol_idx = local_table_index; 217 | ws.stack_pointer = stkp; 218 | ws.type = WSDO; 219 | ws.body_tab = getlabel (); 220 | ws.case_test = getlabel (); 221 | ws.while_exit = getlabel (); 222 | addwhile (&ws); 223 | generate_label (ws.body_tab); 224 | statement (NO); 225 | if (!match ("while")) { 226 | error ("missing while"); 227 | return; 228 | } 229 | generate_label (ws.case_test); 230 | test (ws.body_tab, TRUE); 231 | generate_label (ws.while_exit); 232 | local_table_index = ws.symbol_idx; 233 | stkp = gen_modify_stack (ws.stack_pointer); 234 | delwhile (); 235 | } 236 | 237 | /** 238 | * "for" statement 239 | */ 240 | dofor() { 241 | WHILE ws; 242 | WHILE *pws; 243 | 244 | ws.symbol_idx = local_table_index; 245 | ws.stack_pointer = stkp; 246 | ws.type = WSFOR; 247 | ws.case_test = getlabel (); 248 | ws.incr_def = getlabel (); 249 | ws.body_tab = getlabel (); 250 | ws.while_exit = getlabel (); 251 | addwhile (&ws); 252 | pws = readwhile (); 253 | needbrack ("("); 254 | if (!match (";")) { 255 | expression (YES); 256 | need_semicolon (); 257 | } 258 | generate_label (pws->case_test); 259 | if (!match (";")) { 260 | expression (YES); 261 | gen_test_jump (pws->body_tab, TRUE); 262 | gen_jump (pws->while_exit); 263 | need_semicolon (); 264 | } else 265 | pws->case_test = pws->body_tab; 266 | generate_label (pws->incr_def); 267 | if (!match (")")) { 268 | expression (YES); 269 | needbrack (")"); 270 | gen_jump (pws->case_test); 271 | } else 272 | pws->incr_def = pws->case_test; 273 | generate_label (pws->body_tab); 274 | statement (NO); 275 | gen_jump (pws->incr_def); 276 | generate_label (pws->while_exit); 277 | local_table_index = pws->symbol_idx; 278 | stkp = gen_modify_stack (pws->stack_pointer); 279 | delwhile (); 280 | } 281 | 282 | /** 283 | * "switch" statement 284 | */ 285 | doswitch() { 286 | WHILE ws; 287 | WHILE *ptr; 288 | 289 | ws.symbol_idx = local_table_index; 290 | ws.stack_pointer = stkp; 291 | ws.type = WSSWITCH; 292 | ws.case_test = swstp; 293 | ws.body_tab = getlabel (); 294 | ws.incr_def = ws.while_exit = getlabel (); 295 | addwhile (&ws); 296 | gen_immediate (); 297 | print_label (ws.body_tab); 298 | newline (); 299 | gen_push (HL_REG); 300 | needbrack ("("); 301 | expression (YES); 302 | needbrack (")"); 303 | stkp = stkp + INTSIZE; /* '?case' will adjust the stack */ 304 | gen_jump_case (); 305 | statement (NO); 306 | ptr = readswitch (); 307 | gen_jump (ptr->while_exit); 308 | dumpsw (ptr); 309 | generate_label (ptr->while_exit); 310 | local_table_index = ptr->symbol_idx; 311 | stkp = gen_modify_stack (ptr->stack_pointer); 312 | swstp = ptr->case_test; 313 | delwhile (); 314 | } 315 | 316 | /** 317 | * "case" label 318 | */ 319 | docase() { 320 | int val; 321 | 322 | val = 0; 323 | if (readswitch ()) { 324 | if (!number (&val)) 325 | if (!quoted_char (&val)) 326 | error ("bad case label"); 327 | addcase (val); 328 | if (!match (":")) 329 | error ("missing colon"); 330 | } else 331 | error ("no active switch"); 332 | } 333 | 334 | /** 335 | * "default" label 336 | */ 337 | dodefault() { 338 | WHILE *ptr; 339 | int lab; 340 | 341 | if (ptr = readswitch ()) { 342 | ptr->incr_def = lab = getlabel (); 343 | generate_label (lab); 344 | if (!match (":")) 345 | error ("missing colon"); 346 | } else 347 | error ("no active switch"); 348 | } 349 | 350 | /** 351 | * "return" statement 352 | */ 353 | doreturn() { 354 | if (endst () == 0) 355 | expression (YES); 356 | gen_jump(fexitlab); 357 | } 358 | 359 | /** 360 | * "break" statement 361 | */ 362 | dobreak() { 363 | WHILE *ptr; 364 | 365 | if ((ptr = readwhile ()) == 0) 366 | return; 367 | gen_modify_stack (ptr->stack_pointer); 368 | gen_jump (ptr->while_exit); 369 | } 370 | 371 | /** 372 | * "continue" statement 373 | */ 374 | docont() { 375 | WHILE *ptr; /*int *ptr; */ 376 | 377 | if ((ptr = findwhile ()) == 0) 378 | return; 379 | gen_modify_stack (ptr->stack_pointer); 380 | if (ptr->type == WSFOR) 381 | gen_jump (ptr->incr_def); 382 | else 383 | gen_jump (ptr->case_test); 384 | } 385 | 386 | /** 387 | * dump switch table 388 | */ 389 | dumpsw(WHILE *ws) { 390 | int i,j; 391 | 392 | data_segment_gdata (); 393 | generate_label (ws->body_tab); 394 | if (ws->case_test != swstp) { 395 | j = ws->case_test; 396 | while (j < swstp) { 397 | gen_def_word (); 398 | i = 4; 399 | while (i--) { 400 | output_number (swstcase[j]); 401 | output_byte (','); 402 | print_label (swstlab[j++]); 403 | if ((i == 0) | (j >= swstp)) { 404 | newline (); 405 | break; 406 | } 407 | output_byte (','); 408 | } 409 | } 410 | } 411 | gen_def_word (); 412 | print_label (ws->incr_def); 413 | output_string (",0"); 414 | newline (); 415 | code_segment_gtext (); 416 | } 417 | 418 | -------------------------------------------------------------------------------- /smallC/struct.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File struct.c: (12/12/12,21:31:33) 3 | */ 4 | 5 | #include 6 | #include 7 | #include "defs.h" 8 | #include "data.h" 9 | 10 | /** 11 | * look up a tag in tag table by name 12 | * @param sname 13 | * @return index 14 | */ 15 | int find_tag(char *sname) { 16 | int index; 17 | 18 | index = 0; 19 | while (index < tag_table_index) { 20 | if (astreq (sname, tag_table[index].name, NAMEMAX)) { 21 | return index; 22 | } 23 | ++index; 24 | } 25 | return -1; 26 | } 27 | 28 | /** 29 | * determine if 'sname' is a member of the struct with tag 'tag' 30 | * @param tag 31 | * @param sname 32 | * @return pointer to member symbol if it is, else 0 33 | */ 34 | SYMBOL *find_member(TAG_SYMBOL *tag, char *sname) { 35 | int member_idx; 36 | 37 | member_idx = tag->member_idx; 38 | 39 | while (member_idx < tag->member_idx + tag->number_of_members) { 40 | if (strcmp(member_table[member_idx].name, sname) == 0) 41 | return &member_table[member_idx]; 42 | ++member_idx; 43 | } 44 | return 0; 45 | } 46 | 47 | /** 48 | * add new structure member to table 49 | * @param sname 50 | * @param identity - variable, array, pointer, function 51 | * @param typ 52 | * @param offset 53 | * @param storage 54 | * @return 55 | */ 56 | add_member(char *sname, char identity, char type, int offset, int storage_class, int member_size) { 57 | char *buffer_ptr; 58 | SYMBOL *symbol; 59 | if (member_table_index >= NUMMEMB) { 60 | error("symbol table overflow"); 61 | return 0; 62 | } 63 | symbol = &member_table[member_table_index]; 64 | buffer_ptr = symbol->name; 65 | while (alphanumeric(*buffer_ptr++ = *sname++)); 66 | symbol->identity = identity; 67 | symbol->type = type; 68 | symbol->storage = storage_class; 69 | symbol->offset = offset; 70 | /* set size for arrays */ 71 | symbol->struct_size = member_size; 72 | 73 | member_table_index++; 74 | } 75 | 76 | int define_struct(char *sname, int storage, int is_struct) { 77 | TAG_SYMBOL *symbol; 78 | char *buffer_ptr; 79 | 80 | /*tag_table_index++;*/ 81 | if (tag_table_index >= NUMTAG) { 82 | error("struct table overflow"); 83 | return 0; 84 | } 85 | symbol = &tag_table[tag_table_index]; 86 | buffer_ptr = symbol->name; 87 | while (alphanumeric(*buffer_ptr++ = *sname++)); 88 | symbol->size = 0; 89 | symbol->member_idx = member_table_index; 90 | 91 | needbrack("{"); 92 | do { 93 | do_declarations(storage, &tag_table[tag_table_index], is_struct); 94 | } while (!match ("}")); 95 | symbol->number_of_members = member_table_index - symbol->member_idx; 96 | return tag_table_index++; 97 | } 98 | -------------------------------------------------------------------------------- /smallC/sym.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File sym.c: 2.1 (83/03/20,16:02:19) 3 | */ 4 | 5 | #include 6 | #include "defs.h" 7 | #include "data.h" 8 | 9 | /** 10 | * declare a static variable 11 | * @param type 12 | * @param storage 13 | * @param mtag tag of struct whose members are being declared, or zero 14 | * @param otag tag of struct object being declared. only matters if mtag is 15 | * non-zero 16 | * @param is_struct struct or union or no meaning 17 | * @return 18 | */ 19 | declare_global(int type, int storage, TAG_SYMBOL *mtag, int otag, int is_struct) 20 | { 21 | int dim, identity; 22 | char sname[NAMESIZE]; 23 | 24 | FOREVER { 25 | FOREVER { 26 | if (endst ()) 27 | return; 28 | dim = 1; 29 | if (match ("*")) { 30 | identity = POINTER; 31 | } else { 32 | identity = VARIABLE; 33 | } 34 | if (!symname (sname)) 35 | illname (); 36 | if (find_global (sname) > -1) 37 | multidef (sname); 38 | if (match ("[")) { 39 | dim = needsub (); 40 | /*if (dim || storage == EXTERN) {*/ 41 | identity = ARRAY; 42 | /*} else { 43 | identity = POINTER; 44 | }*/ 45 | } 46 | /* add symbol*/ 47 | if (mtag == 0) { /* real variable, not a struct/union member */ 48 | identity = initials(sname, type, identity, dim, otag); 49 | add_global (sname, identity, type, (!dim ? -1 : dim), storage); 50 | if (type == STRUCT) { 51 | symbol_table[current_symbol_table_idx].tagidx = otag; 52 | } 53 | break; 54 | } else if (is_struct) { 55 | /* structure member, mtag->size is offset */ 56 | add_member(sname, identity, type, mtag->size, storage, (type & CINT) ? dim*INTSIZE : dim); 57 | /* store (correctly scaled) size of member in tag table entry */ 58 | if (identity == POINTER) 59 | type = CINT; 60 | scale_const(type, otag, &dim); 61 | mtag->size += dim; 62 | } 63 | else { 64 | /* union member, offset is always zero */ 65 | add_member(sname, identity, type, 0, storage, (type & CINT) ? dim*INTSIZE : dim); 66 | /* store maximum member size in tag table entry */ 67 | if (identity == POINTER) 68 | type = CINT; 69 | scale_const(type, otag, &dim); 70 | if (mtag->size < dim) 71 | mtag->size = dim; 72 | } 73 | } 74 | if (!match (",")) 75 | return; 76 | } 77 | } 78 | 79 | /** 80 | * initialize global objects 81 | * @param symbol_name 82 | * @param type char or integer or struct 83 | * @param identity 84 | * @param dim 85 | * @return 1 if variable is initialized 86 | */ 87 | int initials(char *symbol_name, int type, int identity, int dim, int otag) { 88 | int dim_unknown = 0; 89 | litptr = 0; 90 | if(dim == 0) { /* allow for xx[] = {..}; declaration */ 91 | dim_unknown = 1; 92 | } 93 | if (!(type & CCHAR) && !(type & CINT) && !(type == STRUCT)) { 94 | error("unsupported storage size"); 95 | } 96 | if(match("=")) { 97 | /* an array or struct */ 98 | if(match("{")) { 99 | /* aggregate initialiser */ 100 | if ((identity == POINTER || identity == VARIABLE) && type == STRUCT) 101 | { 102 | /* aggregate is structure or pointer to structure */ 103 | dim = 0; 104 | struct_init(&tag_table[otag], symbol_name); 105 | } 106 | else { 107 | while((dim > 0) || (dim_unknown)) { 108 | if (identity == ARRAY && type == STRUCT) { 109 | /* array of struct */ 110 | needbrack("{"); 111 | struct_init(&tag_table[otag], symbol_name); 112 | --dim; 113 | needbrack("}"); 114 | } 115 | else { 116 | if (init(symbol_name, type, identity, &dim, 0)) { 117 | dim_unknown++; 118 | } 119 | } 120 | if(match(",") == 0) { 121 | break; 122 | } 123 | } 124 | if(--dim_unknown == 0) 125 | identity = POINTER; 126 | } 127 | needbrack("}"); 128 | /* single constant */ 129 | } else { 130 | init(symbol_name, type, identity, &dim, 0); 131 | } 132 | } 133 | return identity; 134 | } 135 | 136 | /** 137 | * initialise structure 138 | * @param tag 139 | */ 140 | struct_init(TAG_SYMBOL *tag, char *symbol_name) { 141 | int dim ; 142 | int member_idx; 143 | 144 | member_idx = tag->member_idx; 145 | while (member_idx < tag->member_idx + tag->number_of_members) { 146 | init(symbol_name, member_table[tag->member_idx + member_idx].type, 147 | member_table[tag->member_idx + member_idx].identity, &dim, tag); 148 | ++member_idx; 149 | if((!match(",")) && 150 | (member_idx != (tag->member_idx + tag->number_of_members))) 151 | { 152 | error("struct initialisaton out of data"); 153 | break ; 154 | } 155 | } 156 | } 157 | 158 | /** 159 | * evaluate one initializer, add data to table 160 | * @param symbol_name 161 | * @param type 162 | * @param identity 163 | * @param dim 164 | * @param tag 165 | * @return 166 | */ 167 | init(char *symbol_name, int type, int identity, int *dim, TAG_SYMBOL *tag) { 168 | int value, number_of_chars; 169 | if(identity == POINTER) { 170 | error("cannot assign to pointer"); 171 | } 172 | if(quoted_string(&value)) { 173 | if((identity == VARIABLE) || !(type & CCHAR)) 174 | error("found string: must assign to char pointer or array"); 175 | number_of_chars = litptr - value; 176 | *dim = *dim - number_of_chars; 177 | while (number_of_chars > 0) { 178 | add_data_initials(symbol_name, CCHAR, litq[value++], tag); 179 | number_of_chars = number_of_chars - 1; 180 | } 181 | } else if (number(&value)) { 182 | add_data_initials(symbol_name, CINT, value, tag); 183 | *dim = *dim - 1; 184 | } else if(quoted_char(&value)) { 185 | add_data_initials(symbol_name, CCHAR, value, tag); 186 | *dim = *dim - 1; 187 | } else { 188 | return 0; 189 | } 190 | return 1; 191 | } 192 | 193 | /** 194 | * declare local variables 195 | * works just like "declglb", but modifies machine stack and adds 196 | * symbol table entry with appropriate stack offset to find it again 197 | * @param typ 198 | * @param stclass 199 | * @param otag index of tag in tag_table 200 | */ 201 | declare_local(int typ, int stclass, int otag) { 202 | int k, j; 203 | char sname[NAMESIZE]; 204 | 205 | FOREVER { 206 | FOREVER { 207 | if (endst()) 208 | return; 209 | if (match("*")) 210 | j = POINTER; 211 | else 212 | j = VARIABLE; 213 | if (!symname(sname)) 214 | illname(); 215 | if (-1 != find_locale(sname)) 216 | multidef (sname); 217 | if (match("[")) { 218 | k = needsub(); 219 | if (k) { 220 | j = ARRAY; 221 | if (typ & CINT) { 222 | k = k * INTSIZE; 223 | } else if (typ == STRUCT) { 224 | k = k * tag_table[otag].size; 225 | } 226 | } else { 227 | j = POINTER; 228 | k = INTSIZE; 229 | } 230 | } else { 231 | if (j == POINTER) { 232 | k = INTSIZE; 233 | } else { 234 | switch (typ) { 235 | case CCHAR: 236 | case UCHAR: 237 | k = 1; 238 | break; 239 | case STRUCT: 240 | k = tag_table[otag].size; 241 | break; 242 | default: 243 | k = INTSIZE; 244 | } 245 | } 246 | } 247 | if (stclass != LSTATIC) { 248 | stkp = gen_modify_stack(stkp - k); 249 | /* local structs need their tagidx set */ 250 | current_symbol_table_idx = add_local(sname, j, typ, stkp, AUTO); 251 | if(typ == STRUCT) { 252 | symbol_table[current_symbol_table_idx].tagidx = otag; 253 | } 254 | } else { 255 | /* local structs need their tagidx set */ 256 | current_symbol_table_idx = add_local(sname, j, typ, k, LSTATIC); 257 | if(typ == STRUCT) { 258 | symbol_table[current_symbol_table_idx].tagidx = otag; 259 | } 260 | } 261 | break; 262 | } 263 | if (!match(",")) 264 | return; 265 | } 266 | } 267 | 268 | /** 269 | * get required array size. [xx] 270 | * @return array size 271 | */ 272 | needsub() { 273 | int num[1]; 274 | 275 | if (match ("]")) 276 | return (0); 277 | if (!number (num)) { 278 | error ("must be constant"); 279 | num[0] = 1; 280 | } 281 | if (num[0] < 0) { 282 | error ("negative size illegal"); 283 | num[0] = (-num[0]); 284 | } 285 | needbrack ("]"); 286 | return (num[0]); 287 | } 288 | 289 | /** 290 | * search global table for given symbol name 291 | * @param sname 292 | * @return table index 293 | */ 294 | int find_global (char *sname) { 295 | int idx; 296 | 297 | idx = 0; 298 | while (idx < global_table_index) { 299 | if (astreq (sname, symbol_table[idx].name, NAMEMAX)) 300 | return (idx); 301 | idx++; 302 | } 303 | return (-1); 304 | } 305 | 306 | /** 307 | * search local table for given symbol name 308 | * @param sname 309 | * @return table index 310 | */ 311 | int find_locale (char *sname) { 312 | int idx; 313 | 314 | idx = local_table_index; 315 | while (idx >= NUMBER_OF_GLOBALS) { 316 | idx--; 317 | if (astreq (sname, symbol_table[idx].name, NAMEMAX)) 318 | return (idx); 319 | } 320 | return (-1); 321 | } 322 | 323 | /** 324 | * add new symbol to global table 325 | * @param sname 326 | * @param identity 327 | * @param type 328 | * @param offset size in bytes 329 | * @param storage 330 | * @return new index 331 | */ 332 | int add_global (char *sname, int identity, int type, int offset, int storage) { 333 | SYMBOL *symbol; 334 | char *buffer_ptr; 335 | if ((current_symbol_table_idx = find_global(sname)) > -1) { 336 | return (current_symbol_table_idx); 337 | } 338 | if (global_table_index >= NUMBER_OF_GLOBALS) { 339 | error ("global symbol table overflow"); 340 | return (0); 341 | } 342 | current_symbol_table_idx = global_table_index; 343 | symbol = &symbol_table[current_symbol_table_idx]; 344 | buffer_ptr = symbol->name; 345 | while (alphanumeric(*buffer_ptr++ = *sname++)); 346 | symbol->identity = identity; 347 | symbol->type = type; 348 | symbol->storage = storage; 349 | symbol->offset = offset; 350 | global_table_index++; 351 | return (current_symbol_table_idx); 352 | } 353 | 354 | /** 355 | * add new symbol to local table 356 | * @param sname 357 | * @param identity 358 | * @param type 359 | * @param offset size in bytes 360 | * @param storage_class 361 | * @return 362 | */ 363 | int add_local(char *sname, int identity, int type, int offset, 364 | int storage_class) 365 | { 366 | int k; 367 | SYMBOL *symbol; 368 | char *buffer_ptr; 369 | 370 | if ((current_symbol_table_idx = find_locale (sname)) > -1) { 371 | return (current_symbol_table_idx); 372 | } 373 | if (local_table_index >= NUMBER_OF_GLOBALS + NUMBER_OF_LOCALS) { 374 | error ("local symbol table overflow"); 375 | return (0); 376 | } 377 | current_symbol_table_idx = local_table_index; 378 | symbol = &symbol_table[current_symbol_table_idx]; 379 | buffer_ptr = symbol->name; 380 | while (alphanumeric(*buffer_ptr++ = *sname++)); 381 | symbol->identity = identity; 382 | symbol->type = type; 383 | symbol->storage = storage_class; 384 | if (storage_class == LSTATIC) { 385 | data_segment_gdata(); 386 | print_label(k = getlabel()); 387 | output_label_terminator(); 388 | gen_def_storage(); 389 | output_number(offset); 390 | newline(); 391 | code_segment_gtext(); 392 | offset = k; 393 | } 394 | symbol->offset = offset; 395 | local_table_index++; 396 | return (current_symbol_table_idx); 397 | } 398 | 399 | /** 400 | * test if next input string is legal symbol name 401 | */ 402 | symname(char *sname) { 403 | int k; 404 | 405 | blanks(); 406 | if (!alpha (ch ())) 407 | return (0); 408 | k = 0; 409 | while (alphanumeric(ch ())) 410 | sname[k++] = gch (); 411 | sname[k] = 0; 412 | return (1); 413 | } 414 | 415 | /** 416 | * print error message 417 | */ 418 | illname() { 419 | error ("illegal symbol name"); 420 | } 421 | 422 | /** 423 | * print error message 424 | * @param symbol_name 425 | * @return 426 | */ 427 | multidef (char *symbol_name) { 428 | error ("already defined"); 429 | gen_comment (); 430 | output_string (symbol_name); 431 | newline (); 432 | } 433 | 434 | -------------------------------------------------------------------------------- /smallC/while.c: -------------------------------------------------------------------------------- 1 | /* File while.c: 2.1 (83/03/20,16:02:22) */ 2 | /*% cc -O -c % 3 | * 4 | */ 5 | 6 | #include 7 | #include "defs.h" 8 | #include "data.h" 9 | 10 | addwhile (WHILE *ptr) { 11 | /*int ptr[]; 12 | int k; 13 | 14 | if (wsptr == WSMAX) { */ 15 | if (while_table_index == WSTABSZ) { 16 | error ("too many active whiles"); 17 | return; 18 | } 19 | /*k = 0; 20 | while (k < WSSIZ) 21 | *wsptr++ = ptr[k++]; */ 22 | ws[while_table_index++] = *ptr; 23 | } 24 | 25 | delwhile () { 26 | if (readwhile ()) { 27 | /*wsptr = wsptr - WSSIZ;*/ 28 | while_table_index--; 29 | } 30 | } 31 | 32 | WHILE *readwhile () { 33 | if (while_table_index == 0) { 34 | /*if (wsptr == ws) {*/ 35 | error ("no active do/for/while/switch"); 36 | return (0); 37 | } else { 38 | /*return (wsptr-WSSIZ);*/ 39 | return &ws[while_table_index - 1]; 40 | } 41 | } 42 | 43 | WHILE *findwhile () { 44 | /*int *ptr;*/ 45 | int while_table_idx; 46 | 47 | /*for (ptr = wsptr; ptr != ws;) {*/ 48 | while_table_idx = while_table_index; 49 | for (; while_table_idx != 0;) { 50 | /*ptr = ptr - WSSIZ;*/ 51 | while_table_idx--; 52 | /*if (ptr[WSTYP] != WSSWITCH) 53 | return (ptr);*/ 54 | if (ws[while_table_idx].type != WSSWITCH) 55 | return &ws[while_table_idx]; 56 | } 57 | error ("no active do/for/while"); 58 | return (0); 59 | } 60 | 61 | WHILE *readswitch () { 62 | WHILE *ptr; /*int *ptr;*/ 63 | 64 | if (ptr = readwhile ()) { 65 | /*if (ptr[WSTYP] == WSSWITCH)*/ 66 | if (ptr->type == WSSWITCH) { 67 | return (ptr); 68 | } 69 | } 70 | return (0); 71 | } 72 | 73 | addcase (int val) { 74 | int lab; 75 | 76 | if (swstp == SWSTSZ) 77 | error ("too many case labels"); 78 | else { 79 | swstcase[swstp] = val; 80 | swstlab[swstp++] = lab = getlabel (); 81 | print_label (lab); 82 | output_label_terminator (); 83 | newline (); 84 | } 85 | } 86 | 87 | --------------------------------------------------------------------------------