mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-12-09 23:03:02 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <klib.h>
|
||||
#include "machine.h"
|
||||
#include "ctype.h"
|
||||
|
||||
#ifdef PDP11
|
||||
struct {
|
||||
char lobyte;
|
||||
char hibyte;
|
||||
};
|
||||
struct {
|
||||
char *ptrw1;
|
||||
char *ptrw2;
|
||||
};
|
||||
struct {
|
||||
int wd1;
|
||||
int wd2;
|
||||
};
|
||||
struct {
|
||||
int swd1;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef MC68000
|
||||
struct {
|
||||
char hibyte;
|
||||
char lobyte;
|
||||
};
|
||||
struct {
|
||||
char *ptrw2;
|
||||
};
|
||||
struct {
|
||||
int wd1;
|
||||
int wd2;
|
||||
};
|
||||
struct {
|
||||
int swd1;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef VAX
|
||||
struct {
|
||||
short wd2;
|
||||
short wd1;
|
||||
};
|
||||
struct {
|
||||
short swd1;
|
||||
};
|
||||
|
||||
struct {
|
||||
char lobyte;
|
||||
char hibyte;
|
||||
};
|
||||
struct {
|
||||
char *ptrw2;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* format of a symbol entry in the main table*/
|
||||
|
||||
# define NAMELEN 8 /*length of name in symbol table*/
|
||||
struct symtab {
|
||||
char name[NAMELEN]; /*symbol name*/
|
||||
short flags; /*bit flags*/
|
||||
char *tlnk; /*table link*/
|
||||
long vl1; /*symbol value*/
|
||||
};
|
||||
|
||||
struct symtab *symtptr;
|
||||
# define STESIZE (sizeof *symtptr) /*byte length of symbol table entry*/
|
||||
|
||||
/* flags for symbols*/
|
||||
# define SYDF 0100000 /*defined*/
|
||||
# define SYEQ 0040000 /*equated*/
|
||||
# define SYGL 0020000 /*global - entry or external*/
|
||||
# define SYER 0010000 /*equated register*/
|
||||
# define SYXR 0004000 /*external reference*/
|
||||
# define SYRA 0002000 /*DATA based relocatable*/
|
||||
# define SYRO 0001000 /*TEXT based relocatable*/
|
||||
# define SYBS 0000400 /*BSS based relocatable*/
|
||||
# define SYIN 0000200 /*internal symbol -- opcode, directive or equ*/
|
||||
# define SYPC 0000100 /*[vlh]equated using star '*' expression*/
|
||||
# define SYRM 0000040 /*[vlh]register mask equate*/
|
||||
|
||||
/*flags for opcodes and directives*/
|
||||
# define OPDR 0100000 /*0=>opcode, 1=>directive*/
|
||||
# define OPFF 037 /*type of instruction (used as mask)*/
|
||||
|
||||
struct irts {
|
||||
char *irle; /*ptr to last entry in chain*/
|
||||
char *irfe; /*ptr to first entry in chain*/
|
||||
};
|
||||
|
||||
long stlen; /*length of symbol table*/
|
||||
|
||||
/*
|
||||
* intermediate text file
|
||||
* format of the intermediate text for one statement:
|
||||
*
|
||||
* ******************************************************
|
||||
* * it type = ITBS * # it entries * 0
|
||||
* ******************************************************
|
||||
* * absolute line number (long) *
|
||||
* ******************************************************
|
||||
* * it type = ITSY * instr length * 1
|
||||
* ******************************************************
|
||||
* * symbol table pointer for stmt label (long) *
|
||||
* ******************************************************
|
||||
* * it type = ITSY * instr mode length * 2
|
||||
* ******************************************************
|
||||
* * opcode ptr (long) *
|
||||
* ******************************************************
|
||||
* * it type = ITCN * relocation base * 3
|
||||
* ******************************************************
|
||||
* * location counter (pass 1) *
|
||||
* ******************************************************
|
||||
* * it type * relocation flag * 4 - oprnds
|
||||
* ******************************************************
|
||||
* * value (long) *
|
||||
* ******************************************************
|
||||
* .
|
||||
*
|
||||
* .
|
||||
* ******************************************************
|
||||
* * it type * relocation flag * n - oprnds
|
||||
* ******************************************************
|
||||
* * value (long) *
|
||||
* ******************************************************
|
||||
*/
|
||||
|
||||
#define ITOP1 4 /*first it entry for operands*/
|
||||
|
||||
/*
|
||||
* it type meaning
|
||||
* 0 beginning of statement
|
||||
* 1 value is pointer to symbol table
|
||||
* 2 value is a constant
|
||||
* 3 value is a specal char
|
||||
*
|
||||
* relocation flag for opcode it entry is operand length:
|
||||
* 'b' => byte
|
||||
* 'w' => word
|
||||
* 'l' => long
|
||||
*/
|
||||
|
||||
struct it {
|
||||
char itty; /*it type*/
|
||||
char itrl; /*relocation flag or # it entries*/
|
||||
long itop;
|
||||
};
|
||||
|
||||
int mode; /*operand mode (byte, word, long)*/
|
||||
int modelen; /*operand length per mode*/
|
||||
#define BYTE 'b'
|
||||
#define WORD 'w'
|
||||
#define LONG 'l'
|
||||
|
||||
/* parameters that define the main table*/
|
||||
#define SZMT 300 /*initial size of the main table */
|
||||
/*must be large enough to initialize*/
|
||||
#ifdef PDP11
|
||||
#define ICRSZMT 10 /*add to main table when run out*/
|
||||
#else
|
||||
#define ICRSZMT 50 /*add to main table when run out*/
|
||||
#endif
|
||||
int cszmt; /*current size of main table*/
|
||||
char *bmte; /*beginning of main table*/
|
||||
char *emte; /*end of main table*/
|
||||
|
||||
/* intermediate text types*/
|
||||
#define ITBS 0 /*beginning of statement*/
|
||||
#define ITSY 1 /*pointer to symbol table*/
|
||||
#define ITCN 2 /*constant*/
|
||||
#define ITSP 3 /*special*/
|
||||
#define ITRM 4 /*[vlh]register mask!*/
|
||||
#define ITPC 5 /*[vlh]pc relative argument*/
|
||||
|
||||
# define ITBSZ 256 /*size of the it buffer*/
|
||||
short itbuf[ITBSZ]; /*it buffer*/
|
||||
|
||||
#define STMAX 200 /*size of intermediate text buffer*/
|
||||
struct it stbuf[STMAX]; /*holds it for one statement*/
|
||||
|
||||
char sbuf[512]; /*holds one block of source*/
|
||||
|
||||
/*initial reference table for symbols*/
|
||||
# define SZIRT 128
|
||||
char *sirt[SZIRT];
|
||||
|
||||
/*initial reference table to opcodes*/
|
||||
char *oirt[SZIRT];
|
||||
|
||||
/*external symbol table*/
|
||||
#define EXTSZ 512
|
||||
char *extbl[EXTSZ];
|
||||
int extindx; /*index to external symbol table*/
|
||||
char **pexti; /*ptr to external symbol table*/
|
||||
|
||||
int absln; /*absolute line number*/
|
||||
int p2absln; /*pass 2 line number*/
|
||||
int fcflg; /*0=>passed an item. 1=>first char*/
|
||||
int fchr; /*first char in term*/
|
||||
int ifn; /*source file descriptor*/
|
||||
short *pitix; /*ptr to it buffer*/
|
||||
int itwc; /*number of words in it buffer*/
|
||||
struct it *pitw; /*ptr to it buffer next entry*/
|
||||
int itype; /*type of item*/
|
||||
long ival; /*value of item*/
|
||||
char *lblpt; /*label pointer*/
|
||||
char lbt[NAMELEN]; /*holds label name*/
|
||||
char *lmte; /*last entry in main table*/
|
||||
long loctr; /*location counter*/
|
||||
long savelc[4]; /*save relocation counters for 3 bases*/
|
||||
int nite; /*number of entries in stbuf*/
|
||||
struct it *pnite;
|
||||
int lfn; /*loader output file descriptor*/
|
||||
char *opcpt; /*pointer to opcode entry in main table*/
|
||||
int p2flg; /*0=>pass 1 1=>pass 2*/
|
||||
char **pirt; /*entry in initial reference table*/
|
||||
int reloc; /*relocation value returned by expression evaluator (expr)*/
|
||||
int rlflg; /*relocation value of current location counter*/
|
||||
/*relocation values*/
|
||||
# define ABS 0 /*absolute*/
|
||||
# define DATA 1
|
||||
# define TEXT 2
|
||||
# define BSS 3
|
||||
# define EXTRN 4 /*externally defined*/
|
||||
|
||||
#define EOLC '\n' /*end of line character*/
|
||||
#define EOF 0 /*end of file indicator*/
|
||||
#define NULL 0 /* [vlh] character null '\0' */
|
||||
#define TRUE 1 /* [vlh] boolean values */
|
||||
#define FALSE 0 /* [vlh] boolean values */
|
||||
|
||||
int format;
|
||||
int sbuflen; /*number of chars in sbuf*/
|
||||
char *psbuf; /*ptr into sbuf*/
|
||||
int itfn; /*it file number*/
|
||||
char itfnc; /*last char of it file name*/
|
||||
int trbfn; /*temp for text relocation bits*/
|
||||
char trbfnc; /*last char of text rb file*/
|
||||
int dafn; /*file for data stuff*/
|
||||
char dafnc; /*last char of data file*/
|
||||
int drbfn; /*file for data relocation bits*/
|
||||
char drbfnc; /*last char*/
|
||||
int prtflg; /*print output flag*/
|
||||
int undflg; /*make undefined symbols external flag*/
|
||||
|
||||
int starmul; /* * is multiply operator*/
|
||||
|
||||
char *endptr, *addptr;
|
||||
char *orgptr;
|
||||
char *subptr, *addiptr, *addqptr, *subiptr, *subqptr;
|
||||
char *cmpptr, *addaptr, *cmpaptr, *subaptr, *cmpmptr;
|
||||
char *equptr;
|
||||
char *andptr, *andiptr, *eorptr, *eoriptr, *orptr, *oriptr;
|
||||
char *cmpiptr;
|
||||
char *moveptr, *moveqptr;
|
||||
char *exgptr;
|
||||
char *evenptr;
|
||||
char *jsrptr, *bsrptr, *nopptr;
|
||||
char peekc;
|
||||
int numcon[2], numsym[2], indir[2], immed[2], numreg[2];
|
||||
int plevel; /*parenthesis level counter*/
|
||||
int opdix; /*operand index counter*/
|
||||
int p1inlen; /*pass 1 instr length*/
|
||||
int instrlen; /*pass 2 bytes in current instruction*/
|
||||
|
||||
/* effective address mode bits*/
|
||||
#define DDIR 000
|
||||
#define ADIR 010
|
||||
#define INDIRECT 020
|
||||
#define INDINC 030
|
||||
#define DECIND 040
|
||||
#define INDDISP 050
|
||||
#define INDINX 060
|
||||
#define SADDR 070
|
||||
#define LADDR 071
|
||||
#define IMM 074
|
||||
|
||||
#define AREGLO 8
|
||||
#define AREGHI 15
|
||||
|
||||
/* relocation bit definitions:*/
|
||||
#define RBMASK 07 /*tells type of relocation*/
|
||||
#define INSABS 7 /*first word of instr -- absolute*/
|
||||
#define DABS 0 /*data word absolute*/
|
||||
#define TRELOC 2 /* TEXT relocatable*/
|
||||
#define DRELOC 1 /* DATA relocatable*/
|
||||
#define BRELOC 3 /* BSS relocatable*/
|
||||
#define EXTVAR 4 /* ref to external variable*/
|
||||
#define LUPPER 5 /* upper word of long*/
|
||||
#define EXTREL 6 /* external relative mode*/
|
||||
|
||||
/* ptrs to ins[] and rlbits[]*/
|
||||
int *pins;
|
||||
int *prlb;
|
||||
int ins[5]; /*holds instruction words*/
|
||||
|
||||
#define PRTCHLEN 128
|
||||
char prtchars[PRTCHLEN]; /*line buffer for putchar*/
|
||||
char *prtchidx; /*index for putchar*/
|
||||
|
||||
int extflg, extref; /*external in expr*/
|
||||
|
||||
#define CCR 16
|
||||
#define SR 17
|
||||
#define USP 18
|
||||
#define MOVECCR 042300
|
||||
#define MOVESR 043300
|
||||
#define SRMOVE 040300
|
||||
#define MOVEUSP 047140
|
||||
|
||||
struct op {
|
||||
int ea; /* effective address bits*/
|
||||
int len; /* effective address length in bytes*/
|
||||
long con; /*constant or reloc part of operand*/
|
||||
int drlc; /*reloc of con*/
|
||||
int ext; /*external variable #*/
|
||||
int idx; /*index register if any*/
|
||||
int xmod; /*mode of index reg*/
|
||||
} opnd[2];
|
||||
#define OPSTLEN 10
|
||||
#define TREELEN 20
|
||||
struct buf{
|
||||
int fildes;
|
||||
int nunused;
|
||||
char *xfree;
|
||||
char buff[512];
|
||||
};
|
||||
|
||||
struct buf lbuf;
|
||||
struct buf tbuf;
|
||||
struct buf dabuf;
|
||||
struct buf drbuf;
|
||||
|
||||
int nerror; /*# of assembler errors*/
|
||||
int in_err; /*[vlh] don't generate instrlen err if already err state*/
|
||||
int shortadr; /*short addresses if set*/
|
||||
|
||||
#define CLRFOR 24
|
||||
#define CLRVAL 041000
|
||||
|
||||
long itoffset;
|
||||
|
||||
#define LASTCHTFN *tfilptr
|
||||
char *tfilptr; /* -> Changed filename character */
|
||||
#define PC 22
|
||||
|
||||
int equflg; /*doing an equate stmt*/
|
||||
|
||||
#define ANDI 01000
|
||||
#define AND 0140000
|
||||
#define ORI 0
|
||||
#define OR 0100000
|
||||
#define EORI 05000
|
||||
#define EOR 0130000
|
||||
#define MOVE 0
|
||||
|
||||
long lseek();
|
||||
char *sbrk();
|
||||
char *lemt();
|
||||
|
||||
int refpc; /* * referenced in expr*/
|
||||
#define SOH 1
|
||||
|
||||
/* Conditional Assembly variables and constants [vlh] */
|
||||
#define LOW_CA 21 /* [vlh] */
|
||||
#define HI_CA 30 /* [vlh] */
|
||||
|
||||
int ca_true; /* true unless in a false CA*/
|
||||
int ca; /* depth of conditional assembly, none = 0*/
|
||||
int ca_level; /* at what CA depth did CA go false?*/
|
||||
|
||||
/* pass 1 global variables */
|
||||
int numops; /*number of operands*/
|
||||
int inoffset; /*[vlh]offset directive*/
|
||||
int didorg;
|
||||
int initflg; /*initialize flag*/
|
||||
|
||||
/* defines */
|
||||
#define igblk() while(fchr==' ') fchr=gchr()
|
||||
#define ckein() ((pitw >= pnite))
|
||||
|
||||
/* is it an alterable operand */
|
||||
#define memalt(ap) (memea(ap) && altea(ap))
|
||||
#define dataalt(ap) (dataea(ap) && altea(ap))
|
||||
#define altea(ap) ((((ap)->ea&070)!=SADDR || ((ap)->ea&6)==0))
|
||||
|
||||
/* is it the specific type of operand */
|
||||
#define memea(ap) (((ap)->ea&070) >= INDIRECT)
|
||||
#define dataea(ap) (((ap)->ea&070) != ADIR)
|
||||
#define pcea(ap) ((ap)->ea==072 || (ap)->ea==073)
|
||||
#define ckdreg(ap) ((ap)->ea>=0 && (ap)->ea<AREGLO)
|
||||
#define ckareg(ap) ((ap)->ea>=AREGLO && (ap)->ea<=AREGHI)
|
||||
/*
|
||||
* DRI Listing Hacks:
|
||||
*/
|
||||
char *sfname; /* -> Source file name */
|
||||
#define LPP 58 /* # lines / page */
|
||||
int xline; /* Present line # */
|
||||
int xpage; /* Present Page # */
|
||||
@@ -0,0 +1,222 @@
|
||||
*/*
|
||||
* Copyright 1981
|
||||
* Alcyon Corporation
|
||||
* 8716 Production Ave.
|
||||
* San Diego, Ca. 92121
|
||||
**/
|
||||
R0: .equ 0,r
|
||||
R1: .equ 1,r
|
||||
R2: .equ 2,r
|
||||
R3: .equ 3,r
|
||||
R4: .equ 4,r
|
||||
R5: .equ 5,r
|
||||
R6: .equ 6,r
|
||||
R7: .equ 7,r
|
||||
R8: .equ 8,r
|
||||
R9: .equ 9,r
|
||||
R10: .equ 10,r
|
||||
R11: .equ 11,r
|
||||
R12: .equ 12,r
|
||||
R13: .equ 13,r
|
||||
R14: .equ 14,r
|
||||
R15: .equ 15,r
|
||||
D0: .equ 0,r
|
||||
D1: .equ 1,r
|
||||
D2: .equ 2,r
|
||||
D3: .equ 3,r
|
||||
D4: .equ 4,r
|
||||
D5: .equ 5,r
|
||||
D6: .equ 6,r
|
||||
D7: .equ 7,r
|
||||
A0: .equ @10,r
|
||||
A1: .equ @11,r
|
||||
A2: .equ @12,r
|
||||
A3: .equ @13,r
|
||||
A4: .equ @14,r
|
||||
A5: .equ @15,r
|
||||
A6: .equ @16,r
|
||||
A7: .equ @17,r
|
||||
USP: .equ 18,r
|
||||
SP: .equ 15,r
|
||||
CCR: .equ 16,r
|
||||
SR: .equ 17,r
|
||||
r0: .equ 0,r
|
||||
r1: .equ 1,r
|
||||
r2: .equ 2,r
|
||||
r3: .equ 3,r
|
||||
r4: .equ 4,r
|
||||
r5: .equ 5,r
|
||||
r6: .equ 6,r
|
||||
r7: .equ 7,r
|
||||
r8: .equ 8,r
|
||||
r9: .equ 9,r
|
||||
r10: .equ 10,r
|
||||
r11: .equ 11,r
|
||||
r12: .equ 12,r
|
||||
r13: .equ 13,r
|
||||
r14: .equ 14,r
|
||||
r15: .equ 15,r
|
||||
d0: .equ 0,r
|
||||
d1: .equ 1,r
|
||||
d2: .equ 2,r
|
||||
d3: .equ 3,r
|
||||
d4: .equ 4,r
|
||||
d5: .equ 5,r
|
||||
d6: .equ 6,r
|
||||
d7: .equ 7,r
|
||||
a0: .equ @10,r
|
||||
a1: .equ @11,r
|
||||
a2: .equ @12,r
|
||||
a3: .equ @13,r
|
||||
a4: .equ @14,r
|
||||
a5: .equ @15,r
|
||||
a6: .equ @16,r
|
||||
a7: .equ @17,r
|
||||
usp: .equ 18,r
|
||||
sp: .equ 15,r
|
||||
ccr: .equ 16,r
|
||||
sr: .equ 17,r
|
||||
.b: .equ 19,r
|
||||
.B: .equ 19,r
|
||||
.w: .equ 20,r
|
||||
.W: .equ 20,r
|
||||
.l: .equ 21,r
|
||||
.L: .equ 21,r
|
||||
pc: .equ 22,r
|
||||
PC: .equ 22,r
|
||||
abcd: .opd 4,@140400
|
||||
add: .opd 1,@150000
|
||||
adda: .opd 15,@150000
|
||||
addi: .opd 2,@003000
|
||||
addq: .opd 17,@050000
|
||||
inc: .opd 16,@050000
|
||||
addx: .opd 27,@150400
|
||||
and: .opd 1,@140000
|
||||
andi: .opd 2,@001000
|
||||
asl: .opd 8,@160400
|
||||
asr: .opd 8,@160000
|
||||
bcc: .opd 6,@062000
|
||||
bcs: .opd 6,@062400
|
||||
beq: .opd 6,@063400
|
||||
bze: .opd 6,@063400
|
||||
bge: .opd 6,@066000
|
||||
bgt: .opd 6,@067000
|
||||
bhi: .opd 6,@061000
|
||||
bhis: .opd 6,@062000
|
||||
bhs: .opd 6,@062000
|
||||
ble: .opd 6,@067400
|
||||
blo: .opd 6,@062400
|
||||
bls: .opd 6,@061400
|
||||
blos: .opd 6,@061400
|
||||
blt: .opd 6,@066400
|
||||
bmi: .opd 6,@065400
|
||||
bne: .opd 6,@063000
|
||||
bnz: .opd 6,@063000
|
||||
bpl: .opd 6,@065000
|
||||
bvc: .opd 6,@064000
|
||||
bvs: .opd 6,@064400
|
||||
bchg: .opd 7,@000100
|
||||
bclr: .opd 7,@000200
|
||||
bra: .opd 6,@060000
|
||||
bt: .opd 6,@060000
|
||||
bset: .opd 7,@000300
|
||||
bsr: .opd 6,@060400
|
||||
btst: .opd 7,@000000
|
||||
chk: .opd 26,@040600
|
||||
clr: .opd 24,@041000
|
||||
cmp: .opd 26,@130000
|
||||
cmpa: .opd 15,@130000
|
||||
cmpi: .opd 2,@006000
|
||||
cmpm: .opd 10,@130410
|
||||
dbcc: .opd 11,@052310
|
||||
dbcs: .opd 11,@052710
|
||||
dblo: .opd 11,@052710
|
||||
dbeq: .opd 11,@053710
|
||||
dbze: .opd 11,@053710
|
||||
dbra: .opd 11,@050710
|
||||
dbf: .opd 11,@050710
|
||||
dbge: .opd 11,@056310
|
||||
dbgt: .opd 11,@057310
|
||||
dbhi: .opd 11,@051310
|
||||
dbhs: .opd 11,@051310
|
||||
dble: .opd 11,@057710
|
||||
dbls: .opd 11,@051710
|
||||
dblt: .opd 11,@056710
|
||||
dbmi: .opd 11,@055710
|
||||
dbne: .opd 11,@053310
|
||||
dbnz: .opd 11,@053310
|
||||
dbpl: .opd 11,@055310
|
||||
dbt: .opd 11,@050310
|
||||
dbvc: .opd 11,@054310
|
||||
dbvs: .opd 11,@054710
|
||||
divs: .opd 5,@100700
|
||||
divu: .opd 5,@100300
|
||||
eor: .opd 23,@130000
|
||||
eori: .opd 2,@005000
|
||||
exg: .opd 12,@140400
|
||||
ext: .opd 13,@044000
|
||||
jmp: .opd 9,@047300
|
||||
jsr: .opd 9,@047200
|
||||
illegal:.opd 0,@045374
|
||||
lea: .opd 30,@040700
|
||||
link: .opd 19,@047120
|
||||
lsr: .opd 8,@160010
|
||||
lsl: .opd 8,@160410
|
||||
move: .opd 3,@000000
|
||||
movea: .opd 3,@000100
|
||||
movem: .opd 20,@044200
|
||||
movep: .opd 21,@000010
|
||||
moveq: .opd 22,@070000
|
||||
muls: .opd 5,@140700
|
||||
mulu: .opd 5,@140300
|
||||
nbcd: .opd 25,@044000
|
||||
neg: .opd 24,@042000
|
||||
negx: .opd 24,@040000
|
||||
nop: .opd 0,@047161
|
||||
not: .opd 24,@043000
|
||||
or: .opd 1,@100000
|
||||
ori: .opd 2,@000000
|
||||
pea: .opd 29,@044100
|
||||
reset: .opd 0,@047160
|
||||
rol: .opd 8,@160430
|
||||
ror: .opd 8,@160030
|
||||
roxl: .opd 8,@160420
|
||||
roxr: .opd 8,@160020
|
||||
rte: .opd 0,@047163
|
||||
rtr: .opd 0,@047167
|
||||
rts: .opd 0,@047165
|
||||
sbcd: .opd 4,@100400
|
||||
scc: .opd 25,@052300
|
||||
shs: .opd 25,@052300
|
||||
scs: .opd 25,@052700
|
||||
slo: .opd 25,@052700
|
||||
seq: .opd 25,@053700
|
||||
sze: .opd 25,@053700
|
||||
sf: .opd 25,@050700
|
||||
sge: .opd 25,@056300
|
||||
sgt: .opd 25,@057300
|
||||
shi: .opd 25,@051300
|
||||
sle: .opd 25,@057700
|
||||
sls: .opd 25,@051700
|
||||
slt: .opd 25,@056700
|
||||
smi: .opd 25,@055700
|
||||
sne: .opd 25,@053300
|
||||
snz: .opd 25,@053300
|
||||
spl: .opd 25,@055300
|
||||
st: .opd 25,@050300
|
||||
svc: .opd 25,@054300
|
||||
svs: .opd 25,@054700
|
||||
stop: .opd 14,@047162
|
||||
sub: .opd 1,@110000
|
||||
suba: .opd 15,@110000
|
||||
subi: .opd 2,@002000
|
||||
subq: .opd 17,@050400
|
||||
dec: .opd 16,@050400
|
||||
subx: .opd 27,@110400
|
||||
swap: .opd 28,@044100
|
||||
tas: .opd 25,@045300
|
||||
trap: .opd 18,@047100
|
||||
trapv: .opd 0,@047166
|
||||
tst: .opd 24,@045000
|
||||
unlk: .opd 13,@047130
|
||||
.end
|
||||
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "machine.h"
|
||||
#include "ctype.h"
|
||||
|
||||
#ifdef PDP11
|
||||
struct {
|
||||
char lobyte;
|
||||
char hibyte;
|
||||
};
|
||||
struct {
|
||||
char *ptrw1;
|
||||
char *ptrw2;
|
||||
};
|
||||
struct {
|
||||
int wd1;
|
||||
int wd2;
|
||||
};
|
||||
struct {
|
||||
int swd1;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef MC68000
|
||||
struct {
|
||||
char hibyte;
|
||||
char lobyte;
|
||||
};
|
||||
struct {
|
||||
char *ptrw2;
|
||||
};
|
||||
struct {
|
||||
int wd1;
|
||||
int wd2;
|
||||
};
|
||||
struct {
|
||||
int swd1;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef VAX
|
||||
struct {
|
||||
short wd2;
|
||||
short wd1;
|
||||
};
|
||||
struct {
|
||||
short swd1;
|
||||
};
|
||||
|
||||
struct {
|
||||
char lobyte;
|
||||
char hibyte;
|
||||
};
|
||||
struct {
|
||||
char *ptrw2;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* format of a symbol entry in the main table*/
|
||||
|
||||
# define NAMELEN 8 /*length of name in symbol table*/
|
||||
struct symtab {
|
||||
char name[NAMELEN]; /*symbol name*/
|
||||
int flags; /*bit flags*/
|
||||
char *tlnk; /*table link*/
|
||||
long vl1; /*symbol value*/
|
||||
};
|
||||
|
||||
struct symtab *symtptr;
|
||||
# define STESIZE (sizeof *symtptr) /*byte length of symbol table entry*/
|
||||
|
||||
/* flags for symbols*/
|
||||
# define SYDF 0100000 /*defined*/
|
||||
# define SYEQ 0040000 /*equated*/
|
||||
# define SYGL 0020000 /*global - entry or external*/
|
||||
# define SYER 0010000 /*equated register*/
|
||||
# define SYXR 0004000 /*external reference*/
|
||||
# define SYRA 0002000 /*DATA based relocatable*/
|
||||
# define SYRO 0001000 /*TEXT based relocatable*/
|
||||
# define SYBS 0000400 /*BSS based relocatable*/
|
||||
# define SYIN 0000200 /*internal symbol -- opcode, directive or equ*/
|
||||
# define SYPC 0000100 /*[vlh]equated using star '*' expression*/
|
||||
# define SYRM 0000040 /*[vlh]register mask equate*/
|
||||
|
||||
/*flags for opcodes and directives*/
|
||||
# define OPDR 0100000 /*0=>opcode, 1=>directive*/
|
||||
# define OPFF 037 /*type of instruction (used as mask)*/
|
||||
|
||||
struct irts {
|
||||
char *irle; /*ptr to last entry in chain*/
|
||||
char *irfe; /*ptr to first entry in chain*/
|
||||
};
|
||||
|
||||
long stlen; /*length of symbol table*/
|
||||
|
||||
/*
|
||||
* intermediate text file
|
||||
* format of the intermediate text for one statement:
|
||||
*
|
||||
* ******************************************************
|
||||
* * it type = ITBS * # it entries * 0
|
||||
* ******************************************************
|
||||
* * absolute line number (long) *
|
||||
* ******************************************************
|
||||
* * it type = ITSY * instr length * 1
|
||||
* ******************************************************
|
||||
* * symbol table pointer for stmt label (long) *
|
||||
* ******************************************************
|
||||
* * it type = ITSY * instr mode length * 2
|
||||
* ******************************************************
|
||||
* * opcode ptr (long) *
|
||||
* ******************************************************
|
||||
* * it type = ITCN * relocation base * 3
|
||||
* ******************************************************
|
||||
* * location counter (pass 1) *
|
||||
* ******************************************************
|
||||
* * it type * relocation flag * 4 - oprnds
|
||||
* ******************************************************
|
||||
* * value (long) *
|
||||
* ******************************************************
|
||||
* .
|
||||
* .
|
||||
* .
|
||||
* ******************************************************
|
||||
* * it type * relocation flag * n - oprnds
|
||||
* ******************************************************
|
||||
* * value (long) *
|
||||
* ******************************************************
|
||||
*/
|
||||
|
||||
#define ITOP1 4 /*first it entry for operands*/
|
||||
|
||||
/*
|
||||
* it type meaning
|
||||
* 0 beginning of statement
|
||||
* 1 value is pointer to symbol table
|
||||
* 2 value is a constant
|
||||
* 3 value is a specal char
|
||||
*
|
||||
* relocation flag for opcode it entry is operand length:
|
||||
* 'b' => byte
|
||||
* 'w' => word
|
||||
* 'l' => long
|
||||
*/
|
||||
|
||||
struct it {
|
||||
char itty; /*it type*/
|
||||
char itrl; /*relocation flag or # it entries*/
|
||||
long itop;
|
||||
};
|
||||
|
||||
int mode=0; /*operand mode (byte, word, long)*/
|
||||
int modelen=0; /*operand length per mode*/
|
||||
#define BYTE 'b'
|
||||
#define WORD 'w'
|
||||
#define LONG 'l'
|
||||
|
||||
/* parameters that define the main table*/
|
||||
#define SZMT 300 /*initial size of the main table */
|
||||
/*must be large enough to initialize*/
|
||||
#ifdef PDP11
|
||||
#define ICRSZMT 10 /*add to main table when run out*/
|
||||
#else
|
||||
#define ICRSZMT 50 /*add to main table when run out*/
|
||||
#endif
|
||||
int cszmt=0; /*current size of main table*/
|
||||
char *bmte=0; /*beginning of main table*/
|
||||
char *emte=0; /*end of main table*/
|
||||
|
||||
/* intermediate text types*/
|
||||
#define ITBS 0 /*beginning of statement*/
|
||||
#define ITSY 1 /*pointer to symbol table*/
|
||||
#define ITCN 2 /*constant*/
|
||||
#define ITSP 3 /*special*/
|
||||
#define ITRM 4 /*[vlh]register mask!*/
|
||||
#define ITPC 5 /*[vlh]pc relative argument*/
|
||||
|
||||
# define ITBSZ 256 /*size of the it buffer*/
|
||||
int itbuf[ITBSZ]={0}; /*it buffer*/
|
||||
|
||||
#define STMAX 200 /*size of intermediate text buffer*/
|
||||
struct it stbuf[STMAX]={0}; /*holds it for one statement*/
|
||||
|
||||
char sbuf[512]={0}; /*holds one block of source*/
|
||||
|
||||
/*initial reference table for symbols*/
|
||||
# define SZIRT 128
|
||||
char *sirt[SZIRT]={0};
|
||||
|
||||
/*initial reference table to opcodes*/
|
||||
char *oirt[SZIRT]={0};
|
||||
|
||||
/*external symbol table*/
|
||||
#define EXTSZ 512
|
||||
char *extbl[EXTSZ]={0};
|
||||
int extindx=0; /*index to external symbol table*/
|
||||
char **pexti=0; /*ptr to external symbol table*/
|
||||
|
||||
int absln=0; /*absolute line number*/
|
||||
int p2absln=0; /*pass 2 line number*/
|
||||
int fcflg=0; /*0=>passed an item. 1=>first char*/
|
||||
int fchr=0; /*first char in term*/
|
||||
int ifn=0; /*source file descriptor*/
|
||||
int *pitix=0; /*ptr to it buffer*/
|
||||
int itwc=0; /*number of words in it buffer*/
|
||||
struct it *pitw=0; /*ptr to it buffer next entry*/
|
||||
int itype=0; /*type of item*/
|
||||
long ival=0; /*value of item*/
|
||||
char *lblpt=0; /*label pointer*/
|
||||
char lbt[NAMELEN]={0}; /*holds label name*/
|
||||
char *lmte=0; /*last entry in main table*/
|
||||
long loctr=0; /*location counter*/
|
||||
long savelc[4]={0}; /*save relocation counters for 3 bases*/
|
||||
int nite=0; /*number of entries in stbuf*/
|
||||
struct it *pnite=0;
|
||||
int lfn=0; /*loader output file descriptor*/
|
||||
char *opcpt=0; /*pointer to opcode entry in main table*/
|
||||
int p2flg=0; /*0=>pass 1 1=>pass 2*/
|
||||
char **pirt=0; /*entry in initial reference table*/
|
||||
int reloc=0; /*relocation value returned by expression evaluator (expr)*/
|
||||
int rlflg=0; /*relocation value of current location counter*/
|
||||
/*relocation values*/
|
||||
# define ABS 0 /*absolute*/
|
||||
# define DATA 1
|
||||
# define TEXT 2
|
||||
# define BSS 3
|
||||
# define EXTRN 4 /*externally defined*/
|
||||
|
||||
#define EOLC '\n' /*end of line character*/
|
||||
#define EOF 0 /*end of file indicator*/
|
||||
#define NULL 0 /* [vlh] character null '\0' */
|
||||
#define TRUE 1 /* [vlh] boolean values */
|
||||
#define FALSE 0 /* [vlh] boolean values */
|
||||
|
||||
int format=0;
|
||||
int sbuflen=0; /*number of chars in sbuf*/
|
||||
char *psbuf=0; /*ptr into sbuf*/
|
||||
int itfn=0; /*it file number*/
|
||||
char itfnc=0; /*last char of it file name*/
|
||||
int trbfn=0; /*temp for text relocation bits*/
|
||||
char trbfnc=0; /*last char of text rb file*/
|
||||
int dafn=0; /*file for data stuff*/
|
||||
char dafnc=0; /*last char of data file*/
|
||||
int drbfn=0; /*file for data relocation bits*/
|
||||
char drbfnc=0; /*last char*/
|
||||
int prtflg=0; /*print output flag*/
|
||||
int undflg=0; /*make undefined symbols external flag*/
|
||||
|
||||
int starmul=0; /* * is multiply operator*/
|
||||
|
||||
char *endptr=0, *addptr=0;
|
||||
char *orgptr=0;
|
||||
char *subptr=0, *addiptr=0, *addqptr=0, *subiptr=0, *subqptr=0;
|
||||
char *cmpptr=0, *addaptr=0, *cmpaptr=0, *subaptr=0, *cmpmptr=0;
|
||||
char *equptr=0;
|
||||
char *andptr=0, *andiptr=0, *eorptr=0, *eoriptr=0, *orptr=0, *oriptr=0;
|
||||
char *cmpiptr=0;
|
||||
char *moveptr=0, *moveqptr=0;
|
||||
char *exgptr=0;
|
||||
char *evenptr=0;
|
||||
char *jsrptr=0, *bsrptr=0, *nopptr=0;
|
||||
|
||||
char peekc=0;
|
||||
int numcon[2]=0, numsym[2]=0, indir[2]=0, immed[2]=0, numreg[2]=0;
|
||||
int plevel=0; /*parenthesis level counter*/
|
||||
int opdix=0; /*operand index counter*/
|
||||
int p1inlen=0; /*pass 1 instr length*/
|
||||
int instrlen=0; /*pass 2 bytes in current instruction*/
|
||||
|
||||
/* effective address mode bits*/
|
||||
#define DDIR 000
|
||||
#define ADIR 010
|
||||
#define INDIRECT 020
|
||||
#define INDINC 030
|
||||
#define DECIND 040
|
||||
#define INDDISP 050
|
||||
#define INDINX 060
|
||||
#define SADDR 070
|
||||
#define LADDR 071
|
||||
#define IMM 074
|
||||
|
||||
#define AREGLO 8
|
||||
#define AREGHI 15
|
||||
|
||||
/* relocation bit definitions:*/
|
||||
#define RBMASK 07 /*tells type of relocation*/
|
||||
#define INSABS 7 /*first word of instr -- absolute*/
|
||||
#define DABS 0 /*data word absolute*/
|
||||
#define TRELOC 2 /* TEXT relocatable*/
|
||||
#define DRELOC 1 /* DATA relocatable*/
|
||||
#define BRELOC 3 /* BSS relocatable*/
|
||||
#define EXTVAR 4 /* ref to external variable*/
|
||||
#define LUPPER 5 /* upper word of long*/
|
||||
#define EXTREL 6 /* external relative mode*/
|
||||
|
||||
/* ptrs to ins[] and rlbits[]*/
|
||||
int *pins=0;
|
||||
int *prlb=0;
|
||||
int ins[5]={0}; /*holds instruction words*/
|
||||
|
||||
#define PRTCHLEN 128
|
||||
char prtchars[PRTCHLEN]={0}; /*line buffer for putchar*/
|
||||
char *prtchidx=0; /*index for putchar*/
|
||||
|
||||
int extflg=0, extref=0; /*external in expr*/
|
||||
|
||||
#define CCR 16
|
||||
#define SR 17
|
||||
#define USP 18
|
||||
#define MOVECCR 042300
|
||||
#define MOVESR 043300
|
||||
#define SRMOVE 040300
|
||||
#define MOVEUSP 047140
|
||||
|
||||
struct op {
|
||||
int ea; /* effective address bits*/
|
||||
int len; /* effective address length in bytes*/
|
||||
long con; /*constant or reloc part of operand*/
|
||||
int drlc; /*reloc of con*/
|
||||
int ext; /*external variable #*/
|
||||
int idx; /*index register if any*/
|
||||
int xmod; /*mode of index reg*/
|
||||
} opnd[2]={0};
|
||||
#define OPSTLEN 10
|
||||
#define TREELEN 20
|
||||
struct buf{
|
||||
int fildes;
|
||||
int nunused;
|
||||
char *xfree;
|
||||
char buff[512];
|
||||
};
|
||||
|
||||
struct buf lbuf={0};
|
||||
struct buf tbuf={0};
|
||||
struct buf dabuf={0};
|
||||
struct buf drbuf={0};
|
||||
|
||||
int nerror=0; /*# of assembler errors*/
|
||||
int in_err=0; /*[vlh] don't generate instrlen err if already err state*/
|
||||
int shortadr=0; /*short addresses if set*/
|
||||
|
||||
#define CLRFOR 24
|
||||
#define CLRVAL 041000
|
||||
|
||||
long itoffset=0;
|
||||
|
||||
#define LASTCHTFN tfilname[11]
|
||||
#define PC 22
|
||||
|
||||
int equflg=0; /*doing an equate stmt*/
|
||||
|
||||
#define ANDI 01000
|
||||
#define AND 0140000
|
||||
#define ORI 0
|
||||
#define OR 0100000
|
||||
#define EORI 05000
|
||||
#define EOR 0130000
|
||||
#define MOVE 0
|
||||
|
||||
long lseek();
|
||||
char *sbrk();
|
||||
char *lemt();
|
||||
|
||||
int refpc=0; /* * referenced in expr*/
|
||||
#define SOH 1
|
||||
|
||||
/* Conditional Assembly variables and constants [vlh] */
|
||||
#define LOW_CA 21 /* [vlh] */
|
||||
#define HI_CA 30 /* [vlh] */
|
||||
|
||||
int ca_true=0; /* true unless in a false CA*/
|
||||
int ca=0; /* depth of conditional assembly, none = 0*/
|
||||
int ca_level=0; /* at what CA depth did CA go false?*/
|
||||
|
||||
/* pass 1 global variables */
|
||||
int numops=0; /*number of operands*/
|
||||
int inoffset=0; /*[vlh]offset directive*/
|
||||
int didorg=0;
|
||||
int initflg=0; /*initialize flag*/
|
||||
|
||||
/* defines */
|
||||
#define igblk() while(fchr==' ') fchr=gchr()
|
||||
#define ckein() ((pitw >= pnite))
|
||||
|
||||
/* is it an alterable operand */
|
||||
#define memalt(ap) (memea(ap) && altea(ap))
|
||||
#define dataalt(ap) (dataea(ap) && altea(ap))
|
||||
#define altea(ap) ((((ap)->ea&070)!=SADDR || ((ap)->ea&6)==0))
|
||||
|
||||
/* is it the specific type of operand */
|
||||
#define memea(ap) (((ap)->ea&070) >= INDIRECT)
|
||||
#define dataea(ap) (((ap)->ea&070) != ADIR)
|
||||
#define pcea(ap) ((ap)->ea==072 || (ap)->ea==073)
|
||||
#define ckdreg(ap) ((ap)->ea>=0 && (ap)->ea<AREGLO)
|
||||
#define ckareg(ap) ((ap)->ea>=AREGLO && (ap)->ea<=AREGHI)
|
||||
/*
|
||||
* DRI Listing Hacks:
|
||||
*/
|
||||
char *sfname=0; /* -> Source filename */
|
||||
int xline=0; /* Current line number */
|
||||
int xpage=0; /* Current page number */
|
||||
/*
|
||||
* More Initializations:
|
||||
*/
|
||||
char *tfilname[80] = {0}; /* Temp filename area */
|
||||
char *initfnam[80] = {0}; /* Init filename area */
|
||||
struct it exitm={0};
|
||||
int prcnt=0;
|
||||
int rval=0;
|
||||
int lpflg=0;
|
||||
int lastopr=0;
|
||||
int rlbits[5]={0};
|
||||
int pline=0;
|
||||
int prsp=0;
|
||||
int amode=0;
|
||||
long stlen=0;
|
||||
int udfct=0;
|
||||
int errno=0;
|
||||
int nitleft=0;
|
||||
int hibytflg[4]={0};
|
||||
int hibytw[4]={0};
|
||||
struct it *piop=0;
|
||||
struct it *pitr=0;
|
||||
struct it opstk[OPSTLEN]={0};
|
||||
struct it tree[TREELEN]={0};
|
||||
int chmvq=0;
|
||||
int explmod=0;
|
||||
int ftudp=0;
|
||||
int iop=0;
|
||||
int itr=0;
|
||||
char ldfn[40]={0};
|
||||
int opcval=0;
|
||||
int poslab=0;
|
||||
int symcon=0;
|
||||
char *tfilptr=0;
|
||||
int tlab1=0;
|
||||
#define HDSIZE (sizeof couthd) /**.o file header size*/
|
||||
struct hdr {
|
||||
short ch_magic; /*c.out magic number 060016 = $600E*/
|
||||
long ch_tsize; /*text size*/
|
||||
long ch_dsize; /*data size*/
|
||||
long ch_bsize; /*bss size*/
|
||||
long ch_ssize; /*symbol table size*/
|
||||
long ch_stksize; /*stack size*/
|
||||
long ch_entry; /*entry point*/
|
||||
short ch_rlbflg; /*relocation bits suppressed flag*/
|
||||
} couthd={0};
|
||||
|
||||
#define MAGIC 0x601a /* bra .+26 instruction*/
|
||||
@@ -0,0 +1,13 @@
|
||||
#define HDSIZE (sizeof couthd) /**.o file header size*/
|
||||
struct hdr {
|
||||
short ch_magic; /*c.out magic number 060016 = $600E*/
|
||||
long ch_tsize; /*text size*/
|
||||
long ch_dsize; /*data size*/
|
||||
long ch_bsize; /*bss size*/
|
||||
long ch_ssize; /*symbol table size*/
|
||||
long ch_stksize; /*stack size*/
|
||||
long ch_entry; /*entry point*/
|
||||
short ch_rlbflg; /*relocation bits suppressed flag*/
|
||||
} couthd;
|
||||
|
||||
#define MAGIC 0x601a /* bra .+26 instruction*/
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#)ctype - Aug 13, 1982";
|
||||
|
||||
Standard routines... */
|
||||
|
||||
#define isspace(c) ((c)==32 || (c)==9 || (c)==13 || (c)==10 ||(c)==12)
|
||||
|
||||
#define isupper(c) ((c)<='Z' && (c)>='A')
|
||||
|
||||
#define islower(c) ((c)<='z' && (c)>='a')
|
||||
|
||||
#define isalpha(c) (isupper((c)) || islower((c)))
|
||||
|
||||
#define isdigit(c) ((c)<='9' && (c)>='0')
|
||||
|
||||
#define isascii(c) ((c) < 0200 && (c) >= 0)
|
||||
|
||||
#define isalnum(c) (isalpha((c)) || isdigit((c)))
|
||||
|
||||
#define iscntrl(c) (((c) < 040 || (c) == 0177) && isascii((c)))
|
||||
|
||||
#define isprint(c) ((c) >= 040 && (c) < 0177)
|
||||
|
||||
#define ispunct(c) (!isalnum((c)) && isprint(c))
|
||||
|
||||
#define toupper(c) (islower((c)) ? (c) & ~32 : (c))
|
||||
|
||||
#define tolower(c) (isupper((c)) ? (c) | 32 : (c))
|
||||
|
||||
#define toascii(c) ((c) & 0177)
|
||||
@@ -0,0 +1,12 @@
|
||||
$ set def drb0:[steve.cpm68k.v102a.al40.as68]
|
||||
$ assign drb0:[steve.cpm68k.v102a.al40.oldas68] old
|
||||
$ diff DIR.C old:DIR.C
|
||||
$ diff EXPR.C old:EXPR.C
|
||||
$ diff MAIN.C old:MAIN.C
|
||||
$ diff MISC.C old:MISC.C
|
||||
$ diff PASS1A.C old:PASS1A.C
|
||||
$ diff PASS2.C old:PASS2.C
|
||||
$ diff SYMT.C old:SYMT.C
|
||||
$ diff VERSION.C old:VERSION.C
|
||||
$ diff AS68.H old:AS68.H
|
||||
$ diff COUT.H old:COUT.H
|
||||
@@ -0,0 +1,12 @@
|
||||
$ set def drb0:[steve.cpm68k.v102a.al40.as68]
|
||||
$ assign drb0:[steve.cpm68k.v102.as68] old
|
||||
$ diff DIR.C old:DIR.C
|
||||
$ diff EXPR.C old:EXPR.C
|
||||
$ diff MAIN.C old:MAIN.C
|
||||
$ diff MISC.C old:MISC.C
|
||||
$ diff PASS1A.C old:PASS1A.C
|
||||
$ diff PASS2.C old:PASS2.C
|
||||
$ diff SYMT.C old:SYMT.C
|
||||
$ diff VERSION.C old:VERSION.C
|
||||
$ diff AS68.H old:AS68.H
|
||||
$ diff COUT.H old:COUT.H
|
||||
934
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/as68/dir.c
Normal file
934
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/as68/dir.c
Normal file
@@ -0,0 +1,934 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/* Pass 1 and pass 2 directive handling routines */
|
||||
/* code to handle conditional assembly directives */
|
||||
|
||||
#include "as68.h"
|
||||
#include "cout.h"
|
||||
|
||||
long lseek();
|
||||
int p1gi();
|
||||
int p2gi();
|
||||
int igrst();
|
||||
|
||||
/*directive to define an opcode*/
|
||||
hopd()
|
||||
{
|
||||
|
||||
if(!lbt[0]) {
|
||||
xerr(4); /*no label*/
|
||||
return;
|
||||
}
|
||||
setname(); /*move label into main table*/
|
||||
if((lblpt=lemt(oirt,TRUE))!=lmte) {
|
||||
xerr(5); /*opcode redefined*/
|
||||
return;
|
||||
}
|
||||
mmte(); /*make main table entry*/
|
||||
expr(&p1gi); /*get instruction format*/
|
||||
if(itype!=ITCN || ival<0 || ival>OPFF) {
|
||||
xerr(18); /*illegal format specifier*/
|
||||
return;
|
||||
}
|
||||
lblpt->flags =| ival|SYIN; /*remember format*/
|
||||
if(fchr != ',') { /*field separator*/
|
||||
xerr(10);
|
||||
return;
|
||||
}
|
||||
expr(&p1gi); /*get opcode value*/
|
||||
if(itype != ITCN) {
|
||||
xerr(17); /*not a constant*/
|
||||
return;
|
||||
}
|
||||
lblpt->vl1 = ival; /*put value in main table*/
|
||||
igrst(); /*ignore rest of statement-comment*/
|
||||
}
|
||||
|
||||
/* equate directive*/
|
||||
hequ()
|
||||
{
|
||||
if(lbt[0] == 0) {
|
||||
xerr(4); /*no label*/
|
||||
return;
|
||||
}
|
||||
setname();
|
||||
if((lblpt=lemt(sirt,FALSE))!=lmte) { /*aready there*/
|
||||
if(lbt[0] == '~') { /*local symbol*/
|
||||
lblpt = lmte;
|
||||
mmte();
|
||||
}
|
||||
}
|
||||
else
|
||||
mmte();
|
||||
if(lblpt->flags&SYXR) {
|
||||
xerr(29);
|
||||
return;
|
||||
}
|
||||
lblpt->flags =| SYDF|SYEQ; /*defined & equate*/
|
||||
equflg = 1;
|
||||
modelen = 4;
|
||||
expr(&p1gi);
|
||||
equflg = 0;
|
||||
if(itype == ITSY && ival.ptrw2->flags&SYER) {
|
||||
lblpt->flags =| SYER; /*equated register*/
|
||||
ival = ival.ptrw2->vl1;
|
||||
}
|
||||
else if(itype != ITCN) {
|
||||
xerr(7); /*not a constant*/
|
||||
return;
|
||||
}
|
||||
if (inoffset && reloc != ABS) { /* [vlh] */
|
||||
xerr(11);
|
||||
return;
|
||||
}
|
||||
if(initflg) /*doing symbol table initialization*/
|
||||
lblpt->flags =| SYIN; /*internal symbol*/
|
||||
lblpt->vl1 = ival;
|
||||
if(reloc == DATA) /*check relocation*/
|
||||
{
|
||||
lblpt->flags =| SYRA; /*DATA relocatable*/
|
||||
}
|
||||
else if(reloc == TEXT)
|
||||
lblpt->flags =| SYRO; /*TEXT relocatable*/
|
||||
else if(reloc == BSS)
|
||||
lblpt->flags =| SYBS; /*BSS relocatable*/
|
||||
else if(fchr==',' && (fchr=gchr())=='r')
|
||||
lblpt->flags =| SYER; /*equated register*/
|
||||
if (refpc) /*[vlh] flag directive is pc relative */
|
||||
lblpt->flags =| SYPC;
|
||||
igrst();
|
||||
}
|
||||
|
||||
/* process dsect directive*/
|
||||
hdsect()
|
||||
{
|
||||
dorlst(DATA);
|
||||
}
|
||||
|
||||
dorlst(xrtyp)
|
||||
{
|
||||
inoffset = 0; /* [vlh] offset mode terminated my sect directive */
|
||||
chkeven(); /* May need to make pc even */
|
||||
dlabl(); /*define label on old base if there is one*/
|
||||
savelc[rlflg] = loctr; /*save old base relocation*/
|
||||
rlflg = xrtyp;
|
||||
loctr = savelc[xrtyp]; /*set new base relocation ctr*/
|
||||
opitb();
|
||||
stbuf[0].itrl = itwc;
|
||||
wostb();
|
||||
igrst();
|
||||
}
|
||||
|
||||
/*process psect directive*/
|
||||
hpsect()
|
||||
{
|
||||
dorlst(TEXT);
|
||||
}
|
||||
|
||||
hbss()
|
||||
{
|
||||
dorlst(BSS);
|
||||
}
|
||||
|
||||
/*make pc even*/
|
||||
heven()
|
||||
{
|
||||
modelen = 2; /*Try to figure this one out...*/
|
||||
if(loctr&1) { /*have to make it even*/
|
||||
dorlst(rlflg);
|
||||
}
|
||||
else {
|
||||
igrst();
|
||||
}
|
||||
}
|
||||
|
||||
/*process globl directive*/
|
||||
hent()
|
||||
{
|
||||
while(1) {
|
||||
gterm(TRUE); /*get entry symbol*/
|
||||
if(itype!=ITSY) { /*error if not symbol*/
|
||||
xerr(28);
|
||||
return;
|
||||
}
|
||||
if((lblpt=lemt(sirt,FALSE)) == lmte) /*look up in main table*/
|
||||
mmte(); /*not there, make new entry*/
|
||||
else
|
||||
if(lblpt->flags&SYER) /*already there*/
|
||||
uerr(29);
|
||||
lblpt->flags =| SYGL; /*symbol is an entry*/
|
||||
if(lblpt->flags&SYXR) { /*been thru hext code*/
|
||||
lblpt->flags =& ~(SYXR|SYDF); /*reset for init of .comm*/
|
||||
}
|
||||
if (inoffset && reloc != ABS) { /* [vlh] */
|
||||
xerr(11);
|
||||
return;
|
||||
}
|
||||
if(fchr == ',') /*skip ',' between entries*/
|
||||
fchr = gchr();
|
||||
else {
|
||||
igrst(); /*statement finished*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*process comm directive*/
|
||||
hext()
|
||||
{
|
||||
gterm(TRUE); /*get external symbol*/
|
||||
if(itype!=ITSY) { /*error if not symbol*/
|
||||
xerr(28);
|
||||
return;
|
||||
}
|
||||
if((lblpt=lemt(sirt,FALSE)) == lmte) /*look up in main table*/
|
||||
mmte(); /*not there, make new entry*/
|
||||
else
|
||||
if(lblpt->flags&SYDF && (lblpt->flags&SYXR)==0) /*already there*/
|
||||
uerr(29);
|
||||
lblpt->flags =| SYXR | SYDF; /*symbol is an external*/
|
||||
mkextidx(lblpt); /*put into external table*/
|
||||
if(fchr == ',') { /*skip ',' between operands*/
|
||||
fchr = gchr();
|
||||
gterm(TRUE);
|
||||
if(itype != ITCN) {
|
||||
xerr(17);
|
||||
return;
|
||||
}
|
||||
lblpt->vl1.wd1 = ival; /* # bytes of storage required*/
|
||||
}
|
||||
else
|
||||
lblpt->vl1.wd1 = 1; /* default # bytes*/
|
||||
igrst();
|
||||
}
|
||||
|
||||
mkextidx(p)
|
||||
struct symtab *p;
|
||||
{
|
||||
|
||||
if(extindx >= EXTSZ) { /*check for overflow of external symbol tbl*/
|
||||
rpterr("overflow of external table\n");
|
||||
endit();
|
||||
}
|
||||
p->vl1.wd2 = pexti - extbl; /* external symbol index #*/
|
||||
*pexti++ = p; /*save external in external table*/
|
||||
extindx++;
|
||||
}
|
||||
|
||||
/* end statement*/
|
||||
hend()
|
||||
{
|
||||
register short i;
|
||||
register int j;
|
||||
|
||||
inoffset = 0; /*[vlh] turn off inoffset mode*/
|
||||
lblpt = 0; /*no label*/
|
||||
opitb(); /*output beginning of statement*/
|
||||
igrst(); /* [vlh] ignore operands */
|
||||
stbuf[0].itrl = itwc; /*number of it entries*/
|
||||
wostb(); /*write out statement buffer*/
|
||||
for(i=0; i<ITBSZ; i++)
|
||||
doitwr(0);
|
||||
if(initflg) {
|
||||
putsymtab();
|
||||
printf("68000 assembler initialized\n");
|
||||
endit();
|
||||
}
|
||||
if((fchr=gchr())!=EOF) {
|
||||
rpterr("end statement not at end of source\n");
|
||||
}
|
||||
savelc[rlflg] = loctr; /*last location on current reloc base*/
|
||||
fixunds(); /*make golbals and maybe undefineds external*/
|
||||
if(!didorg) /*did not assign to location counter*/
|
||||
pass1a(); /*resolve short branches*/
|
||||
pass2(); /*assembler pass 2*/
|
||||
}
|
||||
|
||||
/* define storage given number of bytes*/
|
||||
hds()
|
||||
{
|
||||
dlabl(); /*define label maybe*/
|
||||
if (!inoffset) /* [vlh] */
|
||||
opitb(); /*output it for beginning of statement*/
|
||||
refpc = 0;
|
||||
expr(&p1gi);
|
||||
if(itype!=ITCN) {
|
||||
xerr(17); /*must be constant*/
|
||||
return;
|
||||
}
|
||||
if(reloc != ABS) {
|
||||
xerr(9); /*must be absolute*/
|
||||
return;
|
||||
}
|
||||
if (!inoffset) { /* [vlh] don't generate it if in offset */
|
||||
opitoo(); /*output one operand*/
|
||||
stbuf[0].itrl = itwc;
|
||||
wostb(); /*write out statement buffer*/
|
||||
loctr =+ (ival*modelen);
|
||||
}
|
||||
igrst();
|
||||
}
|
||||
|
||||
/* make pc even if necessary for .dc and .ds */
|
||||
chkeven()
|
||||
{
|
||||
register char *pi;
|
||||
|
||||
if(modelen>1 && loctr&1) {
|
||||
pi = opcpt;
|
||||
opcpt = evenptr;
|
||||
opitb();
|
||||
stbuf[0].itrl = itwc;
|
||||
wostb();
|
||||
opcpt = pi;
|
||||
loctr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* define byte directive*/
|
||||
hdc()
|
||||
{
|
||||
chkeven();
|
||||
hdata(modelen);
|
||||
}
|
||||
|
||||
/*
|
||||
* define bytes or words of data
|
||||
* call with:
|
||||
* 1 => defining bytes
|
||||
* 2 => defining words
|
||||
* 4 => defining long words
|
||||
*/
|
||||
hdata(mul)
|
||||
{
|
||||
dlabl(); /*define label*/
|
||||
opitb(); /*beginning of statement*/
|
||||
numops = 0; /*initialize count for number of operands*/
|
||||
opito(); /*output it for operands*/
|
||||
stbuf[0].itrl = itwc; /* # of it entries*/
|
||||
wostb(); /*write out statement buffer*/
|
||||
loctr =+ numops*mul; /* count by bytes or words*/
|
||||
}
|
||||
|
||||
/* handle org statement*/
|
||||
horg()
|
||||
{
|
||||
register i;
|
||||
|
||||
if(rlflg==TEXT && loctr!=0)
|
||||
didorg++; /*can't do branch optimization as separate pass now*/
|
||||
expr(&p1gi); /*value of new relocation counter*/
|
||||
if(reloc != rlflg && reloc != ABS) {
|
||||
xerr(27);
|
||||
return;
|
||||
}
|
||||
if(ival < loctr) {
|
||||
xerr(40); /*trying to go backwards*/
|
||||
return;
|
||||
}
|
||||
opcpt = orgptr; /*org directive for pass 2*/
|
||||
opitb();
|
||||
opitoo();
|
||||
stbuf[0].itrl = itwc;
|
||||
wostb();
|
||||
loctr = ival;
|
||||
dlabl(); /*define label*/
|
||||
}
|
||||
|
||||
/* Assemble for mask2 (R9M), ignore... */
|
||||
hmask2() /* [vlh] */
|
||||
{
|
||||
igrst();
|
||||
}
|
||||
|
||||
/* Define register list */
|
||||
hreg() /* [vlh] */
|
||||
{
|
||||
int mask;
|
||||
if(lbt[0]==0) {
|
||||
xerr(4); /*no label*/
|
||||
return;
|
||||
}
|
||||
setname(); /*move label into main table*/
|
||||
if((lblpt=lemt(sirt,FALSE))!=lmte) {
|
||||
xerr(5); /*opcode redefined*/
|
||||
return;
|
||||
}
|
||||
if (inoffset)
|
||||
if (reloc != ABS) {
|
||||
xerr(11);
|
||||
return;
|
||||
}
|
||||
mmte(); /*make main table entry*/
|
||||
if ((mask = mkmask()) == -1) {
|
||||
xerr(6);
|
||||
return;
|
||||
}
|
||||
lblpt->flags =| SYDF|SYEQ|SYRM; /* register mask, defined & equated */
|
||||
lblpt->vl1 = mask;
|
||||
igrst();
|
||||
}
|
||||
|
||||
int regmsk[] {0100000,040000,020000,010000,04000,02000,01000,0400,0200,
|
||||
0100,040,020,010,4,2,1};
|
||||
/* make a register mask for the reg routine */
|
||||
mkmask() /* [vlh] */
|
||||
{
|
||||
register int *p, i, j, mask;
|
||||
|
||||
p = ®msk; mask = 0;
|
||||
while ((i = chkreg()) != -1) {
|
||||
if (fchr == '-') {
|
||||
fchr = gchr();
|
||||
if ((j = chkreg()) == -1) {
|
||||
xerr(40);
|
||||
return(-1);
|
||||
}
|
||||
while (i <= j)
|
||||
mask =| p[i++];
|
||||
}
|
||||
else mask =| p[i];
|
||||
if (fchr != '/' && fchr != ',') break; /*[vlh] Signetics fix*/
|
||||
fchr = gchr();
|
||||
}
|
||||
return(mask);
|
||||
}
|
||||
|
||||
/* get a register # from file, return -1 if none or illegal */
|
||||
chkreg() /* [vlh] */
|
||||
{
|
||||
register int i, j;
|
||||
|
||||
i = j = 0;
|
||||
if (fchr == 'a' || fchr == 'A')
|
||||
i = 8;
|
||||
else if (fchr != 'd' && fchr != 'r' && fchr != 'D' && fchr != 'R')
|
||||
return(-1);
|
||||
fchr = gchr();
|
||||
do {
|
||||
j = (j*10) + (fchr - '0');
|
||||
fchr = gchr();
|
||||
} while (isdigit(fchr));
|
||||
if (j < 0 || j > AREGHI) return(-1);
|
||||
i =+ j;
|
||||
if (i >= 0 && i <= AREGHI) return(i);
|
||||
else return(-1);
|
||||
}
|
||||
|
||||
/* Define constant block */
|
||||
hdcb() /* [vlh] */
|
||||
{
|
||||
chkeven(); /* on even boundary if not byte block. */
|
||||
dlabl(); /* define label... */
|
||||
opitb();
|
||||
opito();
|
||||
stbuf[0].itrl = itwc;
|
||||
numops = stbuf[ITOP1].itop;
|
||||
loctr =+ numops * modelen;
|
||||
wostb(); /* write out statement buffer */
|
||||
}
|
||||
|
||||
/* Command line, similar to ds.b */
|
||||
hcomline() /* [vlh] */
|
||||
{
|
||||
dlabl(); /*define label maybe*/
|
||||
modelen = 1; /* byte store... */
|
||||
opitb(); /*output it for beginning of statement*/
|
||||
refpc = 0;
|
||||
expr(&p1gi);
|
||||
if(itype!=ITCN) {
|
||||
xerr(17); /*must be constant*/
|
||||
return;
|
||||
}
|
||||
if(reloc != ABS) {
|
||||
xerr(9); /*must be absolute*/
|
||||
return;
|
||||
}
|
||||
opitoo(); /*output one operand*/
|
||||
stbuf[0].itrl = itwc;
|
||||
wostb(); /*write out statement buffer*/
|
||||
loctr =+ ival;
|
||||
igrst();
|
||||
}
|
||||
|
||||
/* Relocateable id record, ignore */
|
||||
hidnt() /* [vlh] */
|
||||
{
|
||||
igrst();
|
||||
}
|
||||
|
||||
/* Define offsets */
|
||||
hoffset() /* [vlh] */
|
||||
{
|
||||
inoffset = 1;
|
||||
expr(&p1gi); /* get new location counter */
|
||||
if (itype != ITCN) {
|
||||
xerr(17); /* constant required */
|
||||
return;
|
||||
}
|
||||
if (reloc != ABS) {
|
||||
xerr(9); /* must be absolute */
|
||||
return;
|
||||
}
|
||||
loctr = ival;
|
||||
igrst();
|
||||
}
|
||||
|
||||
/* define sections: map to bss, text and data */
|
||||
hsection() /* [vlh] */
|
||||
{
|
||||
inoffset = 0; /* reseting section turns off offset mode */
|
||||
dlabl(); /* define label on old base if there is one */
|
||||
savelc[rlflg] = loctr; /* save old base relocation */
|
||||
opitb(); /* intermediate table... */
|
||||
expr(&p1gi); /* get section # */
|
||||
if (itype != ITCN) {
|
||||
xerr(17); /* must be a constant */
|
||||
return;
|
||||
}
|
||||
if (ival > 15 || ival < 0) {
|
||||
xerr(9); /* proper range 0..15 */
|
||||
return;
|
||||
}
|
||||
if (ival==14) rlflg = DATA;
|
||||
else if (ival==15) rlflg = BSS;
|
||||
else rlflg = TEXT;
|
||||
loctr = savelc[rlflg];
|
||||
stbuf[3].itop = loctr; /* pass 1 location counter */
|
||||
stbuf[3].itrl = rlflg; /* relocation base */
|
||||
stbuf[0].itrl = itwc;
|
||||
wostb();
|
||||
igrst();
|
||||
}
|
||||
|
||||
/* hopt -- ignore, set up assembler options */
|
||||
hopt() /* vlh */
|
||||
{
|
||||
igrst();
|
||||
}
|
||||
|
||||
/**** Second pass directive handling routines ****/
|
||||
|
||||
/* second pass end statement*/
|
||||
send()
|
||||
{
|
||||
register int i;
|
||||
|
||||
savelc[rlflg] = loctr;
|
||||
if(savelc[TEXT]&1) {
|
||||
rlflg = TEXT;
|
||||
outbyte(0,DABS);
|
||||
savelc[TEXT]++;
|
||||
}
|
||||
if(savelc[DATA]&1) {
|
||||
rlflg = DATA;
|
||||
outbyte(0,DABS);
|
||||
savelc[DATA]++;
|
||||
}
|
||||
if(savelc[BSS]&1) {
|
||||
savelc[BSS]++;
|
||||
}
|
||||
|
||||
ival = 0;
|
||||
reloc = ABS;
|
||||
ckeop(9);
|
||||
print(0);
|
||||
cpdata(); /*copy data to loader file*/
|
||||
osymt(); /*output symbol table*/
|
||||
myfflush(&tbuf); /*flush text relocation bits*/
|
||||
cprlbits(); /*copy relocation bits*/
|
||||
myfflush(&lbuf);
|
||||
i = (sizeof couthd.ch_magic) + 3*(sizeof couthd.ch_tsize);
|
||||
if((lseek(lfn,(long)i,0) == -1) || write(lfn,&stlen,4) != 4)
|
||||
rpterr("I/O error on loader output file\n");
|
||||
endit(); /*end*/
|
||||
}
|
||||
|
||||
/*second pass define storage - ds*/
|
||||
sds()
|
||||
{
|
||||
print(0);
|
||||
if(rlflg == TEXT || rlflg==DATA) {
|
||||
expr(&p2gi);
|
||||
if(itype != ITCN) {
|
||||
uerr(13);
|
||||
return;
|
||||
}
|
||||
ival =* modelen;
|
||||
while(ival) {
|
||||
outbyte(0,DABS);
|
||||
loctr++;
|
||||
ival--;
|
||||
}
|
||||
}
|
||||
else
|
||||
loctr =+ stbuf[ITOP1].itop*modelen; /*reserve storage*/
|
||||
}
|
||||
|
||||
/* second pass - define block storage, initialized */
|
||||
sdcb() /* [vlh] */
|
||||
{
|
||||
register int pfg, i, hflg, len;
|
||||
|
||||
expr(&p2gi);
|
||||
if (itype != ITCN || reloc != ABS) {
|
||||
uerr(13); /* must be absolute constant */
|
||||
return;
|
||||
}
|
||||
len = ival;
|
||||
expr(&p2gi);
|
||||
if (modelen==1 && (ival<-128 || ival>=256 || reloc != ABS)) {
|
||||
uerr(20);
|
||||
ival = 0;
|
||||
reloc = ABS;
|
||||
}
|
||||
while (len--) {
|
||||
if (modelen==1) {
|
||||
if (!hflg) {
|
||||
ins[i].hibyte = ival;
|
||||
outbyte(ival.wd2,DABS);
|
||||
hflg++;
|
||||
}
|
||||
else {
|
||||
ins[i++].lobyte = ival;
|
||||
outbyte(ival.wd2,DABS);
|
||||
hflg=0;
|
||||
}
|
||||
goto sdbl2;
|
||||
}
|
||||
else if (modelen==2) {
|
||||
sdbl1:
|
||||
ins[i++] = ival.wd2;
|
||||
outword(ival.wd2, reloc);
|
||||
sdbl2:
|
||||
if (i>3) {
|
||||
instrlen = i*2;
|
||||
print ((pfg++) ? 2 : 1);
|
||||
loctr =+ instrlen;
|
||||
i=0;
|
||||
}
|
||||
}
|
||||
else { /* long word... */
|
||||
ins[i++] = ival.wd1;
|
||||
outword(ival.wd1,LUPPER);
|
||||
goto sdbl1;
|
||||
}
|
||||
}
|
||||
if (i) { /* more printing */
|
||||
instrlen = i*2 - hflg;
|
||||
print ((pfg) ? 2 : 1);
|
||||
loctr =+ instrlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*second pass data*/
|
||||
sdsect()
|
||||
{
|
||||
savelc[rlflg] = loctr;
|
||||
rlflg = DATA;
|
||||
loctr = savelc[DATA];
|
||||
print(0); /*print the new location counter*/
|
||||
}
|
||||
|
||||
/*second pass text*/
|
||||
spsect()
|
||||
{
|
||||
savelc[rlflg] = loctr;
|
||||
rlflg = TEXT;
|
||||
loctr = savelc[TEXT];
|
||||
print(0); /*print the new location counter*/
|
||||
}
|
||||
|
||||
sbss()
|
||||
{
|
||||
savelc[rlflg] = loctr;
|
||||
rlflg = BSS;
|
||||
loctr = savelc[BSS];
|
||||
print(0); /*print the new location counter*/
|
||||
}
|
||||
|
||||
/* make loctr even*/
|
||||
seven()
|
||||
{
|
||||
if(loctr&1) {
|
||||
if(rlflg==TEXT || rlflg==DATA)
|
||||
outbyte(0,DABS);
|
||||
loctr++;
|
||||
}
|
||||
print(0);
|
||||
}
|
||||
|
||||
/* second pass org*/
|
||||
sorg()
|
||||
{
|
||||
long l;
|
||||
|
||||
if(rlflg==TEXT || rlflg==DATA) { /*must put out zeros*/
|
||||
l = stbuf[ITOP1].itop - loctr; /*# zeroes to output*/
|
||||
ins[0] = 0;
|
||||
print(1);
|
||||
while(l > 0) {
|
||||
outbyte(0,DABS);
|
||||
loctr++;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
else { /*BSS*/
|
||||
loctr = stbuf[ITOP1].itop; /*new location counter*/
|
||||
print(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*second pass define data (words or bytes)
|
||||
* call with
|
||||
* 2 => defining words
|
||||
* 1 => defining bytes
|
||||
* 4 => defining long words
|
||||
*/
|
||||
sdata(dtyp)
|
||||
{
|
||||
register pfg,i;
|
||||
register hflg;
|
||||
|
||||
hflg = i = pfg = 0;
|
||||
while(1) {
|
||||
expr(&p2gi); /*evaluate expression*/
|
||||
if(pitw < pnite)
|
||||
pitw--; /*expr passed a token*/
|
||||
if(itype!=ITCN && reloc != EXTRN) { /*must be constant*/
|
||||
uerr(13);
|
||||
ival=0;
|
||||
reloc = ABS;
|
||||
}
|
||||
if(reloc == EXTRN)
|
||||
reloc = (extref<<3)|EXTVAR; /*gen extern reference*/
|
||||
if(dtyp==1) { /*defining a byte*/
|
||||
if(ival<-128 || ival>=256 || reloc!=ABS) { /*not a byte*/
|
||||
uerr(20);
|
||||
ival=0;
|
||||
reloc = ABS;
|
||||
}
|
||||
if(!hflg) {
|
||||
ins[i].hibyte = ival;
|
||||
outbyte(ival.wd2,DABS);
|
||||
hflg++;
|
||||
}
|
||||
else {
|
||||
ins[i++].lobyte = ival;
|
||||
hflg = 0;
|
||||
outbyte(ival.wd2,DABS);
|
||||
}
|
||||
goto sdal2;
|
||||
}
|
||||
else if(dtyp == 2) { /*defining a word*/
|
||||
sdal1:
|
||||
ins[i++] = ival.wd2;
|
||||
outword(ival.wd2, reloc);
|
||||
sdal2:
|
||||
if(i>3) {
|
||||
instrlen = i*2;
|
||||
print ((pfg++) ? 2 : 1);
|
||||
loctr =+ instrlen;
|
||||
i=0;
|
||||
}
|
||||
}
|
||||
else { /*long words*/
|
||||
ins[i++] = ival.wd1;
|
||||
outword(ival.wd1,LUPPER);
|
||||
goto sdal1;
|
||||
}
|
||||
if(!ckeop(15)) /*should be end of operand*/
|
||||
return;
|
||||
pitw++;
|
||||
if(ckein()) {
|
||||
if(hflg) {
|
||||
ins[i++].lobyte = 0;
|
||||
}
|
||||
if(i) { /*more printing*/
|
||||
instrlen = i*2 - hflg;
|
||||
print ((pfg) ? 2 : 1);
|
||||
loctr =+ instrlen;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sdc()
|
||||
{
|
||||
sdata(modelen);
|
||||
}
|
||||
|
||||
ssection() /* [vlh] */
|
||||
{
|
||||
int sect;
|
||||
|
||||
sect = stbuf[3].itrl;
|
||||
if (sect==DATA) sdsect();
|
||||
else if (sect==BSS) sbss();
|
||||
else spsect();
|
||||
}
|
||||
|
||||
/*define word statement*/
|
||||
sdw()
|
||||
{
|
||||
sdata(0); /*defining words*/
|
||||
}
|
||||
/**** Conditional assembly directives ****/
|
||||
|
||||
hifeq() /* [vlh] */
|
||||
{
|
||||
if (!acok()) return;
|
||||
if (ival) {
|
||||
if (ca_true) ca_level = ca;
|
||||
ca_true = 0;
|
||||
}
|
||||
ca++;
|
||||
}
|
||||
|
||||
hifne() /* [vlh] */
|
||||
{
|
||||
if (!acok()) return;
|
||||
if (!ival) {
|
||||
if (ca_true) ca_level = ca;
|
||||
ca_true = 0;
|
||||
}
|
||||
ca++;
|
||||
}
|
||||
|
||||
hiflt() /* [vlh] */
|
||||
{
|
||||
if (!acok()) return;
|
||||
if (ival >= 0) {
|
||||
if (ca_true) ca_level = ca;
|
||||
ca_true = 0;
|
||||
}
|
||||
ca++;
|
||||
}
|
||||
|
||||
hifle() /* [vlh] */
|
||||
{
|
||||
if (!acok()) return;
|
||||
if (ival > 0) {
|
||||
if (ca_true) ca_level = ca;
|
||||
ca_true = 0;
|
||||
}
|
||||
ca++;
|
||||
}
|
||||
|
||||
hifgt() /* [vlh] */
|
||||
{
|
||||
if (!acok()) return;
|
||||
if (ival <= 0) {
|
||||
if (ca_true) ca_level = ca;
|
||||
ca_true = 0;
|
||||
}
|
||||
ca++;
|
||||
}
|
||||
|
||||
hifge() /* [vlh] */
|
||||
{
|
||||
if (!acok()) return;
|
||||
if (ival < 0) {
|
||||
if (ca_true) ca_level = ca;
|
||||
ca_true = 0;
|
||||
}
|
||||
ca++;
|
||||
}
|
||||
|
||||
hifc() /* [vlh] */
|
||||
{
|
||||
if (!cmp_ops()) {
|
||||
if (ca_true) ca_level = ca;
|
||||
ca_true = 0;
|
||||
}
|
||||
ca++;
|
||||
}
|
||||
|
||||
hifnc() /* [vlh] */
|
||||
{
|
||||
if (cmp_ops()) {
|
||||
if (ca_true) ca_level = ca;
|
||||
ca_true = 0;
|
||||
}
|
||||
ca++;
|
||||
}
|
||||
|
||||
hendc() /* [vlh] */
|
||||
{
|
||||
if (!ca) {
|
||||
xerr(25); /* unexpected endc */
|
||||
return;
|
||||
}
|
||||
ca--;
|
||||
if (!ca_true)
|
||||
if (ca_level == ca) ca_true = 1;
|
||||
igrst();
|
||||
}
|
||||
hpage()
|
||||
{
|
||||
opitb(); /* Output beginning */
|
||||
wostb(); /* Write out buffer */
|
||||
igrst(); /* Ignore rest of line */
|
||||
}
|
||||
spage()
|
||||
{
|
||||
print(0); /* Print the directive */
|
||||
xline = LPP; /* Force page on next print */
|
||||
page();
|
||||
}
|
||||
acok()
|
||||
{
|
||||
expr(&p1gi);
|
||||
if (itype != ITCN) {
|
||||
xerr(7); /* must be a constant */
|
||||
return(0);
|
||||
}
|
||||
if (reloc != ABS) {
|
||||
xerr(11); /* must be absolute, no forward references */
|
||||
return(0);
|
||||
}
|
||||
igrst();
|
||||
return(1);
|
||||
}
|
||||
|
||||
cmp_ops()
|
||||
{
|
||||
char str1[25], str2[25];
|
||||
register int len1, len2;
|
||||
|
||||
if (fchr != '\'') { xerr(9); return(0); }
|
||||
len1 = len2 = 0;
|
||||
while (fchr = gchr()) {
|
||||
if (fchr == '\'') break;
|
||||
if (fchr == EOLC) return(0);
|
||||
str1[len1++] = fchr;
|
||||
}
|
||||
if ((fchr=gchr()) != ',') { xerr(9); return; }
|
||||
if ((fchr=gchr()) != '\'') { xerr(10); return;}
|
||||
while (fchr = gchr()) {
|
||||
if (fchr == '\'') break;
|
||||
if (fchr == EOLC) return(0);
|
||||
str2[len2++] = fchr;
|
||||
}
|
||||
igrst();
|
||||
if (len1 != len2) return(0);
|
||||
str1[len1] = str2[len2] = NULL;
|
||||
if (strcmp(str1,str2) == 0) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
strcmp(s,t)
|
||||
register char *s, *t;
|
||||
{
|
||||
for( ; *s == *t; s++, t++ )
|
||||
if( *s == '\0' )
|
||||
return(0);
|
||||
return( *s - *t );
|
||||
}
|
||||
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/* Expression evaluator */
|
||||
|
||||
# include "as68.h"
|
||||
|
||||
/*precedence of operators*/
|
||||
# define PAO 2 /*AND, OR*/
|
||||
# define PPM 2 /*+ -*/
|
||||
# define PMD 3 /** /*/
|
||||
# define PLP 1 /* (*/
|
||||
# define PRP 4 /* )*/
|
||||
# define PEE 0 /* all other special chars*/
|
||||
|
||||
|
||||
/*global integers for this package*/
|
||||
struct it exitm; /*expression item*/
|
||||
int prcnt; /*paren count*/
|
||||
int rval; /*relocation value*/
|
||||
int lpflg;
|
||||
int lastopr; /*last token was operator when set*/
|
||||
|
||||
long gval(); /*get operand value*/
|
||||
|
||||
/*
|
||||
* expression evaluator
|
||||
* call with:
|
||||
* address of function to get input
|
||||
* returns:
|
||||
* item type in itype
|
||||
* item value in ival
|
||||
* relocation flag in reloc:
|
||||
* 0 => absolute
|
||||
* 1 => data
|
||||
* 2 => text
|
||||
* 3 => bss
|
||||
* 4 => external
|
||||
*
|
||||
* The only expressions involving externals which are legal are
|
||||
* external+constant or external-constant
|
||||
*/
|
||||
|
||||
struct it *piop, *pitr;
|
||||
int iop, itr;
|
||||
|
||||
struct it opstk[OPSTLEN]; /*operator stack*/
|
||||
struct it tree[TREELEN]; /*operand stack*/
|
||||
|
||||
expr(iploc)
|
||||
int (*iploc)();
|
||||
{
|
||||
register int i, ipr;
|
||||
|
||||
extflg = starmul = iop = lpflg = 0;
|
||||
piop = &opstk[0];
|
||||
itr = -1; /*tree stack pointer*/
|
||||
pitr = &tree[0];
|
||||
pitr--;
|
||||
/* form end of expression operator*/
|
||||
opstk[0].itty = ITSP; /*special character*/
|
||||
opstk[0].itop.wd2 = '?';
|
||||
lastopr = 1;
|
||||
|
||||
/* get an input item*/
|
||||
while(1) {
|
||||
if(itr >= TREELEN-2) {
|
||||
rpterr("expr tree overflow\n");
|
||||
abort();
|
||||
}
|
||||
if(iop >= OPSTLEN-1) {
|
||||
rpterr("expr opstk overflow\n");
|
||||
abort();
|
||||
}
|
||||
(*iploc)(); /*get an input term*/
|
||||
if (itype==ITPC) return;
|
||||
starmul=0; /* * is location counter*/
|
||||
|
||||
/* special character*/
|
||||
if(itype==ITSP) {
|
||||
ipr = gprc(i=ival.wd2); /*get precedence of character*/
|
||||
if(ipr==PEE) /*end of expression*/
|
||||
break;
|
||||
lastopr = 1;
|
||||
if(ipr==PLP) { /*left paren*/
|
||||
lpflg++;
|
||||
prcnt++;
|
||||
iop++; /*up stack pointer*/
|
||||
piop++;
|
||||
piop->swd1=exitm.swd1; /*put operator on stack*/
|
||||
piop->itop=exitm.itop;
|
||||
continue;
|
||||
}
|
||||
if(ipr==PRP) { /*right paren*/
|
||||
if(lpflg) { exerr(1); return; }
|
||||
starmul = 1; /* * is multiply*/
|
||||
prcnt--; /*down one level*/
|
||||
|
||||
while (piop->itop != '(') { /* top stk is '(' */
|
||||
itr++; /*up tree pointer*/
|
||||
pitr++;
|
||||
pitr->swd1 = piop->swd1; /*move operator*/
|
||||
pitr->itop = piop->itop;
|
||||
iop--; /*reduce operand stack*/
|
||||
piop--;
|
||||
}
|
||||
iop--; /*remove stack*/
|
||||
piop--;
|
||||
continue;
|
||||
}
|
||||
|
||||
while(ipr<=gprc(i=piop->itop.wd2)) { /* >= precedence */
|
||||
itr++;
|
||||
pitr++;
|
||||
pitr->swd1 = piop->swd1; /*move operator*/
|
||||
pitr->itop = piop->itop;
|
||||
iop--; /*reduce operand stack*/
|
||||
piop--;
|
||||
}
|
||||
iop++; /*up operator stack*/
|
||||
piop++;
|
||||
piop->swd1 = exitm.swd1; /*put in operator stack*/
|
||||
piop->itop = exitm.itop;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* symbol or constant*/
|
||||
else {
|
||||
lastopr = lpflg = 0; /*clear flag*/
|
||||
itr++; /*up tree pointer*/
|
||||
pitr++;
|
||||
pitr->swd1 = exitm.swd1; /*put in tree*/
|
||||
pitr->itop = exitm.itop;
|
||||
starmul = 1; /* * is multiply*/
|
||||
continue;
|
||||
}
|
||||
} /* end while(1)... */
|
||||
|
||||
/*output the rest of the operator stack to the tree*/
|
||||
for(i=iop; i>=0; i--) {
|
||||
itr++;
|
||||
pitr++;
|
||||
pitr->swd1 = piop->swd1; /*move operator*/
|
||||
pitr->itop = piop->itop;
|
||||
piop--;
|
||||
}
|
||||
|
||||
collapse();
|
||||
}
|
||||
|
||||
/* collapse the tree into one entry*/
|
||||
collapse()
|
||||
{
|
||||
register int rv1, rv2, topr, i, bos;
|
||||
register long tv1, tv2;
|
||||
|
||||
bos = 0;
|
||||
exct1:
|
||||
if(itr>=3) {
|
||||
piop = &tree[bos];
|
||||
iop = bos;
|
||||
while (iop<=(itr-3+bos) && (piop->itty==ITSP ||
|
||||
(piop+1)->itty==ITSP || (piop+2)->itty!=ITSP)) {
|
||||
iop++;
|
||||
piop++;
|
||||
}
|
||||
if (iop<=(itr-3+bos)) {
|
||||
tv1 = gval(piop); /*get value of first operand*/
|
||||
rv1 = rval; /*relocation value*/
|
||||
tv2 = gval(piop+1);
|
||||
rv2 = rval;
|
||||
topr = (piop+2)->itop; /*operator*/
|
||||
|
||||
/* handle operators */
|
||||
if (topr == '+') {
|
||||
tv1=+ tv2;
|
||||
rv1 = ckrl1(rv1,rv2); /*relocation*/
|
||||
}
|
||||
else if (topr == '-') {
|
||||
tv1 =- tv2;
|
||||
rv1 = ckrl2(rv1,rv2); /*relocation*/
|
||||
}
|
||||
else {
|
||||
switch(topr) { /*operator*/
|
||||
case '/': /* division */
|
||||
tv1 =/ tv2; break;
|
||||
case '*': /* multiplication */
|
||||
tv1 =* tv2; break;
|
||||
case '&': /* logical and */
|
||||
tv1 =& tv2; break;
|
||||
case '!': /* logical or */
|
||||
tv1 =| tv2; break;
|
||||
case '<': /* left shift */
|
||||
tv1 =<< tv2.wd2; break;
|
||||
case '>': /* right shift */
|
||||
tv1 =>> tv2.wd2; break;
|
||||
default: /*invalid operator*/
|
||||
exerr(2); return;
|
||||
}
|
||||
rv1 = ckrl3(rv1,rv2); /* relocation */
|
||||
}
|
||||
|
||||
/*put new value in tree*/
|
||||
if (iop==bos) {
|
||||
bos =+ 2;
|
||||
iop = bos;
|
||||
}
|
||||
piop = &tree[iop];
|
||||
piop->itty = ITCN; /*must be constant*/
|
||||
piop->itop = tv1; /*value*/
|
||||
piop->itrl = rv1; /*relocation value*/
|
||||
|
||||
if (iop != bos) { /* push up the rest of the tree... */
|
||||
i = iop + 2 - bos;
|
||||
pitr = piop+2;
|
||||
for(; i<itr; i++) {
|
||||
piop++;
|
||||
pitr++;
|
||||
piop->swd1 = pitr->swd1;
|
||||
piop->itop = pitr->itop;
|
||||
}
|
||||
}
|
||||
itr =- 2;
|
||||
goto exct1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for unary minus and unary plus*/
|
||||
if (tree[bos+1].itty!=ITSP && tree[bos].itop.wd2=='?')
|
||||
{ exerr(3); return; }
|
||||
if (tree[bos+1].itty!=ITSP || tree[bos].itty==ITSP) {
|
||||
reloc = ABS;
|
||||
ival = 0;
|
||||
itype = ITCN;
|
||||
return;
|
||||
}
|
||||
|
||||
if(tree[bos+1].itop.wd2!='?') { /*end of statement*/
|
||||
if(tree[bos+1].itop.wd2!='+') { /*ignore unary plus*/
|
||||
if(tree[bos+1].itop.wd2!='-') { /* invalid operator */
|
||||
exerr(4);
|
||||
return;
|
||||
}
|
||||
tree[bos+1].itop = -gval(&tree[bos]);
|
||||
tree[bos+1].itty = ITCN;
|
||||
tree[bos+1].itrl = tree[bos].itrl;
|
||||
bos++;
|
||||
itr--;
|
||||
goto exct1;
|
||||
}
|
||||
}
|
||||
/* send results back to caller*/
|
||||
if ((itype = tree[bos].itty)==ITCN)
|
||||
ival = gval(&tree[bos]);
|
||||
else {
|
||||
ival = tree[bos].itop;
|
||||
if(itype==ITSY && !(ival.ptrw2->flags&SYDF)) { /*undef symbol*/
|
||||
reloc = ABS;
|
||||
ival = 0;
|
||||
itype = ITCN;
|
||||
return;
|
||||
}
|
||||
}
|
||||
get_val(tree[bos].itrl);
|
||||
}
|
||||
|
||||
/*
|
||||
*if defined symbol get value and say constant
|
||||
* except for externals and equated registers
|
||||
*/
|
||||
get_val(reloc_val)
|
||||
int reloc_val;
|
||||
{
|
||||
if(itype==ITSY && (ival.ptrw2->flags&(SYXR|SYER))==0) {
|
||||
if(ival.ptrw2->flags&SYRA) /*get symbol relocation factor*/
|
||||
reloc = DATA;
|
||||
else if(ival.ptrw2->flags&SYRO)
|
||||
reloc = TEXT;
|
||||
else if(ival.ptrw2->flags&SYBS)
|
||||
reloc = BSS;
|
||||
else reloc = ABS;
|
||||
ival = ival.ptrw2->vl1; /*symbol vaue*/
|
||||
itype = ITCN; /*constant*/
|
||||
}
|
||||
else
|
||||
if(itype == ITSY && ival.ptrw2->flags&SYXR) { /*external symbol*/
|
||||
fixext(ival.ptrw2);
|
||||
reloc = EXTRN;
|
||||
}
|
||||
else
|
||||
reloc = reloc_val; /*relocation value of item*/
|
||||
}
|
||||
|
||||
exerr(n) /* [vlh] */
|
||||
int n;
|
||||
{
|
||||
uerr(6);
|
||||
ival = 0;
|
||||
itype = ITCN;
|
||||
reloc = ABS;
|
||||
}
|
||||
|
||||
/*
|
||||
* get precedence of a operator
|
||||
* call with
|
||||
* operator
|
||||
* returns
|
||||
* precedence
|
||||
*/
|
||||
gprc(dprc)
|
||||
{
|
||||
|
||||
switch(dprc) {
|
||||
|
||||
case '+':
|
||||
case '-':
|
||||
case '&': /* and*/
|
||||
case '!': /* or*/
|
||||
case '^': /*exclusive or*/
|
||||
return(PPM);
|
||||
|
||||
case '/':
|
||||
case '*':
|
||||
case '<': /*left shift*/
|
||||
case '>': /*right shift*/
|
||||
return(PMD);
|
||||
|
||||
case '(':
|
||||
if(lastopr)
|
||||
return(PLP);
|
||||
break;
|
||||
|
||||
case ')':
|
||||
if(!prcnt) /*no left parens*/
|
||||
break;
|
||||
return(PRP);
|
||||
|
||||
}
|
||||
return(PEE); /*end of expression*/
|
||||
}
|
||||
|
||||
/*
|
||||
* get value from an it format item
|
||||
* call with
|
||||
* address of it format item
|
||||
* returns
|
||||
* the value
|
||||
* relocation value in rval
|
||||
* calls uerr if it cant get a value
|
||||
*/
|
||||
long gval(avwrd)
|
||||
struct it *avwrd;
|
||||
{
|
||||
register struct it *vwrd;
|
||||
register struct symtab *p;
|
||||
|
||||
vwrd = avwrd;
|
||||
if(vwrd->itty == ITCN) { /*constant*/
|
||||
rval = vwrd->itrl;
|
||||
return(vwrd->itop); /*value*/
|
||||
}
|
||||
if(vwrd->itty != ITSY) {
|
||||
uerr(6);
|
||||
rval = ABS;
|
||||
return(0);
|
||||
}
|
||||
p = vwrd->itop.ptrw2;
|
||||
if(p->flags&SYXR) { /*external reference*/
|
||||
fixext(p);
|
||||
return(0);
|
||||
}
|
||||
if((p->flags&SYDF) != SYDF || (p->flags&SYER)) {
|
||||
uerr(6);
|
||||
rval = ABS;
|
||||
return(0);
|
||||
}
|
||||
rval = (p->flags&SYRA) ? DATA : (p->flags&SYRO) /* reloc of item */
|
||||
? TEXT : (p->flags&SYBS) ? BSS : ABS;
|
||||
return(p->vl1);
|
||||
}
|
||||
|
||||
/*
|
||||
* get items for expression evaluator (pass one)
|
||||
* returns:
|
||||
* item type in itype
|
||||
* item value in ival
|
||||
* item in it format in exitm
|
||||
*/
|
||||
p1gi()
|
||||
{
|
||||
if(fcflg) /*used item so must pass it*/
|
||||
gterm(TRUE);
|
||||
if(!fcflg && ckspc(fchr)==1) {
|
||||
fcflg=1; /*just pass first character*/
|
||||
itype=ITSP; /*special char*/
|
||||
ival=fchr; /*value is the char*/
|
||||
}
|
||||
else { /*get a whole term*/
|
||||
fcflg = 0;
|
||||
gterm(TRUE); /*get a term*/
|
||||
if(itype==ITSY) { /* got a symbol*/
|
||||
ival.ptrw2=lemt(sirt,FALSE); /*look it up in main table*/
|
||||
if(ival.ptrw2==lmte) /*not there before*/
|
||||
mmte(); /*put it in table*/
|
||||
}
|
||||
else
|
||||
if(itype == ITCN)
|
||||
exitm.itrl = reloc;
|
||||
}
|
||||
exitm.itty = itype;
|
||||
exitm.itop = ival;
|
||||
}
|
||||
|
||||
/*
|
||||
* get items for expression evaluator (pass 2)
|
||||
* returns:
|
||||
* item type in itype
|
||||
* item value in ival
|
||||
* item in it format in exitm
|
||||
*/
|
||||
p2gi()
|
||||
{
|
||||
if(pitw==pnite) { /*end of statement*/
|
||||
itype = ITSP;
|
||||
ival = ' '; /*blank*/
|
||||
exitm.itty = itype;
|
||||
exitm.itop = ival;
|
||||
return;
|
||||
}
|
||||
|
||||
if((itype = pitw->itty) == ITPC) { /*vlh*/
|
||||
pitw->itop = loctr;
|
||||
if (p2flg || format==6) itype = pitw->itty = ITCN;
|
||||
}
|
||||
ival = pitw->itop; /*value*/
|
||||
exitm.swd1 = pitw->swd1;
|
||||
exitm.itop = ival;
|
||||
pitw++;
|
||||
}
|
||||
|
||||
/*
|
||||
*check for a special character
|
||||
* call with
|
||||
* character to check
|
||||
* returns:
|
||||
* 0 => character is number or letter
|
||||
*/
|
||||
ckspc(acksc)
|
||||
{
|
||||
register cksc;
|
||||
|
||||
cksc = acksc;
|
||||
if (isalnum(cksc)) return(0);
|
||||
return((index("_~*.@$%\'",cksc) != -1) ? 0 : 1); /*[vlh] compacted*/
|
||||
}
|
||||
|
||||
/* generate new relocation for op + op*/
|
||||
ckrl1(rv1,rv2)
|
||||
{
|
||||
if(rv1==rv2)
|
||||
return(rv1);
|
||||
if(rv1==ABS || rv2==ABS)
|
||||
return(rv1+rv2); /*the one that is not ABS*/
|
||||
uerr(27);
|
||||
return(ABS);
|
||||
}
|
||||
|
||||
/*generate new relocation for op - op*/
|
||||
ckrl2(rv1,rv2)
|
||||
{
|
||||
if(rv2==EXTRN)
|
||||
uerr(26);
|
||||
if(rv1==rv2)
|
||||
return(ABS);
|
||||
if(rv2==ABS)
|
||||
return(rv1+rv2);
|
||||
uerr(27);
|
||||
return(ABS);
|
||||
}
|
||||
|
||||
/*generate new relocation for op /*&|<>^! op*/
|
||||
ckrl3(rv1,rv2)
|
||||
{
|
||||
if(rv1!=ABS || rv2!=ABS)
|
||||
uerr(27);
|
||||
return(ABS);
|
||||
}
|
||||
|
||||
fixext(p)
|
||||
struct symtab *p;
|
||||
{
|
||||
if(extflg)
|
||||
uerr(36); /*two externals in expr*/
|
||||
extflg++;
|
||||
extref = p->vl1.wd2; /*get external #*/
|
||||
rval = EXTRN;
|
||||
itype = ITCN;
|
||||
ival = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
$ num
|
||||
AS68INIT.C
|
||||
AS68INIT.lis
|
||||
$ num
|
||||
DIR.C
|
||||
DIR.lis
|
||||
$ num
|
||||
EXPR.C
|
||||
EXPR.lis
|
||||
$ num
|
||||
MAIN.C
|
||||
MAIN.lis
|
||||
$ num
|
||||
MISC.C
|
||||
MISC.lis
|
||||
$ num
|
||||
PASS1A.C
|
||||
PASS1A.lis
|
||||
$ num
|
||||
PASS2.C
|
||||
PASS2.lis
|
||||
$ num
|
||||
SYMT.C
|
||||
SYMT.lis
|
||||
$ num
|
||||
VERSION.C
|
||||
VERSION.lis
|
||||
$ num
|
||||
AS68.H
|
||||
AS68.lst
|
||||
$ num
|
||||
COUT.H
|
||||
COUT.lst
|
||||
$ num
|
||||
CTYPE.H
|
||||
CTYPE.lst
|
||||
$ num
|
||||
MACHINE.H
|
||||
MACHINE.lst
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1*/ /* 68000 version */
|
||||
/*#define VAX 1*/ /* VAX Version */
|
||||
#define PDP11 1 /* PDP-11 Version*/
|
||||
/*#define CPM 1*/ /* CP/M Operating System*/
|
||||
#define UNIX 1 /* UNIX Operating System*/
|
||||
/*#define VMS 1*/ /* VMS Operating System*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
#define MC68000 1 /* 68000 version */
|
||||
/*#define VAX 1*/ /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
#define CPM 1 /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
/*#define VMS 1*/ /* VMS Operating System*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1*/ /* 68000 version */
|
||||
#define VAX 1 /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
/*#define CPM 1*/ /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
#define VMS 1 /* VMS Operating System*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1*/ /* 68000 version */
|
||||
#define VAX 1 /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
/*#define CPM 1*/ /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
#define VMS 1 /* VMS Operating System*/
|
||||
1100
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/as68/main.c
Normal file
1100
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/as68/main.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
$1stat machine.h=rw
|
||||
$1pip machine.h=machine.68k
|
||||
|
||||
$1cp68 -i 0$1 DIR.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic DIR.s -L
|
||||
$1as68 -f $1 -s 0$1 -l -u DIR.s
|
||||
era dir.s
|
||||
|
||||
$1cp68 -i 0$1 EXPR.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic EXPR.s -L
|
||||
$1as68 -f $1 -s 0$1 -l -u EXPR.s
|
||||
era expr.s
|
||||
|
||||
$1cp68 -i 0$1 MAIN.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic MAIN.s -L
|
||||
$1as68 -f $1 -s 0$1 -l -u MAIN.s
|
||||
era main.s
|
||||
|
||||
$1cp68 -i 0$1 misc.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic MISC.s -L
|
||||
$1as68 -f $1 -s 0$1 -l -u MISC.s
|
||||
era misc.s
|
||||
|
||||
$1cp68 -i 0$1 PASS1A.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic PASS1A.s -L
|
||||
$1as68 -f $1 -s 0$1 -l -u PASS1A.s
|
||||
era pass1a.s
|
||||
|
||||
$1cp68 -i 0$1 PASS2.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic PASS2.s -L
|
||||
$1as68 -f $1 -s 0$1 -l -u PASS2.s
|
||||
era pass2.s
|
||||
|
||||
$1cp68 -i 0$1 STRNCMP.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic STRNCMP.s -L
|
||||
$1as68 -f $1 -s 0$1 -l -u STRNCMP.s
|
||||
era strncmp.s
|
||||
|
||||
$1cp68 -i 0$1 SYMT.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st
|
||||
era $1x.i
|
||||
era $1x.st
|
||||
$1c168 $1x.ic SYMT.s -L
|
||||
$1as68 -f $1 -s 0$1 -l -u SYMT.s
|
||||
era symt.s
|
||||
|
||||
relink $1
|
||||
1078
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/as68/misc.c
Normal file
1078
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/as68/misc.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/* reduce long relative branches to short if possible*/
|
||||
|
||||
#include "as68.h"
|
||||
int nitleft;
|
||||
char tfilname[];
|
||||
int p2gi();
|
||||
long lseek();
|
||||
pass1a()
|
||||
{
|
||||
register long reduced;
|
||||
register int i, wsize;
|
||||
register long oldpos,newpos; /* Old and new file seek pointers */
|
||||
register j; /* temp */
|
||||
|
||||
pitix = itbuf;
|
||||
nitleft = 0;
|
||||
reduced = 0; itoffset = 0; stbuf[0].itrl = 0;
|
||||
wsize = 3*sizeof stbuf[0]; /* [vlh] don't calculate many times */
|
||||
close(itfn);
|
||||
LASTCHTFN = itfnc;
|
||||
itfn = openfi(tfilname,2,1); /*open it for update*/
|
||||
while(ristb()) {
|
||||
opcpt = stbuf[2].itop.ptrw2; /*ptr to opcode entry in main tab*/
|
||||
if(!(opcpt->flags&OPDR)) { /*not a directive*/
|
||||
format = (opcpt->flags)&OPFF;
|
||||
p1inlen = stbuf[1].itrl; /*pass 1 instr length guess*/
|
||||
if(((format==6 && p1inlen==4) || opcpt==jsrptr) &&
|
||||
(rlflg=stbuf[3].itrl)==TEXT) {
|
||||
nite = stbuf[0].itrl & 0377;/* # of it entries */
|
||||
pnite = &stbuf[nite].itty; /*ptr to end of stmt*/
|
||||
modelen = stbuf[2].itrl; /*instr mode length*/
|
||||
opdix = ITOP1; /*first operand*/
|
||||
pitw = &stbuf[ITOP1].itty; /*ptr to first operand*/
|
||||
loctr = stbuf[3].itop - reduced;
|
||||
expr(&p2gi);
|
||||
ival =- loctr+2L;
|
||||
if(itype==ITCN && !extflg && reloc!=ABS) {
|
||||
if(format==9) { /*jsr*/
|
||||
i = (ival>= -128 && ival<=127) ? p1inlen-2 :
|
||||
(ival>= -32768 && ival<=32767) ? p1inlen-4 : 0;
|
||||
if (!i)
|
||||
continue;
|
||||
stbuf[2].itop.ptrw2 = bsrptr; /*chng to bsr*/
|
||||
}
|
||||
else if(ival>= -128 && ival<=127) {
|
||||
i = 2; /*[vlh]was 4 for ival=2*/
|
||||
if (!ival) stbuf[2].itop.ptrw2 = nopptr;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
fixsyadr(i);
|
||||
reduced =+ i;
|
||||
stbuf[1].itrl =- i; /*reduced somewhat*/
|
||||
if(!stbuf[1].itrl)
|
||||
stbuf[1].itrl = -1; /*ignore flag*/
|
||||
oldpos=lseek(itfn,0L,1); /* Remember current position */
|
||||
newpos= itoffset -
|
||||
(stbuf[0].itrl*sizeof stbuf[0]);
|
||||
if(lseek(itfn,newpos,0) < 0) {
|
||||
rpterr("seek error on it file\n");
|
||||
abort();
|
||||
}
|
||||
if(write(itfn,&stbuf[0],wsize) != wsize) {
|
||||
rpterr("write error on it file\n");
|
||||
abort();
|
||||
}
|
||||
lseek(itfn,oldpos,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(opcpt == endptr) {
|
||||
savelc[TEXT] =- reduced;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fix all symbol addresses that are text based and greater than loctr*/
|
||||
/* fix means subtract 2 from them*/
|
||||
fixsyadr(al)
|
||||
{
|
||||
register char **sx1, **sx2;
|
||||
register l;
|
||||
|
||||
l = al;
|
||||
/* loop thru symbol initial reference table*/
|
||||
for(sx1= sirt; sx1<&sirt[SZIRT-1]; sx1 =+ 2) {
|
||||
if(*(sx2 = sx1+1)==0) /* this chain is empty*/
|
||||
continue;
|
||||
|
||||
/* symbols on one chain*/
|
||||
sx2 = *sx2; /*first entry on this chain*/
|
||||
while(1) {
|
||||
if((sx2->flags&SYDF || sx2->flags&SYPC) && sx2->flags&SYRO &&
|
||||
sx2->vl1 > loctr) /* [vlh] */
|
||||
sx2->vl1 =- l;
|
||||
if(sx2 == *sx1) /*end of chain*/
|
||||
break;
|
||||
sx2 = sx2->tlnk; /*next entry in chain*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*
|
||||
* pass two for the 68000 assembler
|
||||
* Bill Allen
|
||||
* March 1980
|
||||
*/
|
||||
|
||||
#include "as68.h"
|
||||
#include "cout.h" /*c.out header definition & MAGIC*/
|
||||
|
||||
#define MOVEA 0100
|
||||
|
||||
int p2gi();
|
||||
|
||||
extern char tfilname[]; /*name of it file*/
|
||||
extern char initfnam[]; /*name of the initilization file*/
|
||||
int (*p2direct[])();
|
||||
|
||||
int opf1(), opf2(), opf3(), opf4(), opf5(), relbr(), opf7(), opf8();
|
||||
int opf9(), opf11(), opf12(), opf13(), opf15(), opf17(), opf20();
|
||||
int opf21(), opf22(), opf23();
|
||||
|
||||
int (*opfary[])() {
|
||||
0, /*0*/
|
||||
opf1, /*1*/
|
||||
opf2, /*2*/
|
||||
opf3, /*3*/
|
||||
opf4, /*4*/
|
||||
opf5, /*5*/
|
||||
relbr, /*6*/
|
||||
opf7, /*7*/
|
||||
opf8, /*8*/
|
||||
opf9, /*9*/
|
||||
opf4, /*10*/
|
||||
opf11, /*11*/
|
||||
opf12, /*12*/
|
||||
opf13, /*13*/
|
||||
opf9, /*14*/
|
||||
opf15, /*15*/
|
||||
opf17, /*16*/
|
||||
opf17, /*17*/
|
||||
opf13, /*18*/
|
||||
opf11, /*19*/
|
||||
opf20, /*20*/
|
||||
opf21, /*21*/
|
||||
opf22, /*22*/
|
||||
opf23, /*23*/
|
||||
opf9, /*24*/
|
||||
opf9, /*25*/
|
||||
opf5, /*26*/ /* [vlh] cmp, chk, extention verification */
|
||||
opf4, /*27*/ /* [vlh] addx, subx, extension verification */
|
||||
opf13, /*28*/ /* [vlh] swap, extension verification */
|
||||
opf9, /*29*/ /* [vlh] pea, extention verification */
|
||||
opf15 /*30*/ /* [vlh] lea, extension verification */
|
||||
};
|
||||
|
||||
#define LSTFRMT 30
|
||||
|
||||
int f1mode[] {0,0,0100,0,0200};
|
||||
int f2mode[] {0,0,0100,0,0200};
|
||||
int f3mode[] {0,010000,030000,0,020000};
|
||||
int f15mode[] {0,0,0300,0,0700};
|
||||
int f5mode[] {0,0,0100,0,0200};
|
||||
int f5amode[] {0,0,0300,0,0700};
|
||||
int f13mode[] {0,0,0200,0,0300};
|
||||
int f23mode[] {0,0400,0500,0,0600};
|
||||
int rlbits[5]; /*holds relocation bits for instr*/
|
||||
int pline; /*number of last printed line*/
|
||||
int brkln2 077777; /*pass 2 break line number for debugging*/
|
||||
int prsp; /*special print alignment flag*/
|
||||
int amode; /*addressing mode*/
|
||||
int nitleft;
|
||||
/*pass two driver*/
|
||||
pass2()
|
||||
{
|
||||
register short *p;
|
||||
register i;
|
||||
register (*dirop)();
|
||||
|
||||
pitix = itbuf; /* This is init for doitrd*/
|
||||
xline = LPP;
|
||||
nitleft = 0;
|
||||
lbuf.nunused = tbuf.nunused = dabuf.nunused = drbuf.nunused = 512;
|
||||
lbuf.fildes = lfn; /*set buffered io for binary file*/
|
||||
lbuf.xfree = &lbuf.buff[0];
|
||||
tbuf.fildes = trbfn; /*set buffered io for text reloc bits file*/
|
||||
tbuf.xfree = &tbuf.buff[0];
|
||||
dabuf.fildes = dafn; /*set buffered io for data bytes*/
|
||||
dabuf.xfree = &dabuf.buff[0];
|
||||
drbuf.fildes = drbfn; /*set buffered io for data reloc bits*/
|
||||
drbuf.xfree = &drbuf.buff[0];
|
||||
couthd.ch_magic = MAGIC;/*c.out magic number*/
|
||||
if(savelc[TEXT]&1)
|
||||
savelc[TEXT]++; /*make it even*/
|
||||
couthd.ch_tsize = savelc[TEXT]; /*text size*/
|
||||
if(savelc[DATA]&1)
|
||||
savelc[DATA]++; /*make it even*/
|
||||
couthd.ch_dsize = savelc[DATA]; /*data size*/
|
||||
couthd.ch_bsize = savelc[BSS]; /*bss size*/
|
||||
/*symbol table size is not known now -- it is set at end of pass 2*/
|
||||
/* entry point and stack size are zero for now*/
|
||||
p = &couthd;
|
||||
for(i=0; i<HDSIZE/2; i++) {
|
||||
putw(*p++,&lbuf); /*write the file header words*/
|
||||
}
|
||||
savelc[0] = 0; savelc[1] = 0; savelc[2] = 0; savelc[3] = 0;
|
||||
loctr = 0; /*location counter*/
|
||||
rlflg = TEXT; /*TEXT relocatable*/
|
||||
p2flg = 1; /*pass two*/
|
||||
#ifdef UNIX
|
||||
if (lseek(ifn,0L,0) == -1) { /*beginning of source*/
|
||||
rpterr("seek error on source file\n");
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
close(ifn); /* This way for goddamn Whitesmith's */
|
||||
ifn=open(sfname,0,0); /* Re-open the fucking source file */
|
||||
if(ifn < 0) /* Couldn't */
|
||||
{
|
||||
printf("Unable to open file %s\n",sfname);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
close(itfn);
|
||||
LASTCHTFN = itfnc;
|
||||
itfn = openfi(tfilname,0); /*open it for reading*/
|
||||
pline = 1; /*no lines printed*/
|
||||
fchr=gchr(); /*get first char*/
|
||||
while(ristb()) { /*pass 2 main loop*/
|
||||
p2absln = stbuf[0].itop; /*line number*/
|
||||
if(p2absln>=brkln2) /*for debugging the assembler*/
|
||||
i=0;
|
||||
opcpt = stbuf[2].itop.ptrw2; /*ptr to opcode entry in main tab*/
|
||||
nite = stbuf[0].itrl & 0377; /*number of it entries*/
|
||||
pnite = &stbuf[nite]; /*ptr to end of stmt*/
|
||||
modelen = stbuf[2].itrl; /*instr mode length*/
|
||||
p1inlen = stbuf[1].itrl; /*pass 1 instr length guess*/
|
||||
opdix = ITOP1; /*first operand*/
|
||||
pitw = &stbuf[ITOP1]; /*ptr to first operand*/
|
||||
prsp = 0; /*special print flag off*/
|
||||
instrlen = 2; /*default for print*/
|
||||
if(opcpt->flags&OPDR) { /*opcode is a directive*/
|
||||
i = opcpt->vl1; /*directive number*/
|
||||
dirop = p2direct[i];
|
||||
(*dirop)(); /*handle directive*/
|
||||
}
|
||||
else {
|
||||
gcist(); /*generate code for one statement*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* generate code for an instruction*/
|
||||
/* call with*/
|
||||
/* intermediate text for instruction in stbuf*/
|
||||
gcist()
|
||||
{
|
||||
register i,j;
|
||||
|
||||
if(stbuf[0].itty != ITBS) /*beginning of statement*/
|
||||
abort();
|
||||
format = (opcpt->flags)&OPFF;
|
||||
in_err = 0; /*[vlh] no error this instruction, yet*/
|
||||
ival = 0; /*initial value for possible operand*/
|
||||
reloc = ABS;
|
||||
instrlen = 2; /*at least 2 bytes*/
|
||||
ins[0] = opcpt->vl1; /*opcode value*/
|
||||
rlbits[0] = INSABS; /*instruction absolute*/
|
||||
pins = &ins[1];
|
||||
prlb = &rlbits[1];
|
||||
if(nite>ITOP1) { /*operands*/
|
||||
if(!format) {
|
||||
uerr(9);
|
||||
}
|
||||
else if(format>LSTFRMT) /* [vlh] was a magic number... */
|
||||
abort();
|
||||
else {
|
||||
(*opfary[format])();
|
||||
}
|
||||
}
|
||||
if (!ckein() && !in_err) /* at end of statement ?? */
|
||||
uerr(6);
|
||||
print(1); /*print source*/
|
||||
|
||||
loctr =+ p1inlen;
|
||||
if (!in_err && p1inlen != instrlen) /* [vlh] 2nd pass error recovery */
|
||||
uerr(38);
|
||||
outinstr(); /*write out instr binary*/
|
||||
}
|
||||
|
||||
/* relative branches*/
|
||||
relbr()
|
||||
{
|
||||
expr(&p2gi);
|
||||
if(extflg) { /*external reference*/
|
||||
instrlen =+ 2; /*long relative*/
|
||||
*pins++ = ival; /*pass constant part*/
|
||||
*prlb++ = (extref<<3)|EXTREL; /*ext ref*/
|
||||
return;
|
||||
}
|
||||
ival =- (loctr+2); /*calc relative offset*/
|
||||
if(itype!=ITCN || reloc != rlflg) {
|
||||
uerr(22); /*invalid relative branch*/
|
||||
ival = 0;
|
||||
}
|
||||
reloc = ABS;
|
||||
if(p1inlen==4) { /*long displacement*/
|
||||
if(ival< (-32768L) || ival > (32767L))
|
||||
uerr(22);
|
||||
instrlen =+ 2;
|
||||
*pins++ = ival;
|
||||
*prlb++ = DABS; /*data absolute*/
|
||||
}
|
||||
else { /*short displacement*/
|
||||
if (ival>127 || ival<-128)
|
||||
uerr(22);
|
||||
ins[0] =| (ival.wd2&0377);
|
||||
}
|
||||
if (!ival) { /* make it a nop */
|
||||
opcpt = nopptr;
|
||||
ins[0] = opcpt->vl1.wd2;
|
||||
pins = &ins[1];
|
||||
if (modelen==4) {
|
||||
*pins++ = opcpt->vl1.wd2;
|
||||
rlbits[1] = INSABS;
|
||||
}
|
||||
}
|
||||
in_err++; /* ignore extra eg. bra *+$d04(pc) vs. bra *+d04 */
|
||||
}
|
||||
|
||||
/* format one -- add, sub, and, or, cmp, etc.*/
|
||||
/* one operand must be a D reg (or A reg dest for add, sub, or cmp)*/
|
||||
opf1()
|
||||
{
|
||||
register int *p;
|
||||
|
||||
if(get2ops())
|
||||
return;
|
||||
if (ins[0]==AND || ins[0]==OR)
|
||||
if (cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
|
||||
if (ins[0]==AND) opcpt = andiptr;
|
||||
else opcpt = oriptr;
|
||||
ins[0] = opcpt->vl1.wd2;
|
||||
format = (opcpt->flags)&OPFF;
|
||||
ccr_or_sr();
|
||||
return;
|
||||
}
|
||||
p = f1mode;
|
||||
if(ckdreg(&opnd[1])) { /*destn is D reg*/
|
||||
if((opcpt==andptr||opcpt==orptr)&&ckareg(&opnd[0])) /*A source*/
|
||||
uerr(20);
|
||||
makef1(opnd[1].ea,p[modelen],&opnd[0]); /*make instr*/
|
||||
return;
|
||||
}
|
||||
else if(ckdreg(&opnd[0]) && memalt(&opnd[1])) { /*source is D reg*/
|
||||
if (pcea(&opnd[1])) uerr(10);
|
||||
makef1(opnd[0].ea,p[modelen]+0400,&opnd[1]);
|
||||
return;
|
||||
}
|
||||
else if(ckareg(&opnd[1])) { /*A reg is dstn*/
|
||||
if(opcpt==addptr)
|
||||
opcpt = addaptr;
|
||||
else if(opcpt==cmpptr)
|
||||
opcpt = cmpaptr;
|
||||
else if(opcpt==subptr)
|
||||
opcpt = subaptr;
|
||||
else {
|
||||
uerr(20);
|
||||
return;
|
||||
}
|
||||
format = (opcpt->flags)&OPFF;
|
||||
opnd[1].ea =& 07;
|
||||
p = f15mode;
|
||||
makef1(opnd[1].ea,p[modelen],&opnd[0]); /*make instr*/
|
||||
return;
|
||||
}
|
||||
else if(!makeimm()) /*make an immediate instr*/
|
||||
uerr(20);
|
||||
}
|
||||
|
||||
/* format 2 -- addi, andi, subi, etc*/
|
||||
opf2()
|
||||
{
|
||||
if(get2ops())
|
||||
return;
|
||||
if(ins[0]==ANDI || ins[0]==ORI || ins[0]==EORI) {
|
||||
if(cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
|
||||
ccr_or_sr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(opnd[0].ea != IMM) {
|
||||
uerr(9);
|
||||
return;
|
||||
}
|
||||
if(!dataalt(&opnd[1]) || pcea(&opnd[1])) {
|
||||
uerr(20);
|
||||
return;
|
||||
}
|
||||
genimm();
|
||||
}
|
||||
|
||||
/*format #3 -- move and movea*/
|
||||
opf3()
|
||||
{
|
||||
register i,j,k;
|
||||
|
||||
if(get2ops())
|
||||
return;
|
||||
if(cksprg(&opnd[1],CCR)) {
|
||||
ins[0] = MOVECCR;
|
||||
opf3l1:
|
||||
if (modelen==1 || modelen==4) uerr(34);
|
||||
if(anysprg(&opnd[0]))
|
||||
uerr(20);
|
||||
ins[0] =| opnd[0].ea;
|
||||
if(!dataea(&opnd[0]))
|
||||
uerr(9);
|
||||
doea(&opnd[0]);
|
||||
return;
|
||||
}
|
||||
if(cksprg(&opnd[1],SR)) {
|
||||
ins[0] = MOVESR;
|
||||
goto opf3l1;
|
||||
}
|
||||
if(cksprg(&opnd[0],SR)) {
|
||||
if (modelen==1 || modelen==4)
|
||||
uerr(34);
|
||||
if(anysprg(&opnd[1]))
|
||||
uerr(20);
|
||||
ins[0] = SRMOVE | opnd[1].ea;
|
||||
if(!dataalt(&opnd[1]) || pcea(&opnd[1]))
|
||||
uerr(10);
|
||||
doea(&opnd[1]);
|
||||
return;
|
||||
}
|
||||
if(cksprg(&opnd[0],USP)) {
|
||||
if (modelen == 1)
|
||||
uerr(34); /* default is word, can't test */
|
||||
if (!ckareg(&opnd[1]))
|
||||
uerr(33);
|
||||
ins[0] = MOVEUSP|8|(opnd[1].ea&7);
|
||||
return;
|
||||
}
|
||||
if(cksprg(&opnd[1],USP)) {
|
||||
if (modelen == 1)
|
||||
uerr(34); /* default is word, can't test */
|
||||
if (!ckareg(&opnd[0]))
|
||||
uerr(33);
|
||||
ins[0] = MOVEUSP|(opnd[0].ea&7);
|
||||
return;
|
||||
}
|
||||
k = ins[0];
|
||||
ins[0] =| f3mode[modelen];
|
||||
ckbytea();
|
||||
ins[0] =| opnd[0].ea; /*source ea*/
|
||||
doea(&opnd[0]);
|
||||
ins[0] =| (opnd[1].ea&7)<<9; /*dest register*/
|
||||
ins[0] =| (opnd[1].ea&070)<<3; /*dest mode*/
|
||||
doea(&opnd[1]);
|
||||
if(k==MOVEA) {
|
||||
if(dataea(&opnd[1]))
|
||||
uerr(20);
|
||||
}
|
||||
else if((pcea(&opnd[1]) && dataea(&opnd[1])) || opnd[1].ea==IMM)
|
||||
uerr(20);
|
||||
}
|
||||
|
||||
/* format 4 -- abcd, sbcd */
|
||||
/* format 10 -- cmpm*/
|
||||
/* format 27 -- addx, subx */
|
||||
opf4()
|
||||
{
|
||||
if(get2ops())
|
||||
return;
|
||||
if (format==27) { /*addx,subx add in size bits*/
|
||||
ins[0] =| f1mode[modelen];
|
||||
}
|
||||
else if(format==10) { /*cmpm*/
|
||||
if((opnd[0].ea&070)!=INDINC || (opnd[1].ea&070)!=INDINC)
|
||||
uerr(20);
|
||||
ins[0] =| f1mode[modelen] | ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
|
||||
return;
|
||||
}
|
||||
if(ckdreg(&opnd[0]) && ckdreg(&opnd[1])) {
|
||||
ins[0] =| ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
|
||||
return;
|
||||
}
|
||||
if((opnd[0].ea&070)==DECIND && (opnd[1].ea&070)==DECIND) {
|
||||
ins[0] =| 010 | ((opnd[0].ea&7)|((opnd[1].ea&7)<<9));
|
||||
return;
|
||||
}
|
||||
uerr(20);
|
||||
}
|
||||
|
||||
/*format 5 -- div, mul*/
|
||||
/*format 26 -- cmp, chk */
|
||||
opf5()
|
||||
{
|
||||
if(get2ops())
|
||||
return;
|
||||
if(!ckdreg(&opnd[1])) {
|
||||
if(opcpt==cmpptr) {
|
||||
if(!dataea(&opnd[1])) /* [vlh] made define */
|
||||
ins[0] =| f5amode[modelen]; /* was pumode */
|
||||
else if(makeimm())
|
||||
return;
|
||||
else
|
||||
uerr(20);
|
||||
}
|
||||
else
|
||||
uerr(20);
|
||||
}
|
||||
if(opcpt==cmpptr) {
|
||||
ins[0] =| f5mode[modelen]; /* was pumode */
|
||||
ckbytea();
|
||||
}
|
||||
else if(!dataea(&opnd[0]))
|
||||
uerr(20);
|
||||
ins[0] =| (opnd[1].ea&7)<<9 | opnd[0].ea;
|
||||
doea(&opnd[0]);
|
||||
}
|
||||
|
||||
#define BTST 0000
|
||||
/* format 7 -- bit instrs -- btst, bclr, bset, etc*/
|
||||
opf7()
|
||||
{
|
||||
if(get2ops())
|
||||
return;
|
||||
if(opnd[1].ea==IMM||(ins[0]!=BTST&&pcea(&opnd[1]))||ckareg(&opnd[1]))
|
||||
uerr(20);
|
||||
if(ckdreg(&opnd[0])) {
|
||||
ins[0] =| (opnd[0].ea<<9)|0400;
|
||||
}
|
||||
else { /*static bit #*/
|
||||
if(opnd[0].con<0L || opnd[0].con>31 ||
|
||||
(opnd[1].ea&INDIRECT&&opnd[0].con>7)) /* [vlh] */
|
||||
uerr(23);
|
||||
if(opnd[0].ea != IMM)
|
||||
uerr(17);
|
||||
ins[0] =| 04000;
|
||||
dodisp(&opnd[0]);
|
||||
}
|
||||
if (modelen==1 && !(memea(&opnd[1]))) /*[vlh]*/
|
||||
uerr(20);
|
||||
else if (!(ckdreg(&opnd[1])) && modelen==4)
|
||||
uerr(20);
|
||||
ins[0] =| opnd[1].ea;
|
||||
doea(&opnd[1]);
|
||||
}
|
||||
|
||||
/* format 8 -- shifts and rotates*/
|
||||
opf8()
|
||||
{
|
||||
register i;
|
||||
|
||||
getea(0); /*get first operand*/
|
||||
if(pitw >= pnite) { /*end of all ops*/
|
||||
if(ckdreg(&opnd[0])) { /*shift dreg one bit*/
|
||||
cpop01(); /*copy opnd 0 to 1*/
|
||||
opnd[0].ea = IMM;
|
||||
opnd[0].con = 1L;
|
||||
if (!ckdreg(&opnd[1])) uerr(20);
|
||||
opf8l1:
|
||||
if(opnd[0].con<1 || opnd[0].con>8) /*[vlh legal range 1..8*/
|
||||
uerr(37);
|
||||
ins[0] =| ((opnd[0].con.wd2&7)<<9)|f1mode[modelen]|opnd[1].ea;
|
||||
return;
|
||||
}
|
||||
i = (ins[0]&077)<<6;
|
||||
ins[0] =& 0177700;
|
||||
ins[0] =| 0300|i|opnd[0].ea;
|
||||
if(!memalt(&opnd[0]) || pcea(&opnd[0]) || modelen != 2)
|
||||
uerr(20);
|
||||
doea(&opnd[0]);
|
||||
return;
|
||||
}
|
||||
if(!ckcomma()) {
|
||||
uerr(10);
|
||||
return;
|
||||
}
|
||||
getea(1); /*get second operand*/
|
||||
if(!ckdreg(&opnd[1])) /* [vlh] second operand must be dreg */
|
||||
uerr(20);
|
||||
if(ckdreg(&opnd[0])) { /*first op is D reg*/
|
||||
ins[0] =| (opnd[0].ea<<9)|040; /*reg # and reg bit*/
|
||||
}
|
||||
else {
|
||||
if(opnd[0].ea != IMM)
|
||||
uerr(20);
|
||||
goto opf8l1;
|
||||
}
|
||||
ins[0] =| f1mode[modelen] | opnd[1].ea; /*put in size and reg #*/
|
||||
}
|
||||
|
||||
/* format 9 -- jmp, jsr */
|
||||
/* format 14 -- stop */
|
||||
/* format 24 -- clr, neg, negx, not */
|
||||
/* format 25 -- s?? */
|
||||
/* format 29 -- pea */
|
||||
/* one operand instructions -- jmp, clr, neg, not, sge, etc.*/
|
||||
opf9()
|
||||
{
|
||||
getea(0);
|
||||
if(format==24) { /*clr, not, etc*/
|
||||
ins[0] =| f1mode[modelen]; /*add size bits*/
|
||||
if(!dataalt(&opnd[0]) || pcea(&opnd[0]))
|
||||
uerr(20);
|
||||
}
|
||||
else if(format==25) { /*tas,scc, etc*/
|
||||
if(ckareg(&opnd[0]) || pcea(&opnd[0]) || opnd[0].ea==IMM)
|
||||
uerr(20);
|
||||
}
|
||||
else if(format==14) { /*stop*/
|
||||
if(modelen!=2 || opnd[0].ea!=IMM)
|
||||
uerr(20);
|
||||
doea(&opnd[0]);
|
||||
return;
|
||||
}
|
||||
else if(!controlea(&opnd[0])) /*jmp, jsr, etc*/
|
||||
uerr(20);
|
||||
ins[0] =| opnd[0].ea;
|
||||
doea(&opnd[0]);
|
||||
}
|
||||
|
||||
/* format 11 -- dbcc*/
|
||||
/* format 19 -- link*/
|
||||
opf11()
|
||||
{
|
||||
if(get2ops())
|
||||
return;
|
||||
if(format==19) { /*link*/
|
||||
if(!ckareg(&opnd[0]))
|
||||
uerr(33);
|
||||
if(opnd[1].ea != IMM)
|
||||
uerr(17);
|
||||
}
|
||||
else {
|
||||
if(!ckdreg(&opnd[0]))
|
||||
uerr(33);
|
||||
if(opnd[1].drlc!=rlflg) /*[vlh]don't chk opnd[1].ea!=LADDR||SADDR*/
|
||||
uerr(22);
|
||||
opnd[1].con =- (loctr+2L);
|
||||
cksize(&opnd[1]);
|
||||
opnd[1].drlc = ABS; /*not relocatable*/
|
||||
}
|
||||
ins[0] =| opnd[0].ea&7; /*put in reg #*/
|
||||
dodisp(&opnd[1]);
|
||||
}
|
||||
|
||||
/* format 12 -- exg*/
|
||||
opf12()
|
||||
{
|
||||
register i;
|
||||
|
||||
if(get2ops())
|
||||
return;
|
||||
if(ckdreg(&opnd[0])) {
|
||||
if(ckdreg(&opnd[1])) { /*exchange D regs*/
|
||||
ins[0] =| 0100 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
|
||||
return;
|
||||
}
|
||||
if(ckareg(&opnd[1])) { /*ins[0] <- A and D flag*/
|
||||
ins[0] =| 0210 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(ckareg(&opnd[0])) {
|
||||
if(ckareg(&opnd[1])) { /*both a regs*/
|
||||
ins[0] =| 0110 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
|
||||
return;
|
||||
}
|
||||
if(ckdreg(&opnd[1])) { /*A and D regs*/
|
||||
i = opnd[0].ea; /*exchg ea's*/
|
||||
opnd[0].ea = opnd[1].ea;
|
||||
opnd[1].ea = i;
|
||||
ins[0] =| 0210 | ((opnd[0].ea&7)<<9) | (opnd[1].ea&7);
|
||||
return;
|
||||
}
|
||||
}
|
||||
uerr(20);
|
||||
}
|
||||
|
||||
/* format 13 -- ext, unlk*/
|
||||
/* format 18 -- trap*/
|
||||
/* format 28 -- swap */
|
||||
#define UNLK 047130
|
||||
|
||||
opf13()
|
||||
{
|
||||
getea(0);
|
||||
if(format==18) { /*trap*/
|
||||
if(opnd[0].con<0 || opnd[0].con>15)
|
||||
uerr(15);
|
||||
ins[0] =| opnd[0].con.wd2;
|
||||
return;
|
||||
}
|
||||
if(ins[0]==UNLK) { /*unlk instr*/
|
||||
if(!ckareg(&opnd[0]))
|
||||
uerr(20);
|
||||
}
|
||||
else {
|
||||
if(!ckdreg(&opnd[0]))
|
||||
uerr(20);
|
||||
if (format==13) /* ext */
|
||||
ins[0] =| f13mode[modelen];
|
||||
}
|
||||
ins[0] =| opnd[0].ea&7;
|
||||
}
|
||||
|
||||
/* format 15 -- adda, cmpa, suba*/
|
||||
/* format 30 -- lea */
|
||||
opf15()
|
||||
{
|
||||
register i;
|
||||
|
||||
if(get2ops())
|
||||
return;
|
||||
if(!ckareg(&opnd[1]))
|
||||
uerr(33);
|
||||
if(format==30) {
|
||||
i = 0700;
|
||||
if(!controlea(&opnd[0]))
|
||||
uerr(20);
|
||||
}
|
||||
else
|
||||
i = f15mode[modelen];
|
||||
makef1(opnd[1].ea&7,i,&opnd[0]);
|
||||
if (format==15 && opnd[0].ea != 071) cksize(&opnd[0]);
|
||||
}
|
||||
|
||||
/*formats 16 and 17 -- addq, inc, subq, dec*/
|
||||
opf17()
|
||||
{
|
||||
if(format==16) { /*inc or dec*/
|
||||
clrea(&opnd[0]);
|
||||
opnd[0].ea = IMM;
|
||||
opnd[0].con = 1L;
|
||||
opnd[0].drlc = ABS;
|
||||
getea(1);
|
||||
}
|
||||
else {
|
||||
if(get2ops())
|
||||
return;
|
||||
}
|
||||
if(opnd[0].ea != IMM || !altea(&opnd[1]) || pcea(&opnd[1]))
|
||||
uerr(20);
|
||||
if(opnd[0].con<=0 || opnd[0].con>8)
|
||||
uerr(15);
|
||||
if(modelen==1 && !dataea(&opnd[1]))
|
||||
uerr(34);
|
||||
ins[0] =| f1mode[modelen]|((opnd[0].con.wd2&7)<<9)|opnd[1].ea;
|
||||
doea(&opnd[1]);
|
||||
}
|
||||
|
||||
/* format 20 -- movem */
|
||||
int regmsk0[] {0100000,040000,020000,010000,04000,02000,01000,0400,0200,
|
||||
0100,040,020,010,4,2,1};
|
||||
int regmsk1[] {1,2,4,010,020,040,0100,0200,0400,01000,02000,04000,010000,
|
||||
020000,040000,0100000};
|
||||
opf20()
|
||||
{
|
||||
register dr;
|
||||
register i,j;
|
||||
|
||||
dr = 0;
|
||||
if(getreg() != -1 || pitw->itty == ITRM) { /*regs to memory*/
|
||||
if (pitw->itty != ITRM) { /* [vlh] */
|
||||
pitw--;
|
||||
j = getrlist(regmsk0);
|
||||
}
|
||||
else {
|
||||
j = pitw->itop;
|
||||
pitw++;
|
||||
}
|
||||
if(!ckcomma())
|
||||
uerr(10);
|
||||
}
|
||||
else
|
||||
dr = 02000;
|
||||
getea(0);
|
||||
if(dr) {
|
||||
if(!ckcomma())
|
||||
uerr(10);
|
||||
if (pitw->itty != ITRM) /* [vlh] */
|
||||
j = getrlist(regmsk1); /*mem to regs*/
|
||||
else {
|
||||
j = pitw->itop;
|
||||
j = fixmask(j);
|
||||
pitw++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(controlea(&opnd[0]))
|
||||
j = fixmask(j);
|
||||
}
|
||||
i = opnd[0].ea&070;
|
||||
if(!controlea(&opnd[0]) && i!=INDINC && i!=DECIND)
|
||||
uerr(20);
|
||||
if(modelen==4) /*long*/
|
||||
ins[0] =| 0100;
|
||||
ins[0] =| opnd[0].ea|dr;
|
||||
*pins++ = j; /*reg mask*/
|
||||
*prlb++ = DABS;
|
||||
instrlen =+ 2;
|
||||
doea(&opnd[0]);
|
||||
if (!dr) { /* 1st argument (2nd is reg list) */
|
||||
if (pcea(&opnd[0]) || (opnd[0].ea&070)==INDINC)
|
||||
uerr(20); /* xx(pc), xx(pc,dx), -(ax) */
|
||||
}
|
||||
else /* 2nd argument (1st is reg list) */
|
||||
if ((opnd[0].ea&070)==DECIND)
|
||||
uerr(20); /* (ax)+ */
|
||||
}
|
||||
|
||||
/*
|
||||
* get a list of registers for the movem instr
|
||||
* call with:
|
||||
* ptr to reg-to-mem or mem-to-reg array of bits
|
||||
*/
|
||||
getrlist(ap)
|
||||
int *ap;
|
||||
{
|
||||
register int *p,i,j;
|
||||
register int mask;
|
||||
|
||||
p = ap;
|
||||
mask = 0;
|
||||
while((i=getreg()) != -1) {
|
||||
if(ckitc(pitw,'-')) {
|
||||
pitw++;
|
||||
if((j=getreg()) == -1) {
|
||||
uerr(40);
|
||||
break;
|
||||
}
|
||||
while(i<=j)
|
||||
mask =| p[i++];
|
||||
}
|
||||
else
|
||||
mask =| p[i];
|
||||
if(ckitc(pitw,'/'))
|
||||
pitw++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(!mask)
|
||||
uerr(40);
|
||||
return(mask);
|
||||
}
|
||||
|
||||
/*reverse a movem register mask for control ea to memory*/
|
||||
fixmask(msk)
|
||||
{
|
||||
register i,j,k;
|
||||
|
||||
k = (msk&1) ? 0100000 : 0;
|
||||
i = 2;
|
||||
j = 040000;
|
||||
while(i) {
|
||||
if(msk&i)
|
||||
k =| j;
|
||||
i =<< 1;
|
||||
j =>> 1;
|
||||
}
|
||||
return(k);
|
||||
}
|
||||
|
||||
/* format 21 -- movep*/
|
||||
opf21()
|
||||
{
|
||||
register m,d;
|
||||
register char *p;
|
||||
|
||||
if(get2ops())
|
||||
return;
|
||||
if(ckdreg(&opnd[0])) { /*d reg source*/
|
||||
m = 0600;
|
||||
d = opnd[0].ea;
|
||||
p = &opnd[1];
|
||||
}
|
||||
else if(ckdreg(&opnd[1])) { /*d reg dest*/
|
||||
m = 0400;
|
||||
d = opnd[1].ea;
|
||||
p = &opnd[0];
|
||||
}
|
||||
else {
|
||||
uerr(20);
|
||||
}
|
||||
if((p->ea&070) != INDDISP)
|
||||
uerr(20);
|
||||
if(modelen == 4)
|
||||
m =| 0100;
|
||||
ins[0] =| (d<<9)|m|(p->ea&7);
|
||||
*pins++ = p->con.wd2;
|
||||
*prlb++ = p->drlc;
|
||||
instrlen =+ 2;
|
||||
}
|
||||
|
||||
/* format 22 -- moveq*/
|
||||
opf22()
|
||||
{
|
||||
if(get2ops())
|
||||
return;
|
||||
if(opnd[0].ea != IMM)
|
||||
uerr(17);
|
||||
if(opnd[0].con>255L || opnd[0].con<-256L)
|
||||
uerr(15);
|
||||
if(!ckdreg(&opnd[1]))
|
||||
uerr(33);
|
||||
ins[0] =| (opnd[1].ea<<9) | (opnd[0].con.wd2&0377);
|
||||
}
|
||||
|
||||
/* format 23 -- eor*/
|
||||
opf23()
|
||||
{
|
||||
if(get2ops())
|
||||
return;
|
||||
if (cksprg(&opnd[1],CCR) || cksprg(&opnd[1],SR)) {
|
||||
opcpt = eoriptr;
|
||||
ins[0] = opcpt->vl1.wd2;
|
||||
format = (opcpt->flags)&OPFF;
|
||||
ccr_or_sr();
|
||||
return;
|
||||
}
|
||||
if(!ckdreg(&opnd[0])) {
|
||||
if(makeimm()) /*must be immediate*/
|
||||
return;
|
||||
uerr(20); /*or error*/
|
||||
}
|
||||
if(!dataalt(&opnd[1]) || pcea(&opnd[1]))
|
||||
uerr(20);
|
||||
ins[0] =| (opnd[0].ea<<9)|f23mode[modelen]|opnd[1].ea;
|
||||
doea(&opnd[1]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
$1lo68 -r -o as68.rel -f $1 -unofloat 0$1s.o dir.o expr.o main.o misc.o pass1a.o pass2.o strncmp.o symt.o 0$1lib6.a 0$1clib
|
||||
era *.o
|
||||
|
||||
user 10!make $1
|
||||
@@ -0,0 +1,30 @@
|
||||
/*********************************************************************
|
||||
* STRNCMP - compares strings up to n chars
|
||||
*
|
||||
* WORD strncmp(s1,s2,n)
|
||||
* BYTE *s1, *s2;
|
||||
* UWORD n;
|
||||
*
|
||||
* 'strncmp' compares null terminated strings s1 and s2, and examines
|
||||
* at most n chars.
|
||||
* Always compares at least 1 char.
|
||||
* n < 0 compares many, many characters.
|
||||
* Returns:
|
||||
* strncmp < 0 if s1<s2 (within n chars)
|
||||
* strncmp = 0 if s1=s2 " " "
|
||||
* strncmp > 0 if s1>s2 " " "
|
||||
*********************************************************************/
|
||||
|
||||
#include <portab.h>
|
||||
|
||||
WORD strncmp(s1,s2,n)
|
||||
REG BYTE *s1, *s2;
|
||||
REG WORD n;
|
||||
{
|
||||
for( ; --n > 0 && (*s1 == *s2); s1++, s2++ )
|
||||
{
|
||||
if( *s1 == NULL )
|
||||
return(0);
|
||||
}
|
||||
return(*s1 - *s2);
|
||||
}
|
||||
@@ -0,0 +1,850 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "as68.h"
|
||||
|
||||
/* symbol table and misc routines*/
|
||||
|
||||
int errno;
|
||||
char *ermsg[];
|
||||
char tfilname[];
|
||||
char initfnam[];
|
||||
char ldfn[];
|
||||
char tlab1[];
|
||||
int stdofd;
|
||||
int ftudp;
|
||||
int poslab;
|
||||
|
||||
/*output it for beginning of statement*/
|
||||
opitb()
|
||||
{
|
||||
stbuf[0].itty = ITBS; /*beginning of statement*/
|
||||
stbuf[0].itop = (fchr!=EOLC) ? absln : absln-1;
|
||||
stbuf[1].itty = ITSY; /*label entry*/
|
||||
stbuf[1].itop.ptrw2 = lblpt; /*pointer to symbol or 0*/
|
||||
|
||||
/*put opcode in it buffer*/
|
||||
stbuf[2].itty = ITSY;
|
||||
stbuf[2].itrl = modelen; /*mode of instr(byte, word, long)*/
|
||||
stbuf[2].itop.ptrw2 = opcpt; /*pointer to opcode in main table*/
|
||||
stbuf[3].itty = ITCN;
|
||||
stbuf[3].itrl = rlflg; /*relocation base*/
|
||||
stbuf[3].itop = loctr; /*pass1 location counter*/
|
||||
itwc = ITOP1; /*next available slot-currently 4*/
|
||||
pitw = &stbuf[ITOP1].itty; /*init the pointer*/
|
||||
}
|
||||
|
||||
/*
|
||||
* get an input term (symbol, constant, or special character)
|
||||
* call with:
|
||||
* the first character in fchr
|
||||
* returns:
|
||||
* item type in itype
|
||||
* item value in ival if item is a constant or special character
|
||||
* if it is a symbol it is placed at the end of the main table
|
||||
|
||||
* meaning of state table:
|
||||
|
||||
* currently getting: symbol(0) constant(1) beginning(2)
|
||||
|
||||
* next char:
|
||||
* digit(0) 0 1 1
|
||||
|
||||
* letter(3) 0 3 0
|
||||
|
||||
* special char(6) 3 3 3
|
||||
|
||||
* contents of the state table is the next state. processing stops when
|
||||
* state 3 is encountered. state 2 is the beginning state.
|
||||
*/
|
||||
int sttbl[] {0,1,1,0,3,0,3,3,3}; /*state table for parser*/
|
||||
|
||||
gterm(constpc)
|
||||
int constpc;
|
||||
{
|
||||
register smode, i;
|
||||
register char *p;
|
||||
register int tmode;
|
||||
register char *j;
|
||||
long num;
|
||||
char istr[80];
|
||||
|
||||
/* if(fchr == '\'' || fchr == '"') */ /* Fucking Whitesmith's */
|
||||
if(fchr == 047 || fchr == 042)
|
||||
if(astring()) /*maybe ascii string*/
|
||||
return;
|
||||
smode = 2; /*beginning state*/
|
||||
i = 0;
|
||||
p = istr;
|
||||
|
||||
/*loop to put item on istr*/
|
||||
while(fchr>=' ') { /*until a control char*/
|
||||
if(smode==2 && fchr=='.')
|
||||
tmode = 3;
|
||||
else if(isalpha(fchr) || fchr=='~' || fchr=='_' || (fchr=='$'&&i))
|
||||
tmode=3;
|
||||
else if(isdigit(fchr))
|
||||
tmode=0;
|
||||
else
|
||||
tmode = 6;
|
||||
tmode = sttbl[tmode+smode]; /*new state*/
|
||||
if(tmode==3) break; /*end of item*/
|
||||
smode = tmode;
|
||||
*p++ = fchr; /*save character*/
|
||||
i++;
|
||||
fchr=gchr();
|
||||
}
|
||||
|
||||
/* end of item*/
|
||||
switch(smode) {
|
||||
|
||||
case 0: /*symbol*/
|
||||
*p = '\0'; /*end of symbol*/
|
||||
itype = ITSY; /*symbol*/
|
||||
pack(istr,lmte); /*put symbol at end of main table*/
|
||||
j = lemt(sirt,FALSE);
|
||||
if(istr[0]!='~' && !poslab && (j->flags&(SYEQ|SYER))==SYEQ) {
|
||||
itype = (j->flags&SYRM) ? ITRM : ITCN; /* [vlh] */
|
||||
ival = j->vl1;
|
||||
reloc = ((j->flags)&SYRO) ? TEXT : ((j->flags)&SYRA) ? DATA :
|
||||
((j->flags)&SYBS) ? BSS : ABS;
|
||||
}
|
||||
return;
|
||||
|
||||
case 1: /*constant*/
|
||||
if(!constant(&num,istr,i)) {
|
||||
uerr(17); /*illegal constant*/
|
||||
num = 0;
|
||||
}
|
||||
ival = num;
|
||||
itype = ITCN;
|
||||
reloc = ABS;
|
||||
return;
|
||||
|
||||
case 2: /*just a special char*/
|
||||
switch(fchr) {
|
||||
|
||||
case '*': /*location counter*/
|
||||
if(starmul) { /*multiply*/
|
||||
starmul = 0;
|
||||
goto specsy;
|
||||
}
|
||||
refpc++; /*referenced pgm ctr*/
|
||||
reloc = rlflg; /*relocation of location counter*/
|
||||
ival = loctr;
|
||||
itype = (constpc) ? ITCN : ITPC;
|
||||
break;
|
||||
|
||||
|
||||
case '$': /*hex constant*/
|
||||
oconst(16);
|
||||
return;
|
||||
|
||||
case '@': /*octal const*/
|
||||
oconst(8);
|
||||
return;
|
||||
|
||||
case '%': /*binary const*/
|
||||
oconst(2);
|
||||
return;
|
||||
|
||||
case '#':
|
||||
immed[opdix]++;
|
||||
goto specsy;
|
||||
|
||||
case '(':
|
||||
indir[opdix]++;
|
||||
plevel++;
|
||||
goto specsy;
|
||||
|
||||
case ')':
|
||||
plevel--;
|
||||
goto specsy;
|
||||
|
||||
default:
|
||||
specsy:
|
||||
itype = ITSP; /*return special char*/
|
||||
ival = fchr;
|
||||
}
|
||||
if(fchr != EOLC)
|
||||
fchr=gchr(); /*get next char*/
|
||||
if((ival=='>' && fchr=='>') || (ival=='<' && fchr=='<'))
|
||||
fchr=gchr(); /*shift op, ignore second char*/
|
||||
return;
|
||||
|
||||
default:
|
||||
abort(); /*not possible*/
|
||||
}
|
||||
}
|
||||
|
||||
/*check for an ascii string enclosed in single quotes*/
|
||||
|
||||
astring()
|
||||
{
|
||||
register char delim;
|
||||
|
||||
/* if(fchr != '\'' && fchr != '"') *//*valid delimiter*/
|
||||
if(fchr != 047 && fchr != 042)
|
||||
return;
|
||||
delim = fchr;
|
||||
if(equflg || (itype==ITSP && ival.wd2=='#')) { /*immediate operand*/
|
||||
if(astr1(delim)) {
|
||||
fchr = gchr();
|
||||
if(fchr!=delim)
|
||||
xerr(19);
|
||||
fchr=gchr();
|
||||
}
|
||||
return((equflg) ? 1 : 0);
|
||||
}
|
||||
while(astr1(delim)) {
|
||||
itype = ITSP;
|
||||
ival = ','; /*separate by commas*/
|
||||
reloc = ABS;
|
||||
opitoo();
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
astr1(adelim)
|
||||
{
|
||||
register delim,i,retv;
|
||||
register long l;
|
||||
|
||||
delim = adelim;
|
||||
i = 0; l = 0;
|
||||
retv = 1;
|
||||
while((fchr=gchr()) != EOF) {
|
||||
if(fchr==delim) {
|
||||
fchr = gchr();
|
||||
if(fchr != delim) {
|
||||
retv = 0; /*end of string*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(fchr == EOLC) {
|
||||
xerr(19);
|
||||
retv = 0; /*end of string*/
|
||||
break;
|
||||
}
|
||||
l = (l<<8) | fchr;
|
||||
if(++i >= modelen) {
|
||||
if((fchr=gchr()) == delim) {
|
||||
fchr = gchr();
|
||||
retv = 0; /*end of string*/
|
||||
}
|
||||
else
|
||||
peekc = fchr; /*next char in string*/
|
||||
break; /*filled one bucket*/
|
||||
}
|
||||
}
|
||||
while(i < modelen) {
|
||||
l =<< 8;
|
||||
i++;
|
||||
}
|
||||
itype = ITCN;
|
||||
ival = l;
|
||||
reloc = ABS;
|
||||
if(!equflg)
|
||||
opitoo(); /*output one operand*/
|
||||
return(retv);
|
||||
}
|
||||
|
||||
/*get constant given radix*/
|
||||
oconst(ardx)
|
||||
{
|
||||
register trdx,j;
|
||||
register long i;
|
||||
|
||||
switch (ardx) { /* radix as power of 2 */
|
||||
case 16 : trdx = 4; break;
|
||||
case 8 : trdx = 3; break;
|
||||
case 2 : trdx = 1; break;
|
||||
default :
|
||||
rpterr("invalid radix in oconst");
|
||||
abort();
|
||||
}
|
||||
i=0;
|
||||
while(1) {
|
||||
fchr=gchr();
|
||||
j=fchr;
|
||||
if(isdigit(j))
|
||||
j =- '0';
|
||||
else if((j=tolower(j))>='a' && j<='f')
|
||||
j = j-'a'+10;
|
||||
else
|
||||
break; /*not valid numeric char*/
|
||||
if(j>=0 && j<ardx)
|
||||
i = (i<<trdx)+j;
|
||||
else
|
||||
break;
|
||||
}
|
||||
ival = i;
|
||||
itype = ITCN;
|
||||
reloc = ABS;
|
||||
}
|
||||
|
||||
|
||||
/*convert ascii constant to binary*/
|
||||
constant(pnum,pstr,idx)
|
||||
long *pnum;
|
||||
char *pstr;
|
||||
{
|
||||
register i,j;
|
||||
register char *p;
|
||||
register long l;
|
||||
|
||||
p = pstr;
|
||||
l = 0;
|
||||
for(i=0; i<idx; i++) {
|
||||
j = *pstr++;
|
||||
if(isdigit(j))
|
||||
j =- '0';
|
||||
if(j<0 || j>=10)
|
||||
return(0);
|
||||
l = (l<<3) + (l<<1) + j; /* l = l*10 + j*/
|
||||
}
|
||||
*pnum = l;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* method for looking up entries in the main table
|
||||
*
|
||||
* Note: The entry to be looked up must be placed at the end
|
||||
* of the main table. The global cell 'lmte'(last main
|
||||
* entry) points to the next available entry in the main
|
||||
* table. The address of an initial reference table must
|
||||
* also be provided.
|
||||
*
|
||||
* 1) Compute the hash code for the symbol and add it to the base address
|
||||
* of the initial reference table given as input. Thus, two words are
|
||||
* accessed which define the chain on which the symbol must be if it
|
||||
* is in the table at all.
|
||||
*
|
||||
* 2) Alter the table link of the last symbol in the chain so that it
|
||||
* points to the symbol being looked up. Note that the symbol to be
|
||||
* looked up is always placed at the end of the main table before
|
||||
* calling the lookup routine. This essentially adds one more element
|
||||
* to the end of the chain, namely the symbol to be looked up.
|
||||
*
|
||||
* 3) Now start at the first symbol in the chain and follow the chain
|
||||
* looking for a symbol equal to the smbol being looked up. It is
|
||||
* guaranteed that such a symbol will be found because it is always
|
||||
* the last symbol on the chain.
|
||||
*
|
||||
* 4) When the symbol is found, check to see if it is the last symbol
|
||||
* on the chain. If not, the symbol being looked for is in the table
|
||||
* and has been found. If it is the last symbol, the symbol being
|
||||
* looked up is not in the table.
|
||||
*
|
||||
* 5) In the case the looked up symbol is not found, it is usually added
|
||||
* to the end of the table. This is done simply b changing the
|
||||
* initial reference table entry which points to the previous
|
||||
* last symbol on the chain so that is now points to the symbol at the
|
||||
* end of the main table. In case the symbol just looked up is not to
|
||||
* be added to the main table then no action is needed . This means
|
||||
* that the table link of the last symbol on a chain may point any-
|
||||
* where.
|
||||
*
|
||||
* look up entry in the main table
|
||||
* call with:
|
||||
* address of initial reference table
|
||||
* entry to be looked up at the end of the main table
|
||||
* returns:
|
||||
* a pointer to the entry. if this pointer is equal to
|
||||
* lmte then the symbol was not previously in the table.
|
||||
*/
|
||||
|
||||
char *lemt(airt,oplook)
|
||||
char **airt;
|
||||
int oplook; /* if true then looking in opcode table */
|
||||
{
|
||||
register char *mtpt;
|
||||
register int *p1, *p2;
|
||||
register int i, j;
|
||||
|
||||
if (oplook) { /* [vlh] get rid of preceding '.', to lowercase */
|
||||
if (lmte->name[0]=='.') {
|
||||
lmte->name[NAMELEN-1] = NULL; /* in case of '.' */
|
||||
j = 1;
|
||||
}
|
||||
else j = 0;
|
||||
for (i=0; j<NAMELEN; i++, j++)
|
||||
lmte->name[i] = tolower(lmte->name[j]);
|
||||
}
|
||||
|
||||
pirt = airt + hash(); /*hashed ptr to irt*/
|
||||
mtpt = pirt->irfe; /*pointer to first entry in chain*/
|
||||
if(!mtpt) /*empty chain*/
|
||||
mtpt = lmte; /*start at end of main table*/
|
||||
else
|
||||
(pirt->irle)->tlnk = lmte; /*last entry in chain is new symbol*/
|
||||
|
||||
/*loop to locate entry in main table*/
|
||||
lemtl:
|
||||
p1 = &mtpt->name[0];
|
||||
p2 = &lmte->name[0];
|
||||
i = NAMELEN/(sizeof i);
|
||||
while(i) {
|
||||
if(*p1++ != *p2++) {
|
||||
mtpt = mtpt->tlnk; /*go to next entry in chain*/
|
||||
goto lemtl;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
return(mtpt);
|
||||
}
|
||||
|
||||
/* compute a hash code for the last entry in the main table*/
|
||||
/* returns the hash code*/
|
||||
hash()
|
||||
{
|
||||
register int i;
|
||||
register ht1;
|
||||
register char *p;
|
||||
|
||||
ht1 = 0;
|
||||
p = &lmte->name[0];
|
||||
for(i=0; i<NAMELEN; i++)
|
||||
ht1 =+ *p++;
|
||||
return(ht1&(SZIRT-2)); /*make hash code even and between 0 & SZIRT-2*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Make an entry in the main table
|
||||
* assumes :
|
||||
* entry to be made is pointed at by lmte
|
||||
* pirt points to the correct initial reference table entry.
|
||||
*/
|
||||
mmte()
|
||||
{
|
||||
pirt->irle = lmte; /*pointer to last entry in chain*/
|
||||
if(pirt->irfe == 0) /*first entry in chain*/
|
||||
pirt->irfe = lmte;
|
||||
lmte =+ STESIZE; /*bump last main table entry pointer*/
|
||||
if(lmte>=emte) { /*main table overflow*/
|
||||
if(sbrk(STESIZE*ICRSZMT) == -1){ /*get more memory*/
|
||||
rpterr("symbol table overflow\n");
|
||||
endit();
|
||||
}
|
||||
else {
|
||||
emte =+ STESIZE*ICRSZMT; /*move end of main table*/
|
||||
cszmt =+ ICRSZMT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* make an entry in the main table for a directive
|
||||
* call with:
|
||||
* pointer to string containing directive name
|
||||
* address of routine to handle directive in pass one
|
||||
* address of routine to handle directive in pass two
|
||||
*/
|
||||
mdemt(mdstr,dirnum)
|
||||
char *mdstr;
|
||||
{
|
||||
register char *mdept;
|
||||
|
||||
pack(mdstr,lmte); /*pack name at end of main table*/
|
||||
mdept=lemt(oirt,TRUE); /*look up in opcode table*/
|
||||
if(mdept != lmte) { /*best not be there already*/
|
||||
uerr(5);
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
mmte(); /*make main table entry*/
|
||||
mdept->flags =| OPDR|SYIN; /*directive*/
|
||||
mdept->vl1 = dirnum; /*directive #*/
|
||||
}
|
||||
|
||||
/*
|
||||
* pack a string into an entry in the main table
|
||||
* call with:
|
||||
* pointer to the string
|
||||
* pointer to desired entry in the main table
|
||||
*/
|
||||
pack(apkstr,apkptr)
|
||||
char *apkstr, *apkptr;
|
||||
{
|
||||
register i;
|
||||
register char *pkstr, *pkptr;
|
||||
|
||||
pkstr = apkstr;
|
||||
pkptr = apkptr;
|
||||
i = NAMELEN;
|
||||
while(*pkstr && i) {
|
||||
*pkptr++ = *pkstr++;
|
||||
i--;
|
||||
}
|
||||
while(i--)
|
||||
*pkptr++ = '\0'; /*pad with nulls*/
|
||||
}
|
||||
|
||||
/* function to get characters for source file*/
|
||||
int xcol = 0; /* Column Counter */
|
||||
int spcnt = 0; /* Space count for tab expansion */
|
||||
gchr()
|
||||
{
|
||||
register chr1;
|
||||
|
||||
if(peekc) {
|
||||
chr1 = peekc;
|
||||
peekc = 0;
|
||||
if(chr1 != SOH)
|
||||
xcol--;
|
||||
}
|
||||
else if (spcnt)
|
||||
{
|
||||
spcnt--;
|
||||
return(' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
gchr1:
|
||||
if(sbuflen<=0){ /*nothing on input buffer*/
|
||||
sbuflen=read(ifn,sbuf,512); /*read in source*/
|
||||
if(sbuflen<=0)
|
||||
return(EOF); /*end of file*/
|
||||
psbuf = sbuf;
|
||||
}
|
||||
chr1 = *psbuf++;
|
||||
sbuflen--;
|
||||
}
|
||||
if (chr1 == SOH) /*preprocessor flag*/
|
||||
goto gchr1; /*ignore it*/
|
||||
if(chr1 == EOLC) { /*end of line*/
|
||||
xcol = -1; /* Clear column counter */
|
||||
if(!p2flg) /*pass 1 only*/
|
||||
absln++;
|
||||
}
|
||||
if(chr1=='\t') /*convert tabs to spaces*/
|
||||
{
|
||||
spcnt += 7 - (xcol&7); /* This many spaces */
|
||||
xcol += spcnt; /* New column number */
|
||||
chr1 = ' ';
|
||||
}
|
||||
xcol++;
|
||||
return(chr1);
|
||||
}
|
||||
|
||||
/*
|
||||
* write out intermediate text for one statement
|
||||
* call with
|
||||
* the it for the statement in stbuf
|
||||
*/
|
||||
wostb()
|
||||
{
|
||||
register int woix;
|
||||
register short *itwo;
|
||||
register int i;
|
||||
|
||||
if(stbuf[0].itty != ITBS) abort(); /*not beginning of stmt*/
|
||||
itwo = &stbuf;
|
||||
woix = stbuf[0].itrl & 0377; /*unsigned byte*/
|
||||
while(woix--) {
|
||||
for(i=0; i<(sizeof stbuf[0])/(sizeof *itwo); i++) {
|
||||
doitwr(*itwo++);
|
||||
}
|
||||
}
|
||||
/* debug(); //call debug package*/
|
||||
}
|
||||
|
||||
doitwr(word)
|
||||
short word;
|
||||
{
|
||||
short i;
|
||||
|
||||
if( pitix < itbuf || pitix > &itbuf[ITBSZ] ) {
|
||||
printf("doitwr: it buffer botch\n");
|
||||
endit();
|
||||
}
|
||||
if( pitix >= &itbuf[ITBSZ]) {
|
||||
if(write(itfn,itbuf,ITBSZ*(sizeof i)) != ITBSZ*(sizeof i)) {
|
||||
rpterr("it write error errno=%o\n",errno);
|
||||
endit();
|
||||
}
|
||||
pitix = itbuf;
|
||||
}
|
||||
*pitix++ = word;
|
||||
}
|
||||
|
||||
/*
|
||||
* user source error
|
||||
* call with:
|
||||
* number to indicate reason for error
|
||||
* types the error number and the line number on which
|
||||
* the error occured.
|
||||
*/
|
||||
uerr(errn)
|
||||
{
|
||||
if(p2flg) { /*pass 2 gets two ampersands*/
|
||||
in_err++; /* [vlh] instrlen <- pass1 estimation */
|
||||
printf("&& %d: %s\n",p2absln,ermsg[errn-1]);
|
||||
}
|
||||
else
|
||||
printf("& %d: %s\n",(fchr==EOLC)?absln-1:absln,ermsg[errn-1]);
|
||||
nerror++;
|
||||
}
|
||||
/*
|
||||
* user error that causes the statement to be abandoned
|
||||
* call with:
|
||||
* error number
|
||||
*/
|
||||
xerr(xern)
|
||||
{
|
||||
uerr(xern); /*type error message*/
|
||||
if(!p2flg) /*pass one*/
|
||||
igrst(); /*pass rest of source*/
|
||||
}
|
||||
|
||||
/* abort the assembly*/
|
||||
abort()
|
||||
{
|
||||
rpterr("as68 abort\n");
|
||||
nerror++;
|
||||
endit();
|
||||
}
|
||||
|
||||
/*ignore rest of statement*/
|
||||
igrst()
|
||||
{
|
||||
while(fchr!=EOLC && fchr!=EOF) /*until end of line*/
|
||||
fchr=gchr();
|
||||
while((fchr=gchr())==EOLC) ; /*ignore null lines*/
|
||||
}
|
||||
|
||||
/*ignore blanks after a label*/
|
||||
ligblk()
|
||||
{
|
||||
if(fchr == EOF) return;
|
||||
igblk();
|
||||
if(fchr==EOLC) {
|
||||
fchr=gchr();
|
||||
ligblk();
|
||||
}
|
||||
}
|
||||
|
||||
rubout()
|
||||
{
|
||||
nerror = -1;
|
||||
endit();
|
||||
}
|
||||
|
||||
/* exit from the assembler*/
|
||||
endit()
|
||||
{
|
||||
LASTCHTFN = itfnc;
|
||||
unlink(tfilname); /*delete temporary files*/
|
||||
LASTCHTFN = trbfnc;
|
||||
unlink(tfilname);
|
||||
LASTCHTFN = dafnc;
|
||||
unlink(tfilname);
|
||||
LASTCHTFN = drbfnc;
|
||||
unlink(tfilname);
|
||||
if(nerror != -1) { /*not rubout*/
|
||||
if(ftudp)
|
||||
putchar('\n');
|
||||
}
|
||||
if(nerror > 0) {
|
||||
fprintf(stderr,"& %d errors\n",nerror);
|
||||
}
|
||||
if (initflg)
|
||||
unlink(ldfn); /* [vlh] get rid of empty .o file */
|
||||
exit(nerror!=0);
|
||||
}
|
||||
|
||||
/*
|
||||
* open files
|
||||
* call with:
|
||||
* pointer to name of file to open
|
||||
* flag for how to open
|
||||
* 0 => read
|
||||
* 1 => write
|
||||
*/
|
||||
openfi(pname,hflag)
|
||||
char *pname;
|
||||
{
|
||||
register fd;
|
||||
|
||||
fd = (hflag==1) ? creat(pname,0666,1) : open(pname,hflag,1);
|
||||
if(fd < 0) { /*open failed*/
|
||||
rpterr("can't open %s errno=%o\n",pname,errno);
|
||||
endit();
|
||||
}
|
||||
return(fd);
|
||||
}
|
||||
|
||||
/* get a temp file for the intermediate text*/
|
||||
char lastfile = 'A';
|
||||
gettempf()
|
||||
{
|
||||
register i,j;
|
||||
register char *p;
|
||||
|
||||
LASTCHTFN = lastfile++; /* Creat temp name */
|
||||
if((j=creat(tfilname,0600,1)) >= 0)
|
||||
return(j); /* File created OK */
|
||||
rpterr("Unable to open temporary file\n");
|
||||
endit();
|
||||
}
|
||||
|
||||
/* move label name from lbt to main table entry pointed to by lmte*/
|
||||
setname()
|
||||
{
|
||||
register i;
|
||||
register int *p1, *p2;
|
||||
|
||||
p1 = &lmte->name[0];
|
||||
for(p2 = &lbt[0]; p2 < &lbt[NAMELEN]; ) {
|
||||
*p1++ = *p2;
|
||||
*p2++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the initialized main table and initial reference tables from*/
|
||||
/* the initialize file*/
|
||||
getsymtab()
|
||||
{
|
||||
long j; /* length for read / write */
|
||||
register char **p;
|
||||
register struct symtab *p1;
|
||||
register char *p2;
|
||||
register fd,i;
|
||||
|
||||
if((fd=open(initfnam,0,1)) < 0) {
|
||||
rerr:
|
||||
printf("& Unable to read init file: %s\n", initfnam);
|
||||
endit();
|
||||
}
|
||||
if(read(fd,sirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) {
|
||||
goto rerr;
|
||||
}
|
||||
|
||||
if(read(fd,oirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0]))
|
||||
goto rerr;
|
||||
|
||||
if(read(fd,&j,(sizeof j)) != (sizeof j)) /* Read Count */
|
||||
goto rerr; /* Y-U-K!!! */
|
||||
|
||||
if((i=read(fd,bmte,(int)j)) != j) /* Read table */
|
||||
goto rerr;
|
||||
|
||||
if((i%STESIZE) != 0)
|
||||
goto rerr;
|
||||
|
||||
lmte = bmte + i;
|
||||
p2 = bmte-1;
|
||||
for(p=sirt; p<&sirt[SZIRT]; p++) {
|
||||
if(*p)
|
||||
*p =+ (long)p2;
|
||||
}
|
||||
for(p=oirt; p<&oirt[SZIRT]; p++) {
|
||||
if(*p)
|
||||
*p =+ (long)p2;
|
||||
}
|
||||
for(p1=bmte; p1<lmte; p1++) {
|
||||
if(p1->tlnk)
|
||||
p1->tlnk =+ (long)p2;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* write the initialization file*/
|
||||
putsymtab()
|
||||
{
|
||||
long j;
|
||||
register char **p;
|
||||
register struct symtab *p1;
|
||||
register char *p2;
|
||||
register fd,i;
|
||||
|
||||
if((fd=creat(initfnam,0644,1))<0) {
|
||||
printf("& Cannot create init: %s\n", initfnam);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* change all pointers so that they are relative to the beginning
|
||||
* of the symbol table
|
||||
*/
|
||||
p2 = bmte-1;
|
||||
for(p=sirt; p<&sirt[SZIRT]; p++) {
|
||||
if(*p)
|
||||
*p =- (long)p2;
|
||||
}
|
||||
for(p=oirt; p<&oirt[SZIRT]; p++) {
|
||||
if(*p)
|
||||
*p =- (long)p2;
|
||||
}
|
||||
for(p1=bmte; p1<lmte; p1++) {
|
||||
if(p1->tlnk)
|
||||
p1->tlnk =- (long)p2;
|
||||
}
|
||||
|
||||
if(write(fd,sirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) {
|
||||
goto werr;
|
||||
}
|
||||
|
||||
if(write(fd,oirt,SZIRT*(sizeof oirt[0])) != SZIRT*(sizeof oirt[0]))
|
||||
goto werr;
|
||||
|
||||
i = lmte - bmte; /*length of current main table*/
|
||||
if((i % STESIZE) != 0) {
|
||||
goto werr;
|
||||
}
|
||||
j = i;
|
||||
if(write(fd,&j,(sizeof j)) != (sizeof j)) /* Y-U-K!! */
|
||||
goto werr;
|
||||
|
||||
if(write(fd,bmte,i) != i) {
|
||||
werr:
|
||||
printf("& Write error on init file: %s\n",initfnam);
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* print an error on file descriptor 2*/
|
||||
/* used for errors with disasterous consequences*/
|
||||
rpterr(ptch,x1,x2,x3,x4,x5,x6)
|
||||
char *ptch;
|
||||
{
|
||||
if(prtflg==0) /* Check for paging output */
|
||||
page(); /* Perform page checks */
|
||||
fprintf(stderr,"& %d: ",absln);
|
||||
fprintf(stderr,ptch,x1,x2,x3,x4,x5,x6);
|
||||
}
|
||||
|
||||
/* set the file name for the relocatable object file (sourcefile.o)*/
|
||||
setldfn(ap)
|
||||
char *ap;
|
||||
{
|
||||
register char *p1,*p2;
|
||||
|
||||
p1 = ap;
|
||||
p2 = ldfn;
|
||||
while(*p1) {
|
||||
*p2++ = *p1++;
|
||||
}
|
||||
if(*(p2-2) != '.') { /*not name.?*/
|
||||
*p2++ = '.';
|
||||
*p2++ = 'o';
|
||||
}
|
||||
else { /* is name.? */
|
||||
*(p2-1) = 'o';
|
||||
}
|
||||
*p2 = '\0';
|
||||
}
|
||||
|
||||
savelab()
|
||||
{
|
||||
register int *p1, *p2;
|
||||
|
||||
p2 = &lmte->name[0];
|
||||
for(p1= &tlab1[0]; p1 < &tlab1[NAMELEN]; )
|
||||
*p1++ = *p2++;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
e:vax DIR.C s
|
||||
e:vax EXPR.C s
|
||||
e:vax MAIN.C s
|
||||
e:vax MISC.C s
|
||||
e:vax PASS1A.C s
|
||||
e:vax PASS2.C s
|
||||
e:vax MAKE.SUB s
|
||||
e:vax STRNCMP.C s
|
||||
e:vax SYMT.C s
|
||||
e:vax VERSION.C s
|
||||
e:vax AS68.H s
|
||||
e:vax COUT.H s
|
||||
e:vax CTYPE.H s
|
||||
e:vax MACHINE.H s
|
||||
e:vax RELINK.SUB s
|
||||
e:vax MACHINE.11 s
|
||||
e:vax MACHINE.68K s
|
||||
e:vax MACHINE.VAX s
|
||||
e:vax AS68INIT. s
|
||||
@@ -0,0 +1 @@
|
||||
char *version "@(#) Tue Nov 23 14:31";
|
||||
@@ -0,0 +1,15 @@
|
||||
$ asm
|
||||
$ !
|
||||
$ ! as68 Version 2.3 make file for VMS
|
||||
$ !
|
||||
$ set noon
|
||||
$ copy machine.vax machine.h
|
||||
$ cx AS68INIT
|
||||
$ cx DIR
|
||||
$ cx EXPR
|
||||
$ cx MAIN
|
||||
$ cx MISC
|
||||
$ cx PASS1A
|
||||
$ cx PASS2
|
||||
$ cx SYMT
|
||||
$ @vrelink
|
||||
@@ -0,0 +1 @@
|
||||
$ clink AS68INIT,DIR,EXPR,MAIN,PASS1A,PASS2,SYMT,MISC,lib:klib/lib as68
|
||||
@@ -0,0 +1,3 @@
|
||||
c68 -L -e *.c -o c068.68 -l6
|
||||
c68 -L -r -n -e *.c -o c068.st -l6
|
||||
cc -f *.c -o c068.11 -lP -lx
|
||||
@@ -0,0 +1,968 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#define DREG 0100 /*data loadable into D-register?*/
|
||||
|
||||
char dinfo[] {
|
||||
0, /*TYPELESS=0*/
|
||||
1|DREG, /*CHAR=1*/
|
||||
2|DREG, /*SHORT=2*/
|
||||
2|DREG, /*INT=3*/
|
||||
4|DREG, /*LONG=4*/
|
||||
1|DREG, /*UCHAR=5*/
|
||||
2|DREG, /*USHORT=6*/
|
||||
2|DREG, /*UNSIGNED=7*/
|
||||
4|DREG, /*ULONG=8*/
|
||||
4|DREG, /*FLOAT=9[vlh]*/
|
||||
4|DREG, /*DOUBLE=10[vlh]*/
|
||||
0, /*STRUCT=11*/
|
||||
0, /*FRSTRUCT=12*/
|
||||
0, /*LLABEL=13*/
|
||||
0, /*INVALID=14*/
|
||||
0, /*INVALID=15*/
|
||||
};
|
||||
|
||||
char aregtab[] { AREG5, AREG4, AREG3, 0 };
|
||||
char dregtab[] { DREG7, DREG6, DREG5, DREG4, DREG3, 0 };
|
||||
int inittype;
|
||||
|
||||
/*
|
||||
* doextdef - external definition syntax
|
||||
* This is fairly complicated since you do not know if you are
|
||||
* parsing a external function declaration or a real function
|
||||
* until after you've already scanned the argument list for the
|
||||
* function. Basically you start off scanning an external declaration
|
||||
* or function in the same way by collecting attributes, scanning
|
||||
* the declarator, then scanning the function arguments if a function.
|
||||
* At that point you look at the next token and if its a '{', keyword
|
||||
* proceed accordingly.
|
||||
* The C Syntax handled by this routine is (roughly):
|
||||
* external_definition:
|
||||
* function_definition
|
||||
* data_definition
|
||||
* function_definition:
|
||||
* type_specifier function_declarator function_body
|
||||
* function_declarator:
|
||||
* declarator ( parameter_list )
|
||||
* data_definition:
|
||||
* EXTERNAL type_specifier init_declarator_list ;
|
||||
* STATIC type_specifier init_declarator_list ;
|
||||
*/
|
||||
doextdef() /* returns 0 for EOF or 1*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
register int dflag;
|
||||
int sc, type;
|
||||
long size;
|
||||
|
||||
if(!next(SEMI)) {
|
||||
opap = exprp = exprarea;
|
||||
sc = EXTERNAL;
|
||||
type = (xflag?LONG:INT);
|
||||
dflag = gettype(&sc,&type,&size);
|
||||
if(type==STRUCT) /* deal with forward ref structures */
|
||||
chksyms();
|
||||
while( dodecl(sc,type,0,size), (sp=dsp) != 0 ) {
|
||||
if( !dflag && notfunction(sp->s_type) ) {
|
||||
synerr("external definition syntax");
|
||||
return;
|
||||
}
|
||||
if( !stypedef(sp) && sc != STATIC )
|
||||
if (notfunction(sp->s_type)) /*[vlh] .globl ext. vars*/
|
||||
outextdef(sp->s_symbol);
|
||||
if( notfunction(sp->s_type) ) { /*not function, check init*/
|
||||
if( !stypedef(sp) ) {
|
||||
doinit(sp);
|
||||
if (sc == STATIC)
|
||||
chksyms();
|
||||
}
|
||||
}
|
||||
else if( peek(RESWORD) || peek(LCURBR) ||
|
||||
(peek(SYMBOL) && stypedef(csp)) ) {
|
||||
if(!stypedef(sp) && sc!=STATIC) /*[vlh] .globl local proc*/
|
||||
outextdef(sp->s_symbol);
|
||||
funcbody(sp);
|
||||
return;
|
||||
}
|
||||
dsp = 0;
|
||||
if( !next(COMMA) )
|
||||
break;
|
||||
}
|
||||
if( gettok() != SEMI )
|
||||
synerr("external definition syntax");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gettype - get attribute types in attribute list
|
||||
* Handles single word keywords, such as int, char, etc. and also
|
||||
* handles the declarations of structures and unions.
|
||||
*/
|
||||
gettype(defsc,deftype,size) /* returns 0 for no type, 1 otherwise*/
|
||||
int *defsc; /* default storage class*/
|
||||
int *deftype; /* default data type*/
|
||||
long *size; /* size of data element 3.4 int=>long*/
|
||||
{
|
||||
register int dtype, sc;
|
||||
register int sflag, uflag, lflag, decflag;
|
||||
register int token, stdflag, sbits;
|
||||
long tsize;
|
||||
register struct symbol *sp, *parent;
|
||||
|
||||
tdp = 0; tdflag = uflag = decflag = lflag = sflag = 0; tsize = 0L;
|
||||
dtype = TYPELESS;
|
||||
sc = *defsc;
|
||||
for( ; ; decflag++ ) {
|
||||
if( (token=gettok()) == SYMBOL && stypedef(csp) ) {
|
||||
dtype = 0;
|
||||
tdp = csp;
|
||||
continue;
|
||||
}
|
||||
if( token != RESWORD )
|
||||
break;
|
||||
switch( cvalue ) {
|
||||
|
||||
case R_TYPEDEF:
|
||||
if( tdflag )
|
||||
error("invalid typedef statement");
|
||||
tdflag++;
|
||||
continue;
|
||||
|
||||
case R_STATIC:
|
||||
if( sc && sc != STATIC && sc != EXTERNAL )
|
||||
error("invalid storage class");
|
||||
sc = STATIC;
|
||||
continue;
|
||||
|
||||
case R_AUTO:
|
||||
if( sc && sc != AUTO )
|
||||
error("invalid storage class");
|
||||
sc = AUTO;
|
||||
continue;
|
||||
|
||||
case R_EXTERNAL:
|
||||
if( sc && sc != EXTERNAL )
|
||||
error("invalid storage class");
|
||||
sc = EXTERNAL;
|
||||
continue;
|
||||
|
||||
case R_REGISTER:
|
||||
if( sc && sc != REGISTER && sc != PDECLIST )
|
||||
error("invalid register specification");
|
||||
sc = REGISTER;
|
||||
continue;
|
||||
|
||||
case R_LONG:
|
||||
lflag++;
|
||||
continue;
|
||||
|
||||
case R_SHORT:
|
||||
sflag++;
|
||||
continue;
|
||||
|
||||
case R_UNSIGNED:
|
||||
uflag++;
|
||||
continue;
|
||||
|
||||
case R_STRUCT:
|
||||
cvalue = STRUCT;
|
||||
case R_UNION:
|
||||
stdflag = tdflag;
|
||||
tdflag = 0; sp = 0;
|
||||
token = cvalue;
|
||||
smember++;
|
||||
if( next(SYMBOL) ) { /*struct [symbol] { ... }*/
|
||||
sp = csp;
|
||||
parent = csp;
|
||||
strucptr[smember+instruct] = sp;
|
||||
if( !sp->s_sc ) {
|
||||
sp->s_attrib =| SDEFINED;
|
||||
if(!infunc)
|
||||
sp->s_attrib =| SGLOBAL;
|
||||
sp->s_sc = STRPROTO;
|
||||
sp->s_type = STRUCT;
|
||||
sp->s_ssp = dalloc(0L);
|
||||
}
|
||||
if( sp->s_sc != STRPROTO )
|
||||
error("redeclaration: %.8s",sp->s_symbol);
|
||||
}
|
||||
else parent = 0;
|
||||
smember = 0;
|
||||
if( next(LCURBR) ) {
|
||||
instruct++;
|
||||
strucptr[smember+instruct] = sp;
|
||||
sbits = boffset;
|
||||
boffset = 0;
|
||||
tsize = dlist(token==STRUCT?STELCL:UNELCL);
|
||||
boffset = sbits;
|
||||
if(!next(RCURBR))
|
||||
synerr("structure declaration syntax");
|
||||
else if( sp ) {
|
||||
if( dtab[sp->s_ssp] )
|
||||
error("redeclaration: %.8s",sp->s_symbol);
|
||||
dtab[sp->s_ssp] = tsize;
|
||||
}
|
||||
instruct--;
|
||||
}
|
||||
else if( !sp )
|
||||
error("no structure name");
|
||||
else if( sp->s_sc != STRPROTO )
|
||||
error("invalid structure prototype: %.8s",sp->s_symbol);
|
||||
else if( !dtab[sp->s_ssp] ) { /* FRSTRUCT */
|
||||
token = FRSTRUCT;
|
||||
if( ++frstp >= NFRSTR )
|
||||
ferror("structure table overflow");
|
||||
frstab[frstp] = sp;
|
||||
}
|
||||
else
|
||||
tsize = dtab[sp->s_ssp];
|
||||
tdflag = stdflag;
|
||||
if( dtype != TYPELESS )
|
||||
error("invalid type declaration");
|
||||
dtype = (token == R_UNION) ? STRUCT : token;
|
||||
continue;
|
||||
|
||||
case R_INT:
|
||||
if( dtype != TYPELESS )
|
||||
error("invalid type declaration");
|
||||
dtype = INT;
|
||||
continue;
|
||||
|
||||
case R_CHAR:
|
||||
if( dtype != TYPELESS )
|
||||
error("invalid type declaration");
|
||||
dtype = CHAR;
|
||||
continue;
|
||||
|
||||
case R_FLOAT: /*[vlh] ver. 3.4*/
|
||||
case R_DOUBLE:
|
||||
if( dtype != TYPELESS )
|
||||
error("invalid type declaration");
|
||||
dtype = FLOAT;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pbtok(token);
|
||||
if( dtype == TYPELESS )
|
||||
dtype = INT;
|
||||
if(!sc)
|
||||
sc = AUTO;
|
||||
if( lflag ) { /*allow: long float, long int*/
|
||||
if( dtype == INT )
|
||||
dtype = LONG;
|
||||
/* else if( dtype == FLOAT ) */
|
||||
/* dtype = DOUBLE; */
|
||||
else
|
||||
error("invalid long declaration");
|
||||
}
|
||||
if( sflag ) {
|
||||
if( dtype != INT )
|
||||
error("invalid short declaration");
|
||||
}
|
||||
if( uflag ) {
|
||||
if( dtype != INT ) /*allow: unsigned int*/
|
||||
error("invalid unsigned declaration");
|
||||
else
|
||||
dtype = UNSIGNED;
|
||||
}
|
||||
if( !sflag && xflag && dtype == INT )
|
||||
dtype = LONG;
|
||||
*defsc = sc;
|
||||
*deftype = dtype;
|
||||
*size = tsize;
|
||||
if (dtype == STRUCT || dtype == FRSTRUCT)
|
||||
csp->s_struc = parent;
|
||||
return(decflag);
|
||||
}
|
||||
|
||||
/*
|
||||
* dodecl - process a single declarator
|
||||
* This does all the grubby handling of a single declarator given
|
||||
* the attributes for the declarator. Handles typedef attributes
|
||||
* adjusts offsets for structure elements, allocates register
|
||||
* variables, etc.
|
||||
*/
|
||||
long /* [vlh] 3.4 int => long */
|
||||
dodecl(sc,type,offset,size) /* returns size of declarator*/
|
||||
int sc; /* storage class*/
|
||||
int type; /* data type*/
|
||||
int offset; /* offset if in structure or union*/
|
||||
long size; /* size of single data item 3.4 i=> l*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
register int redecf, stype, dtype, i, j;
|
||||
|
||||
if( peek(SEMI) || peek(RPAREN) )
|
||||
return(0);
|
||||
if( instruct && next(COLON) ) { /*handle bit filler field*/
|
||||
if(!(i=cexpr()))
|
||||
size = salign(INT,offset);
|
||||
else
|
||||
size = falign(type,i);
|
||||
}
|
||||
else if( (type=|declarator(0)) >= 0 && (sp=dsp) != 0 ) {
|
||||
if( tdp ) /*typedef name in declaration*/
|
||||
type = addtdtype(tdp,type,sp->s_dp,&(sp->s_ssp));
|
||||
else if( btype(type) == STRUCT ) {
|
||||
if( size )
|
||||
sp->s_ssp = dalloc(size);
|
||||
else
|
||||
error("invalid structure declaration: %.8s",sp->s_symbol);
|
||||
}
|
||||
else if( btype(type) == FRSTRUCT )
|
||||
sp->s_ssp = frstp;
|
||||
redecf = 0;
|
||||
switch( sp->s_sc ) { /*check for redeclarations.*/
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case PARMLIST:
|
||||
if( sc != PDECLIST && sc != REGISTER )
|
||||
goto redec;
|
||||
break;
|
||||
|
||||
case BFIELDCL:
|
||||
if( sc != STELCL && sc != UNELCL )
|
||||
goto redec;
|
||||
break;
|
||||
|
||||
case STELCL:
|
||||
case UNELCL:
|
||||
redecf++;
|
||||
break; /* [vlh] get rid of redecf entirely ?? */
|
||||
|
||||
case EXTERNAL:
|
||||
if (sp->s_type == type) {
|
||||
if (sc == sp->s_sc) break;
|
||||
if (sc == AUTO && suptype(type) == FUNCTION) {
|
||||
sc = EXTERNAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
redec:
|
||||
error("redeclaration: %.8s",sp->s_symbol);
|
||||
return(size);
|
||||
}
|
||||
sp->s_type = type;
|
||||
dtype = suptype(type);
|
||||
type = btype(type);
|
||||
if( tdflag ) /*we are declaring typedef?*/
|
||||
sp->s_attrib =| STYPEDEF;
|
||||
if( instruct ) {
|
||||
if( next(COLON) ) { /*handle bit field*/
|
||||
sc = BFIELDCL;
|
||||
i = cexpr();
|
||||
j = (boffset<<8)|i;
|
||||
if( redecf && sp->s_dp != j ) /* ??? */
|
||||
goto redec;
|
||||
sp->s_dp = j;
|
||||
size = j = falign(type,i);
|
||||
}
|
||||
else
|
||||
size = dsize(sp->s_type,sp->s_dp,sp->s_ssp) +
|
||||
(j=salign(type,offset));
|
||||
offset =+ j;
|
||||
/* if( redecf && sp->s_offset != offset )
|
||||
goto redec; */ /* [vlh] */
|
||||
sp->s_offset = offset;
|
||||
}
|
||||
if( dtype == FUNCTION ) {
|
||||
if( sc != AUTO && sc != EXTERNAL && sc != STATIC )
|
||||
error("illegal function declaration");
|
||||
if( sc != STATIC )
|
||||
sc = EXTERNAL;
|
||||
}
|
||||
else if( sc == REGISTER ) {
|
||||
if( !dtype ) {
|
||||
if( !(dinfo[type]&DREG) ) { /* ignore reg specification */
|
||||
/* error("illegal register specification"); */
|
||||
sc = AUTO;
|
||||
}
|
||||
else if( !dregtab[ndregs] )
|
||||
sc = AUTO;
|
||||
else
|
||||
sp->s_offset = dregtab[ndregs++];
|
||||
}
|
||||
else if( dtype != POINTER ) {
|
||||
error("illegal register specification");
|
||||
sc = AUTO; /*no more regs, make it auto*/
|
||||
}
|
||||
else if( !aregtab[naregs] )
|
||||
sc = AUTO;
|
||||
else
|
||||
sp->s_offset = aregtab[naregs++];
|
||||
}
|
||||
if( sc == AUTO ) {
|
||||
localsize =+ walign(dsize(sp->s_type,sp->s_dp,sp->s_ssp));
|
||||
sp->s_offset = -localsize;
|
||||
}
|
||||
else if( sc == STATIC )
|
||||
sp->s_offset = nextlabel++;
|
||||
sp->s_sc = sc;
|
||||
sp->s_attrib =| SDEFINED;
|
||||
if(!infunc)
|
||||
sp->s_attrib =| SGLOBAL;
|
||||
}
|
||||
return(size);
|
||||
}
|
||||
|
||||
/*
|
||||
* doinit - do external definition initialization
|
||||
* Handles following C syntax:
|
||||
* initializer:
|
||||
* = constant_expression
|
||||
* = { initializer_list }
|
||||
* = { initializer_list , }
|
||||
* initializer_list:
|
||||
* constant_expression
|
||||
* initializer_list , initializer_list
|
||||
* { initializer_list }
|
||||
*/
|
||||
doinit(sp) /* returns number of elements init'ed*/
|
||||
struct symbol *sp; /* pointer to symbol to init*/
|
||||
{
|
||||
register int type;
|
||||
long isize, datasize, elsize;
|
||||
|
||||
type = sp->s_type;
|
||||
datasize = dsize(type,sp->s_dp,sp->s_ssp);
|
||||
if( peek(COMMA) || peek(SEMI) ) { /*no initialization*/
|
||||
isize = walign(datasize);
|
||||
if( sp->s_sc == EXTERNAL )
|
||||
outcommon(sp->s_symbol,isize);
|
||||
else {
|
||||
outbss(); /*bss segment*/
|
||||
outlab(sp->s_offset);
|
||||
outresmem(isize);
|
||||
outtext(); /*resume text segment*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
next(ASSIGN); /*ignore '=' if there*/
|
||||
if( type == LONG || pointer(type) )
|
||||
outldata();
|
||||
else if(type == DOUBLE || type == FLOAT) /*[vlh] 3.4*/
|
||||
outfpdata();
|
||||
else
|
||||
outdata();
|
||||
if( sp->s_sc == EXTERNAL )
|
||||
outdlab(sp->s_symbol);
|
||||
else
|
||||
outlab(sp->s_offset);
|
||||
isize = initlist(sp->s_type,sp->s_dp,sp->s_ssp);
|
||||
if( isize < datasize ) {
|
||||
outresmem(datasize-isize);
|
||||
isize = datasize;
|
||||
}
|
||||
if( walign(isize) != isize )
|
||||
outpad();
|
||||
if( isize > datasize ) {
|
||||
if( array(sp->s_type) ) {
|
||||
for( type = sp->s_type; array(type); type = delsp(type) )
|
||||
;
|
||||
dtab[sp->s_dp] = isize / dsize(type,sp->s_dp,sp->s_ssp);
|
||||
}
|
||||
else
|
||||
error("too many initializers");
|
||||
}
|
||||
if( sp->s_sc == STATIC )
|
||||
outtext();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* initlist - handles initializer lists
|
||||
* This handles multi-level braces, and a character pointer pointing
|
||||
* to a string. Most of the work is in keeping track of how many
|
||||
* bytes are left on the current "row", and outputting padding if
|
||||
* necessary.
|
||||
*/
|
||||
long
|
||||
initlist(type,dp,sp) /* returns size of initializers in*/
|
||||
/* bytes*/
|
||||
int type; /* type of data*/
|
||||
int dp; /* dimension pointer*/
|
||||
int sp; /* structure pointer*/
|
||||
{
|
||||
register int nrows;
|
||||
long datasize, i, elsize, nbleft, nbout; /* [vlh] 3.4 int=>long */
|
||||
register int onetype;
|
||||
|
||||
for( onetype = type; array(onetype); onetype = delsp(onetype) )
|
||||
;
|
||||
nbout = 0;
|
||||
datasize = dsize(type,dp,sp);
|
||||
nbleft = 0; /*keep track of no. of bytes left*/
|
||||
if( type == (ARRAY|CHAR) && next(STRING) ) {
|
||||
nbout = cstrsize;
|
||||
outstr();
|
||||
if( datasize > nbout )
|
||||
nbleft = datasize - nbout;
|
||||
}
|
||||
else if( array(type) || (btype(type)==STRUCT && notpointer(type)) ) {
|
||||
elsize = datasize / dsize(delsp(type),dp+1,sp);
|
||||
elsize = datasize / elsize;
|
||||
if(!next(LCURBR))
|
||||
error("missing { in initialization");
|
||||
if( type == (ARRAY|CHAR) && next(STRING) ) {
|
||||
nbout = cstrsize;
|
||||
outstr();
|
||||
if( datasize > nbout )
|
||||
nbleft = datasize - nbout;
|
||||
}
|
||||
else {
|
||||
do { /*in current row.*/
|
||||
if( peek(SEMI) || peek(EOF) )
|
||||
break;
|
||||
if( peek(LCURBR) ) { /*recurse down one level?*/
|
||||
if( nbleft ) {
|
||||
outresmem(nbleft); /*pad rest of current row*/
|
||||
nbout =+ nbleft;
|
||||
nbleft = 0;
|
||||
}
|
||||
i = initlist(delsp(type),dp+1,sp);
|
||||
if( i > elsize )
|
||||
error("initializer list too long");
|
||||
else if( i < elsize )
|
||||
outresmem(elsize-i);
|
||||
nbout =+ elsize;
|
||||
}
|
||||
else if( peek(RCURBR) )
|
||||
break;
|
||||
else {
|
||||
i = oneinit(onetype);
|
||||
nbout =+ i;
|
||||
if(!nbleft)
|
||||
nbleft = elsize;
|
||||
if( i > nbleft )
|
||||
error("initializer alignment");
|
||||
nbleft = (i >= nbleft) ? 0 : nbleft - i;
|
||||
}
|
||||
} while( next(COMMA) );
|
||||
}
|
||||
if(!next(RCURBR))
|
||||
synerr("missing }");
|
||||
}
|
||||
else {
|
||||
i = next(LCURBR); /*pull of optional {*/
|
||||
nbout = oneinit(onetype);
|
||||
if( i && !next(RCURBR) )
|
||||
synerr("missing }");
|
||||
}
|
||||
if( nbleft ) { /*pad current row*/
|
||||
outresmem(nbleft);
|
||||
nbout =+ nbleft;
|
||||
}
|
||||
return(nbout);
|
||||
}
|
||||
|
||||
/*
|
||||
* oneinit - get one initializer expression or constant
|
||||
* This checks the type of the data item expected against the
|
||||
* type obtained from expr. Note that there is no attempt to
|
||||
* match structure initializations against the elements of the
|
||||
* structure, hence, anything goes in a structure.
|
||||
*/
|
||||
oneinit(type) /* returns size of initializer*/
|
||||
int type; /* type of initializer*/
|
||||
{
|
||||
register int op, value;
|
||||
register struct tnode *tp;
|
||||
|
||||
commastop++;
|
||||
tp = expr();
|
||||
commastop--;
|
||||
op = tp->t_op;
|
||||
value = tp->t_value;
|
||||
switch( alltype(type) ) {
|
||||
|
||||
case CHAR:
|
||||
case ARRAY|CHAR:
|
||||
if( op != CINT )
|
||||
break;
|
||||
outc(CHAR,value);
|
||||
return(1);
|
||||
|
||||
case INT:
|
||||
case ARRAY|INT:
|
||||
if( op == CLONG || op == ADDR )
|
||||
if (op == CLONG && clvalue == -32768) { /*[vlh] 4.0*/
|
||||
op = CINT;
|
||||
value = -32768;
|
||||
}
|
||||
else
|
||||
break;
|
||||
if( op == CINT )
|
||||
outc(INT,value);
|
||||
else
|
||||
outinit(tp,inittype);
|
||||
return(2);
|
||||
|
||||
case UNSIGNED: /* [vlh] 4.0 split from INT... */
|
||||
case ARRAY|UNSIGNED:
|
||||
if (op == ADDR)
|
||||
break;
|
||||
if( op == CLONG ) { /* get unsigned values > legit pos ints */
|
||||
if (clvalue < 0L || clvalue > 65535L)
|
||||
break;
|
||||
op = CINT;
|
||||
value = clvalue & 0x7fff;
|
||||
if (clvalue > 32767)
|
||||
value = -value;
|
||||
}
|
||||
else if (op == CINT && value < 0)
|
||||
break;
|
||||
if( op == CINT )
|
||||
outc(INT,value);
|
||||
else
|
||||
outinit(tp,inittype);
|
||||
return(2);
|
||||
|
||||
case LONG:
|
||||
case ARRAY|LONG:
|
||||
case POINTER|CHAR:
|
||||
case POINTER|INT:
|
||||
case POINTER|LONG:
|
||||
case POINTER|STRUCT:
|
||||
case POINTER|UNSIGNED:
|
||||
if( op == CINT ) {
|
||||
clvalue = value; /*[vlh] fix ??? MC ??? */
|
||||
outlong(clvalue);
|
||||
}
|
||||
else if( op == CLONG )
|
||||
outlong(clvalue);
|
||||
else
|
||||
outinit(tp,inittype);
|
||||
return(4);
|
||||
|
||||
case DOUBLE: /* [vlh] 3.4 */
|
||||
case FLOAT:
|
||||
outfp(clvalue);
|
||||
return(4);
|
||||
|
||||
case STRUCT:
|
||||
case ARRAY|STRUCT:
|
||||
if( op == CINT ) {
|
||||
if( xflag ) {
|
||||
clvalue = value;
|
||||
outlong(clvalue);
|
||||
return(4);
|
||||
}
|
||||
outc(INT,value);
|
||||
return(2);
|
||||
}
|
||||
if( op == CLONG ) {
|
||||
outlong(clvalue);
|
||||
return(4);
|
||||
}
|
||||
outinit(tp,inittype);
|
||||
if (xflag || op==ADDR)
|
||||
return(4);
|
||||
if ((op=tp->t_right->t_op)==ADDR || op==CLONG) /*[vlh]*/
|
||||
return(4);
|
||||
if ((op=tp->t_left->t_op)==ADDR || op==CLONG) /*[vlh]*/
|
||||
return(4);
|
||||
return(2);
|
||||
}
|
||||
error("invalid initializer");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* funcbody - do function body declaration
|
||||
* Basically handles function after we have scanned the parameter
|
||||
* list, which is now set up in fargs array. We now proceed to
|
||||
* look for any declarations for the function arguments, then the
|
||||
* function declaration list, followed by the function statement list.
|
||||
* The C syntax is:
|
||||
* function_body:
|
||||
* type_decl_list function_statement
|
||||
* function_statement:
|
||||
* { declaration_list statement_list }
|
||||
*/
|
||||
funcbody(fsp)
|
||||
struct symbol *fsp;
|
||||
{
|
||||
register int olddp;
|
||||
register struct symbol *sp;
|
||||
register struct farg *fp;
|
||||
register int offset, toff;
|
||||
|
||||
infunc++;
|
||||
sp = fsp;
|
||||
opap = exprp;
|
||||
frp = snalloc(delsp(sp->s_type),sp->s_sc,sp->s_type,sp->s_dp,
|
||||
sp->s_ssp);
|
||||
exprp = opap;
|
||||
outtext();
|
||||
outflab(sp->s_symbol);
|
||||
olddp = cdp;
|
||||
dlist(PDECLIST);
|
||||
rlabel = nextlabel++;
|
||||
if(!next(LCURBR))
|
||||
synerr("function body syntax");
|
||||
else {
|
||||
localsize = 0; /*end of first auto offset from l.e.p.*/
|
||||
offset = 8; /*first arg offset from l.e.p.*/
|
||||
for( fp = &fargtab[0]; sp = fp->f_sp; fp++ ) {
|
||||
toff = offset;
|
||||
if( sp->s_type == CHAR ) /*char argument*/
|
||||
toff++; /*offset of lower byte in word*/
|
||||
if( sp->s_sc == REGISTER )
|
||||
fp->f_offset = toff;
|
||||
else {
|
||||
fp->f_offset = 0; /*really is auto arg*/
|
||||
sp->s_offset = toff;
|
||||
sp->s_sc = AUTO;
|
||||
}
|
||||
if( array(sp->s_type) ) { /*change array ref to pointer*/
|
||||
sp->s_type = addsp(delsp(sp->s_type),POINTER);
|
||||
sp->s_dp++;
|
||||
}
|
||||
offset =+ walign(dsize(sp->s_type,sp->s_dp,sp->s_ssp));
|
||||
}
|
||||
dlist(0);
|
||||
chksyms();
|
||||
outbentry(localsize,ndregs,naregs);
|
||||
copyargs(); /*copy args to registers where required*/
|
||||
while(!next(RCURBR)) {
|
||||
if( next(EOF) ) {
|
||||
error("{ not matched by }");
|
||||
break;
|
||||
}
|
||||
stmt();
|
||||
}
|
||||
}
|
||||
outlab(rlabel);
|
||||
outbexit(ndregs,naregs);
|
||||
cdp = olddp;
|
||||
infunc--;
|
||||
freesyms();
|
||||
}
|
||||
|
||||
/*
|
||||
* copyargs - copy args to register where required
|
||||
* fargtab has been set so that args declared to be registers have a
|
||||
* non-zero offset value and the register number is in the symbol
|
||||
* table pointed to by symbol.
|
||||
*/
|
||||
copyargs() /* returns - none*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
register struct farg *fp;
|
||||
|
||||
for( fp = &fargtab[0]; sp = fp->f_sp; fp++ ) {
|
||||
if( fp->f_offset ) /*was declared register*/
|
||||
outassign(snalloc(sp->s_type,sp->s_sc,sp->s_offset,0,0),
|
||||
snalloc(sp->s_type,AUTO,fp->f_offset,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dlist - declaration list
|
||||
* Handles declaration lists in the following places:
|
||||
* function parameter list declarations, structure or union member
|
||||
* declarations and local declarations in functions.
|
||||
*/
|
||||
long
|
||||
dlist(defsc) /* returns length of declarators*/
|
||||
int defsc; /* default storage class*/
|
||||
{
|
||||
register int offset;
|
||||
register struct symbol *sp;
|
||||
register long i, ddsize;
|
||||
long size; /* [vlh] 3.4 int => long */
|
||||
int type, sc, isize;
|
||||
|
||||
offset = 0; ddsize = 0L;
|
||||
do {
|
||||
sc = defsc;
|
||||
type = INT;
|
||||
if( !gettype(&sc,&type,&size) )
|
||||
break;
|
||||
do {
|
||||
i = dodecl(sc,type,offset,size);
|
||||
if( defsc != UNELCL ) {
|
||||
isize = i;
|
||||
offset =+ isize;
|
||||
ddsize =+ i;
|
||||
}
|
||||
else if( i > ddsize )
|
||||
ddsize = i;
|
||||
if( sc == STATIC && dsp && !stypedef(dsp) )
|
||||
doinit(dsp); /*process any initializer*/
|
||||
dsp = 0;
|
||||
} while ( next(COMMA) );
|
||||
if (next(ASSIGN)) {
|
||||
synerr("auto initialization not implemented");
|
||||
break;
|
||||
}
|
||||
if(!next(SEMI)) {
|
||||
synerr("declaration syntax");
|
||||
break;
|
||||
}
|
||||
} while( 1 );
|
||||
isize = ddsize;
|
||||
ddsize =+ salign(INT,isize);
|
||||
return(ddsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* declarator - get one declarator
|
||||
* Basically uses getdecl, which returns the declaration types
|
||||
* reversed in the type word.
|
||||
*/
|
||||
declarator(castflg) /* returns type or -1*/
|
||||
int castflg;
|
||||
{
|
||||
register int type, t;
|
||||
|
||||
dsp = 0;
|
||||
if( (type=getdecl(castflg)) >= 0 )
|
||||
return( revsp(type) );
|
||||
return(type);
|
||||
}
|
||||
|
||||
/*
|
||||
* getdecl - get one declarator, handling *, (), etc.
|
||||
* The significance of the value returned by declarator is: the
|
||||
* least significant two bits represent the values (POINTER,FUNCTION,
|
||||
* ARRAY), these values are repeated through the word. For example,
|
||||
* the declarations result in the following values for declarator:
|
||||
* *x() => (POINTER,FUNCTION)
|
||||
* (*x)() => (FUNCTION,POINTER)
|
||||
* *(*x)() => (POINTER,FUNCTION,POINTER)
|
||||
* The following C syntax is handled here:
|
||||
* function_declarator:
|
||||
* declarator ( parameter_list )
|
||||
* declarator:
|
||||
* identifier
|
||||
* ( declarator )
|
||||
* * declarator
|
||||
* declarator [ constant-expression ]
|
||||
*/
|
||||
getdecl(castflg) /* returns special type of declarator*/
|
||||
int castflg; /* casting flag, 1=>allow no declarator*/
|
||||
{
|
||||
register int type, i, value, sdp;
|
||||
register struct symbol *sp, *tsp;
|
||||
register struct farg *fp;
|
||||
register char *p;
|
||||
long lvalue;
|
||||
|
||||
type = 0;
|
||||
if( next(LPAREN) ) { /*( declarator ) ...*/
|
||||
type = getdecl(castflg);
|
||||
if(!next(RPAREN))
|
||||
goto baddec;
|
||||
}
|
||||
if( next(MULT) )
|
||||
return(addsp(getdecl(castflg),POINTER));
|
||||
sdp = cdp;
|
||||
if( next(SYMBOL) ) {
|
||||
sp = dsp = csp;
|
||||
type = 0;
|
||||
sp->s_dp = sdp;
|
||||
}
|
||||
while( 1 ) {
|
||||
if( next(LPAREN) ) { /*declarator ( ... )*/
|
||||
if(!infunc) {
|
||||
ndregs = naregs = 0;
|
||||
for( fp = &fargtab[0]; next(SYMBOL); ) {
|
||||
p = csp;
|
||||
if( p->s_attrib & SDEFINED )
|
||||
error("redeclaration: %.8s",p->s_symbol);
|
||||
else if( fp >= &fargtab[NFARGS-1] ) {
|
||||
synerr("too many params");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
p->s_attrib =| SDEFINED;
|
||||
p->s_sc = PARMLIST;
|
||||
p->s_type = INT; /*default to int*/
|
||||
fp->f_sp = p;
|
||||
fp++;
|
||||
}
|
||||
if(!next(COMMA))
|
||||
break;
|
||||
}
|
||||
fp->f_sp = 0;
|
||||
}
|
||||
if(!next(RPAREN))
|
||||
break;
|
||||
type = addsp(type,FUNCTION);
|
||||
continue;
|
||||
}
|
||||
if( next(LBRACK) ) { /*declarator [ cexpr ]*/
|
||||
if( next(RBRACK) )
|
||||
dalloc(1L);
|
||||
else {
|
||||
tsp = dsp; /* [vlh] 3.4 save in case of reset */
|
||||
value = cexpr(); /* recurses on sizeof.... resets dsp */
|
||||
dsp = tsp; /* [vlh] 3.4 */
|
||||
lvalue = value; /* [vlh] 3.4 */
|
||||
for( i = sdp; i < cdp; )
|
||||
dtab[i++] =* lvalue;
|
||||
dalloc(lvalue);
|
||||
if( !next(RBRACK) )
|
||||
break;
|
||||
}
|
||||
type = addsp(type,ARRAY);
|
||||
continue;
|
||||
}
|
||||
if( castflg || dsp )
|
||||
return(type);
|
||||
break;
|
||||
}
|
||||
baddec:
|
||||
synerr("invalid declarator");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* addtdtype - add typedef info into declarator
|
||||
* here we very carefully add in the dimensions for an array typedef
|
||||
* declaration. Note that declarator has already allocated the
|
||||
* declarator-specific dimensions, now we allocate the typedef
|
||||
* dimensions and adjust the size of the declarator's dimensions.
|
||||
* Note that this must be done before the dalloc for the structure,
|
||||
* otherwise we would mix up array and structure sizes.
|
||||
*/
|
||||
addtdtype(tddp,type,dp,ssp) /* returns type*/
|
||||
struct symbol *tddp;
|
||||
int type;
|
||||
int dp;
|
||||
int *ssp;
|
||||
{
|
||||
register int ntype, t, i, tdf;
|
||||
|
||||
for( tdf = 0, t = tddp->s_type; suptype(t); t = delsp(t) )
|
||||
if( array(t) ) {
|
||||
tdf++;
|
||||
break;
|
||||
}
|
||||
ntype = 0;
|
||||
for( t = type, i = dp; suptype(t); t = delsp(t) ) {
|
||||
ntype = addsp(ntype,t);
|
||||
if( tdf && array(t) )
|
||||
dtab[i++] =* dtab[tddp->s_dp];
|
||||
}
|
||||
for( t = tddp->s_type, i = tddp->s_dp; suptype(t); t = delsp(t) )
|
||||
if( array(t) )
|
||||
dalloc(dtab[i++]);
|
||||
for( t = tddp->s_type; suptype(ntype); ntype = delsp(ntype) )
|
||||
t = addsp(t,ntype);
|
||||
if( (ntype=btype(t)) == STRUCT )
|
||||
*ssp = tddp->s_ssp;
|
||||
else if( ntype == FRSTRUCT )
|
||||
*ssp = frstp;
|
||||
return(t);
|
||||
}
|
||||
@@ -0,0 +1,910 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
int opdontop;
|
||||
int strassign;
|
||||
|
||||
/*
|
||||
* expr - expression evaluator
|
||||
* This handles all the expression syntax in C. This is a straight-
|
||||
* forward operator-stack/oppri scheme for translating infix into
|
||||
* a binary expression tree.
|
||||
*/
|
||||
char *expr() /* returns 0 or ptr to node*/
|
||||
{
|
||||
register char *p;
|
||||
register char *opdsave, *oprsave;
|
||||
register int token, op, oppri, i, opdotsave;
|
||||
int type, sc;
|
||||
long size;
|
||||
|
||||
opdsave = opdp;
|
||||
strassign = 0;
|
||||
oprsave = opp;
|
||||
opdotsave = opdontop;
|
||||
if( !opp || !opdp ) {
|
||||
opp = opstack;
|
||||
opdp = opdstack;
|
||||
}
|
||||
else
|
||||
opp++;
|
||||
opp->o_op = STACKEND;
|
||||
opp->o_pri = STKPRI;
|
||||
opap = exprp;
|
||||
opdontop = 0;
|
||||
|
||||
while( (token=gettok()) != EOF ) {
|
||||
switch( token ) {
|
||||
/*
|
||||
* the following are the terminal nodes of the expresion tree,
|
||||
* note that when we see a terminal node, we push it and then go
|
||||
* and get the next token. When we see an operator, we need to
|
||||
* check the operator stack to see if we can do a reduction.
|
||||
*/
|
||||
case CINT:
|
||||
if( doopd(cnalloc(INT,cvalue)) ) {
|
||||
exprerr:
|
||||
if( token == SEMI || token == RCURBR )
|
||||
pbtok(token);
|
||||
error("invalid expression");
|
||||
opdp = opdsave;
|
||||
opp = oprsave;
|
||||
opdontop = opdotsave;
|
||||
return(0);
|
||||
}
|
||||
continue;
|
||||
|
||||
case CFLOAT: /*[vlh] 3.4*/
|
||||
if( doopd(fpcnalloc(FLOAT,clvalue)) )
|
||||
goto exprerr;
|
||||
continue;
|
||||
|
||||
case CLONG:
|
||||
if( doopd(lcnalloc(LONG,clvalue)) )
|
||||
goto exprerr;
|
||||
continue;
|
||||
|
||||
case SYMBOL:
|
||||
if( !((p=csp)->s_attrib&SDEFINED) ) {
|
||||
if( peek(LPAREN) ) { /*assume function call*/
|
||||
p->s_sc = EXTERNAL;
|
||||
p->s_type = FUNCTION|INT;
|
||||
}
|
||||
else if( commastop ) /*in initialization?*/
|
||||
p->s_sc = EXTERNAL;
|
||||
else
|
||||
error("undefined symbol: %.8s",p->s_symbol);
|
||||
p->s_attrib =| SDEFINED;
|
||||
}
|
||||
if (p->s_sc==EXTERNAL || function(p->t_type)) {
|
||||
if (!reducep || p->s_sc==EXTERNAL || peek(LPAREN)) {
|
||||
p = enalloc(p);
|
||||
p->t_sc = EXTERNAL;
|
||||
}
|
||||
else { /* [vlh] 3.4 if (main).... */
|
||||
p = cnalloc(CINT,1); /* eval function name */
|
||||
}
|
||||
}
|
||||
else
|
||||
p=snalloc(p->s_type,p->s_sc,p->s_offset,p->s_dp,p->s_ssp);
|
||||
if( doopd(p) )
|
||||
goto exprerr;
|
||||
continue;
|
||||
|
||||
case STRING:
|
||||
outtstr(cvalue);
|
||||
if( doopd(snalloc(ARRAY|CHAR,STATIC,cvalue,0,0)) )
|
||||
goto exprerr;
|
||||
continue;
|
||||
/*
|
||||
* do special checking for unary ops and operators that can be
|
||||
* either unary or binary operators, such as -, &, *, etc.
|
||||
*/
|
||||
case RESWORD:
|
||||
if( cvalue != R_SIZEOF ) {
|
||||
goto exprerr;
|
||||
}
|
||||
token = SIZEOF;
|
||||
case COMPL:
|
||||
case NOT:
|
||||
if( opdontop ) /*can't have: operand unary-op*/
|
||||
goto exprerr;
|
||||
break;
|
||||
|
||||
case LBRACK:
|
||||
opdontop = 0;
|
||||
break;
|
||||
|
||||
case RBRACK:
|
||||
case RPAREN:
|
||||
if( !opdontop ) /*can't be: operator )*/
|
||||
goto exprerr;
|
||||
break;
|
||||
|
||||
case PREINC:
|
||||
if( opdontop ) /*assume its lvalue++*/
|
||||
token = POSTINC;
|
||||
break;
|
||||
|
||||
case PREDEC:
|
||||
if( opdontop ) /*assume its lvalue--*/
|
||||
token = POSTDEC;
|
||||
break;
|
||||
|
||||
case SUB:
|
||||
if(!opdontop) { /*if no operand, assume unary*/
|
||||
if( peek(CINT) ) {
|
||||
cvalue = -cvalue;
|
||||
continue;
|
||||
}
|
||||
if( peek(CLONG) ) {
|
||||
clvalue = -clvalue;
|
||||
continue;
|
||||
}
|
||||
if( peek(CFLOAT) ) { /*[vlh] 3.4*/
|
||||
if (!fflag) { /* IEEE format */
|
||||
if (clvalue & 0x80000000)
|
||||
clvalue =& 0x7fffffff;
|
||||
else
|
||||
clvalue =| 0x80000000;
|
||||
}
|
||||
else /* FFP format */
|
||||
if (clvalue & 0x80)
|
||||
clvalue =& 0xffffff7f;
|
||||
else
|
||||
clvalue =| 0x80;
|
||||
continue;
|
||||
}
|
||||
token = UMINUS;
|
||||
}
|
||||
break;
|
||||
|
||||
case AND:
|
||||
if(!opdontop)
|
||||
token = ADDR;
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
if( !opdontop )
|
||||
token = INDR;
|
||||
break;
|
||||
/*
|
||||
* for left parenthesis, we need to see if this is a casting operator.
|
||||
*/
|
||||
|
||||
case LPAREN:
|
||||
if( !opdontop ) { /*see if casting or abstract declarator*/
|
||||
sc = type = 0;
|
||||
if( gettype(&sc,&type,&size) ) {
|
||||
sc = (type == STRUCT) ? dalloc(size) : cdp;
|
||||
p = snalloc(type,STATIC,0,sc,sc);
|
||||
p->t_type =| declarator(1);
|
||||
if( !next(RPAREN) )
|
||||
goto exprerr;
|
||||
if( tdp )
|
||||
p->t_type=addtdtype(tdp,p->t_type,p->t_dp,
|
||||
&(p->t_ssp));
|
||||
pushopd(p);
|
||||
token = CAST;
|
||||
if( opp->o_op == SIZEOF ) {
|
||||
opdontop++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /*we've seen (), look for NACALL*/
|
||||
token = (next(RPAREN)) ? MPARENS : CALL;
|
||||
break;
|
||||
|
||||
case PERIOD:
|
||||
case APTR:
|
||||
smember++; /*next token needs to be struct membr*/
|
||||
strucptr[smember+instruct] = csp->s_struc;
|
||||
break;
|
||||
|
||||
}
|
||||
/*
|
||||
* we have seen an operator, get its info and then check the operator
|
||||
* stack.
|
||||
*/
|
||||
if( binop(token) ) {
|
||||
/*
|
||||
* handle special binary operators, such as CAST and post-inc and
|
||||
* post-dec.
|
||||
*/
|
||||
if(!opdontop) {
|
||||
if( token != PREDEC && token != PREINC && token != CAST )
|
||||
goto exprerr;
|
||||
}
|
||||
if( token != POSTDEC && token != POSTINC && token != MPARENS )
|
||||
opdontop = 0; /*this fixes x++ op problem.*/
|
||||
}
|
||||
oppri = oppriority(token);
|
||||
if( commastop && token == COMMA ) /*need to stop at comma(init)*/
|
||||
oppri = COLPRI;
|
||||
if( colonstop && token == COLON ) /*need to stop at colon(case)*/
|
||||
oppri = COLPRI;
|
||||
while( 1 ) {
|
||||
if( oppri > opp->o_pri ||
|
||||
(oppri == opp->o_pri && rasop(token)) ) {
|
||||
/*
|
||||
* we have encountered a higher priority (or right-associative)
|
||||
* operator, hence we need to stack it.
|
||||
*/
|
||||
if( ++opp >= &opstack[OPSSIZE] )
|
||||
ferror("expression too complex");
|
||||
if( token == POSTINC || token == POSTDEC )
|
||||
oppri = PSTPRI;
|
||||
else if( token == LPAREN || token == LBRACK ||
|
||||
token == CALL )
|
||||
oppri = CALPRI;
|
||||
opp->o_op = token;
|
||||
opp->o_pri = oppri;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* we have encountered a lower priority operator, hence we need to
|
||||
* do a reduction.
|
||||
*/
|
||||
op = opp->o_op;
|
||||
opp--;
|
||||
type = CINT;
|
||||
switch( op ) {
|
||||
|
||||
case STACKEND: /*we accept the expression...*/
|
||||
pbtok(token);
|
||||
if (!strassign) {
|
||||
if (!maketree(0))
|
||||
goto exprerr;
|
||||
}
|
||||
if (!(p=popopd()))
|
||||
goto exprerr;
|
||||
opdp = opdsave;
|
||||
opp = oprsave;
|
||||
opdontop = opdotsave;
|
||||
return(p);
|
||||
|
||||
case LPAREN: /*assure these have matching )*/
|
||||
case CALL:
|
||||
if( token != RPAREN )
|
||||
goto exprerr;
|
||||
break;
|
||||
|
||||
case MPARENS:
|
||||
if( !maketree(NACALL) )
|
||||
goto exprerr;
|
||||
continue;
|
||||
|
||||
case LBRACK:
|
||||
if( token != RBRACK )
|
||||
goto exprerr;
|
||||
if(!maketree(ADD)) /*array[index]->*(array+index)*/
|
||||
goto exprerr;
|
||||
op = INDR;
|
||||
break;
|
||||
|
||||
case PREINC: /*turn these into binary operators*/
|
||||
case POSTINC: /*which in reality they are...*/
|
||||
case PREDEC:
|
||||
case POSTDEC:
|
||||
pushopd(cnalloc(INT,1));
|
||||
default:
|
||||
if(!maketree(op))
|
||||
goto exprerr;
|
||||
continue; /*see if we can reduce some more...*/
|
||||
}
|
||||
if( op != LPAREN && !maketree(op) )
|
||||
goto exprerr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
error("unexpected EOF");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* doopd - handle constant or symbol node operand*/
|
||||
/* Pushes node onto operand stack and handles opdontop flag.*/
|
||||
doopd(tp) /* returns 1 if syntax error, 0 for ok*/
|
||||
struct tnode *tp; /* pointer to tree node*/
|
||||
{
|
||||
pushopd(tp);
|
||||
if( opdontop )
|
||||
return(1);
|
||||
opdontop++;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This indicates if a conversion operator is needed given the types
|
||||
* of the two operands. The upper diagonal is applied ONLY if this
|
||||
* is an assignment operator and the indexes are swapped so the lower
|
||||
* diagonal is used otherwise.
|
||||
*INT UNSN LONG DOUB PTR
|
||||
*/
|
||||
char cvmap[5][5] {
|
||||
0, UNSN_INT, LONG_INT, DOUB_INT, PTR_INT,
|
||||
INT_UNSN, 0, LONG_UNSN, DOUB_UNSN, PTR_UNSN,
|
||||
INT_LONG, UNSN_LONG, 0, DOUB_LONG, PTR_LONG,
|
||||
INT_DOUB, UNSN_DOUB, LONG_DOUB, 0, BADCONV,
|
||||
INT_PTR, UNSN_PTR, LONG_PTR, BADCONV, PTR_PTR,
|
||||
};
|
||||
|
||||
/*
|
||||
* maketree - given operator, takes operands and builds up tree
|
||||
* This takes the given operator, allocates a node for it
|
||||
* and links up the subtrees on the operand stack. A lot of
|
||||
* work is in inserting the proper conversions.
|
||||
*/
|
||||
maketree(op) /* returns success or failure */
|
||||
int op; /* new root operator*/
|
||||
{
|
||||
register struct tnode *ltp, *rtp, *p;
|
||||
register int type, ltype, rtype, lconv, conv, pconv, ilen, docast;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("maketree op = %d\n",op);
|
||||
#endif
|
||||
if( binop(op) ) {
|
||||
if(!(rtp=popopd()))
|
||||
return(0);
|
||||
rtype = (rtp=funcref(arrayref(rtp)))->t_type;
|
||||
#ifdef DEBUG
|
||||
putexpr("maketree r",rtp);
|
||||
#endif
|
||||
}
|
||||
if(!(ltp=popopd()))
|
||||
return(0);
|
||||
#ifdef DEBUG
|
||||
putexpr("maketree l",ltp);
|
||||
#endif
|
||||
if( op == SIZEOF ) { /* [vlh] 3.4 ilen */
|
||||
ilen = dsize(ltp->t_type,ltp->t_dp,ltp->t_ssp);
|
||||
pushopd(cnalloc(INT,ilen));
|
||||
return(1);
|
||||
}
|
||||
if( op != ADDR ) {
|
||||
ltp = arrayref(ltp);
|
||||
if( op != CALL && op != NACALL )
|
||||
ltp = funcref(ltp);
|
||||
}
|
||||
else { /* [vlh] 4.0 &p->array */
|
||||
if (ltp->t_op == ADD) /* there must be a better way... */
|
||||
if (ltp->t_left->t_op==SYMBOL && ltp->t_right->t_op==CINT) {
|
||||
pushopd(ltp);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
if( specops(op,ltp,rtp) )
|
||||
return( 1 );
|
||||
ltype = ltp->t_type;
|
||||
if( lintegral(op) )
|
||||
integral(ltp,LONG);
|
||||
if( rintegral(op) )
|
||||
integral(rtp,LONG);
|
||||
if( lvalop(op) && ltp->t_op != SYMBOL && ltp->t_op != INDR &&
|
||||
ltp->t_op != BFIELD )
|
||||
error("assignable operand required");
|
||||
if( unaryop(op) ) {
|
||||
if(!unopeval(op,ltp))
|
||||
pushopd(tnalloc(op,ltype,ltp->t_dp,ltp->t_ssp,ltp,0L));
|
||||
return;
|
||||
}
|
||||
if( ltype == STRUCT || rtype == STRUCT ) {
|
||||
if (ltype==STRUCT && rtype==STRUCT && op==ASSIGN) { /*[vlh]*/
|
||||
pushopd(ltp);
|
||||
maketree(ADDR);
|
||||
pushopd(rtp);
|
||||
maketree(ADDR);
|
||||
maketree(STASSIGN);
|
||||
strassign = 1;
|
||||
return(1);
|
||||
}
|
||||
ltype = rtype = INT;
|
||||
error("illegal structure operation");
|
||||
}
|
||||
type = ltype;
|
||||
if( rtype == TYPELESS ) {
|
||||
rtp->t_type = rtype = INT;
|
||||
lconv = conv = 0;
|
||||
}
|
||||
else {
|
||||
lconv = ttoconv(ltype);
|
||||
conv = ttoconv(rtype);
|
||||
if (!asgop(op) && conv > lconv) {
|
||||
conv = cvmap[conv][lconv];
|
||||
lconv = 1;
|
||||
type = rtype;
|
||||
}
|
||||
else {
|
||||
conv = cvmap[lconv][conv];
|
||||
lconv = 0;
|
||||
}
|
||||
}
|
||||
if( asgop(op) ) {
|
||||
if( (op == ASSIGN || op == FRETURN) && (conv == INT_PTR ||
|
||||
conv == UNSN_PTR) && rtp->t_op != CINT )
|
||||
error("short assigned to pointer");
|
||||
if( op == ASSIGN || op == CAST ) {
|
||||
switch( conv ) {
|
||||
|
||||
case INT_PTR:
|
||||
case UNSN_PTR:
|
||||
case PTR_PTR:
|
||||
case PTR_LONG:
|
||||
case LONG_PTR:
|
||||
conv = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( op == COLON && suptype(ltype) != 0 && ltype == rtype )
|
||||
conv = 0;
|
||||
else if( relop(op) && conv == PTR_PTR )
|
||||
conv = 0;
|
||||
pconv = 0;
|
||||
if ((relop(op) || op==FRETURN) && alltype(ltype) == (STRUCT | POINTER)
|
||||
&& (conv == INT_PTR || conv == LONG_PTR)) /* [vlh] 3.4 */
|
||||
conv = 0; /* int compare to struct pointer, no conversion */
|
||||
if( conv == PTR_PTR ) {
|
||||
conv = 0;
|
||||
if( op == SUB ) {
|
||||
type = LONG;
|
||||
pconv++;
|
||||
}
|
||||
else if(op != FRETURN && ( (alltype(ltype) != alltype(rtype) ||
|
||||
alltype(ltype) != (POINTER|CHAR)) ) )
|
||||
conv = BADCONV;
|
||||
}
|
||||
docast=(ltp->t_type==CHAR && rtp->t_sc!=REGISTER && rtp->t_sc<=STATIC);
|
||||
if( conv ) {
|
||||
if( conv == BADCONV )
|
||||
error("illegal type conversion");
|
||||
else if( lconv )
|
||||
ltp = cvopgen(ltp,type,conv,psize(rtp),op);
|
||||
else
|
||||
rtp = cvopgen(rtp,type,conv,psize(ltp),op);
|
||||
}
|
||||
if( op == CAST ) { /* [vlh] 4.0 */
|
||||
if ( docast ) /* predefined to handle conv/cast ops */
|
||||
rtp = tnalloc(TOCHAR,CHAR,0,0,rtp,0L);
|
||||
else if ( rtp->t_type != CHAR && !conv ) {
|
||||
rtp->t_type = ltp->t_type;
|
||||
rtp->t_ssp = ltp->t_ssp; /* [vlh] 3.4 */
|
||||
rtp->t_dp = ltp->t_dp; /* [vlh] 3.4 */
|
||||
}
|
||||
pushopd(rtp);
|
||||
}
|
||||
if( relop(op) )
|
||||
type = INT;
|
||||
if(op != CAST && !binopeval(op,ltp,rtp)) {
|
||||
if( btype(ltype) == STRUCT || btype(rtype) != STRUCT )
|
||||
p = ltp;
|
||||
else
|
||||
p = rtp;
|
||||
pushopd(tnalloc(op,type,p->t_dp,p->t_ssp,ltp,rtp));
|
||||
}
|
||||
if( pconv && ltype != (POINTER|CHAR) ) {
|
||||
if(!(ltp=popopd()))
|
||||
return(0);
|
||||
pushopd(cvopgen(ltp,LONG,PTR_LONG,psize(ltp->t_left),op));
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* specops - handle special operators in building tree*/
|
||||
specops(op,ltp,rtp) /* returns 1 if op special, 0 otherwise*/
|
||||
int op; /* operator*/
|
||||
struct tnode *ltp; /* left subtree pointer*/
|
||||
struct tnode *rtp; /* right subtree pointer*/
|
||||
{
|
||||
register int type, sr_size, sl_size;
|
||||
|
||||
type = ltp->t_type;
|
||||
#ifdef DEBUG
|
||||
putexpr("specops l",ltp);
|
||||
putexpr("specops r",rtp);
|
||||
#endif
|
||||
switch (op) {
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
return(0);
|
||||
|
||||
case APTR: /*expr -> name*/
|
||||
integral(ltp,LONG); /*we need to turn expr into a*/
|
||||
ltp->t_type = POINTER|STRUCT; /*pointer to a struct, then use*/
|
||||
pushopd(ltp); /*expr . name stuff*/
|
||||
maketree(INDR);
|
||||
ltp = popopd(); /*ltp cannot be 0*/
|
||||
case PERIOD: /*expr . name*/
|
||||
if( !(isstel(rtp)) )
|
||||
error("invalid structure member name");
|
||||
type = rtp->t_type;
|
||||
if( array(type) ) {
|
||||
type = delspchk(type);
|
||||
rtp->t_dp++;
|
||||
}
|
||||
tadjust(ltp,type,rtp->t_dp,rtp->t_ssp);
|
||||
pushopd(ltp);
|
||||
maketree(ADDR);
|
||||
pushopd(cnalloc(TYPELESS,rtp->t_offset));
|
||||
maketree(ADD);
|
||||
if( notarray(rtp->t_type) )
|
||||
maketree(INDR);
|
||||
ltp = popopd();
|
||||
if( rtp->t_sc == BFIELDCL ) /*ltp cannot be 0*/
|
||||
ltp = tnalloc(BFIELD,type,rtp->t_dp,rtp->t_ssp,ltp,0L);
|
||||
break;
|
||||
|
||||
case QMARK:
|
||||
if( rtp->t_op != COLON )
|
||||
error("invalid ?: operator syntax");
|
||||
if( ltp->t_op == CINT && rtp->t_left->t_op == CINT &&
|
||||
rtp->t_right->t_op == CINT )
|
||||
ltp->t_value = (ltp->t_value ? rtp->t_left->t_value :
|
||||
rtp->t_right->t_value);
|
||||
else
|
||||
ltp = tnalloc(op,rtp->t_type,0,0,ltp,rtp);
|
||||
break;
|
||||
|
||||
case LAND:
|
||||
case LOR:
|
||||
case COMMA: /*don't need conversions here*/
|
||||
ltp = tnalloc(op,INT,0,0,ltp,rtp);
|
||||
break;
|
||||
|
||||
case INDR:
|
||||
if( ltp->t_op == ADDR ) /**& is null op*/
|
||||
ltp = ltp->t_left;
|
||||
else {
|
||||
if( function(type) )
|
||||
error("indirection on function invalid");
|
||||
ltp = tnalloc(INDR,delspchk(type),ltp->t_dp,ltp->t_ssp,ltp,0L);
|
||||
}
|
||||
break;
|
||||
|
||||
case STASSIGN: /*[vlh]*/
|
||||
sr_size = psize(rtp);
|
||||
sl_size = psize(ltp);
|
||||
if( sl_size >= sr_size )
|
||||
ltp = tnalloc(STASSIGN,sr_size,0,0,ltp,rtp);
|
||||
else
|
||||
error("invalid structure assignment");
|
||||
break;
|
||||
|
||||
case NACALL:
|
||||
case CALL:
|
||||
if( notfunction(type) )
|
||||
error("illegal call");
|
||||
ltp = tnalloc(op,delspchk(type),ltp->t_dp,ltp->t_ssp,ltp,rtp);
|
||||
break;
|
||||
|
||||
case ADDR:
|
||||
if( ltp->t_op == INDR ) { /*&* is null op*/
|
||||
/* ltp->t_left->t_type = addsp(type,POINTER);*/
|
||||
/* ltp->t_left->t_dp = ltp->t_dp;*/
|
||||
/* ltp->t_left->t_ssp = ltp->t_ssp;*/
|
||||
ltp = ltp->t_left;
|
||||
}
|
||||
else if( ltp->t_op == SYMBOL ) {
|
||||
if( ltp->t_sc == REGISTER )
|
||||
error("address of register");
|
||||
ltp = tnalloc(ADDR,addsp(type,POINTER),ltp->t_dp,ltp->t_ssp,
|
||||
ltp,0L);
|
||||
}
|
||||
else
|
||||
error("& operator illegal");
|
||||
break;
|
||||
}
|
||||
pushopd(ltp);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* cvopgen - generate a conversion operator*/
|
||||
/* Generates conversions necessary for integers, pointers and longs.*/
|
||||
char *cvopgen(tp,type,conv,len,op) /* returns pointer to conv node*/
|
||||
struct tnode *tp; /* pointer to node to do conversion*/
|
||||
int type; /* type to convert to*/
|
||||
int conv; /* specified conversion*/
|
||||
long len; /* object length [vlh] 3.4 i=>l */
|
||||
int op; /* for cast operator*/
|
||||
{
|
||||
register struct tnode *rtp;
|
||||
register int cop, ilen;
|
||||
|
||||
switch(conv) {
|
||||
|
||||
case INT_PTR:
|
||||
case UNSN_PTR:
|
||||
if (type == (POINTER|CHAR) && op == CAST ) { /* [vlh] 4.0 */
|
||||
cop = INT2L;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if( op == CAST || op == FRETURN ) {
|
||||
cop = INT2L; /*of the ptd to objects length plus*/
|
||||
if( len != 1L ) { /*an integer to long covnversion*/
|
||||
ilen = len;
|
||||
rtp = cnalloc(INT,ilen);
|
||||
tp = tnalloc(MULT,type,0,0,tp,rtp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTR_LONG: /*need to generate mult or div*/
|
||||
case LONG_PTR: /*of the ptd to objects length*/
|
||||
if( len == 1 )
|
||||
return(tp);
|
||||
ilen = len;
|
||||
cop = (conv == PTR_LONG ? DIV : MULT);
|
||||
rtp = cnalloc(INT,ilen);
|
||||
break;
|
||||
|
||||
case INT_LONG:
|
||||
case UNSN_LONG:
|
||||
cop = INT2L;
|
||||
break;
|
||||
|
||||
case INT_DOUB: /*[vlh] 3.4*/
|
||||
case UNSN_DOUB:
|
||||
cop = INT2F;
|
||||
break;
|
||||
|
||||
case LONG_DOUB: /*[vlh] 3.4*/
|
||||
cop = LONG2F;
|
||||
break;
|
||||
|
||||
case DOUB_LONG: /*[vlh] 3.4*/
|
||||
cop = FLOAT2L;
|
||||
break;
|
||||
|
||||
case DOUB_INT: /*[vlh] 3.4*/
|
||||
case DOUB_UNSN:
|
||||
cop = FLOAT2I;
|
||||
break;
|
||||
|
||||
case LONG_INT:
|
||||
case LONG_UNSN:
|
||||
cop = LONG2I;
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid conversion");
|
||||
return(tp);
|
||||
}
|
||||
return( tnalloc(cop,type,0,0,tp,rtp) );
|
||||
}
|
||||
|
||||
/* tadjust - expression tree type adjustment*/
|
||||
/* Adjusts the types of subtrees to agree with the top of the tree.*/
|
||||
tadjust(tp,type,dp,ssp) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int type; /* type to adjust to*/
|
||||
int dp; /* dimension pointer or info*/
|
||||
int ssp; /* structure pointer*/
|
||||
{
|
||||
register int op;
|
||||
|
||||
tp->t_type = type;
|
||||
if( dp >= 0 ) {
|
||||
tp->t_dp = dp;
|
||||
tp->t_ssp = ssp;
|
||||
}
|
||||
if( (op=tp->t_op) == ADDR )
|
||||
type = delspchk(type);
|
||||
else if( op == INDR )
|
||||
type = addsp(type,POINTER);
|
||||
else if( op != ADD && op != SUB )
|
||||
return;
|
||||
tadjust(tp->t_left,type,dp,ssp);
|
||||
}
|
||||
|
||||
/* funcref - handle tree function reference*/
|
||||
/* Turns a reference to a function into the address of the function.*/
|
||||
char *funcref(tp) /* returns pointer to node*/
|
||||
struct tnode *tp; /* pointer to old node*/
|
||||
{
|
||||
if( function(tp->t_type) )
|
||||
tp = tnalloc(ADDR,addsp(tp->t_type,POINTER),tp->t_dp,
|
||||
tp->t_ssp,tp,0L);
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* arrayref - handle tree array reference*/
|
||||
/* Turns a reference to an array into the address of the array.*/
|
||||
char *arrayref(tp) /* returns pointer to tree node*/
|
||||
struct tnode *tp; /* tree node pointer*/
|
||||
{
|
||||
if( array(tp->t_type) && !(isstel(tp)) ) {
|
||||
tp->t_dp++;
|
||||
pushopd(tp);
|
||||
tadjust(tp,delspchk(tp->t_type),-1,0);
|
||||
maketree(ADDR);
|
||||
tp = popopd(); /*tp cannot be 0*/
|
||||
}
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* integral - checks operand for integral type*/
|
||||
/* This checks for needing an integral operand.*/
|
||||
integral(tp,atype) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree node*/
|
||||
int atype; /* alternate type allowable*/
|
||||
{
|
||||
register int type;
|
||||
|
||||
if( (type=tp->t_type) != INT && type != UNSIGNED && type != CHAR &&
|
||||
!suptype(type) && type != atype )
|
||||
error("invalid operand type");
|
||||
}
|
||||
|
||||
/* ttoconv - maps normal type into conversion table type*/
|
||||
ttoconv(type) /* returns conversion type*/
|
||||
int type; /* type to convert*/
|
||||
{
|
||||
switch(type) {
|
||||
|
||||
case CHAR:
|
||||
case INT:
|
||||
return(0);
|
||||
|
||||
case UNSIGNED:
|
||||
return(1);
|
||||
|
||||
case LONG:
|
||||
return(2);
|
||||
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
return(3);
|
||||
|
||||
default:
|
||||
return(4);
|
||||
}
|
||||
}
|
||||
|
||||
/* binopeval - does binary operator constant expression evaluation*/
|
||||
/* Does the constant expression evaluation for binary operators.*/
|
||||
binopeval(op,ltp,rtp) /* returns 1 if done, 0 if not*/
|
||||
int op; /* operator to evaluate*/
|
||||
struct tnode *ltp; /* pointer to left subtree*/
|
||||
struct tnode *rtp; /* pointer to right subtree*/
|
||||
{
|
||||
register int lvalue, rvalue;
|
||||
|
||||
if( ltp->t_op != CINT )
|
||||
return(0);
|
||||
lvalue = ltp->t_value;
|
||||
if( rtp->t_op != CINT )
|
||||
return(0);
|
||||
rvalue = rtp->t_value;
|
||||
switch (op) {
|
||||
|
||||
case ADD:
|
||||
lvalue =+ rvalue;
|
||||
break;
|
||||
|
||||
case SUB:
|
||||
lvalue =- rvalue;
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
lvalue =* rvalue;
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
lvalue =/ rvalue;
|
||||
break;
|
||||
|
||||
case MOD:
|
||||
lvalue =% rvalue;
|
||||
break;
|
||||
|
||||
case AND:
|
||||
lvalue =& rvalue;
|
||||
break;
|
||||
|
||||
case OR:
|
||||
lvalue =| rvalue;
|
||||
break;
|
||||
|
||||
case XOR:
|
||||
lvalue =^ rvalue;
|
||||
break;
|
||||
|
||||
case LSH:
|
||||
lvalue =<< rvalue;
|
||||
break;
|
||||
|
||||
case RSH:
|
||||
lvalue =>> rvalue;
|
||||
break;
|
||||
|
||||
case EQUALS:
|
||||
lvalue = (lvalue == rvalue);
|
||||
break;
|
||||
|
||||
case NEQUALS:
|
||||
lvalue = (lvalue != rvalue);
|
||||
break;
|
||||
|
||||
case GREAT:
|
||||
lvalue = (lvalue > rvalue);
|
||||
break;
|
||||
|
||||
case LESS:
|
||||
lvalue = (lvalue < rvalue);
|
||||
break;
|
||||
|
||||
case GREATEQ:
|
||||
lvalue = (lvalue >= rvalue);
|
||||
break;
|
||||
|
||||
case LESSEQ:
|
||||
lvalue = (lvalue <= rvalue);
|
||||
break;
|
||||
|
||||
default:
|
||||
return(0);
|
||||
}
|
||||
ltp->t_value = lvalue;
|
||||
pushopd(ltp);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* unopeval - unary operator constant expression evaluation*/
|
||||
/* Does constant expression evaluation for unary operators.*/
|
||||
unopeval(op,tp) /* returns 1 if done, 0 otherwise*/
|
||||
int op; /* operator to evaluate*/
|
||||
struct tnode *tp; /* pointer to subexpression*/
|
||||
{
|
||||
register int value;
|
||||
|
||||
if( tp->t_op != CINT )
|
||||
return(0);
|
||||
value = tp->t_value;
|
||||
switch( op ) {
|
||||
|
||||
case COMPL:
|
||||
value = ~ value;
|
||||
break;
|
||||
|
||||
case UMINUS:
|
||||
value = - value;
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
value = ! value;
|
||||
break;
|
||||
|
||||
default:
|
||||
return(0);
|
||||
}
|
||||
tp->t_value = value;
|
||||
pushopd(tp);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* cexpr - evaluate a constant integer expression*/
|
||||
/* Used in evaluating array bounds, bit field numbers, etc.*/
|
||||
cexpr()
|
||||
{
|
||||
register struct tnode *tp;
|
||||
register char *savep;
|
||||
|
||||
savep = exprp;
|
||||
exprp = opap;
|
||||
commastop++;
|
||||
if( (tp=expr()) && tp->t_op != CINT )
|
||||
error("constant required");
|
||||
commastop--;
|
||||
exprp = savep;
|
||||
return( tp->t_value );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
int bol 1;
|
||||
int inittype;
|
||||
int begseq;
|
||||
/* int onepass; */
|
||||
|
||||
/*
|
||||
This interfaces the Parser and the Code Generator, note that these
|
||||
allow you to link together the Parser and the Code Generator.
|
||||
*/
|
||||
|
||||
/* outbdata - set up for byte data*/
|
||||
outbdata() /* returns - none*/
|
||||
{
|
||||
inittype = CHAR;
|
||||
printf("\t.dc.b ");
|
||||
}
|
||||
|
||||
/* outc - output a constant*/
|
||||
outc(type,value) /* returns - none*/
|
||||
int type;
|
||||
int value;
|
||||
{
|
||||
if( type == CHAR )
|
||||
outbdata();
|
||||
else
|
||||
outwdata();
|
||||
printf("%d\n",value);
|
||||
}
|
||||
|
||||
/* outwdata - set up for word data*/
|
||||
outwdata() /* returns - none*/
|
||||
{
|
||||
inittype = INT;
|
||||
printf("\t.dc.w ");
|
||||
}
|
||||
|
||||
/* outdata - set up for data output*/
|
||||
outdata() /* returns - none*/
|
||||
{
|
||||
inittype = INT;
|
||||
printf("\t.data\n");
|
||||
}
|
||||
|
||||
/* outldata - set up for long data output*/
|
||||
outldata() /* returns - none*/
|
||||
{
|
||||
inittype = LONG;
|
||||
printf("\t.data\n");
|
||||
}
|
||||
|
||||
/* outfpdata - set up for floating point data output*/
|
||||
outfpdata() /*[vlh] 3.4 returns - none*/
|
||||
{
|
||||
inittype = FLOAT;
|
||||
printf("\t.data\n");
|
||||
}
|
||||
|
||||
/* outbentry - outputs block/function entry code*/
|
||||
outbentry(nlocs,nds,nas) /* returns - none*/
|
||||
int nlocs; /* local size*/
|
||||
int nds; /* number of D registers*/
|
||||
int nas; /* number of A registers*/
|
||||
{
|
||||
if( !nds && !nas ) /* adjust for 1 arg*/
|
||||
nlocs =+ 4;
|
||||
printf("\tlink R14,#%d\n",-nlocs);
|
||||
if( nds || nas ) {
|
||||
printf("\tmovem.l R%d-R7",7-nds); /*7 for one arg*/
|
||||
if( nas ) {
|
||||
putchar('/');
|
||||
printf("R%d-R13",14-nas);
|
||||
}
|
||||
printf(",-(sp)\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* outbexit - output function exit code*/
|
||||
outbexit(nds,nas) /* returns - none*/
|
||||
int nds; /* number of D registers*/
|
||||
int nas; /* number of A registers*/
|
||||
{
|
||||
if( nds || nas ) {
|
||||
printf("\ttst.l (sp)+\n\tmovem.l (sp)+,"); /*1 arg stuff*/
|
||||
if( nds ) {
|
||||
printf("R%d-R7",8-nds);
|
||||
if( nas )
|
||||
putchar('/');
|
||||
}
|
||||
if( nas )
|
||||
printf("R%d-R13",14-nas);
|
||||
putchar('\n');
|
||||
}
|
||||
printf("\tunlk R14\n\trts\n");
|
||||
}
|
||||
|
||||
/* outlocal - output local symbol for debugger*/
|
||||
outlocal(type,sc,sym,val)
|
||||
int type; /* local name type*/
|
||||
int sc; /* storage type*/
|
||||
char *sym; /* symbol name*/
|
||||
int val;
|
||||
{
|
||||
switch( sc ) {
|
||||
|
||||
case STATIC:
|
||||
if( notfunction(type) )
|
||||
printf("\t~%.8s=L%d\n",sym,val);
|
||||
break;
|
||||
|
||||
case REGISTER:
|
||||
printf("\t~%.8s=R%d\n",sym,val);
|
||||
break;
|
||||
|
||||
case AUTO:
|
||||
printf("\t~%.8s=%d\n",sym,val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* outswitch - output switch table info*/
|
||||
outswitch(ncases,deflab,sp) /* returns - none*/
|
||||
int ncases; /* number of cases in switch*/
|
||||
int deflab; /* default label*/
|
||||
struct swtch *sp; /* switch table pointer*/
|
||||
{
|
||||
register int vdif, val, hval, i, tlab;
|
||||
register struct swtch *s;
|
||||
|
||||
val = sp->sw_value;
|
||||
hval = sp[ncases-1].sw_value;
|
||||
vdif = hval - val;
|
||||
if( ncases <= 4 ) {
|
||||
/*
|
||||
*simple switch, do compares and brances, followed by branch to default
|
||||
*/
|
||||
for( s = sp; --ncases >= 0; s++ ) {
|
||||
if( !s->sw_value )
|
||||
printf("\ttst R0\n");
|
||||
else
|
||||
printf("\tcmp #%d,R0\n",s->sw_value);
|
||||
printf("\tbeq L%d\n",s->sw_label);
|
||||
}
|
||||
outgoto(deflab);
|
||||
}
|
||||
else if( vdif > 0 && vdif <= ncases*3 ) {
|
||||
|
||||
/*jump switch, uses value in R0 to index into table of labels*/
|
||||
|
||||
if( val )
|
||||
printf("\tsub #%d,R0\n",val);
|
||||
tlab = nextlabel++;
|
||||
printf("\tcmp #%d,R0\n\tbhi L%d\n",vdif,deflab); /*check for max*/
|
||||
printf("\tasl #2,R0\n\tmove R0,R8\n\tadd.l #L%d,R8\n",tlab);
|
||||
printf("\tmove.l (R8),R8\n\tjmp (R8)\n");
|
||||
outdata();
|
||||
outlab(tlab);
|
||||
for( s = sp; val <= hval; val++ ) {
|
||||
if( val == s->sw_value ) {
|
||||
outclab(s->sw_label);
|
||||
s++;
|
||||
}
|
||||
else
|
||||
outclab(deflab);
|
||||
}
|
||||
outtext();
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* direct switch, searches down table of values for match, if match
|
||||
* found, branches to corresponding label in label table.
|
||||
*/
|
||||
tlab = nextlabel++;
|
||||
printf("\text.l R0\n\tmove.l #L%d,R8\n\tmove #%d,R1\n",tlab,ncases);
|
||||
i = nextlabel++;
|
||||
outlab(i); /*loop label*/
|
||||
printf("\tcmp.l (R8)+,R0\n\tdbeq R1,L%d\n",i);
|
||||
printf("\tmove.l %d(R8),R8\n\tjmp (R8)\n",ncases*4);
|
||||
outdata();
|
||||
outlab(tlab);
|
||||
for( s = sp, i = ncases; --i >= 0; s++ )
|
||||
outlcon(s->sw_value);
|
||||
outlcon(0); /* mark for default label*/
|
||||
for( s = sp, i = ncases; --i >= 0; s++ )
|
||||
outclab(s->sw_label);
|
||||
outclab(deflab);
|
||||
outtext();
|
||||
}
|
||||
}
|
||||
|
||||
outeof()
|
||||
{
|
||||
register int c;
|
||||
|
||||
v6flush(&sbuf);
|
||||
v6flush(&obuf);
|
||||
}
|
||||
|
||||
/* copysfile - copy string file to end of output file*/
|
||||
copysfile(fname)
|
||||
char *fname;
|
||||
{
|
||||
register int c;
|
||||
|
||||
close(sbuf.io_fd);
|
||||
if( fopen(fname,&sbuf,0) < 0 ) /* 3rd arg for versados */
|
||||
ferror("can't copy %s",fname);
|
||||
while( (c=getc(&sbuf)) > 0 )
|
||||
putc(c,&obuf);
|
||||
v6flush(&obuf);
|
||||
}
|
||||
|
||||
/* outword - output a word of data*/
|
||||
outword(w) /* word expression*/
|
||||
int w;
|
||||
{
|
||||
if( begseq )
|
||||
putchar(',');
|
||||
begseq++;
|
||||
printf("%d",w);
|
||||
}
|
||||
|
||||
/* outlong - output a long data*/
|
||||
outlong(l) /* returns - none*/
|
||||
long l; /* long data to output*/
|
||||
{
|
||||
outwdata();
|
||||
outword(l.hiword);
|
||||
outword(l.loword);
|
||||
outendseq();
|
||||
}
|
||||
|
||||
/* outfp - output floating point data*/
|
||||
outfp(l) /*[vlh] 3.4 returns - none*/
|
||||
long l; /* floating point data to output*/
|
||||
{
|
||||
outwdata();
|
||||
outword(l.hiword);
|
||||
outword(l.loword);
|
||||
outendseq();
|
||||
}
|
||||
|
||||
outendseq() /* returns - none*/
|
||||
{
|
||||
begseq = 0;
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* outtstr - output text string
|
||||
* This outputs a string to the string file, this is used wherever
|
||||
* you cannot output the string directly to data space, such as in
|
||||
* the middle of expressions.
|
||||
*/
|
||||
outtstr(lab)
|
||||
int lab;
|
||||
{
|
||||
char *savep;
|
||||
int sbol;
|
||||
|
||||
savep = obp; /*save to restore later...*/
|
||||
obp = &sbuf;
|
||||
sbol = bol;
|
||||
bol = 1;
|
||||
printf("\tL%d:",lab);
|
||||
outstr();
|
||||
obp = savep;
|
||||
bol = sbol;
|
||||
}
|
||||
|
||||
/* outstr - output a string as a sequence of bytes*/
|
||||
/* Outputs ".dc.b <byte1>,<byte2>,...,<0>*/
|
||||
outstr()
|
||||
{
|
||||
register char *s;
|
||||
register int i;
|
||||
|
||||
outbdata();
|
||||
for( s = cstr, i = cstrsize; i > 0; i-- )
|
||||
outword(*s++ & 0xff);
|
||||
outendseq();
|
||||
}
|
||||
|
||||
/*
|
||||
* putchar - handle outputting to intermediate or error files
|
||||
* This catches tabs to allow for the integration of the parser
|
||||
* and code generator into one pass. By merely throwing away the
|
||||
* tabs here, the output will be OK for the assembler.
|
||||
*/
|
||||
putchar(c)
|
||||
char c;
|
||||
{
|
||||
if( !obp )
|
||||
write(1,&c,1);
|
||||
else if( c == '\t' ) {
|
||||
if( bol ) /* not used && !onepass ) */
|
||||
putc('(',obp); /*for code generator*/
|
||||
}
|
||||
else {
|
||||
bol = (c == '\n');
|
||||
putc(c,obp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
int bol;
|
||||
|
||||
outinit(tp,type) /* returns - none*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
outexpr(tnalloc(INIT,type,0,0,tp));
|
||||
}
|
||||
|
||||
outcforreg(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
outexpr(tnalloc(CFORREG,tp->t_type,0,0,tp));
|
||||
}
|
||||
|
||||
outifgoto(tp,dir,lab)
|
||||
struct tnode *tp;
|
||||
int dir;
|
||||
int lab;
|
||||
{
|
||||
outexpr(tnalloc(IFGOTO,dir,lab,0,tp));
|
||||
}
|
||||
|
||||
outexpr(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( !bol )
|
||||
putchar('\n');
|
||||
printf(".%x\n",lineno);
|
||||
outtree(tp);
|
||||
}
|
||||
|
||||
outtree(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( !tp )
|
||||
return;
|
||||
printf("%x.%x",tp->t_op,tp->t_type);
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case CINT:
|
||||
printf(".%x\n",tp->t_value);
|
||||
break;
|
||||
|
||||
case CLONG:
|
||||
printf(".%x.%x\n",tp->t_lvalue.hiword,tp->t_lvalue.loword);
|
||||
break;
|
||||
|
||||
case CFLOAT: /*[vlh] 3.4*/
|
||||
printf(".%x.%x\n",tp->t_lvalue.hiword,tp->t_lvalue.loword);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
printf(".%x",tp->t_sc);
|
||||
if( tp->t_sc == EXTERNAL )
|
||||
printf(".%.8s\n",tp->t_symbol);
|
||||
else
|
||||
printf(".%x\n",tp->t_offset);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
putchar('\n');
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
case BFIELD:
|
||||
printf(".%x\n",tp->t_dp);
|
||||
outtree(tp->t_left);
|
||||
break;
|
||||
|
||||
default:
|
||||
putchar('\n');
|
||||
outtree(tp->t_left);
|
||||
if( binop(tp->t_op) )
|
||||
outtree(tp->t_right);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
830
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/c068/lex.c
Normal file
830
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/c068/lex.c
Normal file
@@ -0,0 +1,830 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#define SOI '\01'
|
||||
#define STEL HSIZE/2
|
||||
|
||||
/*
|
||||
* the following are the cases within gettok, all other cases are
|
||||
* single character unambiguous tokens. Note that we need to take
|
||||
* special care not to interfere with the single character unambiguous
|
||||
* operators, this is why there is a gap between WHITSP and EXCLAM.
|
||||
*/
|
||||
#define BADC 0 /*bad character*/
|
||||
#define WHITSP 101 /*white space*/
|
||||
#define EXCLAM 102 /*exlamation point*/
|
||||
#define DQUOTE 103 /*double quote*/
|
||||
#define PERCNT 104 /*percent sign*/
|
||||
#define AMPER 105 /*ampersand*/
|
||||
#define SQUOTE 106 /*single quote*/
|
||||
#define STAR 107 /*asterisk or mult sign*/
|
||||
#define PLUS 108 /*plus sign*/
|
||||
#define MINUS 109 /*minus sign*/
|
||||
#define SLASH 110 /*divide sign*/
|
||||
#define DIGIT 111 /*0..9*/
|
||||
#define LCAROT 112 /*less than sign*/
|
||||
#define EQUAL 113 /*equals sign*/
|
||||
#define RCAROT 114 /*greater than*/
|
||||
#define ALPHA 115 /*a..z,A..Z and underbar*/
|
||||
#define CAROT 116 /*^*/
|
||||
#define BAR 117 /*vertical bar*/
|
||||
|
||||
char ctype[] {
|
||||
BADC, BADC, BADC, BADC, BADC, BADC, BADC, BADC,
|
||||
BADC, WHITSP, WHITSP, WHITSP, WHITSP, BADC, BADC, BADC,
|
||||
BADC, BADC, BADC, BADC, WHITSP, BADC, BADC, BADC,
|
||||
BADC, BADC, BADC, BADC, BADC, BADC, BADC, BADC,
|
||||
WHITSP, EXCLAM, DQUOTE, BADC, BADC, PERCNT, AMPER, SQUOTE,
|
||||
LPAREN, RPAREN, STAR, PLUS, COMMA, MINUS, PERIOD, SLASH,
|
||||
DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
|
||||
DIGIT, DIGIT, COLON, SEMI, LCAROT, EQUAL, RCAROT, QMARK,
|
||||
BADC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, LBRACK, BADC, RBRACK, CAROT, ALPHA,
|
||||
BADC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, LCURBR, BAR, RCURBR, COMPL, BADC
|
||||
};
|
||||
|
||||
/*key word table*/
|
||||
struct resword {
|
||||
char *r_name;
|
||||
int r_value;
|
||||
} reswords[] {
|
||||
"auto", R_AUTO,
|
||||
"break", R_BREAK,
|
||||
"case", R_CASE,
|
||||
"char", R_CHAR,
|
||||
"continue", R_CONTINUE,
|
||||
"do", R_DO,
|
||||
"default", R_DEFAULT,
|
||||
"double", R_DOUBLE,
|
||||
"goto", R_GOTO,
|
||||
"else", R_ELSE,
|
||||
"extern", R_EXTERNAL,
|
||||
"float", R_FLOAT,
|
||||
"for", R_FOR,
|
||||
"if", R_IF,
|
||||
"int", R_INT,
|
||||
"long", R_LONG,
|
||||
"register", R_REGISTER,
|
||||
"return", R_RETURN,
|
||||
"short", R_SHORT,
|
||||
"sizeof", R_SIZEOF,
|
||||
"static", R_STATIC,
|
||||
"struct", R_STRUCT,
|
||||
"switch", R_SWITCH,
|
||||
"typedef", R_TYPEDEF,
|
||||
"union", R_UNION,
|
||||
"unsigned", R_UNSIGNED,
|
||||
"while", R_WHILE,
|
||||
0,
|
||||
};
|
||||
|
||||
#define SELFMOD 0200
|
||||
#define ASMASK 0177
|
||||
|
||||
/*
|
||||
* this table is used to check for an operator after an equals sign.
|
||||
* note that =-, =* and =& may all have an ambiguous meaning if not
|
||||
* followed by a space, this is checked for in gettok.
|
||||
*/
|
||||
char asmap[] {
|
||||
EQUALS, /*==*/
|
||||
EQADD, /*=+*/
|
||||
EQSUB|SELFMOD, /*=-*/
|
||||
EQMULT|SELFMOD, /*=**/
|
||||
EQDIV, /*=/*/
|
||||
EQOR, /*=|*/
|
||||
EQAND|SELFMOD, /*=&*/
|
||||
EQXOR, /*=^*/
|
||||
EQMOD, /*=%*/
|
||||
};
|
||||
|
||||
char escmap[] "\b\n\r\t";
|
||||
int pbchar; /*pushed back character*/
|
||||
struct symbol *symtab[HSIZE]; /*hash table*/
|
||||
struct symbol *symbols; /*pointer to next avail symbol buf*/
|
||||
int nsyms; /*number of symbol bufs in memory*/
|
||||
|
||||
/*
|
||||
* getdec - get a decimal number
|
||||
* Uses Horner's method to get decimal number. Note that
|
||||
* multiplication by 10 is cleverly programmed as two shifts and two
|
||||
* adds. This is because long multiplies are painful on both the
|
||||
* PDP-11 and 68000.
|
||||
*/
|
||||
long getdec() /* returns number*/
|
||||
{
|
||||
register long value;
|
||||
register char c;
|
||||
|
||||
for( value = 0; (c=ngetch()) >= '0' && c <= '9'; ) {
|
||||
value =<< 1; /*value = value*2*/
|
||||
value =+ value << 2; /*value*2 + value*8 = value*10*/
|
||||
value =+ (c-'0');
|
||||
}
|
||||
putback(c);
|
||||
return(value);
|
||||
}
|
||||
|
||||
#define BIAS 127L
|
||||
#define EXPSIZ 4
|
||||
#define FRACSIZ 20
|
||||
|
||||
long toieee();
|
||||
long toffp();
|
||||
float power10();
|
||||
|
||||
/*
|
||||
* getfp - get a floating point constant
|
||||
* we've already gotten the significant digits, now build a
|
||||
* floating point number with possible decimal digits and an
|
||||
* exponent, yields an ieee formated floating point number,
|
||||
* unless the fflag is on, then a ffp constant is generated.
|
||||
*/
|
||||
long
|
||||
getfp(significant)
|
||||
long significant;
|
||||
{
|
||||
register char c;
|
||||
register long places; /* decimal places */
|
||||
int esign;
|
||||
float exp, fraction, fp;
|
||||
|
||||
places = 0L; esign = 0; fraction = significant; exp = 0.0;
|
||||
if ((c = ngetch()) == '.') /* get decimal places */
|
||||
for( ; (c=ngetch()) >= '0' && c <= '9';) {
|
||||
fraction = fraction * 10.0;
|
||||
fraction = fraction + (c - '0');
|
||||
places++;
|
||||
}
|
||||
|
||||
if (c=='e' || c=='E') { /* exponent exists */
|
||||
esign = (peekis('-')) ? 1 : (peekis('+')) ? 0 : 0;
|
||||
for( ; (c=ngetch()) >= '0' && c <= '9'; ) {
|
||||
exp = exp * 10.0;
|
||||
exp = exp + (c - '0');
|
||||
}
|
||||
}
|
||||
|
||||
putback(c);
|
||||
if (esign)
|
||||
exp = -exp;
|
||||
places = exp - places;
|
||||
fp = fraction * power10(places);
|
||||
if (fflag)
|
||||
return( toffp(fp) );
|
||||
else
|
||||
return ( toieee(fp) );
|
||||
}
|
||||
|
||||
float
|
||||
power10(pwr) /* used by getfp, 10^pwr */
|
||||
long pwr;
|
||||
{
|
||||
float f;
|
||||
|
||||
if (pwr < 0L) /* negative power */
|
||||
for (f = 1.0; pwr < 0L; pwr++)
|
||||
f = f / 10.0;
|
||||
else /* positive power */
|
||||
for (f = 1.0; pwr > 0L; pwr--)
|
||||
f = f * 10.0;
|
||||
return(f);
|
||||
}
|
||||
|
||||
long
|
||||
toffp(f) /* converts current machine float to ffp rep */
|
||||
float f;
|
||||
{
|
||||
register long exp;
|
||||
register int sign, count;
|
||||
long l;
|
||||
|
||||
if (f == 0.0)
|
||||
return(0L);
|
||||
if (f < 0.0) {
|
||||
sign = 1;
|
||||
f = -f;
|
||||
}
|
||||
else
|
||||
sign = 0;
|
||||
exp = 0L;
|
||||
for( ; f >= 1.0; f = f / 2.0)
|
||||
exp++;
|
||||
for( ; f < 0.5; f = f * 2.0)
|
||||
exp--;
|
||||
f = f * 16777216.0; /* 2 ^ 24 */
|
||||
l = f;
|
||||
l =<< 8;
|
||||
if (sign)
|
||||
l =| 0x80;
|
||||
exp =+ 0x40;
|
||||
l =| (exp & 0x7f);
|
||||
return(l);
|
||||
}
|
||||
|
||||
long
|
||||
toieee(f) /* converts current machine float to ieee rep */
|
||||
float f;
|
||||
{
|
||||
register long exp;
|
||||
register int sign, count;
|
||||
long l;
|
||||
|
||||
if (f == 0.0)
|
||||
return(0L);
|
||||
if (f < 0.0) {
|
||||
sign = 1;
|
||||
f = -f;
|
||||
}
|
||||
else
|
||||
sign = 0;
|
||||
exp = 0L;
|
||||
for( ; f >= 2.0; f = f / 2.0)
|
||||
exp++;
|
||||
for( ; f < 1.0; f = f * 2.0)
|
||||
exp--;
|
||||
f = f - 1.0;
|
||||
f = f * 8388608.0; /* 2 ^ 23 */
|
||||
l = f;
|
||||
if (sign)
|
||||
l =| 0x80000000;
|
||||
exp = (exp + BIAS)<<23;
|
||||
l =| (exp & 0x7f800000);
|
||||
return(l);
|
||||
}
|
||||
|
||||
#define toupper(c) ((c) & ~32)
|
||||
/* gethex - get an hexidecimal number*/
|
||||
/* Uses Horner's method to get hexidecimal number*/
|
||||
long gethex() /* returns number*/
|
||||
{
|
||||
register long value;
|
||||
register char c, ch;
|
||||
|
||||
value = 0;
|
||||
while( 1 ) {
|
||||
if( (c=ngetch()) >= '0' && c <= '9' )
|
||||
c =- '0';
|
||||
else if((ch=toupper(c)) >= 'A' && ch <= 'F' ) /* [vlh] */
|
||||
c = ch - ('A'-10);
|
||||
else
|
||||
break;
|
||||
value = (value<<4) + c;
|
||||
}
|
||||
putback(c);
|
||||
return(value);
|
||||
}
|
||||
|
||||
/* getoct - get an octal number*/
|
||||
/* Uses Horner's method to get octal number*/
|
||||
long getoct(flag) /* returns number*/
|
||||
int flag; /* string flag 1=>in string, else 0*/
|
||||
{
|
||||
register long value;
|
||||
register char c;
|
||||
register int count;
|
||||
|
||||
count = 0;
|
||||
for( value = 0; (c=ngetch()) >= '0' && c <= '7'; ) {
|
||||
if( flag && ++count > 3 )
|
||||
break;
|
||||
value = (value<<3) + (c-'0');
|
||||
}
|
||||
putback(c);
|
||||
return(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* gettok - get next token from input
|
||||
* Checks pushed-packed token buffer, supresses / * * / comments,
|
||||
* folds multiple character special symbols into single word token.
|
||||
*/
|
||||
gettok() /* returns token type*/
|
||||
{
|
||||
register int c, nextc, i;
|
||||
register char *p;
|
||||
register long value;
|
||||
char sym[SSIZE];
|
||||
|
||||
if( peektok ) {
|
||||
i = peektok;
|
||||
peektok = 0;
|
||||
return(i);
|
||||
}
|
||||
while( (c=ngetch()) != EOF ) {
|
||||
switch(ctype[c]) {
|
||||
|
||||
case BADC: /*bad character*/
|
||||
error("invalid character");
|
||||
break;
|
||||
|
||||
case SEMI:
|
||||
cvalue = 0; /* [vlh] not reserved word... */
|
||||
default:
|
||||
return( ctype[c] );
|
||||
|
||||
case WHITSP: /*skip all white space*/
|
||||
break;
|
||||
|
||||
case EXCLAM: /*!= or !*/
|
||||
return( peekis('=') ? NEQUALS : NOT );
|
||||
|
||||
case DQUOTE: /*quoted string*/
|
||||
getstr(cstr,STRSIZE,'"');
|
||||
cvalue = nextlabel++;
|
||||
return(STRING);
|
||||
|
||||
case PERCNT: /*%= or %*/
|
||||
return( peekis('=') ? EQMOD : MOD );
|
||||
|
||||
case AMPER: /*&=, && or &*/
|
||||
return( peekis('=') ? EQAND : peekis('&') ? LAND : AND );
|
||||
|
||||
case SQUOTE: /*character constant*/
|
||||
getstr(cstr,STRSIZE,'\'');
|
||||
if( cstrsize > CHRSPWORD+1 ) {
|
||||
error("character constant too long");
|
||||
cstrsize = CHRSPWORD + 1;
|
||||
}
|
||||
cvalue = 0;
|
||||
for( p = cstr; --cstrsize > 0; ) {
|
||||
cvalue =<< BITSPCHAR;
|
||||
cvalue =| (*p++ & 0377);
|
||||
}
|
||||
return(CINT);
|
||||
|
||||
case STAR: /**= or **/
|
||||
return( peekis('=') ? EQMULT : MULT );
|
||||
|
||||
case PLUS: /*+=, ++ or +*/
|
||||
return( peekis('=') ? EQADD : peekis('+') ? PREINC : ADD );
|
||||
|
||||
case MINUS: /*-=, --, -> or -*/
|
||||
return( peekis('=') ? EQSUB : peekis('-') ? PREDEC :
|
||||
peekis('>') ? APTR : SUB );
|
||||
|
||||
case SLASH: /*/ *..* /, //..., /= or /*/
|
||||
if( peekis('*') ) {
|
||||
while( (c=ngetch()) != EOF )
|
||||
if( c == '*' && peekis('/') )
|
||||
break;
|
||||
if( c == EOF ) {
|
||||
error("no */ before EOF");
|
||||
return(EOF);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if( peekis('/') ) {
|
||||
while( (c=ngetch()) != EOF && c != EOLC )
|
||||
;
|
||||
continue;
|
||||
}
|
||||
return( peekis('=') ? EQDIV : DIV );
|
||||
|
||||
case DIGIT: /*number constant (long or reg)*/
|
||||
i = 0; /*flags if long constant*/
|
||||
if( c != '0' ) {
|
||||
putback(c);
|
||||
dofp:
|
||||
value = getdec();
|
||||
if ((c=ngetch())=='.' || c=='e' || c=='E') { /*[vlh] 3.4 */
|
||||
putback(c);
|
||||
clvalue = getfp(value);
|
||||
return(CFLOAT);
|
||||
}
|
||||
putback(c);
|
||||
if( value > 32767 || value < -32768 )
|
||||
i++;
|
||||
}
|
||||
else if( peekis('x') || peekis('X') ) {
|
||||
value = gethex();
|
||||
if( value < 0 || value >= 0x10000L )
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
if (peekis('.')) {
|
||||
putback('.');
|
||||
goto dofp;
|
||||
}
|
||||
value = getoct(0);
|
||||
if( value < 0 || value >= 0x10000L )
|
||||
i++;
|
||||
}
|
||||
if( peekis('l') || peekis('L') || i ) {
|
||||
clvalue = value;
|
||||
return(CLONG);
|
||||
}
|
||||
cvalue = value;
|
||||
return(CINT);
|
||||
|
||||
case LCAROT: /*<=, <<, <<= or <*/
|
||||
return( peekis('=') ? LESSEQ : peekis('<') ?
|
||||
(peekis('=') ? EQLSH : LSH) : LESS );
|
||||
|
||||
case EQUAL: /*==, =<<, =>>, =+, ..., =*/
|
||||
if( peekis('<') ) {
|
||||
if( peekis('<') )
|
||||
return(EQLSH);
|
||||
}
|
||||
else if( peekis('>') ) {
|
||||
if( peekis('>') )
|
||||
return(EQRSH);
|
||||
}
|
||||
else if( (i=index("=+-*/|&^%",(c=ngetch()))) >= 0 ) {
|
||||
i = asmap[i];
|
||||
if( i & SELFMOD ) {
|
||||
if( (nextc=ngetch()) != ' ' )
|
||||
if (!wflag) /*[vlh] old fashion initialization*/
|
||||
error("=%c assumed",c);
|
||||
putback(nextc);
|
||||
}
|
||||
return( i & ASMASK );
|
||||
}
|
||||
else
|
||||
putback(c);
|
||||
return(ASSIGN);
|
||||
|
||||
case RCAROT: /*>=, >>, >>= or >*/
|
||||
return( peekis('=') ? GREATEQ : peekis('>') ?
|
||||
(peekis('=') ? EQRSH : RSH) : GREAT );
|
||||
|
||||
case ALPHA: /*[A-Za-z][A-Za-z0-9]**/
|
||||
p = &sym[0];
|
||||
i = SSIZE;
|
||||
for(; ctype[c] == ALPHA || ctype[c] == DIGIT; c=ngetch(),i-- )
|
||||
if( i > 0 )
|
||||
*p++ = c;
|
||||
if( i > 0 )
|
||||
*p = '\0';
|
||||
putback(c);
|
||||
csp = lookup(sym);
|
||||
if( csp->s_attrib & SRESWORD ) {
|
||||
cvalue = csp->s_offset;
|
||||
return(RESWORD);
|
||||
}
|
||||
smember = 0;
|
||||
return(SYMBOL);
|
||||
|
||||
case CAROT: /*^= or ^*/
|
||||
return( peekis('=') ? EQXOR : XOR );
|
||||
|
||||
case BAR: /*|=, || or |*/
|
||||
return( peekis('=') ? EQOR : peekis('|') ? LOR : OR );
|
||||
|
||||
}
|
||||
}
|
||||
return(EOF);
|
||||
}
|
||||
|
||||
/*
|
||||
* peekis - peeks at next character for specific character
|
||||
* Gets next (possibly pushed back) character, if it matches
|
||||
* the given character 1 is returned, otherwise the character
|
||||
* is put back.
|
||||
*/
|
||||
peekis(tc) /* returns 1 if match, 0 otherwise*/
|
||||
int tc; /* test character*/
|
||||
{
|
||||
register int c;
|
||||
|
||||
if( (c=ngetch()) == tc )
|
||||
return(1);
|
||||
putback(c);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* ngetch - get a possibly pushed back character*/
|
||||
/* Checks pbchar variable, returns it if non-zero, handles counting*/
|
||||
/* of new lines and whether you are in an include or not.*/
|
||||
ngetch() /* returns character read or EOF*/
|
||||
{
|
||||
register int c;
|
||||
register char *ifile;
|
||||
|
||||
if( pbchar ) {
|
||||
c = pbchar;
|
||||
pbchar = 0;
|
||||
}
|
||||
else if( (c=getc(&ibuf)) == EOLC ) {
|
||||
if( inclflag )
|
||||
inclflag = 0;
|
||||
else
|
||||
lineno++;
|
||||
}
|
||||
else if( c == SOI) { /*[vlh]add incl filename & line # */
|
||||
inclflag++;
|
||||
ifile = &inclfile;
|
||||
while ((c=getc(&ibuf)) != SOI)
|
||||
*ifile++ = c&0377;
|
||||
*ifile = 0;
|
||||
inclline = getdec() & 077777;
|
||||
c = ' ';
|
||||
}
|
||||
else if( c < 0 )
|
||||
c = EOF;
|
||||
return(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* peekc - peek at the next non-whitespace character after token
|
||||
* This allows for the problem of having to look at two tokens
|
||||
* at once. The second token is always a semi-colon or colon,
|
||||
* so we only look at the single character, rather than going
|
||||
* thru gettok.
|
||||
*/
|
||||
peekc(tc) /* returns 1 if match, 0 otherwise*/
|
||||
int tc; /* character to look for*/
|
||||
{
|
||||
register int c;
|
||||
|
||||
while( ctype[(c=ngetch())] == WHITSP) ;
|
||||
if( c == tc )
|
||||
return(1);
|
||||
putback(c);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* putback - puts back a single character*/
|
||||
/* Checks pbchar for error condition.*/
|
||||
putback(c) /* returns - none*/
|
||||
int c;
|
||||
{
|
||||
if( pbchar )
|
||||
error("too many chars pushed back");
|
||||
else
|
||||
pbchar = c;
|
||||
}
|
||||
|
||||
/* getstr - get a quoted (single or double) character string*/
|
||||
/* Gets specified number of characters, handling escapes.*/
|
||||
getstr(str,nchars,endc) /* returns - none*/
|
||||
char *str; /* pointer to string buffer*/
|
||||
int nchars; /* max number of characters*/
|
||||
char endc; /* ending string character*/
|
||||
{
|
||||
register char *p;
|
||||
register int i;
|
||||
register int c;
|
||||
register int j;
|
||||
|
||||
cstrsize = 1;
|
||||
p = str;
|
||||
for( i = nchars; (c=ngetch()) != endc; i-- ) {
|
||||
if( c == EOF || c == EOLC ) {
|
||||
error("string cannot cross line");
|
||||
break;
|
||||
}
|
||||
if( c == '\\' ) {
|
||||
if( (c=ngetch()) >= '0' && c <= '7' ) {
|
||||
putback(c);
|
||||
if( (c=getoct(1)) < 0 || c > 255 ) {
|
||||
error("bad character constant");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if( (j=index("bnrt",c)) >= 0 )
|
||||
c = escmap[j];
|
||||
else if( c == EOLC ) /*escape followed by nl->ignore*/
|
||||
continue;
|
||||
}
|
||||
if( i > 0 ) { /*room left in string?*/
|
||||
cstrsize++;
|
||||
*p++ = c;
|
||||
}
|
||||
else if( !i ) /*only say error once...*/
|
||||
error("string too long");
|
||||
}
|
||||
if( i <= 0 ) /*string overflow?*/
|
||||
p--;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/* syminit - initialize the symbol table, install reswords*/
|
||||
/* Goes thru the resword table and installs them into the symbol*/
|
||||
/* table.*/
|
||||
syminit() /* returns - none*/
|
||||
{
|
||||
register struct resword *rp;
|
||||
|
||||
for( rp = &reswords[0]; rp->r_name != 0; rp++ )
|
||||
install(rp->r_name,SRESWORD|SDEFINED,rp->r_value);
|
||||
}
|
||||
|
||||
/* install - install a symbol in the symbol table*/
|
||||
/* Allocates a symbol entry, copies info into it and links it*/
|
||||
/* into the hash table chain.*/
|
||||
char *
|
||||
install(sym,attrib,offset) /* returns pointer to symbol struct*/
|
||||
char *sym; /* symbol to install*/
|
||||
int attrib; /* attribues of symbol*/
|
||||
int offset; /* symbol offset (resword value)*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
register int i;
|
||||
|
||||
while( (sp=symbols) <= 0 ) {
|
||||
if( (sp=sbrk(SYMSIZE)) <= 0 )
|
||||
ferror("symbol table overflow");
|
||||
for( i = SYMSIZE/(sizeof *symbols); --i >= 0; ) {
|
||||
if (sp <= 0)
|
||||
ferror("bad symbol table");
|
||||
sp->s_next = symbols;
|
||||
symbols = sp++;
|
||||
}
|
||||
}
|
||||
symbols = sp->s_next;
|
||||
sp->s_attrib = attrib;
|
||||
sp->s_sc = 0; sp->s_type = 0; sp->s_dp = 0; sp->s_ssp = 0;
|
||||
sp->s_offset = offset;
|
||||
sp->s_struc = (instruct) ? strucptr[smember+instruct] : 0;
|
||||
symcopy(sym,sp->s_symbol); /*copy symbol to symbol struct*/
|
||||
i = symhash(sym,instruct|smember); /*link into chain list*/
|
||||
sp->s_next = symtab[i];
|
||||
symtab[i] = sp;
|
||||
return(sp);
|
||||
}
|
||||
|
||||
/* lookup - looks up a symbol in symbol table*/
|
||||
/* Hashes symbol, then goes thru chain, if not found, then*/
|
||||
/* installs the symbol.*/
|
||||
char *lookup(sym) /* returns pointer to symbol buffer*/
|
||||
char *sym; /* pointer to symbol*/
|
||||
{
|
||||
register struct symbol *sp, *hold;
|
||||
register char *p;
|
||||
int exact; /* same name, diff type or offset */
|
||||
|
||||
p = sym;
|
||||
for( sp = symtab[symhash(p,0)]; sp != 0; sp = sp->s_next )
|
||||
if((sp->s_attrib&(SRESWORD|STYPEDEF)) && symequal(p,sp->s_symbol))
|
||||
return(sp);
|
||||
if (!(smember|instruct)) { /*[vlh]*/
|
||||
for( sp=symtab[symhash(p,0)]; sp!=0; sp=sp->s_next )
|
||||
if( symequal(p,sp->s_symbol) ) return(sp);
|
||||
}
|
||||
else { /* doing a declaration or an expression */
|
||||
hold = 0; exact = 0;
|
||||
for( sp=symtab[symhash(p,instruct|smember)]; sp!=0; sp=sp->s_next )
|
||||
if( symequal(p,sp->s_symbol) )
|
||||
if (symsame(sp,hold,&exact)) return(sp);
|
||||
else if (!hold && !exact) hold = sp;
|
||||
if (hold && !exact) return(hold);
|
||||
}
|
||||
return(install(p,0,0));
|
||||
}
|
||||
|
||||
/* freesyms - frees all local symbols at end of function declaration*/
|
||||
/* Searches thru symbol table, deleting all symbols marked as locals*/
|
||||
freesyms() /* returns - none*/
|
||||
{
|
||||
register int i, tinfo;
|
||||
register struct symbol *sp, *tp, *nextp, **htp;
|
||||
|
||||
for( htp = &symtab[0], i = HSIZE; --i >= 0; htp++ )
|
||||
for( tp = 0, sp = *htp; sp != 0; sp = nextp ) {
|
||||
nextp = sp->s_next;
|
||||
if( !(sp->s_attrib&SDEFINED) ) {
|
||||
error("undefined label: %.8s",sp->s_symbol);
|
||||
sp->s_attrib =| SDEFINED;
|
||||
}
|
||||
if( sp->s_attrib & (SGLOBAL|SRESWORD) )
|
||||
tp = sp;
|
||||
else {
|
||||
if( tp )
|
||||
tp->s_next = sp->s_next;
|
||||
else
|
||||
*htp = sp->s_next;
|
||||
sp->s_next = symbols;
|
||||
symbols = sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* chksyms - checks symbol table for undefined symbols, etc.*/
|
||||
/* Goes thru the symbol table checking for undeclared forward*/
|
||||
/* referenced structures, and outputs local symbols for debugger.*/
|
||||
chksyms() /* returns - none*/
|
||||
{
|
||||
register struct symbol **htp, *sp;
|
||||
register int i, sc;
|
||||
|
||||
for( htp = &symtab[0], i = HSIZE; --i >= 0; htp++ )
|
||||
for( sp = *htp; sp != 0; sp = sp->s_next ) {
|
||||
sc = sp->s_sc;
|
||||
if(sc!=0 && sp->s_ssp>=0 && (btype(sp->s_type))==FRSTRUCT) {
|
||||
sp->s_ssp = frstab[sp->s_ssp]->s_ssp; /* 3.4 ssp>0 */
|
||||
sp->s_type = (sp->s_type&~TYPE) | STRUCT;
|
||||
}
|
||||
if( sc == PDECLIST ) {
|
||||
error("not in parameter list: %.8s",sp->s_symbol);
|
||||
sp->s_sc = AUTO;
|
||||
}
|
||||
if( infunc )
|
||||
outlocal(sp->s_type,sp->s_sc,sp->s_symbol,sp->s_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* symhash - compute hash value for symbol*/
|
||||
/* Sums the symbols characters and takes that modulus the hash table*/
|
||||
/* size.*/
|
||||
symhash(sym,stel) /* returns hash value for symbol*/
|
||||
char *sym; /* pointer to symbol*/
|
||||
int stel; /* structure element flag*/
|
||||
{
|
||||
register char *p;
|
||||
register int hashval, i;
|
||||
|
||||
hashval = (stel ? STEL : 0 );
|
||||
for( p = sym, i = SSIZE; *p != '\0' && i > 0; i-- )
|
||||
hashval =+ *p++;
|
||||
return( hashval % HSIZE );
|
||||
}
|
||||
|
||||
/* symequal - check for symbol equality*/
|
||||
/* Does comparison between two symbols.*/
|
||||
symequal(sym1,sym2) /* returns 1 if equal, 0 otherwise*/
|
||||
char *sym1; /* pointer to first symbol*/
|
||||
char *sym2; /* pointer to second symbol*/
|
||||
{
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
for( p = sym1, q = sym2, i = SSIZE; *p == *q++; )
|
||||
if( *p++ == '\0' || --i == 0 )
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* symsame - symbol member same as declared */
|
||||
symsame(sp,hold,exact) /* [vlh] */
|
||||
struct symbol *sp, *hold;
|
||||
int *exact;
|
||||
{
|
||||
if (strucptr[smember+instruct])
|
||||
if (strucptr[smember+instruct]==sp->s_struc) return(1);
|
||||
if (hold)
|
||||
if (sp->s_type != hold->s_type || sp->s_offset != hold->s_offset)
|
||||
*exact = 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* symcopy - symbol copy*/
|
||||
/* Copies one symbol to another.*/
|
||||
symcopy(sym1,sym2) /* returns - none*/
|
||||
char *sym1; /* pointer to symbol to copy*/
|
||||
char *sym2; /* pointer to area to copy to*/
|
||||
{
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
for( p = sym1, q = sym2, i = SSIZE; --i >= 0; )
|
||||
*q++ = ( *p ? *p++ : '\0');
|
||||
}
|
||||
|
||||
/* index - find the index of a character in a string*/
|
||||
/* This is identical to Software Tools index.*/
|
||||
index(str,chr) /* returns index of c in str or -1*/
|
||||
char *str; /* pointer to string to search*/
|
||||
char chr; /* character to search for*/
|
||||
{
|
||||
register char *s;
|
||||
register int i;
|
||||
|
||||
for( s = str, i = 0; *s != '\0'; i++ )
|
||||
if( *s++ == chr )
|
||||
return(i);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* next - if next token matches given token, skip and return success*/
|
||||
/* This allows for clean parsing of declarations.*/
|
||||
next(tok) /* returns 1 if matched, 0 otherwise*/
|
||||
int tok;
|
||||
{
|
||||
register int token;
|
||||
|
||||
if( (token=gettok()) == tok )
|
||||
return(1);
|
||||
peektok = token;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* pbtok - put back the given token*/
|
||||
/* This merely sets the peektok variable*/
|
||||
pbtok(tok) /* returns - none*/
|
||||
int tok;
|
||||
{
|
||||
if( peektok )
|
||||
error("too many tokens pushed back");
|
||||
peektok = tok;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
char *version "@(#) c068 parser 4.0 - Mar 18, 1983";
|
||||
/*
|
||||
ALCYON C Compiler for the Motorola 68000 - Parser
|
||||
|
||||
Called from c68:
|
||||
|
||||
c068 source icode strings
|
||||
|
||||
source: input source code, preprocessed with comments stripped
|
||||
|
||||
icode: contains the intermediate code for the code generator,
|
||||
for a detailed explanaion see ../doc/icode.
|
||||
|
||||
strings: contains all the string constants.
|
||||
|
||||
The basic structure of the parser is as follows:
|
||||
|
||||
main main driver for parser
|
||||
syminit initializes symbol table
|
||||
doextdef external definition syntax
|
||||
getatt get type attributes
|
||||
dlist declaration list for structures/unions
|
||||
getatt recursive gettype call
|
||||
dodecl do one declaration
|
||||
declarator handle declarator syntax
|
||||
dodecl do one external declaraion
|
||||
initlist external initialization list
|
||||
cexpr constant expressions
|
||||
expr arithmetic expressions
|
||||
maketree build operator tree
|
||||
funcbody function body
|
||||
dlist declaration list
|
||||
stmt function statements
|
||||
stmt recursive stmt call
|
||||
expr arithmetic expressions
|
||||
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
int nextlabel 1;
|
||||
int lineno;
|
||||
char *exprp &exprarea[0];
|
||||
|
||||
/*
|
||||
* main - main routine for parser
|
||||
* Checks arguments, opens input and output files, does main loop
|
||||
* for external declarations and blocks.
|
||||
*/
|
||||
main(argc,argv) /* returns - none*/
|
||||
int argc; /* argument count*/
|
||||
char *argv[]; /* argument pointers*/
|
||||
{
|
||||
register char *q;
|
||||
register int i;
|
||||
|
||||
for( i = 4; i < argc; i++ ) {
|
||||
q = argv[i];
|
||||
if( *q++ != '-' )
|
||||
usage();
|
||||
while( 1 ) {
|
||||
switch( *q++ ) {
|
||||
|
||||
case 'f':
|
||||
fflag++;
|
||||
continue;
|
||||
|
||||
case 'e':
|
||||
eflag++;
|
||||
continue;
|
||||
|
||||
case 'w':
|
||||
wflag++;
|
||||
continue;
|
||||
|
||||
case '\0':
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( argc < 4 )
|
||||
usage();
|
||||
if( fopen(argv[1],&ibuf,0) < 0 ) /* 3rd arg for versados */
|
||||
ferror("can't open %s",argv[i]);
|
||||
if( fcreat(argv[2],&obuf,0) < 0 || fcreat(argv[3],&sbuf,0) < 0 )
|
||||
ferror("temp creation error");
|
||||
obp = &obuf;
|
||||
lineno++;
|
||||
frstp = -1; /* [vlh] 3.4 - initialize only once */
|
||||
syminit();
|
||||
while( !peek(EOF) )
|
||||
doextdef();
|
||||
outeof();
|
||||
outdata();
|
||||
copysfile(argv[3]);
|
||||
exit(errcnt!=0);
|
||||
}
|
||||
|
||||
/* usage - output usage error message and die*/
|
||||
usage()
|
||||
{
|
||||
ferror("usage: c068 source icode str [-e] [-f] [-w]");
|
||||
}
|
||||
|
||||
/* error - report an error message*/
|
||||
/* outputs current line number and error message*/
|
||||
error(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* error message*/
|
||||
int x1, x2, x3, x4, x5, x6; /* args for printf*/
|
||||
{
|
||||
register char *savep;
|
||||
|
||||
savep = obp;
|
||||
obp = 0;
|
||||
errcnt++;
|
||||
if (!inclflag) {
|
||||
if( lineno )
|
||||
printf("* %d: ",lineno);
|
||||
}
|
||||
else /*[vlh] generate filename and approp line #*/
|
||||
printf("%s: * %d: ",inclfile,inclline);
|
||||
printf(s,x1,x2,x3,x4,x5,x6);
|
||||
printf("\n");
|
||||
obp = savep;
|
||||
}
|
||||
|
||||
/* ferror - fatal error*/
|
||||
/* Outputs error message and exits*/
|
||||
ferror(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* error message*/
|
||||
int x1, x2, x3, x4, x5, x6; /* args for printf*/
|
||||
{
|
||||
error(s,x1,x2,x3,x4,x5,x6);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
v6flush(v6buf)
|
||||
struct iobuf *v6buf;
|
||||
{
|
||||
register i;
|
||||
|
||||
i = BLEN - v6buf->nunused;
|
||||
v6buf->nunused = BLEN;
|
||||
v6buf->xfree = &(v6buf->buff[0]);
|
||||
if(write(v6buf->fildes,v6buf->xfree,i) != i)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/* alignment, node type altering routines, dimension table allocating */
|
||||
/* routine, and routines to determine elements actual size */
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
#define DTSIZE 077 /*data size in bytes*/
|
||||
|
||||
char dinfo[];
|
||||
|
||||
/* dalloc - dimension table allocation*/
|
||||
/* Allocates an entry in the dimension table.*/
|
||||
dalloc(dimsize) /* returns ptr to dimension allocated*/
|
||||
long dimsize; /* dimension size [vlh] 3.4 i=>l*/
|
||||
{
|
||||
register int i;
|
||||
|
||||
if( (i=cdp++) >= DSIZE-1 )
|
||||
ferror("dimension table overflow");
|
||||
dtab[i] = dimsize;
|
||||
return(i);
|
||||
}
|
||||
|
||||
/* addsp - add special type to special type info*/
|
||||
/* Takes given special type and adds it into the special type field.*/
|
||||
addsp(type,nsptype) /* returns resulting type*/
|
||||
int type; /* old type field*/
|
||||
int nsptype; /* special type to be added*/
|
||||
{
|
||||
register int dtype;
|
||||
|
||||
dtype = btype(type);
|
||||
type =& (~TYPE);
|
||||
return( (type<<SUTYPLEN) | suptype(nsptype) | dtype );
|
||||
}
|
||||
|
||||
/* delsp - delete one special type info field from special type info*/
|
||||
/* Takes given special type field and deletes least sign.*/
|
||||
delsp(type) /* returns resulting type*/
|
||||
int type; /* old special type*/
|
||||
{
|
||||
register int dtype;
|
||||
|
||||
dtype = btype(type);
|
||||
type =& (~(ALLTYPE));
|
||||
return( (type>>SUTYPLEN) | dtype );
|
||||
}
|
||||
|
||||
/*
|
||||
* revsp - reverse special type info
|
||||
* This allows for the processing of the super-type info in
|
||||
* the reverse order, which is necessary for initializations.
|
||||
*/
|
||||
revsp(type) /* returns reversed type info*/
|
||||
int type; /* type to reverse*/
|
||||
{
|
||||
register int t;
|
||||
|
||||
for( t = btype(type); suptype(type) != 0; type = delsp(type) )
|
||||
t = addsp(t,type);
|
||||
return(t);
|
||||
}
|
||||
|
||||
/* falign - handle bit field alignments*/
|
||||
falign(type,flen) /* returns number of bytes padded*/
|
||||
int type; /* data type*/
|
||||
int flen; /* field length*/
|
||||
{
|
||||
register int off;
|
||||
|
||||
off = 0;
|
||||
if( flen <= 0 ) {
|
||||
error("invalid field size");
|
||||
flen = 0;
|
||||
}
|
||||
switch( type ) {
|
||||
|
||||
case INT:
|
||||
case UNSIGNED:
|
||||
if( flen > BITSPWORD )
|
||||
error("field overflows word");
|
||||
if( flen + boffset > BITSPWORD )
|
||||
off = CHRSPWORD;
|
||||
break;
|
||||
|
||||
case CHAR:
|
||||
if( flen > BITSPCHAR )
|
||||
error("field overflows byte");
|
||||
if( flen + boffset > BITSPCHAR )
|
||||
off = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid field type description");
|
||||
return(0);
|
||||
|
||||
}
|
||||
if( off )
|
||||
boffset = 0;
|
||||
boffset =+ flen;
|
||||
return(off);
|
||||
}
|
||||
|
||||
/* salign - structure alignment*/
|
||||
salign(type,offset) /* returns bytes of padding*/
|
||||
int type; /* data type to align*/
|
||||
int offset; /* current structure offset*/
|
||||
{
|
||||
register int off;
|
||||
|
||||
off = offset;
|
||||
if( boffset ) { /*remaining bit fields, flush 'em*/
|
||||
off =+ (boffset+(BITSPCHAR-1))/BITSPCHAR;
|
||||
boffset = 0;
|
||||
}
|
||||
while( array(type) ) /*get base type*/
|
||||
type = delsp(type);
|
||||
if( type != CHAR ) /*need word boundary*/
|
||||
off = walign(off);
|
||||
return( off - offset );
|
||||
}
|
||||
|
||||
/* delspchk - delete one special reference and check if non-zero*/
|
||||
delspchk(type) /*returns new special type*/
|
||||
int type; /* type to modify*/
|
||||
{
|
||||
if(!(suptype(type)))
|
||||
error("bad indirection");
|
||||
return( delsp(type) );
|
||||
}
|
||||
|
||||
/* psize - return size of object ptd at by pointer*/
|
||||
long /* [vlh] 3.4 int => long */
|
||||
psize(tp) /* returns size of object in bytes*/
|
||||
struct tnode *tp; /* pointer to tree node*/
|
||||
{
|
||||
if ( !(suptype(tp->t_type)) ) /* what case ??? */
|
||||
return(1);
|
||||
return( dsize(delsp(tp->t_type),tp->t_dp,tp->t_ssp) );
|
||||
}
|
||||
|
||||
/* dsize - returns size of data object in bytes*/
|
||||
long /* [vlh] 3.4 */
|
||||
dsize(type,dp,sp) /* returns number of bytes*/
|
||||
int type; /* type of node*/
|
||||
int dp; /* dimension pointer*/
|
||||
int sp; /* size pointer if structure*/
|
||||
{
|
||||
register long nel, size;
|
||||
|
||||
nel = 1;
|
||||
for( ; array(type); type = delsp(type) )
|
||||
nel = dtab[dp];
|
||||
if( function(type) )
|
||||
return(0);
|
||||
size = (pointer(type)) ? PTRSIZE : (type == STRUCT) ?
|
||||
dtab[sp] : dinfo[type]&DTSIZE;
|
||||
if(!size)
|
||||
error("invalid data type");
|
||||
return( size * nel );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/* node allocation, node stack manipulation routines */
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
int opdontop;
|
||||
int strassign;
|
||||
|
||||
/* talloc - expression area tree node allocation
|
||||
* Allocates area and checks for overflow.*/
|
||||
char *talloc(size) /* returns pointer to node*/
|
||||
int size; /* size of node to alloc*/
|
||||
{
|
||||
register char *p;
|
||||
|
||||
p = opap;
|
||||
if( p + size >= &exprarea[EXPSIZE] )
|
||||
ferror("expression too complex");
|
||||
opap = p + size;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* enalloc - external name alloc
|
||||
* Allocates an expression tree node for an external name and
|
||||
* copies symbol table info and symbol into tree node.
|
||||
*/
|
||||
char *enalloc(sp) /* returns - none*/
|
||||
struct symbol *sp; /* pointer to symbol table entry*/
|
||||
{
|
||||
register struct extnode *ep;
|
||||
|
||||
ep = talloc(sizeof(*ep));
|
||||
ep->t_op = SYMBOL;
|
||||
ep->t_sc = sp->s_sc;
|
||||
ep->t_type = sp->s_type;
|
||||
ep->t_dp = sp->s_dp;
|
||||
ep->t_ssp = sp->s_ssp;
|
||||
ep->t_offset = sp->s_offset;
|
||||
symcopy(sp->s_symbol,ep->t_symbol);
|
||||
return(ep);
|
||||
}
|
||||
|
||||
/* cnalloc - constant node allocation
|
||||
* Allocates a constant tree node and fills the info fields.*/
|
||||
char *cnalloc(type,value) /* returns pointer to node*/
|
||||
int type; /* data type*/
|
||||
int value; /* constant value*/
|
||||
{
|
||||
register struct conode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CINT;
|
||||
cp->t_type = type;
|
||||
cp->t_dp = 0;
|
||||
cp->t_ssp = 0;
|
||||
cp->t_value = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* lcnalloc - long constant node allocation*/
|
||||
/* Allocates a constant tree node and fills the info fields.*/
|
||||
char *lcnalloc(type,value) /* returns pointer to node*/
|
||||
int type; /* data type*/
|
||||
long value; /* constant value*/
|
||||
{
|
||||
register struct lconode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CLONG;
|
||||
cp->t_type = type;
|
||||
cp->t_dp = 0;
|
||||
cp->t_ssp = 0;
|
||||
cp->t_lvalue = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* fpcnalloc - floating point constant node allocation*/
|
||||
/* Allocates a constant tree node and fills the info fields.*/
|
||||
char *fpcnalloc(type,value) /*[vlh] 3.4 returns pointer to node*/
|
||||
int type; /* data type*/
|
||||
long value; /* constant value*/
|
||||
{
|
||||
register struct lconode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CFLOAT;
|
||||
cp->t_type = type;
|
||||
cp->t_dp = 0;
|
||||
cp->t_ssp = 0;
|
||||
cp->t_lvalue = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* tnalloc - tree node allocation*/
|
||||
/* Allocates an operator tree node and fills the info fields*/
|
||||
char *tnalloc(op,type,dp,ssp,left,right) /* returns pointer to node*/
|
||||
int op; /* operator*/
|
||||
int type; /* operator type*/
|
||||
int dp; /* dimension pointer or other info*/
|
||||
int ssp; /* structure length pointer*/
|
||||
char *left; /* left subtree*/
|
||||
char *right; /* right subtree*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
tp = talloc(sizeof(*tp));
|
||||
tp->t_op = op;
|
||||
tp->t_type = type;
|
||||
tp->t_dp = dp;
|
||||
tp->t_ssp = ssp;
|
||||
tp->t_left = left;
|
||||
tp->t_right = right;
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* snalloc - symbol node allocation*/
|
||||
/* Allocates a tree symbol node and sets the info in it*/
|
||||
char *snalloc(type,sc,off,dp,ssp) /* returns pointer to node alloc'ed*/
|
||||
int type; /* symbol type*/
|
||||
int sc; /* storage class*/
|
||||
int off; /* offset*/
|
||||
int dp; /* dimension pointer or other info*/
|
||||
int ssp; /* structure size pointer*/
|
||||
{
|
||||
register struct symnode *snp;
|
||||
|
||||
snp = talloc(sizeof(*snp));
|
||||
snp->t_op = SYMBOL;
|
||||
snp->t_sc = sc;
|
||||
snp->t_type = type;
|
||||
snp->t_dp = dp;
|
||||
snp->t_ssp = ssp;
|
||||
snp->t_offset = off;
|
||||
return(snp);
|
||||
}
|
||||
|
||||
/* pushopd - put operand node onto operand stack*/
|
||||
/* Checks for operand stack overflow.*/
|
||||
pushopd(tp) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree node to push*/
|
||||
{
|
||||
if( opdp >= &opdstack[OPDSIZE] )
|
||||
ferror("expression too complex");
|
||||
*opdp++ = tp;
|
||||
}
|
||||
|
||||
/* popopd - pop operand stack*/
|
||||
/* Checks for stack underflow*/
|
||||
char *popopd() /* returns ptr to top operand*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
if( opdp <= &opdstack[0] )
|
||||
return(0);
|
||||
tp = *--opdp;
|
||||
return(tp);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
/*#define DEBUG 1*/
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*
|
||||
C68 Parser - include file
|
||||
*/
|
||||
#include "../icode.h"
|
||||
|
||||
/*symbol attribute fields*/
|
||||
#define SRESWORD 001 /*is symbol a reserved word?*/
|
||||
#define SGLOBAL 002 /*is symbol global?*/
|
||||
#define STYPEDEF 004 /*typedef declaration?*/
|
||||
#define SDEFINED 010 /*symbol defined?*/
|
||||
|
||||
/*reserved words*/
|
||||
#define R_AUTO 1
|
||||
#define R_BREAK 2
|
||||
#define R_CASE 3
|
||||
#define R_CHAR 4
|
||||
#define R_CONTINUE 5
|
||||
#define R_DO 6
|
||||
#define R_DEFAULT 7
|
||||
#define R_DOUBLE 8
|
||||
#define R_GOTO 9
|
||||
#define R_ELSE 10
|
||||
#define R_EXTERNAL 11
|
||||
#define R_FLOAT 12
|
||||
#define R_FOR 13
|
||||
#define R_IF 14
|
||||
#define R_INT 15
|
||||
#define R_LONG 16
|
||||
#define R_REGISTER 17
|
||||
#define R_RETURN 18
|
||||
#define R_SHORT 19
|
||||
#define R_SIZEOF 20
|
||||
#define R_STATIC 21
|
||||
#define R_STRUCT 22
|
||||
#define R_SWITCH 23
|
||||
#define R_TYPEDEF 24
|
||||
#define R_UNION 25
|
||||
#define R_UNSIGNED 26
|
||||
#define R_WHILE 27
|
||||
|
||||
/*
|
||||
* mixed-mode conversions, entries in 2-d array indexed by:
|
||||
* (int,unsn,long,doub,ptr)
|
||||
*/
|
||||
#define INT_CHAR 1
|
||||
#define UNSN_CHAR 1
|
||||
#define LONG_CHAR 1
|
||||
#define DOUB_CHAR 1
|
||||
#define PTR_CHAR 1
|
||||
#define INT_UNSN 0 /*no conversion is generated*/
|
||||
#define INT_LONG 2
|
||||
#define INT_DOUB 3
|
||||
#define INT_PTR 4
|
||||
#define UNSN_INT 0 /*no conversion is generated*/
|
||||
#define UNSN_LONG 6
|
||||
#define UNSN_DOUB 7
|
||||
#define UNSN_PTR 8
|
||||
#define LONG_INT 9
|
||||
#define LONG_UNSN 10
|
||||
#define LONG_DOUB 11
|
||||
#define LONG_PTR 12
|
||||
#define DOUB_INT 13
|
||||
#define DOUB_UNSN 14
|
||||
#define DOUB_LONG 15
|
||||
#define PTR_INT 16
|
||||
#define PTR_UNSN 17
|
||||
#define PTR_LONG 18
|
||||
#define PTR_PTR 19
|
||||
#define BADCONV 20
|
||||
|
||||
/* miscellaneous constants */
|
||||
#define OPSSIZE 40 /*operator stack size*/
|
||||
#define OPDSIZE 80 /*operand stack size*/
|
||||
#define HSIZE 517 /*hash table size, 3.4 made prime */
|
||||
/* [vlh] 4.1 was 1024, but 1144 is divisible evenly on the 11 and 68000 */
|
||||
#define SYMSIZE 1144 /*size to alloc for symbol structures*/
|
||||
#define SWSIZE 256 /*max no. of cases in a switch*/
|
||||
#define DSIZE 1000 /*dimension table size*/
|
||||
#define BITSPWORD 16 /*bits per word*/
|
||||
#define AREGLO 010 /*A reg flag*/
|
||||
#define HICREG 2 /*highest reg # used for code generation*/
|
||||
#define BITSPCHAR 8 /*bits per char*/
|
||||
#define CHRSPWORD 2 /*chars per word*/
|
||||
#define STRSIZE 300 /*max string length*/
|
||||
#define NFARGS 40 /*max no. of args to function*/
|
||||
#define NFRSTR 20 /*max no. of forward ref struct proto*/
|
||||
|
||||
/*symbol table node*/
|
||||
struct symbol {
|
||||
char s_attrib; /* defined, resword, global, typedef */
|
||||
char s_sc; /* auto, static, external, register */
|
||||
int s_type; /* 4bits specified, 2 bit fields for ptr... */
|
||||
int s_dp; /* index into dimension table */
|
||||
int s_ssp; /* dimension table/function arg table */
|
||||
int s_offset; /* offset inside of structure */
|
||||
char s_symbol[SSIZE]; /* symbol identifier, to SSIZE chars */
|
||||
struct symbol *s_struc; /* if struct, ptr to parent (sys III) */
|
||||
struct symbol *s_next; /* next symbol table entry */
|
||||
};
|
||||
|
||||
/*expression tree operator node*/
|
||||
struct tnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
struct tnode *t_left;
|
||||
struct tnode *t_right;
|
||||
};
|
||||
|
||||
/*expression tree node for symbol - only keeps location*/
|
||||
struct symnode {
|
||||
int t_op;
|
||||
int t_type; /*data type of symbol*/
|
||||
int t_dp; /*dimension pointer of symbol*/
|
||||
int t_ssp; /*structure size index to dtab*/
|
||||
int t_sc; /*storage class of symbol*/
|
||||
int t_offset; /*offset of symbol*/
|
||||
int t_label;
|
||||
};
|
||||
|
||||
/*expressioon tree node for external symbol - need to keep name*/
|
||||
struct extnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
int t_sc;
|
||||
int t_offset;
|
||||
int t_reg;
|
||||
int t_symbol[SSIZE]; /*symbol name*/
|
||||
};
|
||||
|
||||
/*expression tree node for integer constant*/
|
||||
struct conode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
int t_value; /*constant value*/
|
||||
};
|
||||
|
||||
struct lconode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
long t_lvalue; /*constant value*/
|
||||
};
|
||||
|
||||
struct swtch {
|
||||
int sw_label;
|
||||
int sw_value;
|
||||
} swtab[SWSIZE];
|
||||
|
||||
/*operator and operand stack used by expr*/
|
||||
struct ops { /*operator stack*/
|
||||
int o_op; /*operator*/
|
||||
int o_pri; /*priority*/
|
||||
} opstack[OPSSIZE], *opp;
|
||||
|
||||
char *opdstack[OPDSIZE]; /*operand stack*/
|
||||
char **opdp; /*operand stack pointer*/
|
||||
char *opap; /*ptr to next available loc in exprarea*/
|
||||
char *exprp; /*place to start building expression*/
|
||||
int opinfo[]; /*operator info table*/
|
||||
struct tnode *frp; /*pointer to function return info node*/
|
||||
int swp; /*current entry in switch table*/
|
||||
int cswp; /*current low switch table index*/
|
||||
int nextlabel; /*generates unique label numbers*/
|
||||
int clabel; /*continue label*/
|
||||
int blabel; /*break label*/
|
||||
int rlabel; /*return label*/
|
||||
int dlabel; /*default label*/
|
||||
int lineno; /*current line number of input*/
|
||||
int errcnt; /*count of errors*/
|
||||
int inclflag; /*in include file, don't incr line #'s*/
|
||||
int inclline; /*[vlh]line# in incl file for err rpting*/
|
||||
char inclfile[13]; /*[vlh]include filename for err rpting*/
|
||||
int equalstop; /*stop lex at '=', used for external init*/
|
||||
int commastop; /*stop parse @ comma(used for const expr)*/
|
||||
int colonstop; /*stop parse @ colon(used for case value)*/
|
||||
int instruct; /*set when in structure declaration*/
|
||||
int smember; /*set when seen . or ->*/
|
||||
int infunc; /*set when in function body*/
|
||||
int tdflag; /*declaration is a typedef proto*/
|
||||
char *tdp; /*points to typedef prototype*/
|
||||
int localsize; /*length of local variables*/
|
||||
int naregs; /*keeps track of ptr registers alloc'd*/
|
||||
int ndregs; /*keep track of data registers alloc'd*/
|
||||
int loadreg; /*need to load registers...*/
|
||||
int boffset; /*current bit offset in structure*/
|
||||
int eflag; /*[vlh] 3.4 IEEE floats */
|
||||
int fflag; /*[vlh] 3.4 FFP floats */
|
||||
int xflag; /*translate int's to long's*/
|
||||
int wflag; /*[vlh] don't generate warning mesgs*/
|
||||
int reducep; /*[vlh] if(procid); reduction*/
|
||||
int peektok; /*peeked at token*/
|
||||
|
||||
/*dimension table*/
|
||||
long dtab[DSIZE]; /* [vlh] 3.4 int => long */
|
||||
int cdp; /*next entry in dtab to alloc*/
|
||||
|
||||
/*lexical analyzer values*/
|
||||
int cvalue; /*current token value if keyword or CINT*/
|
||||
int cstrsize; /*current string size*/
|
||||
long clvalue; /*current token value if long constant*/
|
||||
struct symbol *csp; /*current token symbol ptr if SYMBOL*/
|
||||
char cstr[STRSIZE]; /*current token value if CSTRING*/
|
||||
struct symbol *dsp; /*declarator symbol pointer*/
|
||||
|
||||
/* -1 -> not instruct, 0 -> unnamed struct */
|
||||
struct symbol *strucptr[10]; /*[vlh] ptrs to struc symbols*/
|
||||
|
||||
/*function argument table, used to collect function parameters*/
|
||||
struct farg {
|
||||
struct symbol *f_sp;
|
||||
int f_offset;
|
||||
} fargtab[NFARGS];
|
||||
|
||||
/*forward referenced structure prototype names*/
|
||||
struct symbol *frstab[NFRSTR];
|
||||
int frstp;
|
||||
|
||||
/*output buffers for intermediate code and strings*/
|
||||
struct io_buf obuf, sbuf, ibuf, *obp;
|
||||
|
||||
#define stypedef(sp) (sp->s_attrib&STYPEDEF)
|
||||
#define walign(add) ((add+1)&(~1))
|
||||
#define array(type) ((type&SUPTYP)==ARRAY)
|
||||
#define function(type) ((type&SUPTYP)==FUNCTION)
|
||||
#define pointer(type) ((type&SUPTYP)==POINTER)
|
||||
#define notarray(type) ((type&SUPTYP)!=ARRAY)
|
||||
#define notfunction(type) ((type&SUPTYP)!=FUNCTION)
|
||||
#define notpointer(type) ((type&SUPTYP)!=POINTER)
|
||||
#define btype(type) (type&TYPE)
|
||||
#define suptype(type) (type&SUPTYP)
|
||||
#define alltype(type) (type&(SUPTYP|TYPE))
|
||||
#define asgop(op) ((opinfo[op]&OPASSIGN)!=0)
|
||||
#define relop(op) ((opinfo[op]&OPREL)!=0)
|
||||
#define lintegral(op) ((opinfo[op]&OPLWORD)!=0)
|
||||
#define rintegral(op) ((opinfo[op]&OPRWORD)!=0)
|
||||
#define rasop(op) ((opinfo[op]&OPRAS)!=0)
|
||||
#define binop(op) ((opinfo[op]&OPBIN)!=0)
|
||||
#define unaryop(op) ((opinfo[op]&OPBIN)==0)
|
||||
#define leaf(op) ((opinfo[op]&OPTERM)!=0)
|
||||
#define lvalop(op) ((opinfo[op]&OPLVAL)!=0)
|
||||
#define oppriority(op) (opinfo[op]&OPPRI)
|
||||
#define makeiop(op) (op|(0254<<8))
|
||||
/* checks for symbol with structure element storage class */
|
||||
#define isstel(tp) (tp->t_op==SYMBOL && (sesc(tp)))
|
||||
#define sesc(t) (t->t_sc==STELCL||t->t_sc==UNELCL||t->t_sc==BFIELDCL)
|
||||
/* peek at next token, if not read token put back, else delete */
|
||||
/* 1 if matched, 0 otherwise */
|
||||
#define peek(tok) ( (peektok=gettok()) == tok )
|
||||
|
||||
#define outcommon(sym,size) printf("\t.comm _%.8s,%ld\n",sym,size)
|
||||
#define outgoto(lab) if( lab > 0 ) printf("\tbra L%d\n",lab)
|
||||
/* change to text segment */
|
||||
#define outtext() printf("\t.text\n")
|
||||
/* change segment to bss */
|
||||
#define outbss() printf("\t.bss\n")
|
||||
/* output global symbol references */
|
||||
#define outextdef(sym) printf("\t.globl _%.8s\n",sym)
|
||||
/* outputs reserved memory [vlh] 3.4 %d => %ld */
|
||||
#define outresmem(size) printf("\t.ds.b %ld\n",size)
|
||||
/* output padding for word alignments */
|
||||
#define outpad() printf("\t.even\n")
|
||||
/* output long constant to assembler */
|
||||
#define outlcon(val) printf("\t.dc.l %d\n",val)
|
||||
/* output label constant */
|
||||
#define outclab(lab) printf("\t.dc.l L%d\n",lab)
|
||||
/* output a label */
|
||||
#define outlab(lab) printf("\tL%d:",lab)
|
||||
/* output function label */
|
||||
#define outflab(sym) printf("\t_%.8s:\n\t~~%.8s:\n",sym,sym)
|
||||
/* output data label */
|
||||
#define outdlab(sym) printf("\t_%.8s:\n",sym)
|
||||
|
||||
/*functions returning pointers*/
|
||||
char *expr();
|
||||
char *talloc();
|
||||
char *tnalloc();
|
||||
char *enalloc();
|
||||
char *snalloc();
|
||||
char *cnalloc();
|
||||
char *lcnalloc();
|
||||
char *fpcnalloc();
|
||||
char *popopd();
|
||||
char *cvopgen();
|
||||
char *arrayref();
|
||||
char *funcref();
|
||||
char *install();
|
||||
char *lookup();
|
||||
char *balpar();
|
||||
char *sbrk();
|
||||
|
||||
long initlist();
|
||||
long dsize();
|
||||
long psize();
|
||||
long dodecl();
|
||||
long dlist();
|
||||
long getdec();
|
||||
long gethex();
|
||||
long getoct();
|
||||
long getfp();
|
||||
long toieee();
|
||||
long toffp();
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#ifdef DEBUG
|
||||
|
||||
char invalid[] "INVALID";
|
||||
|
||||
char *opname[] {
|
||||
invalid, /*0*/
|
||||
"+", /*1*/
|
||||
"-", /*2*/
|
||||
"*", /*3*/
|
||||
"/", /*4*/
|
||||
"%", /*5*/
|
||||
">>", /*6*/
|
||||
"<<", /*7*/
|
||||
"&", /*8*/
|
||||
"|", /*9*/
|
||||
"^", /*10*/
|
||||
"!", /*11*/
|
||||
"U-", /*12*/
|
||||
"~", /*13*/
|
||||
"--p", /*14*/
|
||||
"++p", /*15*/
|
||||
"p--", /*16*/
|
||||
"p++", /*17*/
|
||||
"=", /*18*/
|
||||
"+=", /*19*/
|
||||
"-=", /*20*/
|
||||
"*=", /*21*/
|
||||
"/=", /*22*/
|
||||
"%=", /*23*/
|
||||
">>=", /*24*/
|
||||
"<<=", /*25*/
|
||||
"&=", /*26*/
|
||||
"|=", /*27*/
|
||||
"^=", /*28*/
|
||||
"jsr", /*29*/
|
||||
"==", /*30*/
|
||||
"!=", /*31*/
|
||||
">", /*32*/
|
||||
">=", /*33*/
|
||||
"<", /*34*/
|
||||
"<=", /*35*/
|
||||
"int->long", /*36*/
|
||||
"long->int", /*37*/
|
||||
"btst", /*38*/
|
||||
"load", /*39*/
|
||||
"long*", /*40*/
|
||||
"long/", /*41*/
|
||||
"long%", /*42*/
|
||||
"long*=", /*43*/
|
||||
"long/=", /*44*/
|
||||
"long%=", /*45*/
|
||||
"=addr", /*46*/
|
||||
"=not", /*47*/
|
||||
"=neg", /*48*/
|
||||
"docast", /*49*/
|
||||
"st=", /*50*/
|
||||
"ltof", /*51*/
|
||||
"ftol", /*52*/
|
||||
"itof", /*53*/
|
||||
"ftoi", /*54*/
|
||||
"tochar", /*55*/
|
||||
invalid, /*56*/
|
||||
invalid, /*57*/
|
||||
invalid, /*58*/
|
||||
invalid, /*59*/
|
||||
"U&", /*60*/
|
||||
"U*", /*61*/
|
||||
"&&", /*62*/
|
||||
"||", /*63*/
|
||||
"?", /*64*/
|
||||
":", /*65*/
|
||||
",", /*66*/
|
||||
"cint", /*67*/
|
||||
"clong", /*68*/
|
||||
"symbol", /*69*/
|
||||
"++a", /*70*/
|
||||
"a--", /*71*/
|
||||
"call", /*72*/
|
||||
"call()", /*73*/
|
||||
"bitfield", /*74*/
|
||||
"if", /*75*/
|
||||
"init", /*76*/
|
||||
"loadR0", /*77*/
|
||||
"divlong", /*78*/
|
||||
};
|
||||
|
||||
char *types[] {
|
||||
invalid, /*0=TYPELESS*/
|
||||
"char", /*1=CHAR*/
|
||||
invalid, /*2=SHORT*/
|
||||
"int", /*3=INT*/
|
||||
"long", /*4=LONG*/
|
||||
invalid, /*5=UCHAR*/
|
||||
invalid, /*6=USHORT*/
|
||||
"uint", /*7=UINT*/
|
||||
invalid, /*8=ULONG*/
|
||||
"float", /*9=FLOAT*/
|
||||
invalid, /*10=DOUBLE*/
|
||||
"struct", /*11=STRUCT*/
|
||||
invalid, /*12=undefined*/
|
||||
invalid, /*13=undefined*/
|
||||
invalid, /*14=undefined*/
|
||||
invalid, /*15=undefined*/
|
||||
};
|
||||
|
||||
char *suvals[] {
|
||||
"zero",
|
||||
"one",
|
||||
"quick",
|
||||
"small",
|
||||
"constant",
|
||||
"Areg",
|
||||
"Dreg",
|
||||
"addressable",
|
||||
"loadable",
|
||||
"easy",
|
||||
"hard",
|
||||
"veryhard",
|
||||
};
|
||||
|
||||
int level;
|
||||
|
||||
putexpr(name,tp)
|
||||
char *name;
|
||||
struct tnode *tp;
|
||||
{
|
||||
printf("%s\n",name);
|
||||
putsexpr(tp);
|
||||
}
|
||||
|
||||
putsexpr(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
register struct tnode *ltp;
|
||||
|
||||
level++;
|
||||
ltp = tp->t_left;
|
||||
outlevel();
|
||||
printf("%s ",opname[tp->t_op]);
|
||||
puttsu(tp);
|
||||
if (tp->t_op < 0 || tp->t_op > 78) {
|
||||
printf("INVALID op\n");
|
||||
return;
|
||||
}
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case DCLONG:
|
||||
case CLONG:
|
||||
case CFLOAT: /*[vlh] 3.4 */
|
||||
printf(" %x.%x\n",tp->t_lvalue.hiword,tp->t_lvalue.loword);
|
||||
break;
|
||||
|
||||
|
||||
case CINT:
|
||||
printf(" %d\n",tp->t_value);
|
||||
break;
|
||||
|
||||
case AUTODEC:
|
||||
case AUTOINC:
|
||||
printf("Autodec or Autoinc");
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
case REGISTER:
|
||||
printf(" Register");
|
||||
break;
|
||||
|
||||
case CINDR:
|
||||
printf(" %d\n",tp->t_offset);
|
||||
break;
|
||||
|
||||
case CLINDR:
|
||||
case CFINDR: /* [vlh] 3.4 */
|
||||
printf(" %x.%x\n",tp->t_offset,tp->t_ssp);
|
||||
break;
|
||||
|
||||
case REGOFF:
|
||||
printf(" Regoffset");
|
||||
break;
|
||||
|
||||
case EXTERNAL:
|
||||
case EXTOFF:
|
||||
printf(" %s+%d",tp->t_symbol,tp->t_offset);
|
||||
if( tp->t_sc == EXTOFF )
|
||||
printf("Ext offset");
|
||||
break;
|
||||
|
||||
case STATIC:
|
||||
case STATOFF:
|
||||
printf(" STATIC or STATOFF");
|
||||
if( tp->t_sc == STATOFF )
|
||||
printf("STATOFF");
|
||||
break;
|
||||
|
||||
case INDEXED:
|
||||
printf(" %d indexed",tp->t_offset);
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
putsexpr(tp->t_left);
|
||||
break;
|
||||
|
||||
default:
|
||||
putchar('\n');
|
||||
putsexpr(tp->t_left);
|
||||
if( binop(tp->t_op) )
|
||||
putsexpr(tp->t_right);
|
||||
break;
|
||||
}
|
||||
level--;
|
||||
}
|
||||
|
||||
outlevel()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for( i = 0; i < level; i++ )
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
puttsu(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
register int i;
|
||||
|
||||
switch( suptype(tp->t_type) ) {
|
||||
|
||||
case FUNCTION:
|
||||
printf("()");
|
||||
break;
|
||||
|
||||
case ARRAY:
|
||||
printf("[]");
|
||||
break;
|
||||
|
||||
case POINTER:
|
||||
printf("*");
|
||||
break;
|
||||
}
|
||||
printf("%s ",types[btype(tp->t_type)]);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#define labgen(l,sl) sl=l;l=nextlabel++
|
||||
int swp -1;
|
||||
|
||||
|
||||
/* stmt - process a single statement*/
|
||||
stmt() /* returns - none*/
|
||||
{
|
||||
register int token, lab, i;
|
||||
register struct tnode *tp;
|
||||
register char *p;
|
||||
|
||||
while( 1 ) {
|
||||
switch(token=gettok()) {
|
||||
|
||||
case LCURBR: /*handle { ... }*/
|
||||
while( !next(EOF) ) {
|
||||
if( next(RCURBR) )
|
||||
return;
|
||||
stmt();
|
||||
}
|
||||
case EOF:
|
||||
error("{ not matched by }");
|
||||
case SEMI: /*null statement*/
|
||||
return;
|
||||
|
||||
case RCURBR:
|
||||
pbtok(token);
|
||||
return;
|
||||
|
||||
case SYMBOL: /*symbol: statement*/
|
||||
if( peekc(':') ) {
|
||||
dolabel();
|
||||
continue;
|
||||
}
|
||||
default: /*anything else...*/
|
||||
pbtok(token);
|
||||
outexpr(expr());
|
||||
break;
|
||||
|
||||
case RESWORD:
|
||||
switch(cvalue) {
|
||||
|
||||
case R_BREAK:
|
||||
lab = brklabel();
|
||||
outgoto(lab); /*branch to break label*/
|
||||
break;
|
||||
|
||||
case R_CASE:
|
||||
docase();
|
||||
continue;
|
||||
|
||||
case R_CONTINUE:
|
||||
lab = contlabel(); /*branch to continue label*/
|
||||
outgoto(lab);
|
||||
break;
|
||||
|
||||
case R_DEFAULT:
|
||||
dodefault();
|
||||
continue;
|
||||
|
||||
case R_DO:
|
||||
dodo();
|
||||
break;
|
||||
|
||||
case R_FOR:
|
||||
dofor();
|
||||
return;
|
||||
|
||||
case R_GOTO:
|
||||
lab = gotolabel();
|
||||
outgoto(lab);
|
||||
break;
|
||||
|
||||
case R_IF:
|
||||
doif();
|
||||
return;
|
||||
|
||||
case R_RETURN:
|
||||
doreturn();
|
||||
break;
|
||||
|
||||
case R_SWITCH:
|
||||
doswitch();
|
||||
return;
|
||||
|
||||
case R_WHILE:
|
||||
dowhile();
|
||||
return;
|
||||
|
||||
default:
|
||||
synerr("invalid keyword");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( !next(SEMI) )
|
||||
synerr("missing semicolon");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* balpar - handle expression within parenthesis for while and if*/
|
||||
/* Merely checks for left and right parens and builds expression.*/
|
||||
char *balpar() /* returns pointer to expression*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
if( next(LPAREN) ) {
|
||||
reducep = 1;
|
||||
tp = expr();
|
||||
reducep = 0;
|
||||
if( next(RPAREN) )
|
||||
return(tp);
|
||||
}
|
||||
synerr("parenthesized expression syntax");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* synerr - syntax error*/
|
||||
/* Outputs error message and tries to resyncronize input.*/
|
||||
synerr(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* printf format string*/
|
||||
int x1, x2, x3, x4, x5, x6; /* printf arguments*/
|
||||
{
|
||||
register int token;
|
||||
|
||||
error(s,x1,x2,x3,x4,x5,x6);
|
||||
while( (token=gettok()) != SEMI && token != EOF && token != LCURBR &&
|
||||
token != RCURBR )
|
||||
;
|
||||
pbtok(token);
|
||||
}
|
||||
|
||||
/* gotolabel - gets label id for goto*/
|
||||
/* This is used for both: goto symbol and if(...)goto symbol*/
|
||||
gotolabel() /* returns 0 if not, else label id*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
if( !next(SYMBOL) )
|
||||
synerr("expected label");
|
||||
else {
|
||||
sp = csp;
|
||||
if( !(sp->s_sc) ) {
|
||||
sp->s_type = LLABEL;
|
||||
if( !sp->s_offset )
|
||||
sp->s_offset = nextlabel++;
|
||||
}
|
||||
if( (!sp->s_sc || sp->s_sc == STATIC ) && sp->s_type == LLABEL )
|
||||
return(sp->s_offset);
|
||||
synerr("invalid label");
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* dolabel - do statement label*/
|
||||
/* Checks current symbol for already being defined, then sets*/
|
||||
/* symbol attributes for label.*/
|
||||
dolabel() /* returns - none*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
sp = csp;
|
||||
if( sp->s_sc )
|
||||
error("label redeclaration: %.8s",sp->s_symbol);
|
||||
else {
|
||||
sp->s_attrib =| SDEFINED;
|
||||
sp->s_sc = STATIC;
|
||||
sp->s_type = LLABEL;
|
||||
if( !sp->s_offset )
|
||||
sp->s_offset = nextlabel++;
|
||||
outlab(sp->s_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* brklabel - generate break label*/
|
||||
/* Checks if break label is undefined, and if so, generates message*/
|
||||
brklabel() /* returns label number*/
|
||||
{
|
||||
if( !blabel )
|
||||
error("invalid break statement");
|
||||
return(blabel);
|
||||
}
|
||||
|
||||
/* contlabel - generate continue label*/
|
||||
/* Checks if continue label is undefined, and if so, generates message*/
|
||||
contlabel() /* returns label number*/
|
||||
{
|
||||
if( !clabel )
|
||||
error("invalid continue statement");
|
||||
return(clabel);
|
||||
}
|
||||
|
||||
/* docase - handles: case constant : statement*/
|
||||
/* Checks for being in a switch statement, adds entry to switch table*/
|
||||
docase() /* returns - none*/
|
||||
{
|
||||
register int value, lab;
|
||||
|
||||
colonstop++;
|
||||
value = cexpr(); /*get case value*/
|
||||
colonstop--;
|
||||
if( !next(COLON) ) /*check for colon*/
|
||||
synerr("missing colon");
|
||||
if( swp < 0 )
|
||||
error("case not inside a switch block");
|
||||
else if( swp >= (SWSIZE-1) )
|
||||
error("too many cases in switch");
|
||||
else {
|
||||
addswitch(&swtab[cswp],swp-cswp,value,lab=nextlabel++);
|
||||
outlab(lab);
|
||||
swp++;
|
||||
}
|
||||
}
|
||||
|
||||
/* dodefault - handles: default : statement*/
|
||||
/* Checks for colon and being in a switch statement*/
|
||||
dodefault() /* returns - none*/
|
||||
{
|
||||
if( !next(COLON) )
|
||||
error("missing colon");
|
||||
if( swp < 0 )
|
||||
error("default not inside a switch block");
|
||||
else {
|
||||
dlabel = nextlabel++; /*allocate default label*/
|
||||
outlab(dlabel); /*output default label*/
|
||||
}
|
||||
}
|
||||
|
||||
/* dodo - handles: do statement while ( expression )*/
|
||||
dodo() /* returns - none*/
|
||||
{
|
||||
register int lab, saveblab, saveclab;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
lab = nextlabel++;
|
||||
outlab(lab); /*branch back to here*/
|
||||
stmt(); /*do statement*/
|
||||
outlab(clabel); /*continue label*/
|
||||
if( !nextrw(R_WHILE) ) {
|
||||
error("missing while"); /*only advisory...*/
|
||||
outgoto(lab);
|
||||
}
|
||||
else
|
||||
outifgoto(balpar(),TRUE,lab); /*while expression*/
|
||||
outlab(blabel); /*break label*/
|
||||
blabel = saveblab; /*restore labels*/
|
||||
clabel = saveclab;
|
||||
}
|
||||
|
||||
#define dobody(l) stmt();outlab((l));clno=lineno;lineno=rinit
|
||||
/*
|
||||
* dofor - handle: for ( expression ; expression ; expression ) statement
|
||||
* Hard part is handling re-initialization expression, which is
|
||||
* parsed and saved, then the statement is parsed, then the reinit
|
||||
* clause expression tree is output.
|
||||
*/
|
||||
dofor() /* returns - none*/
|
||||
{ /* [vlh] 4.0 reordered */
|
||||
register int testlab, stmtlab, saveblab, saveclab;
|
||||
register struct tnode *rip, *cp;
|
||||
register char *savep;
|
||||
int rinit, clno, iscond;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
if( !next(LPAREN) ) {
|
||||
forerr:
|
||||
synerr("invalid for statement");
|
||||
return;
|
||||
}
|
||||
if( !next(SEMI) ) { /*do init expression*/
|
||||
outexpr(expr());
|
||||
if( !next(SEMI) )
|
||||
goto forerr;
|
||||
}
|
||||
savep = exprp; /* save ptr to exprarea */
|
||||
if( !next(SEMI) ) { /* do for condition */
|
||||
testlab = nextlabel++; /* if condition, get a label */
|
||||
outgoto(testlab); /* only goto cond expr if exists*/
|
||||
iscond = 1;
|
||||
cp = expr();
|
||||
exprp = opap;
|
||||
if( !next(SEMI) )
|
||||
goto forerr;
|
||||
}
|
||||
else
|
||||
iscond = 0;
|
||||
stmtlab = nextlabel++;
|
||||
outlab(stmtlab); /* branch back to here */
|
||||
rinit = lineno;
|
||||
if( next(RPAREN) ) { /*no re-init - easy case*/
|
||||
dobody(clabel); /*output statement*/
|
||||
}
|
||||
else { /*there is a re-init clause*/
|
||||
rip = expr(); /*save re-init tree until done*/
|
||||
exprp = opap;
|
||||
if( !next(RPAREN) )
|
||||
goto forerr;
|
||||
dobody(clabel); /*do statment*/
|
||||
outexpr(rip); /*output re-init clause*/
|
||||
}
|
||||
if (iscond) {
|
||||
outlab(testlab); /* branch for test */
|
||||
outifgoto(cp,TRUE,stmtlab);
|
||||
}
|
||||
else
|
||||
outgoto(stmtlab); /* unconditional branch */
|
||||
exprp = savep;
|
||||
lineno = clno;
|
||||
outlab(blabel); /* break label */
|
||||
blabel = saveblab;
|
||||
clabel = saveclab; /*restore labels*/
|
||||
}
|
||||
|
||||
/* doif - handles: if ( expression ) statement [ else statement ]*/
|
||||
/* Handles special cases for goto, break, continue and return.*/
|
||||
doif() /* returns - none*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
register int elselab, exitlab;
|
||||
|
||||
tp = balpar(); /*if( expr )...*/
|
||||
exitlab = 0;
|
||||
if( nextrw(R_GOTO) )
|
||||
exitlab = gotolabel();
|
||||
else if( nextrw(R_BREAK) )
|
||||
exitlab = brklabel();
|
||||
else if( nextrw(R_CONTINUE) )
|
||||
exitlab = contlabel();
|
||||
else if( nextrw(R_RETURN) ) {
|
||||
if( peekc(';') ) {
|
||||
exitlab = rlabel;
|
||||
putback(';');
|
||||
}
|
||||
else
|
||||
pbtok(RESWORD);
|
||||
}
|
||||
if( exitlab ) { /*easy goto, do branch if true*/
|
||||
outifgoto(tp,TRUE,exitlab);
|
||||
if( !next(SEMI) )
|
||||
synerr("missing semicolon");
|
||||
if( nextrw(R_ELSE) ) /*else clause, just output it*/
|
||||
stmt();
|
||||
}
|
||||
else { /*hard goto, branch over statement*/
|
||||
elselab = nextlabel++;
|
||||
outifgoto(tp,FALSE,elselab);
|
||||
stmt();
|
||||
if( nextrw(R_ELSE) ) {
|
||||
exitlab = nextlabel++; /*branches over else clause*/
|
||||
outgoto(exitlab); /*branch out of then clause*/
|
||||
outlab(elselab); /*label to start else clause*/
|
||||
stmt(); /*else statement*/
|
||||
outlab(exitlab);
|
||||
}
|
||||
else
|
||||
outlab(elselab); /*no else, just branch out*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* doreturn - handles: return [ expression ] ;
|
||||
* Expression is the hard part, must create an assignment expression
|
||||
* to assign expression to the type of the function, then get it
|
||||
* loaded into a specific register.
|
||||
*/
|
||||
doreturn() /* returns - none*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
if( !peekc(';') ) /*need to compute return?*/
|
||||
outforreg(FRETURN,frp,expr());
|
||||
else
|
||||
putback(';');
|
||||
outgoto(rlabel); /*branch to the return label*/
|
||||
}
|
||||
|
||||
/*
|
||||
* doswitch - handles: switch ( expression ) statement
|
||||
* Evaluates the expression, forces the result into a known register
|
||||
* collects the case statements in swtab, then outputs the switch
|
||||
* operator and switch cases.
|
||||
*/
|
||||
doswitch() /* returns - none*/
|
||||
{
|
||||
register int saveblab, swlab, savedlab, saveswp, i;
|
||||
register struct tnode *tp;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
tp = balpar();
|
||||
integral(tp,-1); /*must be integral type result*/
|
||||
outforreg(ASSIGN,snalloc(INT,AUTO,0,0,0),tp);
|
||||
saveswp = swp; /*remember old switch pointer*/
|
||||
if( saveswp < 0 )
|
||||
swp++;
|
||||
i = cswp;
|
||||
cswp = swp; /*remember real first entry*/
|
||||
swlab = nextlabel++;
|
||||
outgoto(swlab); /*branch to switch code*/
|
||||
savedlab = dlabel;
|
||||
dlabel = 0;
|
||||
stmt(); /*do switch statement*/
|
||||
outgoto(blabel); /*output branch just in case*/
|
||||
outlab(swlab); /*here we now do the switch code*/
|
||||
if( !dlabel )
|
||||
dlabel = blabel;
|
||||
outswitch(swp-cswp,dlabel,&swtab[cswp]);
|
||||
outlab(blabel); /*break to here*/
|
||||
cswp = i;
|
||||
swp = saveswp;
|
||||
blabel = saveblab;
|
||||
dlabel = savedlab;
|
||||
}
|
||||
|
||||
/* dowhile - handles: while ( expression ) statement*/
|
||||
/* This is fairly straight-forward.*/
|
||||
dowhile() /* returns - none*/
|
||||
{ /* [vlh] 4.0 reworked */
|
||||
register int saveclab, saveblab, lab;
|
||||
register char *savep;
|
||||
register struct tnode *tp;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
labgen(clabel,lab);
|
||||
savep = exprp;
|
||||
if((tp = balpar()) != 0) /*get condition clause*/
|
||||
outgoto(clabel); /*condition label*/
|
||||
exprp = opap;
|
||||
outlab(lab);
|
||||
stmt(); /*statement*/
|
||||
outlab(clabel); /*condition test*/
|
||||
outifgoto(tp,TRUE,lab); /* branch back to top of loop */
|
||||
outlab(blabel); /*break to here*/
|
||||
exprp = savep;
|
||||
blabel = saveblab;
|
||||
clabel = saveclab; /*restore labels*/
|
||||
}
|
||||
|
||||
/* nextrw - is next token the specified reserved word?*/
|
||||
nextrw(rw) /* returns 1 if match, 0 otherwise*/
|
||||
int rw; /* reserved word to match*/
|
||||
{
|
||||
register int token;
|
||||
|
||||
if( (token=gettok()) != RESWORD || cvalue != rw ) {
|
||||
pbtok(token);
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* addswitch - add an entry into current switch table, bubble sorting
|
||||
* This makes it easier on the code generator and also checks for
|
||||
* duplicate labels at the "right" time.
|
||||
*/
|
||||
addswitch(sp,ncases,nval,nlab) /* returns - none*/
|
||||
struct swtch *sp; /* switch table pointer*/
|
||||
int ncases; /* number of cases in switch*/
|
||||
int nval; /* new value*/
|
||||
int nlab; /* new label*/
|
||||
{
|
||||
register struct swtch *nswp, *s;
|
||||
register int temp, i;
|
||||
|
||||
nswp = &sp[ncases];
|
||||
nswp->sw_value = nval;
|
||||
nswp->sw_label = nlab;
|
||||
s = nswp--;
|
||||
for( ; --ncases >= 0; s--, nswp-- ) {
|
||||
if( s->sw_value == nswp->sw_value )
|
||||
error("duplicate case value");
|
||||
if( s->sw_value < nswp->sw_value ) {
|
||||
temp = s->sw_value;
|
||||
s->sw_value = nswp->sw_value;
|
||||
nswp->sw_value = temp;
|
||||
temp = s->sw_label;
|
||||
s->sw_label = nswp->sw_label;
|
||||
nswp->sw_label = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* outforreg - generate assignment for switch and return*/
|
||||
outforreg(op,ltp,rtp) /*returns - none*/
|
||||
int op; /*operator for build tree*/
|
||||
struct tnode *ltp; /*left expression tree*/
|
||||
struct tnode *rtp; /*right expression tree*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
opp = opstack;
|
||||
opdp = opdstack;
|
||||
pushopd(ltp);
|
||||
pushopd(rtp);
|
||||
maketree(op);
|
||||
if( tp = popopd() )
|
||||
outcforreg(tp->t_right);
|
||||
opp = opdp = 0;
|
||||
}
|
||||
|
||||
/* outassign - generate assignment for function args*/
|
||||
outassign(ltp,rtp) /*returns - none*/
|
||||
struct tnode *ltp; /*left expression tree*/
|
||||
struct tnode *rtp; /*right expression tree*/
|
||||
{
|
||||
opp = opstack;
|
||||
opdp = opdstack;
|
||||
pushopd(ltp);
|
||||
pushopd(rtp);
|
||||
maketree(ASSIGN);
|
||||
outexpr(popopd());
|
||||
opp = opdp = 0;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#define ASGOP OPRAS|OPASSIGN|OPLVAL|OPBIN
|
||||
|
||||
/*info on operators:*/
|
||||
/*000077-- OPPRI - priority*/
|
||||
/*000100-- OPBIN - binary operator*/
|
||||
/*000200-- OPLVAL - left operand must be lvalue*/
|
||||
/*000400-- OPREL - relational operator*/
|
||||
/*001000-- OPASSIGN - assignment operator*/
|
||||
/*002000-- OPLWORD - int required on left*/
|
||||
/*004000-- OPRWORD - int required on right*/
|
||||
/*010000-- OPCOM commutative*/
|
||||
/*020000-- OPRAS - right associative*/
|
||||
/*040000-- OPTERM - termination node*/
|
||||
/*100000 - OPCONVS - conversion operator*/
|
||||
int opinfo[] {
|
||||
TRMPRI, /*EOF*/
|
||||
ADDPRI|OPCOM|OPBIN, /*ADD - expr + expr*/
|
||||
ADDPRI|OPBIN, /*SUB - expr - expr*/
|
||||
MULPRI|OPCOM|OPBIN, /*MULT - expr * expr*/
|
||||
MULPRI|OPBIN, /*DIV - expr / expr*/
|
||||
MULPRI|OPBIN, /*MOD - expr % expr*/
|
||||
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*RSH - expr >> expr*/
|
||||
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*LSH - expr << expr*/
|
||||
ANDPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*AND - expr & expr*/
|
||||
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*OR - expr | expr*/
|
||||
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*XOR - expr ^ expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*NOT - ! expr*/
|
||||
UNOPRI|OPRAS, /*UMINUS - - expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*COMPL - ~ expr*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREDEC - --lvalue*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREINC - ++lvalue*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTDEC - lvalue--*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTINC - lvalue++*/
|
||||
ASGPRI|ASGOP, /*ASSIGN - lvalue = expr*/
|
||||
ASGPRI|ASGOP, /*EQADD - lvalue += expr*/
|
||||
ASGPRI|ASGOP, /*EQSUB - lvalue -= expr*/
|
||||
ASGPRI|ASGOP, /*EQMULT - lvalue *= expr*/
|
||||
ASGPRI|ASGOP, /*EQDIV - lvalue /= expr*/
|
||||
ASGPRI|ASGOP, /*EQMOD - lvalue %= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQRSH - lvalue >>= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQLSH - lvalue <<= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQAND - lvalue &= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQOR - lvalue |= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQXOR - lvalue ^= expr*/
|
||||
TRMPRI, /*FJSR - generate function jsr*/
|
||||
EQLPRI|OPREL|OPBIN, /*EQUALS - expr == expr*/
|
||||
EQLPRI|OPREL|OPBIN, /*NEQUALS - expr != expr*/
|
||||
RELPRI|OPREL|OPBIN, /*GREAT - expr > expr*/
|
||||
RELPRI|OPREL|OPBIN, /*GREATEQ - expr >= expr*/
|
||||
RELPRI|OPREL|OPBIN, /*LESS - expr < expr*/
|
||||
RELPRI|OPREL|OPBIN, /*LESSEQ - expr <= expr*/
|
||||
TRMPRI|OPCONVS, /*INT2L*/
|
||||
TRMPRI|OPCONVS, /*LONG2I*/
|
||||
TRMPRI|OPBIN, /*BTST*/
|
||||
TRMPRI, /*LOAD*/
|
||||
TRMPRI|OPBIN, /*LMULT*/
|
||||
TRMPRI|OPBIN, /*LDIV*/
|
||||
TRMPRI|OPBIN, /*LMOD*/
|
||||
TRMPRI|OPBIN, /*LEQMULT*/
|
||||
TRMPRI|OPBIN, /*LEQDIV*/
|
||||
TRMPRI|OPBIN, /*LEQMOD*/
|
||||
TRMPRI|ASGOP, /*EQADDR*/
|
||||
TRMPRI, /*EQNOT*/
|
||||
TRMPRI, /*EQNEG*/
|
||||
TRMPRI|OPBIN, /*DOCAST*/
|
||||
ASGPRI|ASGOP, /*STASSIGN [vlh]*/
|
||||
TRMPRI|OPCONVS, /*LONG2F [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*FLOAT2L [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*INT2F [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*FLOAT2I [vlh] 3.4*/
|
||||
UNOPRI|OPRAS, /*TOCHAR [vlh] 4.0*/
|
||||
TRMPRI, /*unused - 56*/
|
||||
TRMPRI, /*unused - 57*/
|
||||
TRMPRI, /*unused - 58*/
|
||||
TRMPRI, /*unused - 59*/
|
||||
UNOPRI|OPRAS|OPLVAL, /*ADDR - & expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*INDR - * expr*/
|
||||
LNDPRI|OPBIN, /*LAND - expr && expr*/
|
||||
LORPRI|OPBIN, /*LOR - expr || expr*/
|
||||
QMKPRI|OPRAS|OPBIN, /*QMARK - expr ? expr : expr*/
|
||||
QMKPRI|OPRAS|OPBIN, /*COLON*/
|
||||
COMPRI|OPBIN, /*COMMA*/
|
||||
TRMPRI|OPTERM, /*CINT*/
|
||||
TRMPRI|OPTERM, /*CLONG*/
|
||||
TRMPRI|OPTERM, /*SYMBOL*/
|
||||
TRMPRI|OPTERM, /*AUTOINC*/
|
||||
TRMPRI|OPTERM, /*AUTODEC*/
|
||||
LPNPRI|OPBIN, /*CALL - call with arguments*/
|
||||
LPNPRI, /*NACALL - no argument call*/
|
||||
TRMPRI, /*BFIELD - field selection*/
|
||||
TRMPRI, /*IFGOTO*/
|
||||
TRMPRI, /*INIT*/
|
||||
TRMPRI, /*CFORREG*/
|
||||
TRMPRI, /*unused - 78*/
|
||||
TRMPRI|OPTERM, /*CFLOAT [vlh] 3.4*/
|
||||
UNOPRI|OPRAS|OPASSIGN|OPBIN, /*CAST*/
|
||||
TRMPRI, /*SEMI*/
|
||||
TRMPRI, /*LCURBR - {*/
|
||||
TRMPRI, /*RCURBR - }*/
|
||||
LPNPRI, /*LBRACK - [*/
|
||||
RPNPRI, /*RBRACK - ]*/
|
||||
LPNPRI, /*LPAREN - )*/
|
||||
RPNPRI, /*RPAREN - )*/
|
||||
TRMPRI|OPTERM, /*STRING*/
|
||||
TRMPRI, /*RESWORD*/
|
||||
LPNPRI|OPBIN, /*APTR - expr -> symbol*/
|
||||
LPNPRI|OPBIN, /*PERIOD - expr . symbol*/
|
||||
UNOPRI|OPRAS, /*SIZEOF - sizeof expr*/
|
||||
LPNPRI|OPBIN, /*MPARENS - matching parens ()*/
|
||||
UNOPRI|OPRAS|OPASSIGN|OPBIN, /*FRETURN*/
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
char *compiled "@(#) parser - Fri Mar 18 11:33 1983";
|
||||
@@ -0,0 +1,3 @@
|
||||
c68 -L *.c -n -o c168.st -l6 ; setstack c168.st 8192 8192
|
||||
c68 -L *.c -o c168.68 -l6 ; setstack c168.68 8192 8192
|
||||
cc *.c -o c168.11 -lx
|
||||
1006
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/c168/canon.c
Normal file
1006
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/c168/canon.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "../icode.h"
|
||||
//#define NODEBUG 0
|
||||
//#define VERSADOS
|
||||
|
||||
char brtab[][2];
|
||||
int invrel[];
|
||||
int swaprel[];
|
||||
char *strtab[];
|
||||
char null[];
|
||||
|
||||
/*operator tree node for unary and binary operators*/
|
||||
struct tnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*data type of result*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
struct tnode *t_left; /*left sub-tree*/
|
||||
struct tnode *t_right; /*right sub-tree (undefined if unary)*/
|
||||
};
|
||||
|
||||
/*constant terminal node*/
|
||||
struct conode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_value; /*value or label number*/
|
||||
};
|
||||
|
||||
struct lconode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
long t_lvalue; /*value or label number*/
|
||||
};
|
||||
|
||||
/*local symbol terminal node*/
|
||||
struct symnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*symbol data type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_sc; /*storage class*/
|
||||
int t_offset; /*register offset*/
|
||||
int t_reg; /*register number*/
|
||||
int t_label; /*label number if static*/
|
||||
};
|
||||
|
||||
/*external symbol reference node*/
|
||||
struct extnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*symbol data type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_sc; /*storage class*/
|
||||
int t_offset; /*register offset*/
|
||||
int t_reg; /*register number*/
|
||||
char t_symbol[SSIZE]; /*symbol name*/
|
||||
};
|
||||
|
||||
/*68000 special - indexed symbol node*/
|
||||
/*this is used to generate a An(off,Xn.type) address*/
|
||||
struct indexnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_su;
|
||||
int t_ssp;
|
||||
int t_sc;
|
||||
int t_offset;
|
||||
int t_reg;
|
||||
int t_xreg;
|
||||
int t_xtype;
|
||||
};
|
||||
|
||||
int lflag;
|
||||
int dflag;
|
||||
int mflag;
|
||||
int cflag;
|
||||
int eflag;
|
||||
int fflag;
|
||||
int oflag;
|
||||
struct io_buf ibuf, obuf;
|
||||
int lineno;
|
||||
int naregs;
|
||||
int ndregs;
|
||||
int errcnt;
|
||||
int opinfo[];
|
||||
int nextlabel;
|
||||
char null[];
|
||||
char optab[][6];
|
||||
char *mnemonics[];
|
||||
char *codeskels[];
|
||||
int stacksize;
|
||||
|
||||
char *tnalloc();
|
||||
char *snalloc();
|
||||
char *cenalloc();
|
||||
char *xnalloc();
|
||||
char *talloc();
|
||||
char *cnalloc();
|
||||
char *lcnalloc();
|
||||
char *fpcnalloc();
|
||||
char *canon();
|
||||
char *commute();
|
||||
char *constant();
|
||||
char *match();
|
||||
char *addptree();
|
||||
char *fixbfield();
|
||||
char *coffset();
|
||||
char *tcopy();
|
||||
|
||||
#define wallign(add) ((add+1)&(~1))
|
||||
#define array(type) ((type&SUPTYP)==ARRAY)
|
||||
#define function(type) ((type&SUPTYP)==FUNCTION)
|
||||
#define pointer(type) ((type&SUPTYP)==POINTER)
|
||||
#define notarray(type) ((type&SUPTYP)!=ARRAY)
|
||||
#define notfunction(type) ((type&SUPTYP)!=FUNCTION)
|
||||
#define notpointer(type) ((type&SUPTYP)!=POINTER)
|
||||
#define isfloat(type) (type==FLOAT)
|
||||
#define btype(type) (type&TYPE)
|
||||
#define suptype(type) (type&SUPTYP)
|
||||
#define alltype(type) (type&(SUPTYP|TYPE))
|
||||
#define asgop(op) ((opinfo[op]&OPASSIGN)!=0)
|
||||
#define relop(op) ((opinfo[op]&OPREL)!=0)
|
||||
#define lintegral(op) ((opinfo[op]&OPLWORD)!=0)
|
||||
#define rintegral(op) ((opinfo[op]&OPRWORD)!=0)
|
||||
#define rasop(op) ((opinfo[op]&OPRAS)!=0)
|
||||
#define binop(op) ((opinfo[op]&OPBIN)!=0)
|
||||
#define unaryop(op) ((opinfo[op]&(OPBIN|OPTERM))==0)
|
||||
#define leafop(op) ((opinfo[op]&OPTERM)!=0)
|
||||
#define notleafop(op) ((opinfo[op]&OPTERM)==0)
|
||||
#define lvalop(op) ((opinfo[op]&OPLVAL)!=0)
|
||||
#define oppriority(op) (opinfo[op]&OPPRI)
|
||||
#define commop(op) ((opinfo[op]&OPCOM)!=0)
|
||||
#define convop(op) ((opinfo[op]&OPCONVS)!=0)
|
||||
#define notconvop(op) ((opinfo[op]&OPCONVS)==0)
|
||||
#define max(a,b) (a>b?a:b)
|
||||
#define min(a,b) (a<b?a:b)
|
||||
|
||||
#define QUICKVAL 8
|
||||
#define LEP 14
|
||||
#define FORCC 1
|
||||
#define FOREFF 2
|
||||
#define FORSTACK 3
|
||||
#define FORCREG 4
|
||||
#define FORSP 5
|
||||
#define FORREG 4
|
||||
#define HICREG 2
|
||||
#define NCREGS 3
|
||||
#define AREGLO 8
|
||||
#define IMMED 1
|
||||
#define NOTIMMED 0
|
||||
#define NOTLOFFSET 0
|
||||
|
||||
/* one line routines turned into defines [vlh] for speed */
|
||||
|
||||
/*outgoto - output "bra L[labno]"*/
|
||||
#define outgoto(lab) if (lab>0) printf("bra L%d\n",lab)
|
||||
/*outlab - output "L[labno]:"*/
|
||||
#define outlab(lab) if (lab>0) printf("L%d:",lab)
|
||||
|
||||
/*outext - output register sign extension*/
|
||||
#define outext(reg) printf("ext.l R%d\n",reg)
|
||||
/*outuext - output unsigned to long register extension*/
|
||||
#define outuext(reg) printf("swap R%d\nclr R%d\nswap R%d\n",reg,reg,reg)
|
||||
/*outswap - output swap register instruction*/
|
||||
#define outswap(reg) printf("swap R%d\n",reg)
|
||||
/*outaddr - output "add [type] R1 R2" instruction*/
|
||||
#define outaddr(r1,r2,tp) outrr("add",r1,r2,(tp))
|
||||
/*outccsave - ouput instruction to move cc's to register*/
|
||||
#define outccsave(reg) printf("move sr,R%d\n",reg)
|
||||
/*outccrestore - output instruction to restore cc's from register*/
|
||||
#define outccrestore(reg) printf("move R%d,ccr\n",reg)
|
||||
/*basetype - get the btype info sans unsigned*/
|
||||
#define basetype(type) ((type==UNSIGNED) ? INT : type)
|
||||
#define unsign(type) ((type) == UNSIGNED)
|
||||
#define longorptr(type) (type==LONG || (type&SUPTYP))
|
||||
#define unorptr(type) (type==UNSIGNED || (type&SUPTYP))
|
||||
#define dreg(reg) ((reg) & (~AREGLO))
|
||||
#define areg(reg) ((reg) | AREGLO)
|
||||
#define isareg(reg) ((reg) >= AREGLO)
|
||||
#define isdreg(reg) ((reg) < AREGLO)
|
||||
#define isreg(tp) ((tp)->t_op == SYMBOL && (tp)->t_sc == REGISTER)
|
||||
@@ -0,0 +1,756 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
|
||||
/* scodegen - over-all code generation for expression*/
|
||||
/* Picks off post-fix ++, --.*/
|
||||
scodegen(tp,cookie,reg) /* returns register result is in*/
|
||||
struct tnode *tp;
|
||||
int cookie;
|
||||
int reg;
|
||||
{
|
||||
struct tnode *clist[20];
|
||||
struct tnode **clp;
|
||||
register struct tnode **cp;
|
||||
register int r;
|
||||
register int ccflag;
|
||||
register struct tnode *rtp;
|
||||
|
||||
if( tp->t_op == COMMA ) {
|
||||
scodegen(tp->t_left,FOREFF,reg);
|
||||
return(scodegen(tp->t_right,cookie,reg));
|
||||
}
|
||||
ccflag = 0;
|
||||
clp = clist;
|
||||
tp = addptree(tp,&clp);
|
||||
if( clp > clist ) {
|
||||
/*
|
||||
* post ++, -- in tree. We need to compile the tree post operators
|
||||
* then generate code to do the post operators, then do any fix up of
|
||||
* condition codes since the Stupid 68000 architect was a nimnul.
|
||||
*/
|
||||
if( cookie == FORCC ) {
|
||||
/*
|
||||
* here we make the observation that if we are comparing something with
|
||||
* zero OR the top operator of the tree is not a comparison operator,
|
||||
* we can compile the tree to a register, and then set the condition
|
||||
* codes OK with a tst instruction at the end.
|
||||
*/
|
||||
if( relop(tp->t_op) ) {
|
||||
if( (rtp=constant(tp->t_right)) && !rtp->t_value ) {
|
||||
ccflag = 1;
|
||||
tp = tp->t_left;
|
||||
cookie = FORREG;
|
||||
}
|
||||
else
|
||||
ccflag = 2;
|
||||
}
|
||||
else {
|
||||
ccflag = 1;
|
||||
cookie = FORREG;
|
||||
}
|
||||
}
|
||||
}
|
||||
r = codegen(tp,cookie,reg);
|
||||
if( clp > clist ) {
|
||||
if( ccflag == 2 )
|
||||
outccsave(r);
|
||||
for( cp = clist; cp < clp; cp++ )
|
||||
codegen(*cp,FOREFF,r+1);
|
||||
if( ccflag == 1 )
|
||||
outcmp0(r,tp);
|
||||
else if( ccflag == 2 )
|
||||
outccrestore(r);
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* addptree - prune off postfix ++, -- from expression tree*/
|
||||
/* This prunes off ++, -- and collects those expressions for*/
|
||||
/* scodegen.*/
|
||||
char *addptree(tp,clp) /* returns pointer to pruned tree*/
|
||||
struct tnode *tp;
|
||||
struct tnode ***clp;
|
||||
{
|
||||
register int op;
|
||||
|
||||
op = tp->t_op;
|
||||
if( leafop(op) || op == QMARK ) /* [vlh] 4.0 QMARK... */
|
||||
return(tp);
|
||||
if( op == POSTINC || op == POSTDEC ) {
|
||||
*(*clp)++ = tp;
|
||||
return( tcopy(tp->t_left) );
|
||||
}
|
||||
if( binop(op) )
|
||||
tp->t_right = addptree(tp->t_right,clp);
|
||||
tp->t_left = addptree(tp->t_left,clp);
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* codegen - generate code for expression*/
|
||||
/* This calls up rcodegen, which prunes off any special register*/
|
||||
/* optimization code, then calls ucodegen (unrecursive) code*/
|
||||
/* generation.*/
|
||||
codegen(tp,cookie,reg) /* returns reg result is in*/
|
||||
struct tnode *tp; /* tree pointer*/
|
||||
int cookie; /* code generation goals*/
|
||||
int reg; /* first available register*/
|
||||
{
|
||||
register int size, savestk, ssize, r, i, scookie;
|
||||
register struct tnode *rtp;
|
||||
|
||||
#ifndef NODEBUG
|
||||
if( cflag )
|
||||
printf("codegen op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg);
|
||||
#endif
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case CALL:
|
||||
case NACALL:
|
||||
ssize = 0;
|
||||
savestk = stacksize;
|
||||
if( tp->t_left->t_op != SYMBOL )
|
||||
stacksize++;
|
||||
if( tp->t_op == CALL ) {
|
||||
rtp = tp->t_right;
|
||||
while( rtp->t_op == COMMA ) {
|
||||
ssize =+ dofarg(rtp->t_right);
|
||||
rtp = rtp->t_left;
|
||||
}
|
||||
ssize =+ dofarg(rtp);
|
||||
}
|
||||
tp->t_op = FJSR; /*generate JSR (unary op)*/
|
||||
codegen(tp,FORREG,reg);
|
||||
popstack(ssize);
|
||||
stacksize = savestk;
|
||||
fixresult(tp,cookie,0);
|
||||
return(0); /*result in R0*/
|
||||
|
||||
case COMMA:
|
||||
codegen(tp->t_left,FOREFF,reg);
|
||||
return(codegen(tp->t_right,cookie,reg));
|
||||
|
||||
case AND:
|
||||
if( cookie == FORCC && (i=isonebit(tp->t_right)) >= 0 &&
|
||||
(i=dobitadd(tp->t_left,i)) >= 0 ) {
|
||||
if( convop(tp->t_right->t_op) )
|
||||
tp->t_right = tp->t_right->t_left;
|
||||
tp->t_right->t_value = i;
|
||||
tp->t_op = BTST;
|
||||
tp = canon(tp);
|
||||
sucomp(tp,reg,1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( rcodegen(&tp,cookie,reg) ) {
|
||||
if( cookie == FORCC && tp->t_op == SYMBOL && tp->t_sc == REGISTER
|
||||
&& isdreg(tp->t_reg))
|
||||
return(reg);
|
||||
}
|
||||
r = ucodegen(tp,cookie,reg);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* fixresult - fix result of code generation*/
|
||||
fixresult(tp,cookie,reg) /* returns - none*/
|
||||
struct tnode *tp;
|
||||
int cookie; /* wanted this cookie*/
|
||||
int reg;
|
||||
{
|
||||
#ifndef NODEBUG
|
||||
if (cflag)
|
||||
printf("fixresult cookie=%d reg=%d op=%d\n",cookie,reg,tp->t_op);
|
||||
#endif
|
||||
switch( cookie ) {
|
||||
|
||||
case FORCC:
|
||||
outcmp0(reg,tp);
|
||||
break;
|
||||
|
||||
case FORSP:
|
||||
case FORSTACK:
|
||||
stacksize++;
|
||||
outrpush(reg,tp,cookie==FORSTACK);
|
||||
break;
|
||||
|
||||
}
|
||||
return(reg);
|
||||
}
|
||||
|
||||
/* ucodegen - generate code for tree given cookie and starting register*/
|
||||
/* Handles the matching of the expression tree node with the*/
|
||||
/* corresponding code generation table. When a match is found,*/
|
||||
/* expand is called to expand the code skeleton macro.*/
|
||||
ucodegen(tp,cookie,reg) /* returns reg result is in*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int cookie; /* (FORCC,FOREFF,FORREG,FORSTACK)*/
|
||||
int reg; /* first available register*/
|
||||
{
|
||||
register int r;
|
||||
register char *p;
|
||||
|
||||
#ifndef NODEBUG
|
||||
if(cflag)
|
||||
putexpr("ucodegen",tp);
|
||||
#endif
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case STASSIGN: /*[vlh]*/
|
||||
outstrcpy(codegen(tp->t_left,FORREG,areg(reg)),
|
||||
codegen(tp->t_right,FORREG,areg(reg+1)), tp->t_type);
|
||||
return(reg);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
if( cookie == FOREFF )
|
||||
return(reg);
|
||||
break;
|
||||
|
||||
case LSH:
|
||||
if( (isareg(reg)) && (p=constant(tp->t_right)) &&
|
||||
!(unsign(tp->t_left->t_type)) &&
|
||||
(p->t_value == 1 || p->t_value == 2) ) {
|
||||
r = codegen(tp->t_left,FORREG,reg);
|
||||
outmovr(r,reg,tp->t_left);
|
||||
if( p->t_value == 2 )
|
||||
outaddr(reg,reg,tp);
|
||||
outaddr(reg,reg,tp);
|
||||
fixresult(tp,cookie,reg);
|
||||
return(reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case EQMULT:
|
||||
case EQDIV:
|
||||
case LEQMULT:
|
||||
case LEQDIV:
|
||||
case EQMOD:
|
||||
case LEQMOD:
|
||||
case EQRSH:
|
||||
case EQLSH:
|
||||
case EQAND:
|
||||
case EQOR:
|
||||
case EQXOR:
|
||||
if( indexreg(tp->t_left) ) {
|
||||
reg = dreg(reg);
|
||||
outmovr(r=tp->t_left->t_reg,reg,tp);
|
||||
tp->t_left->t_reg = reg;
|
||||
codegen(tp,cookie,reg+1);
|
||||
outmovr(reg,r,tp);
|
||||
return(reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case ADD:
|
||||
case EQADD:
|
||||
if( (p=constant(tp->t_right)) && p->t_value < 0 &&
|
||||
p->t_value >= -QUICKVAL ) {
|
||||
p->t_value = - p->t_value;
|
||||
tp->t_op =+ (SUB-ADD);
|
||||
}
|
||||
break;
|
||||
}
|
||||
sucomp(tp,reg,1);
|
||||
if( (r=loadexpr(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( (r=cqmark(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( (r=hardrel(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( cookie == FORCC && (p=match(tp,FOREFF,reg)) != 0 ) {
|
||||
r = expand(tp,FOREFF,reg,p);
|
||||
if( asgop(tp->t_op) && indexreg(tp->t_left) )
|
||||
outcmp0(tp->t_left->t_reg,tp->t_left);
|
||||
}
|
||||
else if( p = match(tp,cookie,reg) )
|
||||
r = expand(tp,cookie,reg,p);
|
||||
else if( cookie != FORREG )
|
||||
r = fixresult(tp,cookie,ucodegen(tp,FORREG,reg));
|
||||
else
|
||||
error("no code table for %d",tp->t_op);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* outstrcpy - output structure copy */
|
||||
outstrcpy(lr,rr,size) /*[vlh]*/
|
||||
int lr, rr; /* left register, right register */
|
||||
int size; /* structure size to copy */
|
||||
{
|
||||
register int lab;
|
||||
lab = nextlabel++;
|
||||
printf("move #%d,r%d\n",(size/2)-1,dreg(lr));
|
||||
outlab(lab);
|
||||
printf("move (r%d)+,(r%d)+\ndbra r%d,L%d\n",rr,lr,dreg(lr),lab);
|
||||
}
|
||||
|
||||
/* loadexpr - load an addressable expression into a register*/
|
||||
/* This checks for any possible usage of the register indexed*/
|
||||
/* addressing mode. Note that this relies on the good graces of the*/
|
||||
/* load code skeletons not to muck up the compiler registers before*/
|
||||
/* loading an addressable expression...*/
|
||||
loadexpr(tp,cookie,reg) /* returns register loaded or -1*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int reg; /* register to load*/
|
||||
{
|
||||
register struct tnode *rtp, *ltp, *xtp, *atp;
|
||||
register int off, r, type, nr, ar, xr, xt;
|
||||
|
||||
if( tp->t_op == INDR || LOADABLE(tp) ) {
|
||||
type = tp->t_type;
|
||||
if( tp->t_op == INDR && (ltp=tp->t_left)->t_op == ADD ) {
|
||||
rtp = ltp->t_right;
|
||||
ltp = ltp->t_left;
|
||||
off = 0;
|
||||
if( rtp->t_op == CINT && ((off=rtp->t_value) < -128 ||
|
||||
off > 127 || ltp->t_op != ADD ) ) {
|
||||
tp = snalloc(type,AUTO,off,0,0);
|
||||
if( indexreg(ltp) )
|
||||
tp->t_reg = ltp->t_reg;
|
||||
else {
|
||||
r = codegen(ltp,FORREG,areg(reg));
|
||||
if( isdreg(r) )
|
||||
outmovr(r,areg(r),ltp);
|
||||
tp->t_reg = areg(r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( rtp->t_op == CINT ) {
|
||||
rtp = ltp->t_right;
|
||||
ltp = ltp->t_left;
|
||||
}
|
||||
if(indexreg(rtp) || (!(indexreg(ltp)) && (isreg(rtp)))) {
|
||||
xtp = ltp;
|
||||
ltp = rtp;
|
||||
rtp = xtp;
|
||||
}
|
||||
xtp = atp = 0;
|
||||
if( indexreg(ltp) ) {
|
||||
ar = ltp->t_reg;
|
||||
if( (isreg(rtp)) && rtp->t_type != CHAR ) {
|
||||
xr = rtp->t_reg;
|
||||
xt = rtp->t_type;
|
||||
}
|
||||
else
|
||||
xtp = rtp;
|
||||
}
|
||||
else if( (isreg(ltp)) && ltp->t_type != CHAR &&
|
||||
(lflag || rtp->t_op != ADDR) ) {
|
||||
xr = ltp->t_reg;
|
||||
xt = ltp->t_type;
|
||||
atp = rtp;
|
||||
}
|
||||
else if( rtp->t_op == ADDR ) {
|
||||
atp = ltp;
|
||||
xtp = rtp;
|
||||
}
|
||||
else {
|
||||
atp = rtp;
|
||||
xtp = ltp;
|
||||
}
|
||||
nr = 0;
|
||||
if( atp )
|
||||
nr++;
|
||||
if( xtp && (xtp->t_op != ADDR || lflag ) )
|
||||
nr++;
|
||||
if( dreg(nr+reg) <= HICREG ) {
|
||||
r = reg;
|
||||
if( atp ) {
|
||||
ar = codegen(atp,FORREG,areg(r));
|
||||
if( isdreg(ar) ) {
|
||||
outmovr(ar,areg(ar),atp);
|
||||
ar = areg(ar);
|
||||
}
|
||||
r++;
|
||||
}
|
||||
if( xtp && xtp->t_op == ADDR && !lflag ) {
|
||||
tp = xtp->t_left;
|
||||
tp->t_sc =+ (EXTOFF-EXTERNAL);
|
||||
tp->t_offset =+ off;
|
||||
tp->t_reg = ar;
|
||||
}
|
||||
else {
|
||||
if( xtp ) {
|
||||
xr = codegen(xtp,FORREG,areg(r));
|
||||
xt = xtp->t_type;
|
||||
}
|
||||
tp = xnalloc(type,ar,off,xr,xt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (isareg(reg)) && tp->t_type == CHAR )
|
||||
reg = dreg(reg);
|
||||
tp = tnalloc(LOAD,tp->t_type,SU_EASY,0,tp,null);
|
||||
return( codegen(tp,cookie,reg) );
|
||||
}
|
||||
return(-1);
|
||||
|
||||
}
|
||||
|
||||
/* coffset - check offset for addressable node*/
|
||||
char *coffset(tp) /* returns ptr to const off node*/
|
||||
struct tnode *tp; /* pointer to node*/
|
||||
{
|
||||
register struct tnode *rtp;
|
||||
|
||||
if( tp->t_op == ADD ) {
|
||||
rtp = tp->t_right;
|
||||
if( rtp->t_op == CINT )
|
||||
return(rtp);
|
||||
if(!lflag) {
|
||||
if( rtp->t_op == ADDR )
|
||||
return(rtp->t_left);
|
||||
rtp = tp->t_left;
|
||||
if( rtp->t_op == ADDR ) {
|
||||
tp->t_left = tp->t_right;
|
||||
tp->t_right = rtp;
|
||||
return(rtp->t_left);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* hardrel - do relationals returning a value*/
|
||||
hardrel(tp,cookie,reg) /* returns reg or -1*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int cookie; /* cookie for code generation*/
|
||||
int reg; /* low register*/
|
||||
{
|
||||
char *p;
|
||||
int op, lab1, lab2;
|
||||
|
||||
if( cookie != FORCC && (relop(op=tp->t_op) || op == LOR ||
|
||||
op == LAND || op == NOT) ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(tp,TRUE,lab1,reg);
|
||||
p = canon(cnalloc(INT,0));
|
||||
codegen(p,cookie,reg);
|
||||
lab2 = nextlabel++;
|
||||
outgoto(lab2);
|
||||
outlab(lab1);
|
||||
p = canon(cnalloc(INT,1));
|
||||
codegen(p,cookie,reg);
|
||||
outlab(lab2);
|
||||
return(reg);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* cqmark - compile question mark operator*/
|
||||
/* This does the compilation of the question mark operator.*/
|
||||
cqmark(tp,cookie,reg) /* returns reg or -1*/
|
||||
struct tnode *tp;
|
||||
int cookie;
|
||||
int reg;
|
||||
{
|
||||
register int lab1, lab2, savestk, r;
|
||||
|
||||
if( tp->t_op == QMARK && cookie != FORCC ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(tp->t_left,FALSE,lab1,reg);
|
||||
savestk = stacksize;
|
||||
r = scodegen(tp->t_right->t_left,cookie,reg); /* [mc] 4.0 */
|
||||
outmovr(r,reg,tp);
|
||||
stacksize = savestk;
|
||||
outgoto(lab2=nextlabel++);
|
||||
outlab(lab1);
|
||||
r = scodegen(tp->t_right->t_right,cookie,reg); /* [mc] 4.0 */
|
||||
outmovr(r,reg,tp);
|
||||
outlab(lab2);
|
||||
return(reg);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* condbr - handle conditional branch code generation*/
|
||||
/* This handles the conditional branch code generation, handling*/
|
||||
/* the special cases for constants, ||, &&, ! and generating the*/
|
||||
/* correct conditional branch instruction.*/
|
||||
condbr(tp,dir,lab,reg)
|
||||
struct tnode *tp;
|
||||
int dir;
|
||||
int lab;
|
||||
int reg;
|
||||
{
|
||||
register struct tnode *ltp, *rtp;
|
||||
register int lab1, optype, op, subdir;
|
||||
|
||||
ltp = tp->t_left;
|
||||
if( binop(op=tp->t_op) )
|
||||
rtp = tp->t_right;
|
||||
subdir = dir; /*set up for LOR*/
|
||||
switch( op ) {
|
||||
|
||||
case CINT:
|
||||
if( !tp->t_value ) {
|
||||
if( dir == FALSE )
|
||||
outgoto(lab);
|
||||
}
|
||||
else if( dir != FALSE )
|
||||
outgoto(lab);
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
condbr(ltp,!dir,lab,reg);
|
||||
break;
|
||||
|
||||
case LAND:
|
||||
dir = !dir;
|
||||
case LOR:
|
||||
if( dir == FALSE ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(ltp,!subdir,lab1,reg);
|
||||
condbr(rtp,subdir,lab,reg);
|
||||
outlab(lab1);
|
||||
}
|
||||
else {
|
||||
condbr(ltp,subdir,lab,reg);
|
||||
condbr(rtp,subdir,lab,reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMA:
|
||||
scodegen(tp->t_left,FOREFF,reg);
|
||||
condbr(tp->t_right,dir,lab,reg);
|
||||
break;
|
||||
|
||||
default:
|
||||
if( op == NEQUALS && ltp->t_op == PREDEC &&
|
||||
isdreg(ltp->t_left->t_reg) && ltp->t_left->t_type == INT &&
|
||||
rtp->t_op == CINT && rtp->t_value == -1 ) {
|
||||
outdbra(ltp->t_left->t_reg,lab);
|
||||
break;
|
||||
}
|
||||
if( relop(op) && ltp->t_op == AUTOINC && rtp->t_op == AUTOINC &&
|
||||
ltp->t_type == rtp->t_type )
|
||||
outcmpm(tp);
|
||||
else
|
||||
scodegen(tp,FORCC,reg);
|
||||
optype = 0;
|
||||
if( relop(op) ) {
|
||||
if( unorptr(ltp->t_type) || unorptr(rtp->t_type) )
|
||||
optype =+ 1;
|
||||
}
|
||||
else
|
||||
op = NEQUALS;
|
||||
if(!dir)
|
||||
op = invrel[op-EQUALS];
|
||||
optype = brtab[op-EQUALS][optype];
|
||||
printf("%s L%d\n",mnemonics[optype],lab);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rcodegen(tpp,cookie,reg) /* returns changed flag*/
|
||||
struct tnode **tpp; /* pointer to tree*/
|
||||
int cookie; /* code generation cookie*/
|
||||
int reg; /* register to use for code*/
|
||||
{
|
||||
register int change, op;
|
||||
register struct tnode *tp;
|
||||
|
||||
tp = *tpp;
|
||||
op = tp->t_op;
|
||||
change = 0;
|
||||
if( notleafop(op) && op != COMMA ) {
|
||||
change =+ rcodegen(&tp->t_left,cookie,reg);
|
||||
if( binop(op) )
|
||||
change =+ rcodegen(&tp->t_right,cookie,reg);
|
||||
change =+ rcgen(tpp,cookie,reg);
|
||||
}
|
||||
if( change )
|
||||
*tpp = canon(*tpp);
|
||||
return(change);
|
||||
}
|
||||
|
||||
rcgen(tpp,cookie,reg) /* returns changed flag*/
|
||||
struct tnode **tpp; /* pointer to tree*/
|
||||
int cookie; /* code generation goals*/
|
||||
int reg; /* register to use*/
|
||||
{
|
||||
register struct tnode *tp, *p, *ltp, *rtp;
|
||||
register int op, change;
|
||||
|
||||
change = 0;
|
||||
for( tp = *tpp ; binop(op=tp->t_op); *tpp=tp=canon(tp), change++ ) {
|
||||
ltp = tp->t_left;
|
||||
if( ltp->t_op != SYMBOL )
|
||||
break;
|
||||
rtp = tp->t_right;
|
||||
switch( op ) {
|
||||
|
||||
case ASSIGN:
|
||||
if( ltp->t_sc != REGISTER )
|
||||
return(change);
|
||||
switch( rtp->t_op ) {
|
||||
|
||||
case MULT:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case AND:
|
||||
case OR:
|
||||
case XOR:
|
||||
case LSH:
|
||||
case RSH:
|
||||
if( isareg(ltp->t_reg) )
|
||||
return(change);
|
||||
case ADD:
|
||||
case SUB:
|
||||
p = rtp->t_right;
|
||||
if(NOTADDRESSABLE(ltp) || !noref(rtp->t_right,ltp->t_reg))
|
||||
return(change);
|
||||
p = rtp->t_left;
|
||||
if( p->t_op != SYMBOL || p->t_sc != REGISTER ||
|
||||
p->t_reg != ltp->t_reg ) {
|
||||
tp->t_right = p;
|
||||
#ifndef NODEBUG
|
||||
if( cflag > 1 )
|
||||
putexpr("rcgen",tp);
|
||||
#endif
|
||||
codegen(tp,FOREFF,reg);
|
||||
}
|
||||
tp->t_right = rtp->t_right;
|
||||
tp->t_op = rtp->t_op + (EQADD-ADD);
|
||||
continue;
|
||||
}
|
||||
case EQLSH:
|
||||
case EQRSH:
|
||||
if( ltp->t_sc != REGISTER )
|
||||
return(change);
|
||||
case EQADD:
|
||||
case EQSUB:
|
||||
case EQAND:
|
||||
case EQOR:
|
||||
case EQXOR:
|
||||
if( ltp->t_type == CHAR )
|
||||
return(change);
|
||||
#ifndef NODEBUG
|
||||
if( cflag > 1 )
|
||||
putexpr("rcgen",tp);
|
||||
#endif
|
||||
ucodegen(tp,FOREFF,reg);
|
||||
tp = ltp;
|
||||
continue;
|
||||
|
||||
case PREDEC:
|
||||
case PREINC:
|
||||
if( cookie == FORCC || ltp->t_type == CHAR )
|
||||
return(change);
|
||||
ucodegen(tp,FOREFF,reg);
|
||||
tp = ltp;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return(change);
|
||||
}
|
||||
|
||||
noref(tp,reg) /* 4.0 change */
|
||||
struct tnode *tp; /* returns 1 if no reference in tree to reg */
|
||||
int reg;
|
||||
{
|
||||
if ( leafop(tp->t_op) ) {
|
||||
if (tp->t_op == SYMBOL && tp->t_sc == REGISTER && tp->t_reg == reg)
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
if ( !noref(tp->t_left,reg) )
|
||||
return(0);
|
||||
if (binop(tp->t_op))
|
||||
return( noref(tp->t_right,reg) );
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* cdsize - compute size of data item*/
|
||||
cdsize(tp) /* returns data size in bytes*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
register int type;
|
||||
|
||||
type = tp->t_type;
|
||||
if( suptype(type) )
|
||||
return(PTRSIZE);
|
||||
switch( type ) {
|
||||
|
||||
case CHAR:
|
||||
case INT:
|
||||
case UNSIGNED:
|
||||
return(INTSIZE);
|
||||
|
||||
case LONG:
|
||||
case FLOAT: /* [vlh] 3.4 */
|
||||
return(LONGSIZE);
|
||||
}
|
||||
error("cdsize: invalid type %d",type);
|
||||
return(0);
|
||||
}
|
||||
|
||||
dofarg(tp) /* returns number of bytes pushed*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
{
|
||||
register int nb;
|
||||
|
||||
nb = 0;
|
||||
if( tp->t_op == SYMBOL && tp->t_sc == STRUCT )
|
||||
error("structure operation not implemented");
|
||||
else if( stacksize ) {
|
||||
codegen(tp,FORSTACK,0);
|
||||
nb = cdsize(tp);
|
||||
}
|
||||
else
|
||||
codegen(tp,FORSP,0);
|
||||
return( nb );
|
||||
}
|
||||
|
||||
/* dobitadd - do bit operation address checking and fixup*/
|
||||
dobitadd(tp,bitno) /* returns -1 if can't or bitno*/
|
||||
struct tnode *tp;
|
||||
int bitno;
|
||||
{
|
||||
register int offset;
|
||||
|
||||
if( tp->t_type == CHAR )
|
||||
offset = 0;
|
||||
else
|
||||
offset = cdsize(tp) - (bitno/BITSPBYTE) - 1;
|
||||
if( tp->t_op == SYMBOL ) {
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
case REGISTER:
|
||||
if( isdreg(tp->t_reg) )
|
||||
return(bitno);
|
||||
default:
|
||||
return(-1);
|
||||
|
||||
case EXTERNAL:
|
||||
case STATIC:
|
||||
case REGOFF:
|
||||
case STATOFF:
|
||||
case EXTOFF:
|
||||
tp->t_offset =+ offset;
|
||||
return( bitno % BITSPBYTE );
|
||||
}
|
||||
}
|
||||
else if( tp->t_op == INDR ) {
|
||||
tp->t_left = tnalloc(ADD,tp->t_left->t_type,0,0,tp->t_left,
|
||||
cnalloc(INT,offset));
|
||||
return( bitno % BITSPBYTE );
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
isonebit(tp) /* returns -1 if not 1 bit, else bitno*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
{
|
||||
if( tp = constant(tp) )
|
||||
return( onebit(tp->t_value) );
|
||||
return(-1);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8474 Commerce Av.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*built-in literals*/
|
||||
#define MOV 128
|
||||
#define MOVL 129
|
||||
#define JSR 130
|
||||
#define CLR 131
|
||||
#define CLRL 132
|
||||
#define EXTW 133
|
||||
#define EXTL 134
|
||||
#define LEA 135
|
||||
#define STK 136
|
||||
|
||||
/*built-in macros*/
|
||||
#define TREE 141
|
||||
#define LEFT 142
|
||||
#define RIGHT 143
|
||||
#define LOFFSET 144
|
||||
#define ROFFSET 145
|
||||
#define LADDR 146
|
||||
#define RADDR 147
|
||||
#define CR 148
|
||||
#define NR 149
|
||||
#define CAR 150
|
||||
#define NAR 151
|
||||
#define TLEFT 152
|
||||
#define TRIGHT 153
|
||||
#define TEITHER 154
|
||||
#define TLEFTL 155
|
||||
#define OP 156
|
||||
#define AOP 157
|
||||
#define MODSWAP 158
|
||||
#define EXL 159
|
||||
#define EXLR 160
|
||||
#define EXLRN 161
|
||||
#define EXRL 162
|
||||
#define EXRLN 163
|
||||
#define PSH 164
|
||||
#define POP 165
|
||||
#define POP8 166
|
||||
#define OPCALL 167
|
||||
#define POP4 169
|
||||
#define LADDRP 168
|
||||
|
||||
/*modifiers for compiling sub-trees*/
|
||||
#define S_INDR 1 /*indirection*/
|
||||
#define S_STACK 2 /*onto stack*/
|
||||
#define S_FORCC 4 /*set condition codes*/
|
||||
#define S_NEXT 8 /*into next register*/
|
||||
|
||||
/*Sethy-Ullman values*/
|
||||
#define SU_ZERO 0x000 /*zero*/
|
||||
#define SU_ONE 0x100 /*one*/
|
||||
#define SU_SMALL 0x200 /*constant between 1 and 8*/
|
||||
#define SU_QUICK 0x300 /*quick constant between -128 and 127*/
|
||||
#define SU_CONST 0x400 /*any constant*/
|
||||
#define SU_AREG 0x500 /*A register*/
|
||||
#define SU_REG 0x600 /*register*/
|
||||
#define SU_ADDR 0x700 /*addressable*/
|
||||
#define SU_XREG 0x800 /*A register used as data...*/
|
||||
#define SU_EASY 0x900 /*easy*/
|
||||
#define SU_HARD 0xa00 /*hard*/
|
||||
#define SU_VHARD 0xb00 /*very hard ... function calls, etc.*/
|
||||
#define SU_ANY 0xf00 /*anything*/
|
||||
#define ADDRESSABLE(x) (x->t_su<=SU_ADDR)
|
||||
#define NOTADDRESSABLE(x) (x->t_su>SU_ADDR)
|
||||
#define LOADABLE(x) (x->t_su<=SU_XREG)
|
||||
|
||||
/*flag byte (operand type):*/
|
||||
#define T_CHAR 1 /*char only*/
|
||||
#define T_SHORT 2 /*short*/
|
||||
#define T_INT 3 /*int only*/
|
||||
#define T_LONG 4 /*long*/
|
||||
#define T_UCHAR 5 /*unsigned char*/
|
||||
#define T_USHORT 6 /*unsigned short*/
|
||||
#define T_UNSN 7 /*unsigned int*/
|
||||
#define T_ULONG 8 /*unsigned long*/
|
||||
#define T_FLOAT 9 /*float*/
|
||||
#define T_DOUB 10 /*double*/
|
||||
#define T_ANY 11 /*int or word (implied)*/
|
||||
#define T_INDR 0x10 /*pointer type (bit)*/
|
||||
|
||||
struct skeleton {
|
||||
int sk_left;
|
||||
int sk_right;
|
||||
char *sk_def;
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
int bol;
|
||||
int onepass;
|
||||
|
||||
/* outexpr - output expression*/
|
||||
outexpr(tp) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree node*/
|
||||
{
|
||||
if( dflag )
|
||||
outline();
|
||||
if( exprok(tp) )
|
||||
scodegen(canon(tp),FOREFF,0);
|
||||
}
|
||||
|
||||
outifgoto(tp,dir,lab)
|
||||
struct tnode *tp;
|
||||
int dir;
|
||||
int lab;
|
||||
{
|
||||
if( dflag )
|
||||
outline();
|
||||
if( exprok(tp) )
|
||||
condbr(canon(tp),dir,lab,0);
|
||||
}
|
||||
|
||||
outcforreg(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( dflag )
|
||||
outline();
|
||||
if( exprok(tp) )
|
||||
outmovr(scodegen(canon(tp),FORREG,0),0,tp);
|
||||
}
|
||||
|
||||
outinit(tp) /* returns - none*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
register int typeout;
|
||||
|
||||
if( dflag )
|
||||
outline();
|
||||
if( exprok(tp) ) {
|
||||
typeout = tp->t_type;
|
||||
tp = canon(tp);
|
||||
if( tp->t_op == ADDR )
|
||||
tp = tp->t_left;
|
||||
if( tp->t_op == CINT || tp->t_op == SYMBOL ) {
|
||||
if( tp->t_op != CINT )
|
||||
printf(".dc.l ");
|
||||
else {
|
||||
printf(".dc");
|
||||
outtype(typeout);
|
||||
putchar(' ');
|
||||
}
|
||||
outaexpr(tp,NOTIMMED); /* [vlh] 4.0 not immed... */
|
||||
}
|
||||
else
|
||||
error("invalid initialization");
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
/* snalloc - code generator symbol node allocation*/
|
||||
/* This might be coalesced into parser snalloc.*/
|
||||
char *snalloc(type,sc,offset,dp,ssp) /* returns ptr to node alloced*/
|
||||
int type; /* type of symbol*/
|
||||
int sc; /* storage class*/
|
||||
int offset; /* offset from Local Environment Ptr*/
|
||||
int dp; /*for compatability with parser*/
|
||||
int ssp; /*for compatability with parser*/
|
||||
{
|
||||
register struct symnode *sp;
|
||||
|
||||
sp = talloc(sizeof(*sp));
|
||||
sp->t_op = SYMBOL;
|
||||
sp->t_type = type;
|
||||
sp->t_su = dp;
|
||||
sp->t_ssp = ssp;
|
||||
sp->t_sc = sc;
|
||||
switch( sc ) {
|
||||
|
||||
case STATIC:
|
||||
sp->t_offset = 0;
|
||||
sp->t_reg = 0;
|
||||
sp->t_label = offset;
|
||||
break;
|
||||
|
||||
case REGISTER:
|
||||
sp->t_offset = 0;
|
||||
sp->t_reg = offset;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
|
||||
case AUTO:
|
||||
sp->t_sc = REGOFF;
|
||||
sp->t_offset = offset;
|
||||
sp->t_reg = LEP;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
sp->t_offset = offset;
|
||||
sp->t_reg = 0;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
}
|
||||
return(sp);
|
||||
}
|
||||
|
||||
exprok(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( tp < exprarea || tp > &exprarea[EXPSIZE] )
|
||||
return(0);
|
||||
if( leafop(tp->t_op) )
|
||||
return(1);
|
||||
if( binop(tp->t_op) && !exprok(tp->t_right) )
|
||||
return(0);
|
||||
return( exprok(tp->t_left) );
|
||||
}
|
||||
|
||||
outline()
|
||||
{
|
||||
if( onepass && !bol )
|
||||
putchar('\n');
|
||||
printf("*line %d\n",lineno);
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
char *version "@(#) c168 code generator 4.0 - Mar 18, 1983";
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
char *opap;
|
||||
int errflg;
|
||||
int nextlabel 10000;
|
||||
char *readtree();
|
||||
char *readsym();
|
||||
|
||||
|
||||
/* main - main routine, handles arguments and files*/
|
||||
main(argc,argv) /* returns - none*/
|
||||
int argc; /* arg count*/
|
||||
char **argv; /* arg pointers*/
|
||||
{
|
||||
register char *q;
|
||||
register int i;
|
||||
|
||||
#ifdef VERSADOS
|
||||
lflag++;
|
||||
#endif
|
||||
for( i = 3; i < argc; i++ ) {
|
||||
q = argv[i];
|
||||
if( *q++ != '-' )
|
||||
usage(argc,argv,1);
|
||||
while( 1 ) {
|
||||
switch( *q++ ) {
|
||||
|
||||
case 'D':
|
||||
dflag++;
|
||||
continue;
|
||||
|
||||
case 'L':
|
||||
lflag++;
|
||||
continue;
|
||||
|
||||
case 'e':
|
||||
eflag++;
|
||||
continue;
|
||||
|
||||
case 'f':
|
||||
fflag++;
|
||||
continue;
|
||||
|
||||
case 'm':
|
||||
mflag++;
|
||||
continue;
|
||||
|
||||
case 'o':
|
||||
oflag++;
|
||||
continue;
|
||||
|
||||
case 'c':
|
||||
cflag++;
|
||||
continue;
|
||||
|
||||
case '\0':
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(argc,argv,2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( argc < 3 )
|
||||
usage(argc,argv,3);
|
||||
if( fopen(argv[1],&ibuf,0) < 0 ) /* 3rd arg for versados */
|
||||
ferror("can't open %s\n",argv[1]);
|
||||
if( fcreat(argv[2],&obuf,0) < 0 ) /* 3rd arg for versados */
|
||||
ferror("can't create %s\n",argv[2]);
|
||||
readicode();
|
||||
v6flush(&obuf);
|
||||
exit(errcnt!=0);
|
||||
}
|
||||
|
||||
/* readicode - read intermediate code and dispatch output*/
|
||||
/* This copies assembler lines beginning with '(' to assembler*/
|
||||
/* output and builds trees starting with '.' line.*/
|
||||
readicode() /*returns - none*/
|
||||
{
|
||||
register int c;
|
||||
register struct tnode *tp;
|
||||
|
||||
while( (c=getc(&ibuf)) > 0 ) {
|
||||
switch(c) {
|
||||
|
||||
case '.':
|
||||
lineno = readint();
|
||||
opap = exprarea;
|
||||
if( tp = readtree() ) {
|
||||
#ifndef NODEBUG
|
||||
if( cflag )
|
||||
putexpr("readicode",tp);
|
||||
#endif
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case INIT:
|
||||
outinit(tp->t_left);
|
||||
break;
|
||||
|
||||
case CFORREG:
|
||||
outcforreg(tp->t_left);
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
outifgoto(tp->t_left,tp->t_type,tp->t_su);
|
||||
break;
|
||||
|
||||
default:
|
||||
outexpr(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '(':
|
||||
while( (c=getc(&ibuf)) != '\n' )
|
||||
putchar(c);
|
||||
putchar(c);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("intermediate code error %c,%d",c,c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* readtree - recursive intermediate code tree read*/
|
||||
char *readtree() /* returns ptr to expression tree*/
|
||||
{
|
||||
register int op, type, sc;
|
||||
register struct tnode *tp, *rtp;
|
||||
char sym[SSIZE];
|
||||
long l;
|
||||
|
||||
if( (op=readint()) <= 0 )
|
||||
return(0);
|
||||
type = readint();
|
||||
switch( op ) {
|
||||
|
||||
case SYMBOL:
|
||||
if( (sc=readint()) == EXTERNAL )
|
||||
tp = cenalloc(type,sc,readsym(sym));
|
||||
else
|
||||
tp = snalloc(type,sc,readint(),0,0);
|
||||
break;
|
||||
|
||||
case CINT:
|
||||
tp = cnalloc(type,readint());
|
||||
break;
|
||||
|
||||
case CLONG:
|
||||
l.hiword = readint();
|
||||
l.loword = readint();
|
||||
tp = lcnalloc(type,l);
|
||||
break;
|
||||
|
||||
case CFLOAT: /* [vlh] 3.4 */
|
||||
l.hiword = readint();
|
||||
l.loword = readint();
|
||||
tp = fpcnalloc(type,l);
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
case BFIELD:
|
||||
sc = readint();
|
||||
if( tp = readtree() )
|
||||
tp = tnalloc(op,type,sc,0,tp,null);
|
||||
break;
|
||||
|
||||
default:
|
||||
if( binop(op) ) {
|
||||
if( !(tp=readtree()) )
|
||||
return(0);
|
||||
if( !(rtp=readtree()) )
|
||||
return(0);
|
||||
tp = tnalloc(op,type,0,0,tp,rtp);
|
||||
}
|
||||
else if( tp = readtree() )
|
||||
tp = tnalloc(op,type,0,0,tp,null);
|
||||
break;
|
||||
}
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* readint - reads an integer value from intermediate code*/
|
||||
readint()
|
||||
{
|
||||
register int i, c;
|
||||
|
||||
i = 0;
|
||||
while(1) {
|
||||
switch( c = getc(&ibuf) ) {
|
||||
|
||||
case '.':
|
||||
case '\n':
|
||||
return(i);
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
i =<< 4;
|
||||
i =+ (c-'0');
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
i =<< 4;
|
||||
i =+ (c-('a'-10));
|
||||
break;
|
||||
|
||||
default:
|
||||
error("intermediate code error - %c,%d",c,c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* readsym - read a symbol from intermediate code*/
|
||||
char *readsym(sym)
|
||||
char *sym;
|
||||
{
|
||||
register int i, c;
|
||||
register char *s;
|
||||
|
||||
for( i = SSIZE, s = sym; (c=getc(&ibuf)) != '\n'; )
|
||||
if( --i >= 0 )
|
||||
*s++ = c;
|
||||
if( i > 0 )
|
||||
*s = '\0';
|
||||
return(sym);
|
||||
}
|
||||
|
||||
/* error - output an error message*/
|
||||
error(s,x1,x2,x3,x4,x5,x6)
|
||||
char *s;
|
||||
int x1, x2, x3, x4, x5, x6;
|
||||
{
|
||||
errcnt++;
|
||||
errflg++;
|
||||
if( lineno != 0 )
|
||||
printf("** %d: ",lineno);
|
||||
printf(s,x1,x2,x3,x4,x5,x6);
|
||||
putchar('\n');
|
||||
errflg--;
|
||||
}
|
||||
|
||||
/* ferror - output error message and die*/
|
||||
ferror(s,x1,x2,x3,x4,x5,x6)
|
||||
char *s;
|
||||
int x1, x2, x3, x4, x5, x6;
|
||||
{
|
||||
error(s,x1,x2,x3,x4,x5,x6);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* tnalloc - allocate binary expression tree node*/
|
||||
/* returns ptr to node made.*/
|
||||
char *tnalloc(op,type,info,dummy,left,right)
|
||||
int op; /* operator*/
|
||||
int type; /* resultant node type*/
|
||||
int info; /* info field*/
|
||||
int dummy; /* dummy field - used to match pass1 args*/
|
||||
struct tnode *left; /* left sub-tree*/
|
||||
struct tnode *right; /* righst sub-tree*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
tp = talloc(sizeof(*tp));
|
||||
tp->t_op = op;
|
||||
tp->t_type = type;
|
||||
tp->t_su = info; /* info for bit-field & condbr's*/
|
||||
tp->t_left = left;
|
||||
tp->t_right = right;
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* cnalloc - allocate constant expression tree node*/
|
||||
char *cnalloc(type,value) /* returns pointer to node alloced*/
|
||||
int type; /* type of constant*/
|
||||
int value; /* value of constant*/
|
||||
{
|
||||
register struct conode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CINT;
|
||||
cp->t_type = type;
|
||||
cp->t_value = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* lcnalloc - allocate constant expression tree node*/
|
||||
char *lcnalloc(type,value) /* returns pointer to node alloced*/
|
||||
int type; /* type of constant*/
|
||||
long value; /* value of constant*/
|
||||
{
|
||||
register struct lconode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CLONG;
|
||||
cp->t_type = type;
|
||||
cp->t_lvalue = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* fpcnalloc - allocate constant expression tree node*/
|
||||
char *fpcnalloc(type,value) /* returns pointer to node alloced*/
|
||||
int type; /* type of constant*/
|
||||
long value; /* value of constant*/
|
||||
{ /* [vlh] 3.4 */
|
||||
register struct lconode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CFLOAT;
|
||||
cp->t_type = type;
|
||||
cp->t_lvalue = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* talloc - allocate expression tree area*/
|
||||
char *talloc(size) /* returns pointer to area alloced*/
|
||||
int size; /* number of bytes to alloc*/
|
||||
{
|
||||
register char *p;
|
||||
|
||||
p = opap;
|
||||
if( p + size >= &exprarea[EXPSIZE] )
|
||||
ferror("expression too complex");
|
||||
opap = p + size;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/* symcopy - copy symbol*/
|
||||
symcopy(sym1,sym2) /* returns - none*/
|
||||
char *sym1; /* from symbol*/
|
||||
char *sym2; /* to symbol*/
|
||||
{
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
for( p = sym1, q = sym2, i = SSIZE; --i >= 0; )
|
||||
*q++ = (*p ? *p++ : '\0');
|
||||
}
|
||||
|
||||
/* usage - ouput usage message*/
|
||||
usage(argc,argv,n)
|
||||
char *argv[];
|
||||
{
|
||||
register int i;
|
||||
error("usage call #%d:\n",n);
|
||||
for (i=0; i<argc; i++) error(" argv[%d] = %s\n",i,argv[i]);
|
||||
ferror("usage: c168 icode asm [-DLmec]");
|
||||
}
|
||||
|
||||
/* putchar - special version*/
|
||||
/* This allows the use of printf for error messages, debugging*/
|
||||
/* output and normal output.*/
|
||||
putchar(c) /* returns - none*/
|
||||
char c; /* character to output*/
|
||||
{
|
||||
if( errflg ) /*error message?*/
|
||||
write(1,&c,1); /*write to standard output*/
|
||||
else {
|
||||
if( dflag > 1 )
|
||||
write(1,&c,1); /*to standard output*/
|
||||
putc(c,&obuf); /*put to assembler file*/
|
||||
}
|
||||
}
|
||||
|
||||
v6flush(v6b)
|
||||
struct iobuf *v6b;
|
||||
{
|
||||
register i;
|
||||
|
||||
i = BLEN - v6b->nunused;
|
||||
v6b->nunused = BLEN;
|
||||
v6b->xfree = &(v6b->buff[0]);
|
||||
if(write(v6b->fildes,v6b->xfree,i) != i)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
|
||||
#define I_NULL 0
|
||||
#define I_ADD 1
|
||||
#define I_INC 2
|
||||
#define I_SUB 3
|
||||
#define I_DEC 4
|
||||
#define I_MULS 5
|
||||
#define I_MULU 6
|
||||
#define I_DIVS 7
|
||||
#define I_DIVU 8
|
||||
#define I_ASR 9
|
||||
#define I_LSR 10
|
||||
#define I_ASL 11
|
||||
#define I_LSL 12
|
||||
#define I_AND 13
|
||||
#define I_OR 14
|
||||
#define I_EOR 15
|
||||
#define I_NEG 16
|
||||
#define I_NOT 17
|
||||
#define I_MOVE 18
|
||||
#define I_CLR 19
|
||||
#define I_CMP 20
|
||||
#define I_TST 21
|
||||
#define I_LMUL 22
|
||||
#define I_LDIV 23
|
||||
#define I_LREM 24
|
||||
#define I_LEML 25
|
||||
#define I_LERM 27
|
||||
#define I_BEQ 28
|
||||
#define I_BNE 29
|
||||
#define I_BGT 30
|
||||
#define I_BGE 31
|
||||
#define I_BLT 32
|
||||
#define I_BLE 33
|
||||
#define I_BLS 34
|
||||
#define I_BLO 35
|
||||
#define I_BCC 36
|
||||
#define I_BHI 37
|
||||
#define I_BRA 38
|
||||
#define I_NOP 39
|
||||
#define I_BTST 40
|
||||
|
||||
char *mnemonics[] {
|
||||
"",
|
||||
"add",
|
||||
"inc",
|
||||
"sub",
|
||||
"dec",
|
||||
"muls",
|
||||
"mulu",
|
||||
"divs",
|
||||
"divu",
|
||||
"asr",
|
||||
"lsr",
|
||||
"asl",
|
||||
"lsl",
|
||||
"and",
|
||||
"or",
|
||||
"eor",
|
||||
"neg",
|
||||
"not",
|
||||
"move",
|
||||
"clr",
|
||||
"cmp",
|
||||
"tst",
|
||||
"lmul",
|
||||
"_ldiv",
|
||||
"lrem",
|
||||
"almul",
|
||||
"aldiv",
|
||||
"alrem",
|
||||
"beq",
|
||||
"bne",
|
||||
"bgt",
|
||||
"bge",
|
||||
"blt",
|
||||
"ble",
|
||||
"bls",
|
||||
"blo",
|
||||
"bcc",
|
||||
"bhi",
|
||||
"jmp",
|
||||
"*nop",
|
||||
"btst",
|
||||
};
|
||||
|
||||
#define FE_EQOP 1
|
||||
#define FE_ASSIGN 2
|
||||
#define FE_EQSHFT 3
|
||||
#define FE_EQXOR 4
|
||||
#define FE_EQADDR 5
|
||||
#define FC_FIX 6
|
||||
#define FC_REL 7
|
||||
#define FC_BTST 8
|
||||
#define FS_OP 9
|
||||
#define FS_ITL 10
|
||||
#define FS_LD 11
|
||||
#define FR_ADD 12
|
||||
#define FR_MULT 13
|
||||
#define FR_DIV 14
|
||||
#define FR_SHFT 15
|
||||
#define FR_XOR 16
|
||||
#define FR_NEG 17
|
||||
#define FR_EQOP 18
|
||||
#define FR_POSTOP 19
|
||||
#define FR_ASSIGN 20
|
||||
#define FR_EQMULT 21
|
||||
#define FR_EQDIV 22
|
||||
#define FR_EQSHFT 23
|
||||
#define FR_EQXOR 24
|
||||
#define FR_CALL 25
|
||||
#define FR_ITL 26
|
||||
#define FR_LTI 27
|
||||
#define FR_LD 28
|
||||
#define FR_EQADDR 29
|
||||
#define FR_EQNOT 30
|
||||
#define FE_EQNOT 31
|
||||
#define FR_DOCAST 32
|
||||
#define FS_DOCAST 33
|
||||
#define FR_FTOL 34
|
||||
#define FR_LTOF 35
|
||||
#define FR_FTOI 36
|
||||
#define FR_ITOF 37
|
||||
#define FE_EQMULT 38
|
||||
#define FE_EQDIV 39
|
||||
#define FE_EQMOD 40
|
||||
#define FR_TOCHAR 41
|
||||
|
||||
char
|
||||
fe_eqop[], /* 1=FE_EQOP */
|
||||
fe_assign[], /* 2=FE_ASSIGN */
|
||||
fe_eqshft[], /* 3=FE_EQSHFT */
|
||||
fe_eqxor[], /* 4=FE_EQXOR */
|
||||
fe_eqaddr[], /* 5=FE_EQADDR */
|
||||
fc_fix[], /* 6=FC_FIX */
|
||||
fc_rel[], /* 7=FC_REL */
|
||||
fc_btst[], /* 8=FC_BTST */
|
||||
fs_op[], /* 9=FS_OP */
|
||||
fs_itl[], /* 10=FS_ITL */
|
||||
fs_ld[], /* 11=FS_LD */
|
||||
fr_op[], /* 12=FR_OP */
|
||||
fr_mult[], /* 13=FR_MULT */
|
||||
fr_div[], /* 14=FR_DIV */
|
||||
fr_shft[], /* 15=FR_SHFT */
|
||||
fr_xor[], /* 16=FR_XOR */
|
||||
fr_neg[], /* 17=FR_NEG */
|
||||
fr_eqop[], /* 18=FR_EQOP */
|
||||
fr_postop[], /* 19=FR_POSTOP */
|
||||
fr_assign[], /* 20=FR_ASSIGN */
|
||||
fr_eqmult[], /* 21=FR_EQMULT */
|
||||
fr_eqdiv[], /* 22=FR_EQDIV */
|
||||
fr_eqshft[], /* 23=FR_EQSHFT */
|
||||
fr_eqxor[], /* 23=FR_EQXOR */
|
||||
fr_call[], /* 24=FR_CALL */
|
||||
fr_itl[], /* 25=FR_ITL */
|
||||
fr_lti[], /* 26=FR_LTI */
|
||||
fr_ld[], /* 27=FR_LD */
|
||||
fr_eqaddr[], /* 28=FR_EQADDR */
|
||||
fr_eqnot[], /* 29=FR_EQNOT */
|
||||
fe_eqnot[], /* 30=FE_EQNOT */
|
||||
fr_docast[], /* 31=FR_DOCAST */
|
||||
fs_docast[], /* 32=FS_DOCAST */
|
||||
fr_ftol[], /* 34=FE_FTOL */
|
||||
fr_ltof[], /* 35=FE_LTOF */
|
||||
fr_ftoi[], /* 36=FE_FTOI */
|
||||
fr_itof[], /* 37=FE_ITOF */
|
||||
fe_eqmult[], /* 38=FE_EQMULT */
|
||||
fe_eqdiv[], /* 39=FE_EQDIV */
|
||||
fe_eqmod[], /* 40=FE_EQMOD */
|
||||
fr_tochar[]; /* 41=FR_TOCHAR */
|
||||
|
||||
char *codeskels[] {
|
||||
0, /*NULL*/
|
||||
fe_eqop, /*1=FE_EQOP*/
|
||||
fe_assign, /*2=FE_ASSIGN*/
|
||||
fe_eqshft, /*3=FE_EQSHFT*/
|
||||
fe_eqxor, /*4=FE_EQXOR*/
|
||||
fe_eqaddr, /*5=FE_EQADDR*/
|
||||
fc_fix, /*6=FC_FIX*/
|
||||
fc_rel, /*7=FC_REL*/
|
||||
fc_btst, /*8=FC_BTST*/
|
||||
fs_op, /*9=FS_OP*/
|
||||
fs_itl, /*10=FS_ITL*/
|
||||
fs_ld, /*11=FS_LD*/
|
||||
fr_op, /*12=FR_OP*/
|
||||
fr_mult, /*13=FR_MULT*/
|
||||
fr_div, /*14=FR_DIV*/
|
||||
fr_shft, /*15=FR_SHFT*/
|
||||
fr_xor, /*16=FR_XOR*/
|
||||
fr_neg, /*17=FR_NEG*/
|
||||
fr_eqop, /*18=FR_EQOP*/
|
||||
fr_postop, /*19=FR_POSTOP*/
|
||||
fr_assign, /*20=FR_ASSIGN*/
|
||||
fr_eqmult, /*21=FR_EQMULT*/
|
||||
fr_eqdiv, /*22=FR_EQDIV*/
|
||||
fr_eqshft, /*23=FR_EQSHFT*/
|
||||
fr_eqxor, /*24=FR_EQXOR*/
|
||||
fr_call, /*25=FR_CALL*/
|
||||
fr_itl, /*26=FR_ITL*/
|
||||
fr_lti, /*27=FR_LTI*/
|
||||
fr_ld, /*28=FE_LD*/
|
||||
fr_eqaddr, /*29=FE_EQADDR*/
|
||||
fr_eqnot, /*30=FE_EQNOT*/
|
||||
fe_eqnot, /*31=FE_EQNOT*/
|
||||
fr_docast, /*32=FE_DOCAST*/
|
||||
fs_docast, /*33=FS_DOCAST*/
|
||||
fr_ftol, /*34=FE_FTOL*/
|
||||
fr_ltof, /*35=FE_LTOF*/
|
||||
fr_ftoi, /*36=FE_FTOI*/
|
||||
fr_itof, /*37=FE_ITOF*/
|
||||
fe_eqmult, /*38=FE_EQMULT*/
|
||||
fe_eqdiv, /*39=FE_EQDIV*/
|
||||
fe_eqmod, /*40=FE_EQMOD*/
|
||||
fr_tochar, /*41=FR_TOCHAR*/
|
||||
};
|
||||
/*
|
||||
*This is the major table directing the code generation process.
|
||||
*It is indexed by an O_op operator, which is obtained from the
|
||||
*opinfo table for an intermediate code operator. The actual
|
||||
*code skeleton macros are in cskels.c, which are in a linked
|
||||
*list in order of decreasing order of difficulty.
|
||||
*/
|
||||
char optab[][6] {
|
||||
|
||||
/* I I2 effect cc's stack register*/
|
||||
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*0=NULL*/
|
||||
I_ADD, I_INC, I_NULL, FC_FIX, FS_OP, FR_ADD, /*1=ADD*/
|
||||
I_SUB, I_DEC, I_NULL, FC_FIX, FS_OP, FR_ADD, /*2=SUB*/
|
||||
I_MULS, I_MULU, I_NULL, FC_FIX, I_NULL, FR_MULT, /*3=MULT*/
|
||||
I_DIVS, I_DIVU, I_NULL, FC_FIX, I_NULL, FR_DIV, /*4=DIV*/
|
||||
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*5=MOD*/
|
||||
I_ASR, I_LSR, I_NULL, FC_FIX, I_NULL, FR_SHFT, /*6=RSH*/
|
||||
I_ASL, I_LSL, I_NULL, FC_FIX, I_NULL, FR_SHFT, /*7=LSH*/
|
||||
I_AND, I_AND, I_NULL, FC_FIX, FS_OP, FR_ADD, /*8=AND*/
|
||||
I_OR, I_OR, I_NULL, FC_FIX, FS_OP, FR_ADD, /*9=OR*/
|
||||
I_EOR, I_EOR, I_NULL, FC_FIX, I_NULL, FR_XOR, /*10=XOR*/
|
||||
I_NULL, I_NULL, I_NULL, FC_FIX, I_NULL, I_NULL, /*11=NOT*/
|
||||
I_NEG, I_NEG, I_NULL, FC_FIX, I_NULL, FR_NEG, /*12=NEG*/
|
||||
I_NOT, I_NOT, I_NULL, I_NULL, I_NULL, FR_NEG, /*13=COMPL*/
|
||||
I_SUB, I_DEC, FE_EQOP, FC_FIX, I_NULL, FR_EQOP, /*14=PREDEC*/
|
||||
I_ADD, I_INC, FE_EQOP, FC_FIX, I_NULL, FR_EQOP, /*15=PREINC*/
|
||||
I_SUB, I_DEC, FE_EQOP, I_NULL, I_NULL, FR_POSTOP, /*16=POSTDEC*/
|
||||
I_ADD, I_INC, FE_EQOP, I_NULL, I_NULL, FR_POSTOP, /*17=POSTINC*/
|
||||
I_MOVE, I_CLR, FE_ASSIGN, I_NULL, I_NULL, FR_ASSIGN, /*18=ASSIGN*/
|
||||
I_ADD, I_INC, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*19=EQADD*/
|
||||
I_SUB, I_DEC, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*20=EQSUB*/
|
||||
I_MULS, I_MULU, FE_EQMULT, FC_FIX, I_NULL, FR_EQMULT, /*21=EQMULT*/
|
||||
I_DIVS, I_DIVU, FE_EQDIV, FC_FIX, I_NULL, FR_EQDIV, /*22=EQDIV*/
|
||||
I_DIVS, I_DIVU, FE_EQMOD, I_NULL, I_NULL, FR_EQDIV, /*23=EQMOD*/
|
||||
I_ASR, I_LSR, FE_EQSHFT, I_NULL, I_NULL, FR_EQSHFT, /*24=EQRSH*/
|
||||
I_ASL, I_LSL, FE_EQSHFT, I_NULL, I_NULL, FR_EQSHFT, /*25=EQLSH*/
|
||||
I_AND, I_AND, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*26=EQAND*/
|
||||
I_OR, I_OR, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*27=EQOR*/
|
||||
I_EOR, I_EOR, FE_EQXOR, FC_FIX, I_NULL, FR_EQXOR, /*28=EQXOR*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_CALL, /*29=FJSR*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*30=EQUALS*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*31=NEQUALS*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*32=GREAT*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*33=GREATEQ*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*34=LESS*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*35=LESSEQ*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, FS_ITL, FR_ITL, /*36=INT2L*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_LTI, /*37=LONG2I*/
|
||||
I_BTST, I_BTST, I_NULL, FC_BTST, I_NULL, I_NULL, /*38=BTST*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, FS_LD, FR_LD, /*39=LOAD*/
|
||||
I_MULS, I_MULU, I_NULL, I_NULL, I_NULL, FR_MULT, /*40=LMULT*/
|
||||
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*41=LDIV*/
|
||||
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*42=LMOD*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*43=NULL*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*44=NULL*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*45=NULL*/
|
||||
I_NULL, I_NULL, FE_EQADDR, I_NULL, I_NULL, FR_EQADDR, /*46=EQADDR*/
|
||||
I_NOT, I_NOT, FE_EQNOT, I_NULL, I_NULL, FR_EQNOT, /*47=EQNOT*/
|
||||
I_NEG, I_NEG, FE_EQNOT, I_NULL, I_NULL, FR_EQNOT, /*48=EQNEG*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, FS_DOCAST, FR_DOCAST, /*49=DOCAST*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*50=STASSIGN*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_LTOF, /*51=LONG2F*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_FTOL, /*52=FLOAT2L*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_ITOF, /*53=INT2F*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_FTOI, /*54=FLOAT2I*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_TOCHAR, /*55=TOCHAR*/
|
||||
};
|
||||
|
||||
|
||||
/*this maps comparison operators and comparison types into the*/
|
||||
/*actual branch opcode used.*/
|
||||
char brtab[][2] {
|
||||
I_BEQ, I_BEQ, /*EQUALS*/
|
||||
I_BNE, I_BNE, /*NEQUALS*/
|
||||
I_BGT, I_BHI, /*GREAT*/
|
||||
I_BGE, I_BCC, /*GREATEQ*/
|
||||
I_BLT, I_BLO, /*LESS*/
|
||||
I_BLE, I_BLS, /*LESSEQ*/
|
||||
};
|
||||
|
||||
/*turns !x>y into x<=y*/
|
||||
int invrel[] { NEQUALS, EQUALS, LESSEQ, LESS, GREATEQ, GREAT };
|
||||
|
||||
/*turns x>y into y<=x*/
|
||||
int swaprel[] { EQUALS, NEQUALS, LESS, LESSEQ, GREAT, GREATEQ };
|
||||
|
||||
/*code skeleton built-in strings*/
|
||||
char *strtab[] {
|
||||
"move", /*MOV*/
|
||||
"move.l", /*MOVL*/
|
||||
"jsr", /*JSR*/
|
||||
"clr", /*CLR*/
|
||||
"clr.l", /*CLRL*/
|
||||
"ext.w", /*EXTW*/
|
||||
"ext.l", /*EXTL*/
|
||||
"lea", /*LEA*/
|
||||
"(sp)", /*STK*/
|
||||
};
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#ifndef NODEBUG
|
||||
|
||||
char invalid[] "INVALID";
|
||||
|
||||
char *opname[] {
|
||||
invalid, /*0*/
|
||||
"+", /*1*/
|
||||
"-", /*2*/
|
||||
"*", /*3*/
|
||||
"/", /*4*/
|
||||
"%", /*5*/
|
||||
">>", /*6*/
|
||||
"<<", /*7*/
|
||||
"&", /*8*/
|
||||
"|", /*9*/
|
||||
"^", /*10*/
|
||||
"!", /*11*/
|
||||
"U-", /*12*/
|
||||
"~", /*13*/
|
||||
"--p", /*14*/
|
||||
"++p", /*15*/
|
||||
"p--", /*16*/
|
||||
"p++", /*17*/
|
||||
"=", /*18*/
|
||||
"+=", /*19*/
|
||||
"-=", /*20*/
|
||||
"*=", /*21*/
|
||||
"/=", /*22*/
|
||||
"%=", /*23*/
|
||||
">>=", /*24*/
|
||||
"<<=", /*25*/
|
||||
"&=", /*26*/
|
||||
"|=", /*27*/
|
||||
"^=", /*28*/
|
||||
"jsr", /*29*/
|
||||
"==", /*30*/
|
||||
"!=", /*31*/
|
||||
">", /*32*/
|
||||
">=", /*33*/
|
||||
"<", /*34*/
|
||||
"<=", /*35*/
|
||||
"int->long", /*36*/
|
||||
"long->int", /*37*/
|
||||
"btst", /*38*/
|
||||
"load", /*39*/
|
||||
"long*", /*40*/
|
||||
"long/", /*41*/
|
||||
"long%", /*42*/
|
||||
"long*=", /*43*/
|
||||
"long/=", /*44*/
|
||||
"long%=", /*45*/
|
||||
"=addr", /*46*/
|
||||
"=not", /*47*/
|
||||
"=neg", /*48*/
|
||||
"docast", /*49*/
|
||||
"st=", /*50*/
|
||||
"long->float", /*51*/
|
||||
"float->long", /*52*/
|
||||
"int->float", /*53*/
|
||||
"float->int", /*54*/
|
||||
"tochar", /*55*/
|
||||
invalid, /*56*/
|
||||
invalid, /*57*/
|
||||
invalid, /*58*/
|
||||
invalid, /*59*/
|
||||
"U&", /*60*/
|
||||
"U*", /*61*/
|
||||
"&&", /*62*/
|
||||
"||", /*63*/
|
||||
"?", /*64*/
|
||||
":", /*65*/
|
||||
",", /*66*/
|
||||
"cint", /*67*/
|
||||
"clong", /*68*/
|
||||
"symbol", /*69*/
|
||||
"++a", /*70*/
|
||||
"a--", /*71*/
|
||||
"call", /*72*/
|
||||
"call()", /*73*/
|
||||
"bitfield", /*74*/
|
||||
"if", /*75*/
|
||||
"init", /*76*/
|
||||
"loadR0", /*77*/
|
||||
"divlong", /*78*/
|
||||
};
|
||||
|
||||
char *types[] {
|
||||
invalid, /*0=TYPELESS*/
|
||||
"char", /*1=CHAR*/
|
||||
invalid, /*2=SHORT*/
|
||||
"int", /*3=INT*/
|
||||
"long", /*4=LONG*/
|
||||
invalid, /*5=UCHAR*/
|
||||
invalid, /*6=USHORT*/
|
||||
"uint", /*7=UINT*/
|
||||
invalid, /*8=ULONG*/
|
||||
"float", /*9=FLOAT*/
|
||||
invalid, /*10=DOUBLE*/
|
||||
"struct", /*11=STRUCT*/
|
||||
invalid, /*12=undefined*/
|
||||
invalid, /*13=undefined*/
|
||||
invalid, /*14=undefined*/
|
||||
invalid, /*15=undefined*/
|
||||
};
|
||||
|
||||
char *suvals[] {
|
||||
"zero",
|
||||
"one",
|
||||
"quick",
|
||||
"small",
|
||||
"constant",
|
||||
"Areg",
|
||||
"Dreg",
|
||||
"addressable",
|
||||
"loadable",
|
||||
"easy",
|
||||
"hard",
|
||||
"veryhard",
|
||||
};
|
||||
|
||||
int level;
|
||||
|
||||
putexpr(name,tp)
|
||||
char *name;
|
||||
struct tnode *tp;
|
||||
{
|
||||
printf("%s\n",name);
|
||||
putsexpr(tp);
|
||||
}
|
||||
|
||||
putsexpr(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
register struct tnode *ltp;
|
||||
|
||||
level++;
|
||||
ltp = tp->t_left;
|
||||
outlevel();
|
||||
printf("%s ",opname[tp->t_op]);
|
||||
if( tp->t_op == BFIELD || tp->t_op == IFGOTO ) {
|
||||
if( tp->t_op == BFIELD )
|
||||
printf("off=%d len=%d\n",(tp->t_su>>8)&0377,tp->t_su&0377);
|
||||
else
|
||||
printf("%s goto L%d\n",tp->t_type?"TRUE":"FALSE",tp->t_su);
|
||||
putsexpr(tp->t_left);
|
||||
level--;
|
||||
return;
|
||||
}
|
||||
puttsu(tp);
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case DCLONG:
|
||||
case CLONG:
|
||||
case CFLOAT: /*[vlh] 3.4 */
|
||||
printf(" %x.%x\n",tp->t_lvalue.hiword,tp->t_lvalue.loword);
|
||||
break;
|
||||
|
||||
|
||||
case CINT:
|
||||
printf(" %d\n",tp->t_value);
|
||||
break;
|
||||
|
||||
case AUTODEC:
|
||||
case AUTOINC:
|
||||
printf(" R%d\n",tp->t_reg);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
case REGISTER:
|
||||
printf(" R%d",tp->t_reg);
|
||||
break;
|
||||
|
||||
case CINDR:
|
||||
printf(" %d\n",tp->t_offset);
|
||||
break;
|
||||
|
||||
case CLINDR:
|
||||
case CFINDR: /* [vlh] 3.4 */
|
||||
printf(" %x.%x\n",tp->t_offset,tp->t_ssp);
|
||||
break;
|
||||
|
||||
case REGOFF:
|
||||
printf(" %d(R%d)",tp->t_offset,tp->t_reg);
|
||||
break;
|
||||
|
||||
case EXTERNAL:
|
||||
case EXTOFF:
|
||||
printf(" %s+%d",tp->t_symbol,tp->t_offset);
|
||||
if( tp->t_sc == EXTOFF )
|
||||
printf("(R%d)",tp->t_reg);
|
||||
break;
|
||||
|
||||
case STATIC:
|
||||
case STATOFF:
|
||||
printf(" L%d+%d",tp->t_label,tp->t_offset);
|
||||
if( tp->t_sc == STATOFF )
|
||||
printf("(R%d)",tp->t_reg);
|
||||
break;
|
||||
|
||||
case INDEXED:
|
||||
printf(" %d(R%d,R%d)",tp->t_offset,tp->t_reg,tp->t_xreg);
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
putsexpr(tp->t_left);
|
||||
break;
|
||||
|
||||
default:
|
||||
putchar('\n');
|
||||
putsexpr(tp->t_left);
|
||||
if( binop(tp->t_op) )
|
||||
putsexpr(tp->t_right);
|
||||
break;
|
||||
}
|
||||
level--;
|
||||
}
|
||||
|
||||
outlevel()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for( i = 0; i < level; i++ )
|
||||
putchar('\t');
|
||||
}
|
||||
|
||||
puttsu(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
register int i;
|
||||
|
||||
if( suptype(tp->t_type) )
|
||||
putchar('*');
|
||||
printf("%s ",types[btype(tp->t_type)]);
|
||||
if( tp->t_su != 0 || (tp->t_op == CINT && tp->t_value == 0) ) {
|
||||
i = tp->t_su >> 8;
|
||||
if( i > 15 || i < 0 )
|
||||
printf("INVALID");
|
||||
else
|
||||
printf("%s",suvals[tp->t_su>>8]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/* Code Skeleton expansion and matching */
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
#define SK_TYPE(x) (x&017)
|
||||
|
||||
/* expand - code skeleton expansion*/
|
||||
/* Handles the expansion of code skeleton macros.*/
|
||||
expand(tp,cookie,freg,skp) /* returns register result is in*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int cookie; /* goal of expression tree*/
|
||||
int freg; /* register to leave results in*/
|
||||
struct skeleton *skp; /* pointer to code skeleton*/
|
||||
{
|
||||
register int op, nreg, reg;
|
||||
register int c;
|
||||
register int extf, i2f;
|
||||
register struct tnode *ltp, *rtp;
|
||||
register char *p;
|
||||
register int i, inaddreg, sreg, flag, subtrees, scookie;
|
||||
register char *macro;
|
||||
|
||||
#ifndef NODEBUG
|
||||
if( eflag )
|
||||
printf("expand op=%d left=%x right=%x skp=%o\n",tp->t_op,
|
||||
skp->sk_left,skp->sk_right,skp);
|
||||
#endif
|
||||
if( ((op=tp->t_op) >= MULT && op <= XOR) || tp->t_type == CHAR )
|
||||
freg = dreg(freg);
|
||||
macro = skp->sk_def;
|
||||
extf = 0;
|
||||
i2f = 0;
|
||||
rtp = ltp = tp->t_left;
|
||||
subtrees = 1;
|
||||
if( binop(op) ) {
|
||||
subtrees++;
|
||||
rtp = tp->t_right;
|
||||
if( (longorptr(tp->t_type)) && (op == DIV || op == MOD ||
|
||||
(op != MULT && (isdreg(freg)) &&
|
||||
!(longorptr(ltp->t_type)) && !(longorptr(rtp->t_type)))) )
|
||||
extf++;
|
||||
switch( op ) {
|
||||
|
||||
case RSH:
|
||||
case LSH:
|
||||
case EQLSH:
|
||||
case EQRSH:
|
||||
if( unsign(ltp->t_type) )
|
||||
i2f++;
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
case EQMULT:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case EQDIV:
|
||||
case EQMOD:
|
||||
if( unsign(ltp->t_type) || unsign(rtp->t_type) )
|
||||
i2f++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nreg = freg + 1;
|
||||
while( c = *macro++ ) {
|
||||
c =& 0xff;
|
||||
switch( c ) {
|
||||
|
||||
default:
|
||||
putchar(c);
|
||||
break;
|
||||
|
||||
case POP:
|
||||
stacksize--;
|
||||
printf("(sp)+");
|
||||
break;
|
||||
|
||||
case POP4:
|
||||
stacksize--;
|
||||
popstack(4);
|
||||
break;
|
||||
|
||||
case POP8:
|
||||
stacksize =- 2;
|
||||
popstack(8);
|
||||
break;
|
||||
|
||||
case PSH:
|
||||
if( cookie == FORSP ) /*don't affect sp*/
|
||||
printf("(sp)");
|
||||
else
|
||||
printf("-(sp)");
|
||||
stacksize++;
|
||||
break;
|
||||
|
||||
case MOV:
|
||||
case MOVL:
|
||||
case JSR:
|
||||
case CLR:
|
||||
case CLRL:
|
||||
case EXTW:
|
||||
case EXTL:
|
||||
case LEA:
|
||||
case STK:
|
||||
printf("%s",strtab[c-128]);
|
||||
break;
|
||||
|
||||
case OPCALL:
|
||||
if( isfloat(tp->t_type) || isfloat(ltp->t_type) ) {
|
||||
switch( op ) {
|
||||
|
||||
case ADD:
|
||||
case EQADD:
|
||||
printf("_fpadd");
|
||||
break;
|
||||
|
||||
case SUB:
|
||||
case EQSUB:
|
||||
printf("_fpsub");
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
case EQMULT:
|
||||
printf("_fpmult");
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
case EQDIV:
|
||||
printf("_fpdiv");
|
||||
break;
|
||||
|
||||
case UMINUS:
|
||||
case EQNEG:
|
||||
printf("_fpneg");
|
||||
break;
|
||||
|
||||
case FLOAT2L:
|
||||
case FLOAT2I:
|
||||
printf("_fpftol");
|
||||
break;
|
||||
|
||||
case LONG2F:
|
||||
case INT2F:
|
||||
printf("_fpltof");
|
||||
break;
|
||||
|
||||
case EQUALS:
|
||||
case NEQUALS:
|
||||
case GREAT:
|
||||
case GREATEQ:
|
||||
case LESS:
|
||||
case LESSEQ:
|
||||
printf("_fpcmp");
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid floating op %d\n",op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch( op ) {
|
||||
|
||||
case MULT:
|
||||
case LMULT:
|
||||
printf("lmul");
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
case LDIV:
|
||||
printf("ldiv");
|
||||
break;
|
||||
|
||||
case MOD:
|
||||
case LMOD:
|
||||
printf("lrem");
|
||||
break;
|
||||
|
||||
default:
|
||||
error("opcall bad op %d",op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TLEFT:
|
||||
outtype( leafop(op) ? tp->t_type : ltp->t_type );
|
||||
break;
|
||||
|
||||
case TLEFTL:
|
||||
outatype( leafop(op) ? tp->t_type : ltp->t_type );
|
||||
break;
|
||||
|
||||
case TEITHER:
|
||||
if( longorptr(rtp->t_type) || longorptr(ltp->t_type) )
|
||||
outtype(LONG);
|
||||
break;
|
||||
|
||||
case TRIGHT:
|
||||
outtype(rtp->t_type);
|
||||
break;
|
||||
|
||||
case OP:
|
||||
case AOP:
|
||||
if( c == AOP || i2f )
|
||||
i = optab[op][1];
|
||||
else
|
||||
i = optab[op][0];
|
||||
printf(mnemonics[i]);
|
||||
break;
|
||||
|
||||
case LADDR:
|
||||
case RADDR:
|
||||
p = (c==RADDR?rtp:ltp);
|
||||
outaexpr(p,IMMED);
|
||||
break;
|
||||
|
||||
case CR:
|
||||
outcreg(freg);
|
||||
break;
|
||||
|
||||
case NR:
|
||||
outcreg(nreg);
|
||||
break;
|
||||
|
||||
case CAR:
|
||||
outcreg(areg(freg));
|
||||
break;
|
||||
|
||||
case NAR:
|
||||
outcreg(areg(nreg));
|
||||
break;
|
||||
|
||||
case EXL:
|
||||
outextend(ltp,LONG,freg);
|
||||
break;
|
||||
|
||||
case EXRL:
|
||||
case EXRLN:
|
||||
outextend(rtp,ltp->t_type,c==EXRL?freg:nreg);
|
||||
break;
|
||||
|
||||
case EXLR:
|
||||
case EXLRN:
|
||||
outextend(ltp,rtp->t_type,c==EXLR?freg:nreg);
|
||||
break;
|
||||
|
||||
case LEFT:
|
||||
case RIGHT:
|
||||
subtrees--;
|
||||
case TREE:
|
||||
p = (c==LEFT?ltp:c==RIGHT?rtp:tp);
|
||||
flag = *macro++;
|
||||
scookie = FORREG;
|
||||
if( flag & S_STACK ) {
|
||||
if( cookie == FORSP )
|
||||
scookie = FORSP;
|
||||
else
|
||||
scookie = FORSTACK;
|
||||
}
|
||||
else if( flag & S_FORCC )
|
||||
scookie = FORCC;
|
||||
if( flag & S_NEXT )
|
||||
reg = nreg;
|
||||
else
|
||||
reg = freg;
|
||||
if( flag & S_INDR ) {
|
||||
if( p->t_op != INDR )
|
||||
error("code skeleton error: %d\n",op);
|
||||
p = p->t_left; /*skip INDR*/
|
||||
if( coffset(p) )
|
||||
p = p->t_left;
|
||||
reg = areg(reg);
|
||||
}
|
||||
sreg = codegen(p,scookie,reg); /*code for subtree*/
|
||||
if( scookie == FORREG ) {
|
||||
if( flag & S_INDR ) {
|
||||
if( isdreg(sreg) )
|
||||
outmovr(sreg,areg(reg),p);
|
||||
}
|
||||
else if( flag & S_NEXT )
|
||||
nreg = sreg;
|
||||
else if( sreg != reg ) {
|
||||
/*
|
||||
* result was not in expected register, if remaining sub-tree can be
|
||||
* compiled using the remaining registers, update current and next
|
||||
* registers, saving us the trouble of moving the register.
|
||||
*/
|
||||
if( c == TREE || ((isdreg(sreg)) && subtrees > 0 &&
|
||||
((c == LEFT &&
|
||||
sucomp(rtp,sreg,0) <= skp->sk_right &&
|
||||
sucomp(rtp,sreg,1) <= SU_ANY) ||
|
||||
( c == RIGHT &&
|
||||
sucomp(ltp,sreg,0) <= skp->sk_left &&
|
||||
sucomp(ltp,sreg,1) <= SU_ANY))) ) {
|
||||
freg = dreg(sreg);
|
||||
nreg = freg + 1;
|
||||
}
|
||||
else
|
||||
outmovr(sreg,dreg(freg),p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LOFFSET:
|
||||
case ROFFSET:
|
||||
p = (c==LOFFSET) ? ltp->t_left : rtp->t_left;
|
||||
if((p=coffset(p)) != 0 && (p->t_op != CINT || p->t_value != 0))
|
||||
outaexpr(p,NOTIMMED);
|
||||
break;
|
||||
|
||||
case MODSWAP:
|
||||
switch( op ) {
|
||||
|
||||
case MOD:
|
||||
case EQMOD:
|
||||
case LMOD:
|
||||
case LEQMOD:
|
||||
outswap(freg);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if( extf && cookie == FORREG && (isdreg(freg)) ) {
|
||||
if( unsign(ltp->t_type) || unsign(rtp->t_type) )
|
||||
outuext(freg);
|
||||
else
|
||||
outext(freg);
|
||||
}
|
||||
#ifndef NODEBUG
|
||||
if( eflag )
|
||||
printf("ending expand skp=%o\n",skp);
|
||||
#endif
|
||||
return(freg);
|
||||
}
|
||||
|
||||
/*
|
||||
* match - try to match expression tree with code skeleton
|
||||
* Given the expression tree, tries to match the given tree with
|
||||
* the appropriate code skeleton. The code skeleton list is
|
||||
* gotten from the root operator and the cookie value. The code
|
||||
* skeleton list is then searched, checking the Sethy-Ullman numbers
|
||||
* of the sub-trees against the Sethy-Ullman numbers in the code
|
||||
* skeleton list. If the Sethy-Ullman numbers are OK, then the
|
||||
* left and right sub-trees are checked for compatability, e.g.
|
||||
* integer pointers, etc. If a match is found, the code skeleton
|
||||
* list pointer is returned.
|
||||
*/
|
||||
char *match(tp,cookie,reg) /* returns ptr to code skeleton*/
|
||||
/* or 0 if no skeleton*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int cookie; /* goal for code expansion*/
|
||||
int reg; /* register to use*/
|
||||
{
|
||||
register struct skeleton *skp;
|
||||
register int op, bop, opndx;
|
||||
int i;
|
||||
register struct tnode *ltp, *rtp;
|
||||
|
||||
#ifndef NODEBUG
|
||||
if( mflag )
|
||||
printf("match op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg);
|
||||
#endif
|
||||
if( (op=tp->t_op) >= LCGENOP )
|
||||
return(0);
|
||||
if( leafop(op) )
|
||||
ltp = tp;
|
||||
else
|
||||
ltp = tp->t_left;
|
||||
if( (bop=binop(op)) ) {
|
||||
rtp = tp->t_right;
|
||||
if( convop(ltp->t_op) ) {
|
||||
if( op != LSH && notconvop(rtp->t_op) ) {
|
||||
if( !(unsign(ltp->t_left->t_type)) || op == ASSIGN ) {
|
||||
tp->t_left = ltp->t_left;
|
||||
if( (skp=match(tp,cookie,reg)) != 0 )
|
||||
return(skp);
|
||||
tp->t_left = ltp;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( convop(rtp->t_op) ) {
|
||||
if( !(unsign(rtp->t_left->t_type)) || op == ASSIGN ) {
|
||||
tp->t_right = rtp->t_left;
|
||||
if( (skp=match(tp,cookie,reg)) != 0 )
|
||||
return(skp);
|
||||
tp->t_right = rtp;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch( cookie ) {
|
||||
|
||||
case FORCC:
|
||||
i = 3;
|
||||
break;
|
||||
|
||||
case FOREFF:
|
||||
i = 2;
|
||||
break;
|
||||
|
||||
case FORSTACK:
|
||||
case FORSP:
|
||||
i = 4;
|
||||
break;
|
||||
|
||||
case FORREG:
|
||||
i = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
error("match cookie=%d\n",cookie);
|
||||
return(0);
|
||||
}
|
||||
#ifndef NODEBUG
|
||||
if( mflag )
|
||||
printf("match op=%d i=%d ",op,i);
|
||||
#endif
|
||||
if( !(i=optab[op][i]) )
|
||||
return(0);
|
||||
skp = codeskels[i];
|
||||
#ifndef NODEBUG
|
||||
if( mflag )
|
||||
printf("codeskels[%d]=%o\n",i,skp);
|
||||
#endif
|
||||
#ifndef NODEBUG
|
||||
if(mflag) {
|
||||
printf("match LEFT ");
|
||||
puttsu(ltp);
|
||||
if(bop) {
|
||||
printf(" RIGHT ");
|
||||
puttsu(rtp);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
#endif
|
||||
for( ; skp->sk_left != 0; skp++ ) {
|
||||
#ifndef NODEBUG
|
||||
if( mflag > 1 )
|
||||
printf("sk_left=%x sk_right=%x\n",skp->sk_left,skp->sk_right);
|
||||
#endif
|
||||
if( !(skelmatch(ltp,skp->sk_left)) )
|
||||
continue;
|
||||
if( bop && !(skelmatch(rtp,skp->sk_right)) )
|
||||
continue;
|
||||
#ifndef NODEBUG
|
||||
if( mflag )
|
||||
printf("match found skp=%o left=%x right=%x\n",skp,
|
||||
skp->sk_left,skp->sk_right);
|
||||
#endif
|
||||
return(skp);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* skelmatch - sub-tree type matching for match*/
|
||||
/* This checks a subtree for type compatability in match.*/
|
||||
skelmatch(tp,skinfo) /* returns 1 if matched, else 0*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int skinfo;
|
||||
{
|
||||
register int type, unsignf, const, stype;
|
||||
|
||||
if( tp->t_su > skinfo || ((skinfo&T_INDR) && tp->t_op != INDR) )
|
||||
return(0);
|
||||
stype = SK_TYPE(skinfo);
|
||||
type = tp->t_type;
|
||||
if( function(type) )
|
||||
type = btype(type);
|
||||
if( unsignf = unsign(type) )
|
||||
type = basetype(type);
|
||||
const = 0;
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case CFLOAT: /* [vlh] 3.4 */
|
||||
case CLONG:
|
||||
if( tp->t_su > SU_CONST )
|
||||
break;
|
||||
case CINT:
|
||||
const++;
|
||||
break;
|
||||
}
|
||||
switch( stype ) {
|
||||
|
||||
case T_CHAR:
|
||||
return( type == CHAR );
|
||||
|
||||
case T_ANY: /*either int or char*/
|
||||
if( type == CHAR )
|
||||
return(1);
|
||||
case T_INT:
|
||||
return( type == INT || const );
|
||||
|
||||
case T_UNSN:
|
||||
return( unsignf );
|
||||
|
||||
case T_LONG:
|
||||
return( longorptr(type) );
|
||||
|
||||
case T_FLOAT:
|
||||
return( isfloat(type) );
|
||||
|
||||
default:
|
||||
error("skelmatch type: %x",stype);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
/* sucomp - Sethy-Ullman expression complexity measure computation*/
|
||||
/* This is a heuristic computation of the Sethy-Ullman numbers*/
|
||||
/* for expressions. This gives an approximation of the complexity*/
|
||||
/* of the expression. The code generation scheme works best if*/
|
||||
/* the most complex expressions are done first.*/
|
||||
sucomp(tp,nregs,flag) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int nregs; /* number of registers left*/
|
||||
int flag; /* 1=>set values in tree, 0=>return*/
|
||||
{
|
||||
register int su, sur, op, i;
|
||||
register struct tnode *ltp, *rtp;
|
||||
|
||||
nregs = dreg(nregs);
|
||||
if( binop(op=tp->t_op) ) {
|
||||
ltp = tp->t_left;
|
||||
rtp = tp->t_right;
|
||||
}
|
||||
else if( unaryop(op) )
|
||||
ltp = tp->t_left;
|
||||
switch( op ) {
|
||||
|
||||
case CLONG:
|
||||
if( tp->t_lvalue >= 0x8000L || tp->t_lvalue <= 0xffff8000L ) {
|
||||
su = SU_ADDR;
|
||||
break;
|
||||
}
|
||||
i = tp->t_lvalue;
|
||||
case CINT:
|
||||
if( op == CINT )
|
||||
i = tp->t_value;
|
||||
if( i == 0 )
|
||||
su = SU_ZERO;
|
||||
else if( i == 1 )
|
||||
su = SU_ONE;
|
||||
else if( i >= 1 && i <= QUICKVAL )
|
||||
su = SU_SMALL;
|
||||
else if( i >= -128 && i <= 127 )
|
||||
su = SU_QUICK;
|
||||
else
|
||||
su = SU_CONST;
|
||||
break;
|
||||
|
||||
case COMMA:
|
||||
su = max(sucomp(rtp,nregs,flag),sucomp(ltp,nregs,flag));
|
||||
su = max(su,SU_EASY);
|
||||
break;
|
||||
|
||||
case ADDR:
|
||||
su = sucomp(ltp,nregs,flag);
|
||||
break;
|
||||
|
||||
case CFLOAT:
|
||||
case DCLONG:
|
||||
case AUTOINC:
|
||||
case AUTODEC:
|
||||
su = SU_ADDR;
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
if( tp->t_sc != REGISTER )
|
||||
su = SU_ADDR;
|
||||
else if( isdreg(tp->t_reg) )
|
||||
su = SU_REG;
|
||||
else
|
||||
su = SU_AREG;
|
||||
break;
|
||||
|
||||
case LDIV:
|
||||
case LMOD:
|
||||
case LMULT:
|
||||
case CALL:
|
||||
sucomp(rtp,nregs,flag);
|
||||
case NACALL:
|
||||
sucomp(ltp,nregs,flag);
|
||||
su = SU_VHARD; /*very hard*/
|
||||
break;
|
||||
|
||||
default:
|
||||
su = sucomp(ltp,nregs,flag);
|
||||
if( binop(op) ) {
|
||||
if( su <= SU_ADDR )
|
||||
su = max(su,sucomp(rtp,nregs,flag));
|
||||
else {
|
||||
sur = sucomp(rtp,nregs+1,flag);
|
||||
if( sur > SU_ADDR && nregs > HICREG )
|
||||
su = max(su,SU_HARD);
|
||||
}
|
||||
su = max(SU_EASY,su);
|
||||
}
|
||||
else if( su <= SU_XREG )
|
||||
su = max(SU_EASY,su);
|
||||
if( isfloat(tp->t_type) )
|
||||
su = SU_VHARD;
|
||||
break;
|
||||
}
|
||||
if( flag )
|
||||
tp->t_su = su;
|
||||
return(su);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#define ASGOP OPRAS|OPASSIGN|OPLVAL|OPBIN
|
||||
|
||||
/*info on operators:*/
|
||||
/*000077-- OPPRI - priority*/
|
||||
/*000100-- OPBIN - binary operator*/
|
||||
/*000200-- OPLVAL - left operand must be lvalue*/
|
||||
/*000400-- OPREL - relational operator*/
|
||||
/*001000-- OPASSIGN - assignment operator*/
|
||||
/*002000-- OPLWORD - int required on left*/
|
||||
/*004000-- OPRWORD - int required on right*/
|
||||
/*010000-- OPCOM commutative*/
|
||||
/*020000-- OPRAS - right associative*/
|
||||
/*040000-- OPTERM - termination node*/
|
||||
/*100000 - OPCONVS - conversion operator*/
|
||||
int opinfo[] {
|
||||
TRMPRI, /*EOF*/
|
||||
ADDPRI|OPCOM|OPBIN, /*ADD - expr + expr*/
|
||||
ADDPRI|OPBIN, /*SUB - expr - expr*/
|
||||
MULPRI|OPCOM|OPBIN, /*MULT - expr * expr*/
|
||||
MULPRI|OPBIN, /*DIV - expr / expr*/
|
||||
MULPRI|OPBIN, /*MOD - expr % expr*/
|
||||
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*RSH - expr >> expr*/
|
||||
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*LSH - expr << expr*/
|
||||
ANDPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*AND - expr & expr*/
|
||||
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*OR - expr | expr*/
|
||||
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*XOR - expr ^ expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*NOT - ! expr*/
|
||||
UNOPRI|OPRAS, /*UMINUS - - expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*COMPL - ~ expr*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREDEC - --lvalue*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREINC - ++lvalue*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTDEC - lvalue--*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTINC - lvalue++*/
|
||||
ASGPRI|ASGOP, /*ASSIGN - lvalue = expr*/
|
||||
ASGPRI|ASGOP, /*EQADD - lvalue += expr*/
|
||||
ASGPRI|ASGOP, /*EQSUB - lvalue -= expr*/
|
||||
ASGPRI|ASGOP, /*EQMULT - lvalue *= expr*/
|
||||
ASGPRI|ASGOP, /*EQDIV - lvalue /= expr*/
|
||||
ASGPRI|ASGOP, /*EQMOD - lvalue %= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQRSH - lvalue >>= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQLSH - lvalue <<= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQAND - lvalue &= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQOR - lvalue |= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQXOR - lvalue ^= expr*/
|
||||
TRMPRI, /*FJSR - generate function jsr*/
|
||||
EQLPRI|OPREL|OPBIN, /*EQUALS - expr == expr*/
|
||||
EQLPRI|OPREL|OPBIN, /*NEQUALS - expr != expr*/
|
||||
RELPRI|OPREL|OPBIN, /*GREAT - expr > expr*/
|
||||
RELPRI|OPREL|OPBIN, /*GREATEQ - expr >= expr*/
|
||||
RELPRI|OPREL|OPBIN, /*LESS - expr < expr*/
|
||||
RELPRI|OPREL|OPBIN, /*LESSEQ - expr <= expr*/
|
||||
TRMPRI|OPCONVS, /*INT2L*/
|
||||
TRMPRI|OPCONVS, /*LONG2I*/
|
||||
TRMPRI|OPBIN, /*BTST*/
|
||||
TRMPRI, /*LOAD*/
|
||||
TRMPRI|OPBIN, /*LMULT*/
|
||||
TRMPRI|OPBIN, /*LDIV*/
|
||||
TRMPRI|OPBIN, /*LMOD*/
|
||||
TRMPRI|OPBIN, /*LEQMULT*/
|
||||
TRMPRI|OPBIN, /*LEQDIV*/
|
||||
TRMPRI|OPBIN, /*LEQMOD*/
|
||||
TRMPRI|ASGOP, /*EQADDR*/
|
||||
TRMPRI, /*EQNOT*/
|
||||
TRMPRI, /*EQNEG*/
|
||||
TRMPRI|OPBIN, /*DOCAST*/
|
||||
ASGPRI|ASGOP, /*STASSIGN [vlh]*/
|
||||
TRMPRI|OPCONVS, /*LONG2F [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*FLOAT2L [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*INT2F [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*FLOAT2I [vlh] 3.4*/
|
||||
UNOPRI|OPRAS, /*TOCHAR [vlh] 4.0*/
|
||||
TRMPRI, /*unused - 56*/
|
||||
TRMPRI, /*unused - 57*/
|
||||
TRMPRI, /*unused - 58*/
|
||||
TRMPRI, /*unused - 59*/
|
||||
UNOPRI|OPRAS|OPLVAL, /*ADDR - & expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*INDR - * expr*/
|
||||
LNDPRI|OPBIN, /*LAND - expr && expr*/
|
||||
LORPRI|OPBIN, /*LOR - expr || expr*/
|
||||
QMKPRI|OPRAS|OPBIN, /*QMARK - expr ? expr : expr*/
|
||||
QMKPRI|OPRAS|OPBIN, /*COLON*/
|
||||
COMPRI|OPBIN, /*COMMA*/
|
||||
TRMPRI|OPTERM, /*CINT*/
|
||||
TRMPRI|OPTERM, /*CLONG*/
|
||||
TRMPRI|OPTERM, /*SYMBOL*/
|
||||
TRMPRI|OPTERM, /*AUTOINC*/
|
||||
TRMPRI|OPTERM, /*AUTODEC*/
|
||||
LPNPRI|OPBIN, /*CALL - call with arguments*/
|
||||
LPNPRI, /*NACALL - no argument call*/
|
||||
TRMPRI, /*BFIELD - field selection*/
|
||||
TRMPRI, /*CONDBR*/
|
||||
TRMPRI, /*INIT*/
|
||||
TRMPRI, /*LOADREG*/
|
||||
TRMPRI|OPTERM, /*DCLONG - divide const long*/
|
||||
TRMPRI|OPTERM, /*CFLOAT [vlh] 3.4*/
|
||||
UNOPRI|OPRAS|OPASSIGN|OPBIN, /*CAST*/
|
||||
TRMPRI, /*SEMI*/
|
||||
TRMPRI, /*LCURBR - {*/
|
||||
TRMPRI, /*RCURBR - }*/
|
||||
LPNPRI, /*LBRACK - [*/
|
||||
RPNPRI, /*RBRACK - ]*/
|
||||
LPNPRI, /*LPAREN - )*/
|
||||
RPNPRI, /*RPAREN - )*/
|
||||
TRMPRI|OPTERM, /*STRING*/
|
||||
TRMPRI, /*RESWORD*/
|
||||
LPNPRI|OPBIN, /*APTR - expr -> symbol*/
|
||||
LPNPRI|OPBIN, /*PERIOD - expr . symbol*/
|
||||
UNOPRI|OPRAS, /*SIZEOF - sizeof expr*/
|
||||
LPNPRI|OPBIN, /*MPARENS - matching parens ()*/
|
||||
};
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
/* xnalloc - allocate address-indexed node*/
|
||||
char *xnalloc(type,ar,off,xr,xt) /* returns ptr to node alloced*/
|
||||
int type; /* data type*/
|
||||
int ar; /* address register*/
|
||||
int off; /* 8-bit offset*/
|
||||
int xr; /* index register*/
|
||||
int xt; /* index register type*/
|
||||
{
|
||||
register struct indexnode *xp;
|
||||
|
||||
xp = talloc(sizeof(*xp));
|
||||
xp->t_op = SYMBOL;
|
||||
xp->t_type = type;
|
||||
xp->t_sc = INDEXED;
|
||||
xp->t_reg = ar;
|
||||
xp->t_su = SU_ADDR;
|
||||
xp->t_offset = off;
|
||||
xp->t_xreg = xr;
|
||||
xp->t_xtype = xt;
|
||||
return(xp);
|
||||
}
|
||||
|
||||
/* tcopy - expression tree copy*/
|
||||
char *tcopy(tp) /* returns ptr to copied tree*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case SYMBOL:
|
||||
if( tp->t_sc == EXTERNAL || tp->t_sc == EXTOFF )
|
||||
p = cenalloc(tp->t_type,tp->t_sc,tp->t_symbol);
|
||||
else {
|
||||
p = snalloc(tp->t_type,tp->t_sc,tp->t_offset,0,0);
|
||||
p->t_label = tp->t_label;
|
||||
}
|
||||
p->t_offset = tp->t_offset;
|
||||
p->t_reg = tp->t_reg;
|
||||
return(p);
|
||||
|
||||
case CINT:
|
||||
return(cnalloc(tp->t_type,tp->t_value));
|
||||
|
||||
case CLONG:
|
||||
return(lcnalloc(tp->t_type,tp->t_lvalue));
|
||||
|
||||
case CFLOAT: /*[vlh] 3.4 */
|
||||
return(fpcnalloc(tp->t_type,tp->t_lvalue));
|
||||
|
||||
case DCLONG:
|
||||
p = lcnalloc(tp->t_type,tp->t_lvalue);
|
||||
p->t_op = DCLONG;
|
||||
return(p);
|
||||
|
||||
default:
|
||||
if( binop(tp->t_op) )
|
||||
return(tnalloc(tp->t_op,tp->t_type,0,0,tcopy(tp->t_left),
|
||||
tcopy(tp->t_right)));
|
||||
if( unaryop(tp->t_op) )
|
||||
return(tnalloc(tp->t_op,tp->t_type,0,0,tcopy(tp->t_left),
|
||||
null));
|
||||
error("tcopy op=%d",tp->t_op);
|
||||
return(tp);
|
||||
}
|
||||
}
|
||||
|
||||
/* outaexpr - output address expression*/
|
||||
outaexpr(tp,flags) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int flags; /* flags (IMMED,LOFFSET,...)*/
|
||||
{
|
||||
register int off, reg, lab;
|
||||
long l;
|
||||
|
||||
if( tp->t_op == ADDR ) {
|
||||
tp = tp->t_left;
|
||||
putchar('#');
|
||||
}
|
||||
off = tp->t_offset;
|
||||
reg = tp->t_reg;
|
||||
lab = tp->t_label;
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case AUTOINC:
|
||||
printf("(R%d)+",reg);
|
||||
break;
|
||||
|
||||
case AUTODEC:
|
||||
printf("-(R%d)",reg);
|
||||
break;
|
||||
|
||||
case CINT:
|
||||
if( flags & IMMED )
|
||||
putchar('#');
|
||||
printf("%d",tp->t_value);
|
||||
break;
|
||||
|
||||
case DCLONG:
|
||||
case CLONG:
|
||||
case CFLOAT: /*[vlh] 3.4 */
|
||||
if( flags & IMMED )
|
||||
putchar('#');
|
||||
outlval(tp->t_lvalue);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
if( off ) {
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
default:
|
||||
printf("%d+",off);
|
||||
break;
|
||||
|
||||
case REGOFF:
|
||||
printf("%d",off);
|
||||
case CINDR:
|
||||
case CLINDR:
|
||||
case CFINDR: /* [vlh] 3.4 */
|
||||
case INDEXED:
|
||||
break;
|
||||
|
||||
case REGISTER:
|
||||
error("invalid register expression");
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
case REGISTER:
|
||||
printf("R%d",reg);
|
||||
break;
|
||||
|
||||
case REGOFF:
|
||||
printf("(R%d)",reg);
|
||||
break;
|
||||
|
||||
case EXTERNAL:
|
||||
printf("_%.8s",tp->t_symbol);
|
||||
break;
|
||||
|
||||
case EXTOFF:
|
||||
printf("_%.8s(R%d)",tp->t_symbol,reg);
|
||||
break;
|
||||
|
||||
case STATIC:
|
||||
printf("L%d",lab);
|
||||
break;
|
||||
|
||||
case STATOFF:
|
||||
printf("L%d(R%d)",lab,reg);
|
||||
break;
|
||||
|
||||
case INDEXED:
|
||||
printf("%d(R%d,R%d",off,reg,tp->t_xreg);
|
||||
outatype(tp->t_xtype);
|
||||
putchar(')');
|
||||
break;
|
||||
|
||||
case CINDR:
|
||||
printf("%d",off);
|
||||
break;
|
||||
/*
|
||||
* the following will work on: PDP-11, 68000, IBM-360, VAX, etc.
|
||||
* it will not work on word machines or on machines where either
|
||||
* longs two ints or two shorts.
|
||||
*/
|
||||
case CLINDR:
|
||||
case CFINDR: /* [vlh] 3.4 */
|
||||
l.hiword = tp->t_offset;
|
||||
l.loword = tp->t_ssp;
|
||||
outlval(l);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid storage class %d\n",tp->t_sc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid operator %d\n",tp->t_op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* outlval - output long value*/
|
||||
/* This is a big pain because the PDP-11 doesn't do long divides*/
|
||||
/* in hardware.*/
|
||||
outlval(lval)
|
||||
long lval;
|
||||
{
|
||||
char digs[8];
|
||||
register int i, c;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
digs[i++] = lval & 0xf;
|
||||
lval =>> 4;
|
||||
lval =& 0xfffffff;
|
||||
} while ( lval );
|
||||
putchar('$');
|
||||
while( --i >= 0 ) {
|
||||
c = digs[i];
|
||||
putchar(c>=10?c+('a'-10):c+'0');
|
||||
}
|
||||
}
|
||||
|
||||
/* outtype - output 68000 type (null, .b, .l) depending on data type*/
|
||||
outtype(type)
|
||||
int type;
|
||||
{
|
||||
if( isfloat(type) )
|
||||
printf(".l");
|
||||
else if( longorptr(type) )
|
||||
printf(".l");
|
||||
else if( type == CHAR )
|
||||
printf(".b");
|
||||
}
|
||||
|
||||
/* outatype - output address type (.l or null) depending on data type*/
|
||||
outatype(type)
|
||||
int type;
|
||||
{
|
||||
if( longorptr(type) || isfloat(type) )
|
||||
printf(".l");
|
||||
}
|
||||
|
||||
/* outextend - output register extension to long depending on type*/
|
||||
outextend(tp,type,reg) /* returns - none*/
|
||||
struct tnode *tp; /* tree to convert from*/
|
||||
int type; /* type to convert to*/
|
||||
int reg; /* register to convert*/
|
||||
{
|
||||
if( (isdreg(reg)) && !(longorptr(tp->t_type)) && (longorptr(type)) ) {
|
||||
if( unsign(tp->t_type) )
|
||||
outuext(reg);
|
||||
else
|
||||
outext(reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* outrr - output register to register instruction*/
|
||||
outrr(ins,r1,r2,tp)
|
||||
char *ins;
|
||||
int r1;
|
||||
int r2;
|
||||
struct tnode *tp;
|
||||
{
|
||||
printf("%s",ins);
|
||||
if( isareg(r1) || isareg(r2) )
|
||||
outatype(tp->t_type);
|
||||
else
|
||||
outtype(tp->t_type);
|
||||
printf(" R%d,R%d\n",r1,r2);
|
||||
}
|
||||
|
||||
/* outmovr - output "move[type] R1,R2" instruction*/
|
||||
outmovr(r1,r2,tp)
|
||||
int r1;
|
||||
int r2;
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( r1 != r2 )
|
||||
outrr("move",r1,r2,tp);
|
||||
}
|
||||
|
||||
/* outcmpm - output "cmpm[type] (R1)+,(R2)+"*/
|
||||
outcmpm(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
printf("cmpm");
|
||||
outtype(tp->t_left->t_type);
|
||||
printf(" (R%d)+,(R%d)+\n",tp->t_left->t_reg,tp->t_right->t_reg);
|
||||
}
|
||||
|
||||
/* outcreg - output reference to compiler temp register*/
|
||||
outcreg(reg)
|
||||
int reg;
|
||||
{
|
||||
if( (dreg(reg)) > HICREG )
|
||||
error("expression too complex");
|
||||
printf("R%d",reg);
|
||||
}
|
||||
|
||||
/* outcmp0 - output a compare with 0, special for address register*/
|
||||
outcmp0(reg,tp)
|
||||
int reg;
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( isareg(reg) ) {
|
||||
printf("cmp");
|
||||
outatype(tp->t_type);
|
||||
printf(" #0,R%d\n",reg);
|
||||
}
|
||||
else {
|
||||
printf("tst");
|
||||
outtype(tp->t_type);
|
||||
printf(" R%d\n",reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* outrpush - output "move[type] R1,[-](sp)"*/
|
||||
outrpush(reg,tp,pflag)
|
||||
int reg;
|
||||
struct tnode *tp;
|
||||
int pflag;
|
||||
{
|
||||
printf("move");
|
||||
outatype(tp->t_type);
|
||||
printf(" R%d,%c(sp)\n",reg,pflag?'-':'\0');
|
||||
}
|
||||
|
||||
outdbra(reg,lab)
|
||||
int reg;
|
||||
int lab;
|
||||
{
|
||||
printf("dbra R%d,L%d\n",reg,lab);
|
||||
}
|
||||
|
||||
/* cenalloc - code generator external node allocation*/
|
||||
/* This may be coalesced into enalloc in parser.*/
|
||||
char *cenalloc(type,sc,sym) /* returns ptr to node alloced*/
|
||||
int type; /* type of symbol*/
|
||||
int sc; /* storage class*/
|
||||
char *sym; /* symbol name*/
|
||||
{
|
||||
register struct extnode *ep;
|
||||
|
||||
ep = talloc(sizeof(*ep));
|
||||
ep->t_op = SYMBOL;
|
||||
ep->t_type = type;
|
||||
ep->t_sc = sc;
|
||||
ep->t_su = 0;
|
||||
ep->t_offset = 0;
|
||||
symcopy(sym,ep->t_symbol);
|
||||
return(ep);
|
||||
}
|
||||
|
||||
/*popstack - clear off the stack after a call if necessary */
|
||||
popstack(nb)
|
||||
{
|
||||
if (nb > 0 && nb <= 8)
|
||||
printf("addq.l #%d,sp\n",nb);
|
||||
else if (nb > 0)
|
||||
printf("adda.l #%d,sp\n",nb);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
char *compiled "@(#) code generator - Fri Mar 18 12:02 1983";
|
||||
@@ -0,0 +1,3 @@
|
||||
mkver; c68 -r -L *.c -o c68.68 -l6 ; setstack68 c68.68 8192 8192
|
||||
mkver; c68 -r -L -n *.c -o c68.st -l6 ; setstack68 c68.st 8192 8192
|
||||
mkver; cc -n *.c -o c68.11 -lx
|
||||
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "preproc.h"
|
||||
|
||||
#define OPPRI 077
|
||||
#define OPBIN 0100
|
||||
#define STKLEN 64
|
||||
int oprstk[STKLEN]; /*operator stack*/
|
||||
int opnstk[STKLEN]; /*operand stack*/
|
||||
int pristk[STKLEN]; /*operator priority stack*/
|
||||
int *oprptr; /*pointer to operator stack*/
|
||||
int *opnptr; /*pointer to operand stack*/
|
||||
int *priptr; /*pointer to priority stack*/
|
||||
int cvalue;
|
||||
|
||||
int opinfo[] {
|
||||
0, /*EOF=0*/
|
||||
16|OPBIN, /*SUB=1*/
|
||||
16|OPBIN, /*ADD=2*/
|
||||
20, /*NOT=3*/
|
||||
20, /*NEG=4*/
|
||||
22, /*LPAREN=5*/
|
||||
2, /*RPAREN=6*/
|
||||
6|OPBIN, /*QMARK=7*/
|
||||
6|OPBIN, /*COLON=8*/
|
||||
8|OPBIN, /*OR=9*/
|
||||
10|OPBIN, /*AND=10*/
|
||||
8|OPBIN, /*XOR=11*/
|
||||
12|OPBIN, /*EQUAL=12*/
|
||||
12|OPBIN, /*NEQUAL=13*/
|
||||
14|OPBIN, /*LESS=14*/
|
||||
14|OPBIN, /*LSEQUAL=15*/
|
||||
14|OPBIN, /*GREAT=16*/
|
||||
14|OPBIN, /*GREQUAL=17*/
|
||||
4|OPBIN, /*LSHIFT=18*/
|
||||
4|OPBIN, /*RSHIFT=19*/
|
||||
18|OPBIN, /*MULT=20*/
|
||||
18|OPBIN, /*DIV=21*/
|
||||
18|OPBIN, /*MOD=22*/
|
||||
20, /*COMPL=23*/
|
||||
};
|
||||
|
||||
/* cexpr - constant expression evaluation*/
|
||||
/* Does priority-driven operator/operand stack evaluation of*/
|
||||
/* constant expressions.*/
|
||||
cexpr() /* returns constant evaluated*/
|
||||
{
|
||||
register int lop, type;
|
||||
|
||||
oprptr = &oprstk[0];
|
||||
opnptr = &opnstk[0];
|
||||
priptr = &pristk[0];
|
||||
*priptr = 0;
|
||||
lop = -1;
|
||||
while(1) {
|
||||
switch( type = getctok() ) {
|
||||
|
||||
case CONST:
|
||||
if( !lop ) /*last was not operator*/
|
||||
goto syntax;
|
||||
if( opnptr >= &opnstk[STKLEN] ) {
|
||||
error("expression stack overflow");
|
||||
cexit();
|
||||
}
|
||||
lop = FALSE;
|
||||
*++opnptr = cvalue;
|
||||
continue;
|
||||
|
||||
case SUB:
|
||||
if( lop )
|
||||
type = NEG; /*unary minus*/
|
||||
break;
|
||||
|
||||
case ADD:
|
||||
if( lop )
|
||||
continue; /*ignore unary +*/
|
||||
break;
|
||||
|
||||
case COMPL:
|
||||
case LPAREN:
|
||||
case NOT:
|
||||
if( !lop )
|
||||
goto syntax;
|
||||
break;
|
||||
|
||||
case RPAREN:
|
||||
if( lop )
|
||||
goto syntax;
|
||||
lop = FALSE;
|
||||
if( !stkop(type) )
|
||||
goto syntax;
|
||||
continue;
|
||||
|
||||
case NEWL:
|
||||
case EOF:
|
||||
if( lop || !stkop(EOF) || opnptr != &opnstk[1] )
|
||||
goto syntax;
|
||||
type = opnstk[1];
|
||||
putback('\n');
|
||||
return(type);
|
||||
|
||||
default:
|
||||
if( lop || type > LASTOP )
|
||||
goto syntax;
|
||||
break;
|
||||
}
|
||||
lop = TRUE;
|
||||
if( !stkop(type) )
|
||||
goto syntax;
|
||||
}
|
||||
syntax:
|
||||
error("expression syntax");
|
||||
if( type == NEWL )
|
||||
putback('\n');
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* getctok - get a constant expression token*/
|
||||
/* Handles conversion of quoted character strings and numbers.*/
|
||||
getctok()
|
||||
{
|
||||
register int type, c, count;
|
||||
register char *p;
|
||||
char token[TOKSIZE];
|
||||
|
||||
while( 1 ) {
|
||||
switch( type = getntok(token) ) {
|
||||
|
||||
case DIGIT:
|
||||
cvalue = const(token);
|
||||
return(CONST);
|
||||
|
||||
case SQUOTE:
|
||||
for( cvalue = 0, p = &token[1], count = 2; --count >= 0; ) {
|
||||
if( (c= *p++) == '\'' )
|
||||
break;
|
||||
if( c == '\\' ) {
|
||||
if( *p >= '0' && *p <= '7' ) {
|
||||
for( c = 0; *p >= '0' && *p <= '7'; )
|
||||
c = (c<<3) + (*p++ - '0');
|
||||
}
|
||||
else switch( c = *p++ ) {
|
||||
|
||||
case 'n':
|
||||
c = '\n';
|
||||
break;
|
||||
|
||||
case 't':
|
||||
c = '\t';
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
c = '\b';
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
c = '\r';
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
c = '\f';
|
||||
break;
|
||||
}
|
||||
}
|
||||
cvalue = (cvalue<<8) | c;
|
||||
}
|
||||
return(CONST);
|
||||
|
||||
case ALPHA:
|
||||
if( p = lookup(token) )
|
||||
expand(p);
|
||||
else
|
||||
return(ALPHA);
|
||||
break;
|
||||
|
||||
default:
|
||||
return(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* stkop - stack an operator on the operand stack*/
|
||||
/* Unstack all operators of lower priority, evaluating them as*/
|
||||
/* they are unstacked.*/
|
||||
stkop(opr) /* returns 1 if ok, 0 otherwise*/
|
||||
int opr; /* operator to stack*/
|
||||
{
|
||||
register int i, j, op1, op2, pri;
|
||||
|
||||
for( pri = opinfo[opr]&OPPRI; pri < *priptr; ) {
|
||||
if( *oprptr == LPAREN ) {
|
||||
if( opr == RPAREN ) {
|
||||
oprptr--;
|
||||
priptr--;
|
||||
return(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
op1 = *opnptr;
|
||||
if( (i=opinfo[*oprptr]) & OPBIN ) {
|
||||
op2 = op1;
|
||||
op1 = *--opnptr;
|
||||
}
|
||||
switch(*oprptr) { /*operator*/
|
||||
|
||||
case ADD:
|
||||
op1 =+ op2;
|
||||
break;
|
||||
|
||||
case SUB:
|
||||
op1 =- op2;
|
||||
break;
|
||||
|
||||
case COLON:
|
||||
priptr--;
|
||||
if( *--oprptr != QMARK )
|
||||
return(0);
|
||||
op1 = (*--opnptr ? op1 : op2);
|
||||
break;
|
||||
|
||||
case QMARK:
|
||||
return(0);
|
||||
|
||||
case XOR:
|
||||
op1 =^ op2;
|
||||
break;
|
||||
|
||||
case OR:
|
||||
op1 =| op2;
|
||||
break;
|
||||
|
||||
case AND:
|
||||
op1 =& op2;
|
||||
break;
|
||||
|
||||
case EQUAL:
|
||||
op1 = (op1 == op2);
|
||||
break;
|
||||
|
||||
case NEQUAL:
|
||||
op1 = (op1 != op2);
|
||||
break;
|
||||
|
||||
case LESS:
|
||||
op1 = (op1 < op2);
|
||||
break;
|
||||
|
||||
case LSEQUAL:
|
||||
op1 = (op1 <= op2);
|
||||
break;
|
||||
|
||||
case GREAT:
|
||||
op1 = (op1 > op2);
|
||||
break;
|
||||
|
||||
case GREQUAL:
|
||||
op1 = (op1 >= op2);
|
||||
break;
|
||||
|
||||
case LSHIFT:
|
||||
op1 = (op1 << op2);
|
||||
break;
|
||||
|
||||
case RSHIFT:
|
||||
op1 = (op1 >> op2);
|
||||
break;
|
||||
|
||||
case NEG:
|
||||
op1 = -op1;
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
op1 = !op1;
|
||||
break;
|
||||
|
||||
case COMPL:
|
||||
op1 = ~ op1;
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
op1 =* op2;
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
op1 =/ op2;
|
||||
break;
|
||||
|
||||
case MOD:
|
||||
op1 =% op2;
|
||||
break;
|
||||
|
||||
}
|
||||
*opnptr = op1;
|
||||
priptr--;
|
||||
oprptr--;
|
||||
}
|
||||
if( priptr >= &pristk[STKLEN-1] ) {
|
||||
error("expression operator stack overflow");
|
||||
cexit();
|
||||
}
|
||||
*++oprptr = opr; /*operator value*/
|
||||
*++priptr = pri; /*operator priority*/
|
||||
return(1);
|
||||
}
|
||||
|
||||
#define toupper(c) ((c) & ~32)
|
||||
/* const - alpha to int conversion, handles octal and hexidecimal*/
|
||||
/* Uses Horner's method to evaluate number.*/
|
||||
const(str) /* returns number evaluated*/
|
||||
char *str; /* pointer to string to convert*/
|
||||
{
|
||||
register int c, ch, i, radix;
|
||||
|
||||
i = 0;
|
||||
radix = 10;
|
||||
if( *str == '0' ) {
|
||||
radix = 8;
|
||||
if( *++str == 'x' || *str == 'X' ) {
|
||||
radix = 16;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
while( c = *str++ ) {
|
||||
if( (ch=toupper(c)) >= 'A' && ch <= 'F' )
|
||||
c = ch - ('A'-10);
|
||||
else if( c >= '0' && c <= '9' )
|
||||
c =- '0';
|
||||
else
|
||||
break;
|
||||
if( c >= radix )
|
||||
break;
|
||||
i = i*radix + c;
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
353
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/c68/lex.c
Normal file
353
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/c68/lex.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "preproc.h"
|
||||
|
||||
int Eflag;
|
||||
char null[] "";
|
||||
|
||||
char ctype[] {
|
||||
EOF, ANYC, ANYC, ANYC, ANYC, ANYC, ANYC, ANYC,
|
||||
ANYC, WHITE, NEWL, ANYC, ANYC, ANYC, ANYC, ANYC,
|
||||
ANYC, ANYC, ANYC, ANYC, NEWL, ANYC, ANYC, ANYC,
|
||||
ANYC, ANYC, ANYC, ANYC, ANYC, ANYC, ANYC, ANYC,
|
||||
WHITE, NOT, DQUOTE, POUND, ANYC, MOD, AND, SQUOTE,
|
||||
LPAREN, RPAREN, MULT, ADD, COMMA, SUB, ANYC, DIV,
|
||||
DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
|
||||
DIGIT, DIGIT, COLON, ANYC, LESS, EQUAL, GREAT, QMARK,
|
||||
ANYC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ANYC, BSLASH, ANYC, XOR, ALPHA,
|
||||
ANYC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ANYC, OR, ANYC, COMPL, ANYC
|
||||
}; /* BUG2 - ANYC */
|
||||
|
||||
/* symhash - compute hash value for symbol*/
|
||||
/* Sums the symbols characters and takes that modulus the hash table*/
|
||||
/* size.*/
|
||||
symhash(sym) /* returns hash value for symbol*/
|
||||
char *sym; /* pointer to symbol*/
|
||||
{
|
||||
register char *p;
|
||||
register int hashval, i;
|
||||
|
||||
for( p = sym, i = SSIZE, hashval = 0; *p != '\0' && i > 0; i-- )
|
||||
hashval =+ *p++;
|
||||
return( hashval % HSIZE );
|
||||
}
|
||||
|
||||
/* symequal - check for symbol equality*/
|
||||
/* Does comparison between two symbols.*/
|
||||
symequal(sym1,sym2) /* returns 1 if equal, 0 otherwise*/
|
||||
char *sym1; /* pointer to first symbol*/
|
||||
char *sym2; /* pointer to second symbol*/
|
||||
{
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
q = sym2;
|
||||
i = SSIZE;
|
||||
for( p = sym1; *p == *q++; )
|
||||
if( *p++ == '\0' || --i == 0 )
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* symcopy - symbol copy*/
|
||||
/* Copies one symbol to another.*/
|
||||
symcopy(sym1,sym2) /* returns - none*/
|
||||
char *sym1; /* pointer to symbol to copy*/
|
||||
char *sym2; /* pointer to area to copy to*/
|
||||
{
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
for( p = sym1, q = sym2, i = SSIZE; --i >= 0; )
|
||||
if( *p )
|
||||
*q++ = *p++;
|
||||
else
|
||||
*q++ = '\0';
|
||||
}
|
||||
|
||||
/* error - output error message*/
|
||||
/* Outputs line number and error message and keeps track of errors.*/
|
||||
error(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* printf string*/
|
||||
int x1, x2, x3, x4, x5, x6; /* printf args*/
|
||||
{
|
||||
if (filep == &filestack[0]) /* [vlh] 3.4 not in include */
|
||||
printf("# %d: ",lineno);
|
||||
else
|
||||
printf("%s : # %d: ",(filep-1)->ifile,(filep-1)->lineno);
|
||||
printf(s,x1,x2,x3,x4,x5,x6);
|
||||
putchar('\n');
|
||||
mfail++;
|
||||
}
|
||||
|
||||
/* putback - puts back a single character*/
|
||||
/* Checks for push back buffer overflow.*/
|
||||
putback(c)
|
||||
int c;
|
||||
{
|
||||
if( pbp >= &pbbuf[PBSIZE] ) {
|
||||
error("too many characters pushed back");
|
||||
cexit();
|
||||
}
|
||||
*pbp++ = c;
|
||||
}
|
||||
|
||||
/* pbtok - push back a token*/
|
||||
/* Reverses token as its pushing it back.*/
|
||||
pbtok(s)
|
||||
char *s;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
for( p = s + strlen(s); p > s ; )
|
||||
putback(*--p);
|
||||
}
|
||||
|
||||
/* ngetch - get a (possibly) pushed back character*/
|
||||
/* This handles the include file stack and incrementing the line*/
|
||||
/* number for the lowest level file.*/
|
||||
ngetch() /* returns character or EOF*/
|
||||
{
|
||||
register int c, i;
|
||||
register char *p, *q;
|
||||
|
||||
if( pbp > &pbbuf[0] )
|
||||
return(*--pbp);
|
||||
pbflag = 0;
|
||||
while( (c=getc(&inbuf)) < 0 ) {
|
||||
if( filep == &filestack[0] )
|
||||
return(EOF);
|
||||
close(inbuf.fd);
|
||||
filep--;
|
||||
#ifdef NONEST
|
||||
inbuf.fd = holdbuf.fd;
|
||||
inbuf.nc = holdbuf.nc;
|
||||
inbuf.bp = holdbuf.bp;
|
||||
p = &inbuf.buffer[0];
|
||||
q = &holdbuf.buffer[0];
|
||||
for(i = 0; i<BUFSIZE; i++)
|
||||
*p++ = *q++;
|
||||
#else
|
||||
inbuf.fd = filep->ifd;
|
||||
inbuf.nc = 0;
|
||||
inbuf.bp = &inbuf.buffer[0];
|
||||
#endif
|
||||
if( filep == &filestack[0] ) { /*need line for #include...*/
|
||||
doputc('\n',&outbuf);
|
||||
lineno++;
|
||||
}
|
||||
}
|
||||
return( c );
|
||||
}
|
||||
|
||||
/* getsp - get symbol pointer*/
|
||||
/* Calculates the symbol table pointer for a given symbol, if symbol*/
|
||||
/* is not defined, will point to appropriate place to insert symbol.*/
|
||||
struct symbol *getsp(name)
|
||||
char *name;
|
||||
{
|
||||
register int wrap;
|
||||
register struct symbol *sp, *asp;
|
||||
|
||||
wrap = 0;
|
||||
asp = 0;
|
||||
for( sp = &symtab[symhash(name)]; sp->s_def != null; ) {
|
||||
if( symequal(sp->s_name,name) )
|
||||
return(sp);
|
||||
if( !asp && sp->s_def == null )
|
||||
asp = sp;
|
||||
if( ++sp >= &symtab[HSIZE] ) {
|
||||
if( wrap++ ) {
|
||||
error("symbol table overflow");
|
||||
cexit();
|
||||
}
|
||||
sp = &symtab[0];
|
||||
}
|
||||
}
|
||||
return( asp ? asp : sp );
|
||||
}
|
||||
|
||||
/* lookup - looks up a symbol to see if it is defined*/
|
||||
/* Returns pointer to definition if found.*/
|
||||
char *lookup(name) /* returns 0 or ptr to symbol*/
|
||||
char *name; /* symbol name*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
sp = getsp(name);
|
||||
if( sp->s_def == 0 || sp->s_def == null )
|
||||
return(0);
|
||||
return(sp);
|
||||
}
|
||||
|
||||
/* gettok - gets next token from input*/
|
||||
/* Collects character string in token and handles special tokens for*/
|
||||
/* the expression evaluator.*/
|
||||
gettok(token) /* returns token type*/
|
||||
char *token;
|
||||
{
|
||||
register char *p, c;
|
||||
register int type, count, t, l;
|
||||
|
||||
p = token;
|
||||
c = ngetch();
|
||||
*p++ = c;
|
||||
switch( type = ctype[c] ) {
|
||||
|
||||
case SQUOTE:
|
||||
case DQUOTE:
|
||||
getstr(token,TOKSIZE,c);
|
||||
return(type);
|
||||
|
||||
case DIGIT:
|
||||
case ALPHA:
|
||||
for( ; p < &token[TOKSIZE]; p++ ) {
|
||||
*p = ngetch();
|
||||
if( (t=ctype[*p]) != ALPHA && t != DIGIT )
|
||||
break;
|
||||
}
|
||||
putback(*p);
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
if( peekis('=') ) {
|
||||
type = NEQUAL;
|
||||
*p++ = '=';
|
||||
}
|
||||
break;
|
||||
|
||||
case GREAT:
|
||||
if( peekis('>') ) {
|
||||
type = RSHIFT;
|
||||
*p++ = '>';
|
||||
}
|
||||
else if( peekis('=') ) {
|
||||
type = GREQUAL;
|
||||
*p++ = '=';
|
||||
}
|
||||
break;
|
||||
|
||||
case LESS:
|
||||
if( peekis('<') ) {
|
||||
type = LSHIFT;
|
||||
*p++ = '<';
|
||||
}
|
||||
else if( peekis('=') ) {
|
||||
type = LSEQUAL;
|
||||
*p++ = '=';
|
||||
}
|
||||
break;
|
||||
|
||||
case EQUAL:
|
||||
if( peekis('=') )
|
||||
*p++ = '=';
|
||||
else
|
||||
type = ANYC;
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
if( peekis('*') ) {
|
||||
l = lineno;
|
||||
while( (c=ngetch()) != EOF )
|
||||
if( c == '\n' ) {
|
||||
if( filep == &filestack[0] && pbp == &pbbuf[0] ) {
|
||||
lineno++;
|
||||
doputc('\n',&outbuf);
|
||||
}
|
||||
}
|
||||
else if( c == '*' && peekis('/') )
|
||||
break;
|
||||
if( c == EOF ) {
|
||||
lineno = l;
|
||||
error("no */ before EOF");
|
||||
}
|
||||
type = WHITE;
|
||||
token[0] = ' ';
|
||||
}
|
||||
else if( peekis('/') ) {
|
||||
while( (c=ngetch()) != EOF && c != '\n' )
|
||||
;
|
||||
type = NEWL;
|
||||
token[0] = '\n';
|
||||
}
|
||||
break;
|
||||
|
||||
case BADC:
|
||||
error("bad character 0%o",c);
|
||||
break;
|
||||
|
||||
}
|
||||
*p = '\0';
|
||||
return(type);
|
||||
}
|
||||
|
||||
/* getstr - get a quoted (single or double) character string*/
|
||||
/* Gets specified number of characters, handling escapes.*/
|
||||
getstr(str,nchars,endc) /* returns - none*/
|
||||
char *str; /* pointer to string buffer*/
|
||||
int nchars; /* max number of characters*/
|
||||
char endc; /* ending string character*/
|
||||
{
|
||||
register char *p;
|
||||
register int i;
|
||||
register int c;
|
||||
register int j;
|
||||
|
||||
p = str;
|
||||
*p++ = endc;
|
||||
for( i = nchars-2; (c=ngetch()) != endc; ) {
|
||||
if( c == EOF || c == '\n' ) {
|
||||
error("string cannot cross line");
|
||||
break;
|
||||
}
|
||||
if( --i > 0 ) /*BUG 1*/
|
||||
*p++ = c;
|
||||
else if( !i )
|
||||
error("string too long");
|
||||
if( c == '\\' ) {
|
||||
c = ngetch();
|
||||
if( --i > 0 ) /*BUG 1*/
|
||||
*p++ = c;
|
||||
else if( !i )
|
||||
error("string too long");
|
||||
}
|
||||
}
|
||||
*p++ = endc;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/* peekis - peeks at next character for specific character*/
|
||||
/* Gets next (possibly pushed back) character, if it matches*/
|
||||
/* the given character 1 is returned, otherwise the character*/
|
||||
/* is put back.*/
|
||||
peekis(tc) /* returns 1 if match, 0 otherwise*/
|
||||
int tc; /* test character*/
|
||||
{
|
||||
register int c;
|
||||
|
||||
if( (c=ngetch()) == tc )
|
||||
return(1);
|
||||
putback(c);
|
||||
return(0);
|
||||
}
|
||||
|
||||
doputc(ch,buffer)
|
||||
char ch;
|
||||
struct ibuf *buffer;
|
||||
{
|
||||
if (!Eflag)
|
||||
putc(ch,buffer);
|
||||
else
|
||||
putchar(ch);
|
||||
}
|
||||
@@ -0,0 +1,743 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "preproc.h"
|
||||
|
||||
#define CSTKSIZE 20
|
||||
#define FILESEP '/'
|
||||
#define NINCL 10
|
||||
|
||||
char *stdincl "/usr/include/"; /*standard include directory*/
|
||||
int clabel 1000;
|
||||
int nlabel 1001;
|
||||
int nincl;
|
||||
int literal; /*[vlh] 4.0 lnum and file name specified using #line */
|
||||
char *incl[10];
|
||||
char tmp[6];
|
||||
char ctype[];
|
||||
|
||||
struct builtin {
|
||||
char *b_name;
|
||||
int b_type;
|
||||
} btab[] {
|
||||
"define", DEFINE,
|
||||
"include", INCLUDE,
|
||||
"undef", UNDEF,
|
||||
"ifdef", IFDEF,
|
||||
"ifndef", IFNDEF,
|
||||
"else", ELSE,
|
||||
"endif", ENDIF,
|
||||
"if", IF,
|
||||
"line", LINE,
|
||||
0,
|
||||
};
|
||||
|
||||
char *getinclude();
|
||||
char cstack[CSTKSIZE];
|
||||
char *cstkptr, inclname[TOKSIZE];
|
||||
|
||||
/* domacro - do macro processing*/
|
||||
/* Does the macro pre-processing on the input file and leaves the*/
|
||||
/* result on the output file.*/
|
||||
domacro(infile,outfile,nd) /* returns 1 if ok, 0 otherwise*/
|
||||
char *infile; /* input file name*/
|
||||
char *outfile; /* output file name*/
|
||||
int nd; /* number of defines*/
|
||||
{
|
||||
register struct builtin *bp;
|
||||
register char *l;
|
||||
register struct symbol *sp;
|
||||
register int x, nonewline; /* handle empty new lines with SOH */
|
||||
register char *p;
|
||||
|
||||
filep = &filestack[0]; /* [vlh] 4.0 moved for error msgs */
|
||||
lineno = 1; /* [vlh] 4.0 moved for error msgs */
|
||||
if( fopen(infile,&inbuf,0) < 0 ) { /* 3rd arg for versados */
|
||||
error("can't open source file %s\n",infile);
|
||||
return(0);
|
||||
}
|
||||
if( fcreat(outfile,&outbuf,0) < 0 ) { /* 3rd arg for versados */
|
||||
error("can't creat %s\n",outfile);
|
||||
return(0);
|
||||
}
|
||||
for (sp= &symtab[0]; sp<= &symtab[HSIZE-1]; sp++) /*3.4*/
|
||||
sp->s_def = null; /* clear out symbol table */
|
||||
if( !defap ) {
|
||||
defp = defap = sbrk(1024);
|
||||
defmax = defcount = 1024;
|
||||
}
|
||||
else { /* multiple files, define area already exists */
|
||||
defcount = defmax;
|
||||
for (x = defmax, defp = defap; x>0; x--)
|
||||
*defp++ = 0;
|
||||
defp = defap;
|
||||
}
|
||||
nonewline = defused = mfail = 0;
|
||||
pbp = &pbbuf[0];
|
||||
cstkptr = &cstack[0];
|
||||
install("Newlabel",NEWLABEL);
|
||||
install("Label",LABEL);
|
||||
while( --nd >= 0 )
|
||||
dinstall(defs[nd].ptr,defs[nd].value);
|
||||
while( getline(infile) ) {
|
||||
l = line;
|
||||
if( filep == &filestack[0] && pbp == &pbbuf[0] )
|
||||
lineno++;
|
||||
else if ( !pflag && !asflag && !literal ) { /*[vlh] include file*/
|
||||
if (*l) {
|
||||
putid((filep-1)->ifile,(filep-1)->lineno); /* 4.0 */
|
||||
if (!(*l)) doputc(' ',&outbuf);
|
||||
}
|
||||
else nonewline++;
|
||||
(filep-1)->lineno++;
|
||||
}
|
||||
while( *l )
|
||||
doputc(*l++,&outbuf);
|
||||
if (!nonewline) doputc('\n',&outbuf);
|
||||
else nonewline = 0;
|
||||
literal = 0;
|
||||
}
|
||||
if( cstkptr != &cstack[0] )
|
||||
error("unmatched conditional");
|
||||
if( defused > defmax )
|
||||
defmax = defused;
|
||||
v6flush(&outbuf);
|
||||
close(outbuf.fd);
|
||||
close(inbuf.fd);
|
||||
return(mfail==0);
|
||||
}
|
||||
|
||||
putid(fname,lnum) /* [vlh] 4.0 SOH line header */
|
||||
char *fname;
|
||||
int lnum;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if (asflag || pflag)
|
||||
return;
|
||||
doputc(SOH,&outbuf);
|
||||
for (p = fname; *p; p++)
|
||||
doputc(*p,&outbuf);
|
||||
doputc(SOH,&outbuf);
|
||||
itoa(lnum,tmp,5);
|
||||
for (p = tmp; *p==' '; ) p++;
|
||||
for ( ; *p; p++)
|
||||
doputc(*p,&outbuf);
|
||||
doputc(' ',&outbuf);
|
||||
}
|
||||
|
||||
install(name,def)
|
||||
char *name;
|
||||
int def;
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
sp = getsp(name);
|
||||
symcopy(name,sp->s_name);
|
||||
sp->s_def = defp;
|
||||
putd(def);
|
||||
putd('\0');
|
||||
}
|
||||
|
||||
dinstall(name,def) /* returns - none*/
|
||||
char *name; /* macro name*/
|
||||
char *def; /* pointer to definition*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
sp = getsp(name);
|
||||
symcopy(name,sp->s_name);
|
||||
sp->s_def = defp;
|
||||
putd(NOARGS);
|
||||
if (def) /* [vlh] character strings... */
|
||||
while(*def) putd(*def++);
|
||||
else putd('1'); /* [vlh] default define value */
|
||||
putd('\0');
|
||||
}
|
||||
|
||||
/* kwlook - look up the macro built-in names*/
|
||||
/* Searches thru the built-in table for the name.*/
|
||||
kwlook(name) /* returns keyword index or 0*/
|
||||
char *name; /* keyword name to lookup*/
|
||||
{
|
||||
register struct builtin *bp;
|
||||
|
||||
for( bp = &btab[0]; bp->b_name; bp++ )
|
||||
if( strcmp(bp->b_name,name) == 0 )
|
||||
return(bp->b_type);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* getline - get input line handling macro statements
|
||||
* Checks for a preprocessor statement on the line and if there
|
||||
* is one there, it processes it. Note that most of the work is
|
||||
* in determining whether we need to skip the current line or not.
|
||||
* This is all handled with the condition stack and the skip variable.
|
||||
* The skip variable is non-zero if any condition on the condition
|
||||
* stack is SKIP.
|
||||
*/
|
||||
getline(infile) /* returns 0 for EOF, 1 otherwise*/
|
||||
char *infile; /* [vlh] for quoted include files */
|
||||
{
|
||||
char token[TOKSIZE];
|
||||
register int type, i;
|
||||
register char *p;
|
||||
|
||||
initl();
|
||||
if( (type=gettok(token)) == EOF )
|
||||
return(0);
|
||||
if( type == POUND ) {
|
||||
if( (type=getntok(token)) == NEWL )
|
||||
return(1);
|
||||
switch( kwlook(token) ) {
|
||||
|
||||
case IFDEF:
|
||||
if( getntok(token) == ALPHA && lookup(token) )
|
||||
push(NOSKIP);
|
||||
else {
|
||||
push(SKIP);
|
||||
skip++;
|
||||
}
|
||||
break;
|
||||
|
||||
case IFNDEF:
|
||||
if( getntok(token) == ALPHA && lookup(token) ) {
|
||||
push(SKIP);
|
||||
skip++;
|
||||
}
|
||||
else
|
||||
push(NOSKIP);
|
||||
break;
|
||||
|
||||
case ENDIF:
|
||||
if( (i=pop()) == SKIP )
|
||||
skip--;
|
||||
else if( i != NOSKIP )
|
||||
error("invalid #endif");
|
||||
break;
|
||||
|
||||
case ELSE:
|
||||
if( (i=pop()) == SKIP ) {
|
||||
skip--;
|
||||
push(NOSKIP);
|
||||
}
|
||||
else if( i == NOSKIP ) {
|
||||
skip++;
|
||||
push(SKIP);
|
||||
}
|
||||
else
|
||||
error("invalid #else");
|
||||
break;
|
||||
|
||||
case DEFINE:
|
||||
if( !skip ) /*if in skip, don't do define*/
|
||||
dodefine();
|
||||
break;
|
||||
|
||||
case UNDEF:
|
||||
if( !skip ) { /*if in skip, don't undef*/
|
||||
if( (type=getntok(token)) == ALPHA )
|
||||
undefine(token);
|
||||
}
|
||||
break;
|
||||
|
||||
case INCLUDE:
|
||||
if( !skip ) /*if in skip, don't do include*/
|
||||
doinclude(infile);
|
||||
break;
|
||||
|
||||
case IF:
|
||||
if( cexpr() ) /*evaluate constant expression*/
|
||||
push(NOSKIP); /*non-zero, so don't skip*/
|
||||
else {
|
||||
push(SKIP);
|
||||
skip++;
|
||||
}
|
||||
break;
|
||||
|
||||
case LINE: /* [vlh] 4.0 */
|
||||
doline(infile);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid preprocessor command");
|
||||
break;
|
||||
}
|
||||
eatup();
|
||||
}
|
||||
else if( type == NEWL )
|
||||
;
|
||||
else if( skip ) {
|
||||
eatup();
|
||||
}
|
||||
else {
|
||||
for( ; type != NEWL && type != EOF ; type = gettok(token) ) {
|
||||
if( type == ALPHA && (p=lookup(token)) )
|
||||
expand(p);
|
||||
else {
|
||||
for( p = token; *p ; )
|
||||
putl(*p++);
|
||||
}
|
||||
}
|
||||
}
|
||||
putl('\0');
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* eatup - eat up the rest of the input line until a newline or EOF*/
|
||||
/* Does gettok calls.*/
|
||||
eatup() /* returns - none*/
|
||||
{
|
||||
register int type;
|
||||
char etoken[TOKSIZE];
|
||||
|
||||
while( (type=gettok(etoken)) != NEWL && type != EOF )
|
||||
;
|
||||
}
|
||||
|
||||
/* putl - put a character to the current output line*/
|
||||
/* Checks for line overflow.*/
|
||||
putl(c) /* returns - none*/
|
||||
int c; /* character to put on line*/
|
||||
{
|
||||
if( linep < &line[LINESIZE] )
|
||||
*linep++ = c;
|
||||
else if ( !loverflow ) {
|
||||
loverflow++;
|
||||
error("line overflow");
|
||||
}
|
||||
}
|
||||
|
||||
/* initl - initialize current line*/
|
||||
/* Sets the line pointer and the line overflow flag.*/
|
||||
initl() /* returns - none*/
|
||||
{
|
||||
*(linep= &line[0]) = '\0';
|
||||
loverflow = 0;
|
||||
}
|
||||
|
||||
/* putd - put a character to the define buffer*/
|
||||
/* Does dynamic allocation for define buffer*/
|
||||
putd(c) /* returns - none*/
|
||||
int c; /* character to put in buffer*/
|
||||
{
|
||||
if( !defcount ) {
|
||||
if( sbrk(DEFSIZE) == -1 ) {
|
||||
error("define table overflow");
|
||||
cexit();
|
||||
}
|
||||
defcount = DEFSIZE;
|
||||
}
|
||||
defused++;
|
||||
defcount--;
|
||||
*defp++ = c;
|
||||
}
|
||||
|
||||
/* undefine - does undef command*/
|
||||
/* Sets the symbols definition to the null pointer*/
|
||||
undefine(name) /* returns - none*/
|
||||
char *name; /* pointer to name to undef*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
sp = getsp(name);
|
||||
if( sp->s_def )
|
||||
sp->s_def = null;
|
||||
}
|
||||
|
||||
/* dodefine - do #define processing*/
|
||||
/* Checks the define name, collects formal arguements and saves*/
|
||||
/* macro definition, substituting for formal arguments as it goes.*/
|
||||
dodefine() /* returns - none*/
|
||||
{
|
||||
char token[TOKSIZE], *args[MAXARGS], argbuf[ARGBSIZE];
|
||||
register char *abp, *p;
|
||||
register int type, nargs, i;
|
||||
register struct symbol *sp;
|
||||
|
||||
if( (type=getntok(token)) != ALPHA ) {
|
||||
error("bad define name: %s",token);
|
||||
return;
|
||||
}
|
||||
sp = getsp(token);
|
||||
symcopy(token,sp->s_name);
|
||||
sp->s_def = defp;
|
||||
nargs = 0;
|
||||
abp = argbuf;
|
||||
if( (type=gettok(token)) == LPAREN ) {
|
||||
for( ; (type=getfarg(token)) != RPAREN; nargs++ ) {
|
||||
if( nargs >= MAXARGS ) {
|
||||
error("too many arguments");
|
||||
break;
|
||||
}
|
||||
args[nargs] = abp;
|
||||
for( p = token; *abp++ = *p++; ) {
|
||||
if( abp >= &argbuf[ARGBSIZE] ) {
|
||||
error("argument buffer overflow");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
putd(nargs);
|
||||
}
|
||||
else {
|
||||
pbtok(token);
|
||||
putd(NOARGS);
|
||||
}
|
||||
type = getntok(token); /*get next non-white token*/
|
||||
for( ; type != NEWL && type != EOF; type = gettok(token) ) {
|
||||
if( type == ALPHA ) {
|
||||
for( i = 0; i < nargs; i++ ) {
|
||||
if( strcmp(args[i],token) == 0 )
|
||||
break;
|
||||
}
|
||||
if( i < nargs ) { /*sub ARG marker for formal arg*/
|
||||
putd(i+1);
|
||||
putd(ARG);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if( type == BSLASH ) {
|
||||
if( (i=ngetch()) == '\n' ) { /*multi-line macro?*/
|
||||
if( filep == &filestack[0] && pbp == &pbbuf[0] ) {
|
||||
lineno++;
|
||||
doputc('\n',&outbuf);
|
||||
}
|
||||
}
|
||||
putd(i);
|
||||
continue;
|
||||
}
|
||||
for( p = token; *p ; )
|
||||
putd(*p++);
|
||||
}
|
||||
pbtok(token);
|
||||
putd('\0');
|
||||
}
|
||||
|
||||
/* expand - expands the macro definition*/
|
||||
/* Checks for define recursion and #define x x problems, collects*/
|
||||
/* the actual arguments using getaarg, and then expands the macro*/
|
||||
/* by pushing it onto the push back buffer, substituting arguments*/
|
||||
/* as it goes.*/
|
||||
expand(sp) /* returns - none*/
|
||||
struct symbol *sp; /* pointer to macro to expand*/
|
||||
{
|
||||
char argbuf[ARGBSIZE], *args[MAXARGS], token[TOKSIZE];
|
||||
register char *p, *abp, *mdef;
|
||||
register int i, j, nargs, type;
|
||||
|
||||
if( pbflag++ > 100 ) {
|
||||
error("define recursion");
|
||||
return;
|
||||
}
|
||||
if( strcmp(sp->s_name,mdef=sp->s_def) == 0 ) { /*handle #define x x*/
|
||||
while( *mdef )
|
||||
putl(*mdef++);
|
||||
return;
|
||||
}
|
||||
nargs = 0;
|
||||
if( *mdef == NOARGS ) /*suppress grabbing of args*/
|
||||
;
|
||||
else if( gettok(token) != LPAREN )
|
||||
pbtok(token);
|
||||
else {
|
||||
abp = &argbuf[0];
|
||||
while( (type=getaarg(token)) != EOF ) {
|
||||
if( nargs >= MAXARGS ) {
|
||||
error("too many arguments");
|
||||
return;
|
||||
}
|
||||
args[nargs++] = abp;
|
||||
for( p = token; *abp++ = *p++; ) {
|
||||
if( abp >= &argbuf[ARGBSIZE] ) {
|
||||
error("argument buffer overflow");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( type == RPAREN )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( *mdef == NEWLABEL ) {
|
||||
clabel = nlabel;
|
||||
if( !nargs )
|
||||
nlabel++;
|
||||
else
|
||||
nlabel =+ atoi(args[0]);
|
||||
}
|
||||
else if( *mdef == LABEL ) {
|
||||
if( !nargs )
|
||||
i = clabel;
|
||||
else
|
||||
i = clabel + atoi(args[0]);
|
||||
pbnum(i);
|
||||
pbtok("_L");
|
||||
}
|
||||
else {
|
||||
mdef++; /*skip no. of args*/
|
||||
for( p = mdef + strlen(mdef) - 1; p >= mdef; p-- ) {
|
||||
if( *p == ARG ) {
|
||||
if( (j= *--p) <= nargs )
|
||||
pbtok(args[j-1]);
|
||||
}
|
||||
else
|
||||
putback(*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* getfarg - get macro formal parameters*/
|
||||
/* Skips blanks and handles "," and ")".*/
|
||||
getfarg(token) /* returns token type*/
|
||||
char *token; /* token returned*/
|
||||
{
|
||||
register int type;
|
||||
|
||||
if( (type=getntok(token)) == RPAREN || type == ALPHA )
|
||||
return(type);
|
||||
if( type != COMMA || (type=getntok(token)) != ALPHA )
|
||||
error("bad argument:%s",token);
|
||||
return(type);
|
||||
}
|
||||
|
||||
/* getntok - get next token, suppressing white space*/
|
||||
/* Merely gettok's until non-white space is there*/
|
||||
getntok(token) /* returns token type*/
|
||||
char *token; /* token returned*/
|
||||
{
|
||||
register int type;
|
||||
|
||||
while( (type=gettok(token)) == WHITE )
|
||||
;
|
||||
return(type);
|
||||
}
|
||||
|
||||
/* getaarg - get macro actual argument*/
|
||||
/* This handles the collecting of the macro's call arguments.*/
|
||||
/* Note that you may have parenthesis as part of the macro argument,*/
|
||||
/* hence you need to keep track of them.*/
|
||||
getaarg(argp) /* returns token type*/
|
||||
char *argp; /* argument returned*/
|
||||
{
|
||||
int type, plevel, i;
|
||||
register char *p, *ap;
|
||||
char token[TOKSIZE];
|
||||
|
||||
ap = argp;
|
||||
*ap = '\0';
|
||||
plevel = 0;
|
||||
i = TOKSIZE;
|
||||
while( ((type=gettok(token)) != COMMA && type != RPAREN) || plevel ) {
|
||||
for( p = token; *ap = *p++; ap++ )
|
||||
if( --i <= 0 ) {
|
||||
error("macro argument too long");
|
||||
return(EOF);
|
||||
}
|
||||
if( type == LPAREN )
|
||||
plevel++;
|
||||
else if( type == RPAREN )
|
||||
plevel--;
|
||||
else if( type == EOF ) {
|
||||
error("unexpected EOF");
|
||||
cexit();
|
||||
}
|
||||
}
|
||||
if( ap == argp )
|
||||
type = EOF;
|
||||
return(type);
|
||||
}
|
||||
|
||||
/* push - push a #ifdef condition value on condition stack*/
|
||||
/* Checks for stack overflow.*/
|
||||
push(val) /* returns - none*/
|
||||
int val; /* value to push*/
|
||||
{
|
||||
if( cstkptr >= &cstack[CSTKSIZE] ) {
|
||||
error("condition stack overflow");
|
||||
cexit();
|
||||
}
|
||||
*cstkptr++ = val;
|
||||
}
|
||||
|
||||
/* pop - pop the #ifdef, etc. condition stack*/
|
||||
/* Checks for stack undeflow.*/
|
||||
pop() /* returns - top of condition stack*/
|
||||
{
|
||||
if( cstkptr <= &cstack[0] )
|
||||
return(-1);
|
||||
return( *--cstkptr );
|
||||
}
|
||||
|
||||
/* doinclude - handle #include command*/
|
||||
/* Checks for file name or library file name and pushes file on*/
|
||||
/* include file stack.*/
|
||||
doinclude(infile) /* returns - none*/
|
||||
char *infile; /* [vlh] for quoted include files */
|
||||
{
|
||||
register int type, fd;
|
||||
char token[TOKSIZE], fname[TOKSIZE];
|
||||
register char *p, *q, c, *ptr1, *ptr2;
|
||||
int i, j;
|
||||
|
||||
p = fname;
|
||||
if( (type=getntok(token)) == SQUOTE || type == DQUOTE ) {
|
||||
for( c = token[0], q = &token[1]; *q != c; )
|
||||
*p++ = *q++;
|
||||
*p = '\0';
|
||||
p = getinclude(fname,infile);
|
||||
}
|
||||
else if( type != LESS ) {
|
||||
error("bad include file");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
while( (type=gettok(token))!=GREAT && type!=NEWL && type!=EOF )
|
||||
for( q = token; *p = *q++; p++ )
|
||||
;
|
||||
if( type != GREAT ) {
|
||||
error("bad include file name");
|
||||
pbtok(token);
|
||||
return;
|
||||
}
|
||||
p = getinclude(fname,0L);
|
||||
}
|
||||
eatup(); /*need here...*/
|
||||
if( filep >= &filestack[FSTACK] )
|
||||
error("includes nested too deeply");
|
||||
else {
|
||||
#ifdef NONEST
|
||||
if (filep != &filestack[0]) { /* in main file ?? */
|
||||
error("can not nest include files");
|
||||
putback('\n');
|
||||
return;
|
||||
}
|
||||
holdbuf.fd = inbuf.fd;
|
||||
holdbuf.nc = inbuf.nc;
|
||||
holdbuf.bp = inbuf.bp;
|
||||
ptr1 = &holdbuf.buffer[0];
|
||||
ptr2 = &inbuf.buffer[0];
|
||||
for(i=0; i<BUFSIZE; i++)
|
||||
*ptr1++ = *ptr2++;
|
||||
#else
|
||||
fd = inbuf.fd;
|
||||
seek(fd,-inbuf.nc,1); /*back up file ptr*/
|
||||
#endif
|
||||
inbuf.nc = 0;
|
||||
if( fopen(p,&inbuf,0) < 0 ) /* 3rd arg for versados */
|
||||
error("can't open include file %s\n",p);
|
||||
else {
|
||||
filep->ifd = fd;
|
||||
filep->lineno = 0; /* [vlh] */
|
||||
doifile(p);
|
||||
filep++;
|
||||
}
|
||||
}
|
||||
putback('\n'); /*for eatup in domacro*/
|
||||
}
|
||||
|
||||
doifile(p) /* [vlh] */
|
||||
char *p;
|
||||
{
|
||||
register char *iptr;
|
||||
register int ndx;
|
||||
|
||||
while ((ndx = index(p,FILESEP)) >= 0) p =+ ndx+1;
|
||||
for( iptr = filep->ifile; *p; ) *iptr++ = *p++;
|
||||
*iptr = 0;
|
||||
}
|
||||
|
||||
/* getinclude - get include file full pathname */
|
||||
char *
|
||||
getinclude(fname,parent) /* [vlh] */
|
||||
char *fname;
|
||||
char *parent; /* search parent-file home directory ? */
|
||||
{
|
||||
register char *q, *t;
|
||||
register int i, fd, ndx;
|
||||
|
||||
if (parent) { /* include filename surrounded by quotes */
|
||||
q = (filep == &filestack[0]) ? parent : (filep-1)->ifile;
|
||||
t = &inclname;
|
||||
while ((ndx = index(q,FILESEP)) >= 0) {
|
||||
ndx++;
|
||||
while (ndx--) *t++ = *q++;
|
||||
}
|
||||
for (q=fname; *t++ = *q++; );
|
||||
*t = 0;
|
||||
if ((fd = open(inclname,0)) >= 0) { /* found it */
|
||||
close(fd);
|
||||
return(&inclname);
|
||||
}
|
||||
}
|
||||
for (i=0; i<nincl; i++) {
|
||||
for(t=inclname, q=incl[i]; *t++ = *q++; ) ;
|
||||
for(q=fname, --t; *t++ = *q++; ) ;
|
||||
*t = 0;
|
||||
if ((fd = open(inclname,0)) >= 0) {
|
||||
close(fd);
|
||||
return(&inclname);
|
||||
}
|
||||
}
|
||||
for(t=inclname, q=stdincl; *t++ = *q++; ) ;
|
||||
for(q=fname, --t; *t++ = *q++; ) ;
|
||||
*t = 0;
|
||||
return(&inclname);
|
||||
}
|
||||
|
||||
doline(infile) /* [vlh] 4.0 : returns - none */
|
||||
char *infile;
|
||||
{
|
||||
register char *ptr;
|
||||
char token[TOKSIZE];
|
||||
register int ch, lnum, type;
|
||||
|
||||
while ((type = gettok(token)) == WHITE); /* skip white space */
|
||||
if (type != DIGIT) {
|
||||
error("invalid #line args");
|
||||
return;
|
||||
}
|
||||
lnum = atoi(token);
|
||||
do {
|
||||
ch = ngetch();
|
||||
} while (ctype[ch] == WHITE);
|
||||
if (ctype[ch] != NEWL && ctype[ch] != EOF) {
|
||||
ptr = &token;
|
||||
do {
|
||||
*ptr++ = ch;
|
||||
ch = ngetch();
|
||||
} while (ctype[ch]!=NEWL && ctype[ch]!=EOF && ctype[ch]!=WHITE);
|
||||
*ptr = 0;
|
||||
putid(token,lnum);
|
||||
}
|
||||
else {
|
||||
if (filep == &filestack[0] && pbp == &pbbuf[0])
|
||||
putid(infile,lnum);
|
||||
else
|
||||
putid((filep-1)->ifile,lnum);
|
||||
}
|
||||
literal = 1;
|
||||
for( ; ctype[ch]!=NEWL && ctype[ch]!=EOF; )
|
||||
ch = ngetch();
|
||||
if (ctype[ch] != EOF)
|
||||
while ( ctype[ ch = ngetch() ] != NEWL && ctype[ch] != EOF)
|
||||
putl(ch);
|
||||
putback('\n');
|
||||
}
|
||||
|
||||
pbnum(num) /* returns - none*/
|
||||
int num;
|
||||
{
|
||||
register int digit;
|
||||
|
||||
do {
|
||||
digit = num % 10;
|
||||
num =/ 10;
|
||||
putback(digit+'0');
|
||||
} while( num > 0 );
|
||||
}
|
||||
|
||||
659
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/c68/main.c
Normal file
659
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/al40/c68/main.c
Normal file
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
char *version "@(#) c68 preprocessor 4.0 - Mar 18, 1983";
|
||||
#include "preproc.h"
|
||||
|
||||
#define NARGS 64
|
||||
#define NINCL 10
|
||||
#define ARGSIZE 1024
|
||||
#define ICODE 0
|
||||
#define STRINGS 1
|
||||
#define MTEMP 2
|
||||
#define ASTEMP 3
|
||||
#define NTEMPS 4
|
||||
|
||||
char *fargs[NARGS+1];
|
||||
char **fargp;
|
||||
char argbuf[ARGSIZE];
|
||||
char *cfiles[NARGS+1];
|
||||
char *loadargs[NARGS+1];
|
||||
char *fns[NTEMPS];
|
||||
char *tfns[NTEMPS];
|
||||
int ndefs;
|
||||
char *incl[NINCL];
|
||||
int nincl;
|
||||
char *argp &argbuf[0];
|
||||
int cflag;
|
||||
int nflag;
|
||||
int fflag; /* [vlh] 3.4 fast floating point format and library */
|
||||
int eflag; /* [vlh] 3.4 ieee floating point format and library */
|
||||
int lflag;
|
||||
int oflag;
|
||||
int pflag;
|
||||
int Eflag; /* [vlh] 4.0 flag, Preprocessor only to stdout */
|
||||
int sflag;
|
||||
int wflag; /* [vlh] turn on warning messages */
|
||||
int verbose; /* [vlh] 3.4 force printing of file being processed */
|
||||
int xflag;
|
||||
int v6flag; /* [vlh] 3.4 compile for version 6 */
|
||||
int v7flag; /* [vlh] 3.4 */
|
||||
int s3flag; /* [vlh] 3.4 */
|
||||
int s5flag; /* [vlh] 3.4 */
|
||||
int optimize; /* [vlh] 3.4 recognize optimization flag '-O' */
|
||||
int status;
|
||||
int oneflag;
|
||||
int errno;
|
||||
char *cptrone 1;
|
||||
|
||||
char *parser "/lib/c068";
|
||||
char *cgen "/lib/c168";
|
||||
char *onepass "/lib/c0168";
|
||||
char *pref "/lib/c680.o";
|
||||
char *loader "/bin/lo68";
|
||||
char *asmprog "/bin/as68";
|
||||
|
||||
char *deflib "/lib/lib7.a";
|
||||
char *deflibfp "/lib/libF.a"; /* [vlh] 3.4 */
|
||||
char *deflibep "/lib/libE.a"; /* [vlh] 3.4 */
|
||||
char *v6lib "/lib/libv6.a"; /* [vlh] 3.4 */
|
||||
char *v7lib "/lib/libv7.a"; /* [vlh] 3.4 */
|
||||
char *s3lib "/lib/libs3.a"; /* [vlh] 3.4 */
|
||||
char *s5lib "/lib/libs5.a"; /* [vlh] 3.4 */
|
||||
|
||||
char *v6incl "/usr/include/v6/\0"; /* [vlh] 3.4 */
|
||||
char *v7incl "/usr/include/v7/\0"; /* [vlh] 3.4 */
|
||||
char *s3incl "/usr/include/sys3/\0"; /* [vlh] 3.4 */
|
||||
char *s5incl "/usr/include/sys5/\0"; /* [vlh] 3.4 */
|
||||
|
||||
char *ldflg "-r";
|
||||
int mmuflag; /*[vlh]replace nommu #ifdef'd var*/
|
||||
|
||||
|
||||
/* cexit - exit from C compiler driver*/
|
||||
/* This deletes any existing temps and exits with the error status.*/
|
||||
cexit() /* returns - none*/
|
||||
{
|
||||
register int i;
|
||||
|
||||
if( !pflag )
|
||||
for( i = 0; i < NTEMPS; i++ )
|
||||
if( fns[i] )
|
||||
unlink(fns[i]);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* main - main routine for c68 Compiler system
|
||||
* Handles the C68 arguments. For each C file given, the macro
|
||||
* pre-processor is called, then the parser, code generator and
|
||||
* assember are fexec'd. The loader arguments are collected and
|
||||
* the loader is fexec'd.
|
||||
*/
|
||||
main(argc,argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register char *arg, **p, **cfilep, **loadp, *sp;
|
||||
register int nloadfiles, c, i, j, x;
|
||||
|
||||
#ifdef NOFORKS
|
||||
if (argc != 3) {
|
||||
error("usage: c68 inputfile outputfile");
|
||||
exit(-1);
|
||||
}
|
||||
pflag++;
|
||||
domacro(argv[1],argv[2],ndefs);
|
||||
#else
|
||||
cfilep = &cfiles[0];
|
||||
loadp = &loadargs[0];
|
||||
nloadfiles = 0;
|
||||
sysinfo(0,&mmuflag); /*[vlh] mmu system ??*/
|
||||
if (!mmuflag) { /*[vlh] default args*/
|
||||
*loadp = ldflg;
|
||||
lflag++;
|
||||
}
|
||||
for( p = argv, j = argc; --j > 0; ) { /*process arguments*/
|
||||
if( *(arg= *++p) == '-' ) {
|
||||
arg++;
|
||||
for( i = 0; c = *arg++; i++ ) {
|
||||
switch( c ) {
|
||||
|
||||
case 'c':
|
||||
cflag++;
|
||||
continue;
|
||||
|
||||
case '1':
|
||||
oneflag++;
|
||||
parser = onepass;
|
||||
continue;
|
||||
|
||||
case 'D':
|
||||
defs[ndefs].ptr = arg;
|
||||
if ((x=index(arg,'=')) != -1) {
|
||||
defs[ndefs++].value = (arg+x+1);
|
||||
arg[x] = 0; /* get rid of value */
|
||||
}
|
||||
else defs[ndefs++].value = 0;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
incl[nincl++] = arg;
|
||||
i++;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
nflag++;
|
||||
continue;
|
||||
|
||||
case 'e': /* [vlh] 3.4 */
|
||||
eflag++;
|
||||
if (fflag)
|
||||
ferror("incompatible flags : '-f' and '-e'");
|
||||
continue;
|
||||
|
||||
case 'f': /* [vlh] 3.4 */
|
||||
fflag++;
|
||||
if (eflag)
|
||||
ferror("incompatible flags : '-f' and '-e'");
|
||||
continue;
|
||||
|
||||
case 'L':
|
||||
lflag++;
|
||||
continue;
|
||||
|
||||
case 'o':
|
||||
if( --j <= 0 )
|
||||
ferror("bad -o option");
|
||||
*loadp++ = *p++;
|
||||
if( strend(*p,".c") || strend(*p,".s") ||
|
||||
strend(*p,".o") ) {
|
||||
sp = makecopy(*p);
|
||||
sp[strlen(sp)-2] = '\0';
|
||||
*loadp++ = sp;
|
||||
*loadp++ = setend(*p,'o');
|
||||
nloadfiles++;
|
||||
if( !strend(*p,".o") )
|
||||
*cfilep++ = *p;
|
||||
}
|
||||
else
|
||||
*loadp++ = *p;
|
||||
continue;
|
||||
|
||||
case 'E': /* [vlh] 4.0 Preprocessor to stdout */
|
||||
Eflag++;
|
||||
case 'P':
|
||||
pflag++;
|
||||
cflag++;
|
||||
continue;
|
||||
|
||||
case 'S':
|
||||
sflag++;
|
||||
cflag++;
|
||||
nflag++;
|
||||
continue;
|
||||
|
||||
case 't':
|
||||
if( (c= *arg++) == '0' )
|
||||
parser = "/usr/c68/c068";
|
||||
else if( c == '1' )
|
||||
cgen = "/usr/c68/c168";
|
||||
else if( c == '\0' )
|
||||
arg--;
|
||||
continue;
|
||||
|
||||
case 'w': /* [vlh] */
|
||||
wflag++;
|
||||
continue;
|
||||
|
||||
case 'O': /* [vlh] 3.4 */
|
||||
optimize++;
|
||||
continue;
|
||||
|
||||
case 'v': /* [vlh] 3.4 print file name */
|
||||
verbose++;
|
||||
continue;
|
||||
|
||||
case '6': /* [vlh] 3.4 v6 compatibility */
|
||||
v6flag++;
|
||||
incl[nincl++] = v6incl;
|
||||
continue;
|
||||
|
||||
case '7': /* [vlh] 3.4 v7 compatibility */
|
||||
v7flag++;
|
||||
incl[nincl++] = v7incl;
|
||||
continue;
|
||||
|
||||
case '3': /* [vlh] 3.4 s3 compatibility */
|
||||
s3flag++;
|
||||
incl[nincl++] = s3incl;
|
||||
continue;
|
||||
|
||||
case '5': /* [vlh] 3.4 s5 compatiblity */
|
||||
s5flag++;
|
||||
incl[nincl++] = s5incl;
|
||||
continue;
|
||||
|
||||
default:
|
||||
if( loadp >= &loadargs[NARGS] )
|
||||
ferror("too many loader args");
|
||||
*loadp++ = *p;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( i )
|
||||
continue;
|
||||
}
|
||||
if( strend(arg,".c") || strend(arg,".s") ) {
|
||||
|
||||
/*C or Assembler files to process*/
|
||||
|
||||
if( cfilep >= &cfiles[NARGS] )
|
||||
ferror("too many files");
|
||||
*cfilep++ = arg;
|
||||
nloadfiles++;
|
||||
if( !chkdup(arg) ) {
|
||||
if( loadp >= &loadargs[NARGS] )
|
||||
ferror("too many loader args");
|
||||
*loadp++ = setend(arg,'o');
|
||||
}
|
||||
}
|
||||
else if( !chkdup(arg) ) { /*check for loader args*/
|
||||
if( loadp >= &loadargs[NARGS] )
|
||||
ferror("too many loader args");
|
||||
*loadp++ = arg;
|
||||
if( strend(arg,".o") )
|
||||
nloadfiles++;
|
||||
}
|
||||
}
|
||||
if( cfilep != &cfiles[0] ) { /*had a C file?*/
|
||||
if( signal(2,cexit) == cptrone ) /*catch rubouts, check ignore*/
|
||||
signal(2,cptrone);
|
||||
for( i = 0; i < NTEMPS; i++ ) /*allocate temps*/
|
||||
fns[i] = maketemp(i);
|
||||
for( p = &cfiles[0]; arg = *p++; ) { /*handle each C file*/
|
||||
for( i = 0; i < NTEMPS; i++ )
|
||||
tfns[i] = fns[i];
|
||||
if( cfilep != &cfiles[1] || verbose )
|
||||
printf("%s:\n",arg);
|
||||
/*
|
||||
* the following sets things up for the parser, the macro pre-processor
|
||||
* is called (not forked), then the parser is fexec'd.
|
||||
*/
|
||||
asflag = strend(arg,".s");
|
||||
if( pflag || asflag )
|
||||
tfns[MTEMP] = setend(arg,'i');
|
||||
if( domacro(arg,tfns[MTEMP],ndefs) == 0 || pflag ) {
|
||||
cflag++;
|
||||
status =+ mfail; /* preprocessor failure */
|
||||
continue;
|
||||
}
|
||||
if( !asflag ) {
|
||||
tfns[ASTEMP] = setend(arg,'s');
|
||||
initfargs();
|
||||
addfarg(parser);
|
||||
addfarg(tfns[MTEMP]);
|
||||
if( oneflag ) {
|
||||
addfarg(tfns[ASTEMP]);
|
||||
addfarg(tfns[STRINGS]);
|
||||
if( lflag )
|
||||
addfarg("-L");
|
||||
if( sflag || nflag )
|
||||
addfarg("-D");
|
||||
addfarg("-1");
|
||||
}
|
||||
else {
|
||||
addfarg(tfns[ICODE]);
|
||||
addfarg(tfns[STRINGS]);
|
||||
if ( fflag ) /* [vlh] 3.4 */
|
||||
addfarg("-f");
|
||||
else if ( eflag ) /* [vlh] 3.4 */
|
||||
addfarg("-e");
|
||||
if ( wflag )
|
||||
addfarg("-w");
|
||||
}
|
||||
endfargs();
|
||||
if( fexec(parser,fargs) ) {
|
||||
status++;
|
||||
cflag++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*this sets things up for the code generator*/
|
||||
|
||||
if( !oneflag ) {
|
||||
initfargs();
|
||||
addfarg(cgen);
|
||||
addfarg(tfns[ICODE]);
|
||||
addfarg(tfns[ASTEMP]);
|
||||
if( !sflag )
|
||||
fns[ASTEMP] = tfns[ASTEMP];
|
||||
if( lflag )
|
||||
addfarg("-L");
|
||||
if( nflag || sflag )
|
||||
addfarg("-D");
|
||||
endfargs();
|
||||
if( fexec(cgen,fargs) ) {
|
||||
status++;
|
||||
cflag++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( sflag )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
tfns[ASTEMP] = tfns[MTEMP];
|
||||
|
||||
/*this sets things up for the assembler*/
|
||||
|
||||
initfargs();
|
||||
addfarg(asmprog);
|
||||
if( !asflag )
|
||||
addfarg("-u");
|
||||
if( lflag )
|
||||
addfarg("-L");
|
||||
addfarg(tfns[ASTEMP]);
|
||||
endfargs();
|
||||
if( fexec(asmprog,fargs) ) {
|
||||
cflag++;
|
||||
status++;
|
||||
}
|
||||
unlink(tfns[ASTEMP]);
|
||||
}
|
||||
}
|
||||
if( !cflag && (loadp != &loadargs[0] || cfilep != &cfiles[0] )) {
|
||||
/*
|
||||
* set things up for the loader, this means that we need to add the
|
||||
* C preface at the beginning of the program which has the jsr to
|
||||
* main and then exits after return from main.
|
||||
*/
|
||||
initfargs();
|
||||
addfarg(loader);
|
||||
addfarg("-X");
|
||||
i = 1;
|
||||
for( p = loadargs; *p ; p++ ) {
|
||||
if( i && strend(*p,".o") ) { //insert pref before 1st .o
|
||||
i = 0;
|
||||
addfarg(pref);
|
||||
}
|
||||
addfarg(*p);
|
||||
}
|
||||
if (fflag) /* [vlh] 3.4 */
|
||||
addfarg(deflibfp);
|
||||
if (eflag) /* [vlh] 3.4 */
|
||||
addfarg(deflibep);
|
||||
if (v6flag) /* [vlh] 3.4 */
|
||||
addfarg(v6lib);
|
||||
if (v7flag) /* [vlh] 3.4 */
|
||||
addfarg(v7lib);
|
||||
if (s3flag) /* [vlh] 3.4 */
|
||||
addfarg(s3lib);
|
||||
if (s5flag) /* [vlh] 3.4 */
|
||||
addfarg(s5lib);
|
||||
addfarg(deflib);
|
||||
endfargs();
|
||||
status =| fexec(loader,fargs);
|
||||
/*
|
||||
* if we were given one C file and there is one ".o" file, we remove
|
||||
* the ".o" file.
|
||||
*/
|
||||
if( cfilep == &cfiles[1] && nloadfiles == 1 )
|
||||
unlink(setend(cfiles[0],'o'));
|
||||
}
|
||||
#endif
|
||||
cexit();
|
||||
}
|
||||
|
||||
/* fexec - fork and exec*/
|
||||
/* This forks a new task, then does an execv to execute the given*/
|
||||
/* program with the given arguements.*/
|
||||
fexec(fname,args) /* returns 1 if error, 0 otherwise*/
|
||||
char *fname; /* file to execute*/
|
||||
char **args; /* arguments to pass*/
|
||||
{
|
||||
register int pid, i;
|
||||
int fstat;
|
||||
|
||||
/* if( (pid=fork()) == 0 ) { //child process*/
|
||||
/* execv(fname,args);*/
|
||||
/* printf("can't execv %s errno=%d\n",fname,errno);*/
|
||||
/* exit(1);*/
|
||||
/* }*/
|
||||
pid = maketask(fname,0,0,args); /*do fork & exec*/
|
||||
if( pid < 0 ) {
|
||||
printf("can't maketask %s err=%o\n",fname,errno);
|
||||
return(1);
|
||||
}
|
||||
while( pid != wait(&fstat) ) /*wait for child*/
|
||||
;
|
||||
if( (i=fstat&0377) != 0 && i != 14 ) {
|
||||
if( i != 2 )
|
||||
printf("%s error terminated, status $%x\n",fname,i);
|
||||
status++;
|
||||
cexit();
|
||||
}
|
||||
return( (fstat>>8) & 0377 );
|
||||
}
|
||||
|
||||
/* setend - set the end character of a string*/
|
||||
/* This grabs a copy of the string and sets the last character to*/
|
||||
/* the given character. This is used to generate ".o", ".i" and*/
|
||||
/* ".s" file names.*/
|
||||
char *setend(s,c) /* returns pointer to string*/
|
||||
char *s; /* pointer to old string*/
|
||||
int c; /* character to end string with*/
|
||||
{
|
||||
register char *p;
|
||||
|
||||
p = makecopy(s);
|
||||
p[strlen(p)-1] = c;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/* chkdup - checks for duplicate ".o" files in file list*/
|
||||
/* Goes thru the loader argument list checking for the given*/
|
||||
/* ".o" file name.*/
|
||||
chkdup(s) /* returns 1 if found, 0 otherwise*/
|
||||
char *s; /* pointer to argument*/
|
||||
{
|
||||
register char **l;
|
||||
|
||||
if( strend(s,".o") ) {
|
||||
for( l = &loadargs[0]; *l; )
|
||||
if( !strcmp(*l++,s) )
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* makecopy - makes a copy of a string*/
|
||||
/* This allows for manipulating the file name, while allowing the*/
|
||||
/* saving of the old file name.*/
|
||||
char *makecopy(s) /* returns pointer to string*/
|
||||
char *s; /* string to copy*/
|
||||
{
|
||||
register char *p;
|
||||
register int ndx;
|
||||
|
||||
if (strncmp("/tmp/",s,5) != 0) /* don't truncate tmp file names */
|
||||
while ((ndx = index(s,'/')) != -1) s =+ ndx+1; /* [vlh] */
|
||||
for( p = argp; *argp++ = *s++; )
|
||||
;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/* initfargs - initialize fexec arg block*/
|
||||
/* This sets the arg block pointer to the beginning of the block.*/
|
||||
initfargs() /* returns - none*/
|
||||
{
|
||||
fargp = &fargs[0];
|
||||
}
|
||||
|
||||
/* addfarg - add fexec argument*/
|
||||
/* This takes the given arguement and adds it to the argment block*/
|
||||
addfarg(s)
|
||||
char *s;
|
||||
{
|
||||
if( fargp >= &fargs[NARGS] )
|
||||
ferror("too many args");
|
||||
*fargp++ = s;
|
||||
}
|
||||
|
||||
/* endfargs - end fexec argument block*/
|
||||
/* This ends the argument block with a zero pointer.*/
|
||||
endfargs() /* returns - none*/
|
||||
{
|
||||
*fargp = 0;
|
||||
}
|
||||
|
||||
/* ferror - fatal error*/
|
||||
/* Outputs error message and exits with error status.*/
|
||||
ferror(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* printf string*/
|
||||
int x1, x2, x3, x4, x5, x6; /* printf args*/
|
||||
{
|
||||
printf(s,x1,x2,x3,x4,x5,x6);
|
||||
printf("\n");
|
||||
status++;
|
||||
cexit();
|
||||
}
|
||||
|
||||
/* maketemp - make a temporary file name*/
|
||||
/* Generates unique file name with process id*/
|
||||
char *maketemp(arb) /* returns file name*/
|
||||
int arb; /* arbitrary number*/
|
||||
{
|
||||
#ifndef NOFORKS
|
||||
char *p, tmp[6];
|
||||
|
||||
p = makecopy("/tmp/ct6");
|
||||
argp--;
|
||||
itoa(getpid(),tmp,1);
|
||||
makecopy(tmp);
|
||||
argp--;
|
||||
makecopy(".");
|
||||
argp--;
|
||||
itoa(arb,tmp,1);
|
||||
makecopy(tmp);
|
||||
return(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* strcmp - string comparison*/
|
||||
/* Compares two strings for equality, less or greater.*/
|
||||
strcmp(s,t) /* returns 0 for equality,*/
|
||||
/* neg for < and pos for >.*/
|
||||
char *s; /* first string*/
|
||||
char *t; /* second string*/
|
||||
{
|
||||
for( ; *s == *t; s++, t++ )
|
||||
if( *s == '\0' )
|
||||
return(0);
|
||||
return( *s - *t );
|
||||
}
|
||||
|
||||
/* strncmp - string comparison*/
|
||||
/* Compares two strings for equality, less or greater.*/
|
||||
strncmp(s,t,n) /* neg for < and pos for >.*/
|
||||
char *s; /* first string*/
|
||||
char *t; /* second string*/
|
||||
{
|
||||
for( ; *s == *t && n; s++, t++, n--)
|
||||
if( *s == '\0' )
|
||||
return(0);
|
||||
return((n) ? *s - *t : 0);
|
||||
}
|
||||
|
||||
/* strlen - string length*/
|
||||
/* Computes number of bytes in string.*/
|
||||
strlen(s) /* returns string length*/
|
||||
char *s; /* string to compute length*/
|
||||
{
|
||||
register int n;
|
||||
|
||||
for( n = 0; *s++ != '\0'; )
|
||||
n++;
|
||||
return(n);
|
||||
}
|
||||
|
||||
/* itoa - integer to ASCII conversion*/
|
||||
/* Converts integer to ASCII string, handles '-'.*/
|
||||
itoa(n,s,w) /* returns - none*/
|
||||
int n; /* number to convert*/
|
||||
char *s; /* resulting string*/
|
||||
int w; /* minimum width of string*/
|
||||
{
|
||||
register char *tp;
|
||||
register int sign, i;
|
||||
char temp[6];
|
||||
|
||||
if( (sign=n) < 0 )
|
||||
n = -n;
|
||||
i = 0;
|
||||
tp = &temp;
|
||||
do {
|
||||
i++;
|
||||
*tp++ = n % 10 + '0';
|
||||
} while( (n =/ 10) > 0 );
|
||||
if( sign < 0 ) {
|
||||
i++;
|
||||
*tp++ = '-';
|
||||
}
|
||||
while( --w >= i ) /*pad on left with blanks*/
|
||||
*s++ = ' ';
|
||||
while( --i >= 0 ) /*move chars reversed*/
|
||||
*s++ = *--tp;
|
||||
*s = '\0';
|
||||
}
|
||||
|
||||
/* strend - set string end*/
|
||||
/* This is used to compare the endings of file names for ".c", etc.*/
|
||||
strend(s,t) /* returns 1 if match, 0 otherwise*/
|
||||
char *s; /* string to compare*/
|
||||
char *t; /* string ending*/
|
||||
{
|
||||
int ls, lt;
|
||||
|
||||
if( (ls=strlen(s)) < (lt=strlen(t)) )
|
||||
return(0);
|
||||
if( !strcmp(&s[ls-lt],t) )
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
v6flush(v6buf)
|
||||
struct iobuf *v6buf;
|
||||
{
|
||||
register i;
|
||||
|
||||
i = BLEN - v6buf->nunused;
|
||||
v6buf->nunused = BLEN;
|
||||
v6buf->xfree = &(v6buf->buff[0]);
|
||||
if(write(v6buf->fildes,v6buf->xfree,i) != i)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* index - find the index of a character in a string*/
|
||||
/* This is identical to Software Tools index.*/
|
||||
index(str,chr) /* returns index of c in str or -1*/
|
||||
char *str; /* pointer to string to search*/
|
||||
char chr; /* character to search for*/
|
||||
{
|
||||
register char *s;
|
||||
register int i;
|
||||
|
||||
for( s = str, i = 0; *s != '\0'; i++ )
|
||||
if( *s++ == chr )
|
||||
return(i);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// maketask call for unix
|
||||
int maketask(fname,flags,priority,argptrs)
|
||||
char *fname;
|
||||
int flags,priority;
|
||||
char **argptrs;
|
||||
{
|
||||
|
||||
register int pid;
|
||||
|
||||
if(flags==0) { //fork and exec
|
||||
if((pid=fork()) == 0) { //child process
|
||||
doexecv:
|
||||
execv(fname,argptrs);
|
||||
printf("execv failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
return(pid); //return child process id
|
||||
}
|
||||
if(flags==2) { //fork only
|
||||
return(fork());
|
||||
}
|
||||
if(flags==4) { //exec only
|
||||
goto doexecv;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "../icode.h"
|
||||
|
||||
/*cexpr operators*/
|
||||
#define EOF 0
|
||||
#define SUB 1
|
||||
#define ADD 2
|
||||
#define NOT 3
|
||||
#define NEG 4
|
||||
#define LPAREN 5
|
||||
#define RPAREN 6
|
||||
#define QMARK 7
|
||||
#define COLON 8
|
||||
#define OR 9
|
||||
#define AND 10
|
||||
#define XOR 11
|
||||
#define EQUAL 12
|
||||
#define NEQUAL 13
|
||||
#define LESS 14
|
||||
#define LSEQUAL 15
|
||||
#define GREAT 16
|
||||
#define GREQUAL 17
|
||||
#define LSHIFT 18
|
||||
#define RSHIFT 19
|
||||
#define MULT 20
|
||||
#define DIV 21
|
||||
#define MOD 22
|
||||
#define COMPL 23
|
||||
#define CONST 24
|
||||
#define LASTOP COMPL /*up to here used by cexpr*/
|
||||
#define SQUOTE 25
|
||||
#define DQUOTE 26
|
||||
#define ANYC 27
|
||||
#define BADC 28
|
||||
#define COMMA 29
|
||||
#define NEWL 30
|
||||
#define POUND 31
|
||||
#define ALPHA 32
|
||||
#define DIGIT 33
|
||||
#define BSLASH 34
|
||||
#define WHITE 35
|
||||
#define BUFSIZE 512
|
||||
#define LINESIZE 512
|
||||
#define ARG -1
|
||||
#define NEWLABEL -2
|
||||
#define LABEL -3
|
||||
#define NOARGS -4
|
||||
#define MAXARGS 60
|
||||
#define ARGBSIZE 1000
|
||||
#define TOKSIZE 300 /*BUG 4/20/82 was 128*/
|
||||
#define DEFSIZE 1024
|
||||
#define PBSIZE 1000
|
||||
#define DEFINE 1
|
||||
#define UNDEF 2
|
||||
#define INCLUDE 3
|
||||
#define IFDEF 4
|
||||
#define IFNDEF 5
|
||||
#define ELSE 6
|
||||
#define ENDIF 7
|
||||
#define IF 8
|
||||
#define LINE 9
|
||||
#define SKIP 0
|
||||
#define NOSKIP 1
|
||||
#define SOH '\01'
|
||||
#define SSIZE 8
|
||||
#define HSIZE 517 /* 3.4 made prime */
|
||||
#define FSTACK 10
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NDEFS 20
|
||||
|
||||
struct symbol {
|
||||
char s_name[SSIZE];
|
||||
char *s_def;
|
||||
} symtab[HSIZE];
|
||||
|
||||
/*buffered I/O structure*/
|
||||
struct ibuf {
|
||||
int fd;
|
||||
int nc;
|
||||
char *bp;
|
||||
char buffer[BUFSIZE];
|
||||
} inbuf, outbuf;
|
||||
|
||||
/* command line define structure */
|
||||
struct defstruc {
|
||||
char *ptr;
|
||||
char *value;
|
||||
} defs[NDEFS];
|
||||
|
||||
struct stackstruc { /* [vlh] */
|
||||
int ifd;
|
||||
char ifile[13];
|
||||
int lineno;
|
||||
} filestack[FSTACK], *filep; /* stack of incl files, ptr to... */
|
||||
|
||||
#ifdef VERSADOS
|
||||
#define NONEST 1
|
||||
#define NOFORKS 1
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
#define NONEST 1
|
||||
#endif
|
||||
|
||||
#ifdef NONEST
|
||||
struct ibuf holdbuf; /* alternate buffer, hold main file info */
|
||||
#endif
|
||||
|
||||
int mfail; /*macro error flag*/
|
||||
int skip; /*skipping current line*/
|
||||
char *defap; /*pointer to available define area*/
|
||||
char *defp; /*pointer to next avail define byte*/
|
||||
int defcount; /*bytes left in define area*/
|
||||
int defused; /*number of bytes used in define area*/
|
||||
int defmax; /*maximum define area used*/
|
||||
int pflag;
|
||||
int asflag;
|
||||
|
||||
/*line to output after macro substitution*/
|
||||
char line[LINESIZE+2]; /*line buffer*/
|
||||
char *linep; /*current line pointer*/
|
||||
int loverflow; /*line overflow flag*/
|
||||
int lineno;
|
||||
|
||||
/*push back buffer*/
|
||||
char pbbuf[PBSIZE]; /*push back buffer*/
|
||||
char *pbp; /*push back pointer*/
|
||||
int pbflag; /*checks for recursive definition*/
|
||||
|
||||
char null[]; /*used for undef'd symbols*/
|
||||
|
||||
char *lookup();
|
||||
char *setend();
|
||||
char *makecopy();
|
||||
char *makecopy();
|
||||
char *maketemp();
|
||||
char *sbrk();
|
||||
struct symbol *getsp();
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/* fake sysinfo call for PDP-11, returns as if MMU system */
|
||||
sysinfo(flag,addr)
|
||||
int flag, *addr;
|
||||
{
|
||||
*addr = 1;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
atoi(as)
|
||||
char *as;
|
||||
{
|
||||
register int n, sign;
|
||||
register char *s;
|
||||
|
||||
s = as;
|
||||
while( *s==' ' || *s=='\n' || *s == '\t')
|
||||
s++;
|
||||
sign = 1;
|
||||
if( *s == '+' || *s == '-' )
|
||||
sign = (*s++=='+') ? 1 : -1;
|
||||
for( n = 0; *s >= '0' && *s <= '9'; s++ )
|
||||
n = (n * 10) + (*s - '0');
|
||||
return( sign * n );
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
char *compiled "@(#) preprocessor - Fri Mar 18 12:37 1983";
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
$ diff DECL.c drb0:[steve.cpm68k.c.fparser]DECL.c
|
||||
$ diff EXPR.c drb0:[steve.cpm68k.c.fparser]EXPR.c
|
||||
$ diff ICODE.c drb0:[steve.cpm68k.c.fparser]ICODE.c
|
||||
$ diff INIT.c drb0:[steve.cpm68k.c.fparser]INIT.c
|
||||
$ diff INTERF.c drb0:[steve.cpm68k.c.fparser]INTERF.c
|
||||
$ diff LEX.c drb0:[steve.cpm68k.c.fparser]LEX.c
|
||||
$ diff MAIN.c drb0:[steve.cpm68k.c.fparser]MAIN.c
|
||||
$ diff STMT.c drb0:[steve.cpm68k.c.fparser]STMT.c
|
||||
$ diff TABL.c drb0:[steve.cpm68k.c.fparser]TABL.c
|
||||
$ diff VERSION.c drb0:[steve.cpm68k.c.fparser]VERSION.c
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
int bol 1;
|
||||
int inittype;
|
||||
int begseq;
|
||||
/* int onepass; */
|
||||
|
||||
/*
|
||||
This interfaces the Parser and the Code Generator, note that these
|
||||
allow you to link together the Parser and the Code Generator.
|
||||
*/
|
||||
|
||||
/* outbdata - set up for byte data*/
|
||||
outbdata() /* returns - none*/
|
||||
{
|
||||
inittype = CHAR;
|
||||
printf("\t.dc.b ");
|
||||
}
|
||||
|
||||
/* outc - output a constant*/
|
||||
outc(type,value) /* returns - none*/
|
||||
int type;
|
||||
int value;
|
||||
{
|
||||
if( type == CHAR )
|
||||
outbdata();
|
||||
else
|
||||
outwdata();
|
||||
printf("%d\n",value);
|
||||
}
|
||||
|
||||
/* outwdata - set up for word data*/
|
||||
outwdata() /* returns - none*/
|
||||
{
|
||||
inittype = INT;
|
||||
printf("\t.dc.w ");
|
||||
}
|
||||
|
||||
/* outdata - set up for data output*/
|
||||
outdata() /* returns - none*/
|
||||
{
|
||||
inittype = INT;
|
||||
printf("\t.data\n");
|
||||
}
|
||||
|
||||
/* outldata - set up for long data output*/
|
||||
outldata() /* returns - none*/
|
||||
{
|
||||
inittype = LONG;
|
||||
printf("\t.data\n");
|
||||
}
|
||||
|
||||
/* outfpdata - set up for floating point data output*/
|
||||
outfpdata() /*[vlh] 3.4 returns - none*/
|
||||
{
|
||||
inittype = FLOAT;
|
||||
printf("\t.data\n");
|
||||
}
|
||||
|
||||
/* outbentry - outputs block/function entry code*/
|
||||
outbentry(nlocs,nds,nas) /* returns - none*/
|
||||
int nlocs; /* local size*/
|
||||
int nds; /* number of D registers*/
|
||||
int nas; /* number of A registers*/
|
||||
{
|
||||
if( !nds && !nas ) /* adjust for 1 arg*/
|
||||
nlocs =+ 4;
|
||||
printf("\tlink R14,#%d\n",-nlocs);
|
||||
if( nds || nas ) {
|
||||
printf("\tmovem.l R%d-R7",7-nds); /*7 for one arg*/
|
||||
if( nas ) {
|
||||
putchar('/');
|
||||
printf("R%d-R13",14-nas);
|
||||
}
|
||||
printf(",-(sp)\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* outbexit - output function exit code*/
|
||||
outbexit(nds,nas) /* returns - none*/
|
||||
int nds; /* number of D registers*/
|
||||
int nas; /* number of A registers*/
|
||||
{
|
||||
if( nds || nas ) {
|
||||
printf("\ttst.l (sp)+\n\tmovem.l (sp)+,"); /*1 arg stuff*/
|
||||
if( nds ) {
|
||||
printf("R%d-R7",8-nds);
|
||||
if( nas )
|
||||
putchar('/');
|
||||
}
|
||||
if( nas )
|
||||
printf("R%d-R13",14-nas);
|
||||
putchar('\n');
|
||||
}
|
||||
printf("\tunlk R14\n\trts\n");
|
||||
}
|
||||
|
||||
/* outlocal - output local symbol for debugger*/
|
||||
outlocal(type,sc,sym,val)
|
||||
int type; /* local name type*/
|
||||
int sc; /* storage type*/
|
||||
char *sym; /* symbol name*/
|
||||
int val;
|
||||
{
|
||||
switch( sc ) {
|
||||
|
||||
case STATIC:
|
||||
if( notfunction(type) )
|
||||
printf("\t~%.8s=L%d\n",sym,val);
|
||||
break;
|
||||
|
||||
case REGISTER:
|
||||
printf("\t~%.8s=R%d\n",sym,val);
|
||||
break;
|
||||
|
||||
case AUTO:
|
||||
printf("\t~%.8s=%d\n",sym,val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* outswitch - output switch table info*/
|
||||
outswitch(ncases,deflab,sp) /* returns - none*/
|
||||
int ncases; /* number of cases in switch*/
|
||||
int deflab; /* default label*/
|
||||
struct swtch *sp; /* switch table pointer*/
|
||||
{
|
||||
register int vdif, val, hval, i, tlab;
|
||||
register struct swtch *s;
|
||||
|
||||
val = sp->sw_value;
|
||||
hval = sp[ncases-1].sw_value;
|
||||
vdif = hval - val;
|
||||
if( ncases <= 4 ) {
|
||||
/*
|
||||
*simple switch, do compares and brances, followed by branch to default
|
||||
*/
|
||||
for( s = sp; --ncases >= 0; s++ ) {
|
||||
if( !s->sw_value )
|
||||
printf("\ttst R0\n");
|
||||
else
|
||||
printf("\tcmp #%d,R0\n",s->sw_value);
|
||||
printf("\tbeq L%d\n",s->sw_label);
|
||||
}
|
||||
outgoto(deflab);
|
||||
}
|
||||
else if( vdif > 0 && vdif <= ncases*3 ) {
|
||||
|
||||
/*jump switch, uses value in R0 to index into table of labels*/
|
||||
|
||||
if( val )
|
||||
printf("\tsub #%d,R0\n",val);
|
||||
tlab = nextlabel++;
|
||||
printf("\tcmp #%d,R0\n\tbhi L%d\n",vdif,deflab); /*check for max*/
|
||||
printf("\tasl #2,R0\n\tmove R0,R8\n\tadd.l #L%d,R8\n",tlab);
|
||||
printf("\tmove.l (R8),R8\n\tjmp (R8)\n");
|
||||
outdata();
|
||||
outlab(tlab);
|
||||
for( s = sp; val <= hval; val++ ) {
|
||||
if( val == s->sw_value ) {
|
||||
outclab(s->sw_label);
|
||||
s++;
|
||||
}
|
||||
else
|
||||
outclab(deflab);
|
||||
}
|
||||
outtext();
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* direct switch, searches down table of values for match, if match
|
||||
* found, branches to corresponding label in label table.
|
||||
*/
|
||||
tlab = nextlabel++;
|
||||
printf("\text.l R0\n\tmove.l #L%d,R8\n\tmove #%d,R1\n",tlab,ncases);
|
||||
i = nextlabel++;
|
||||
outlab(i); /*loop label*/
|
||||
printf("\tcmp.l (R8)+,R0\n\tdbeq R1,L%d\n",i);
|
||||
printf("\tmove.l %d(R8),R8\n\tjmp (R8)\n",ncases*4);
|
||||
outdata();
|
||||
outlab(tlab);
|
||||
for( s = sp, i = ncases; --i >= 0; s++ )
|
||||
outlcon(s->sw_value);
|
||||
outlcon(0); /* mark for default label*/
|
||||
for( s = sp, i = ncases; --i >= 0; s++ )
|
||||
outclab(s->sw_label);
|
||||
outclab(deflab);
|
||||
outtext();
|
||||
}
|
||||
}
|
||||
|
||||
outeof()
|
||||
{
|
||||
register int c;
|
||||
|
||||
v6flush(&sbuf);
|
||||
v6flush(&obuf);
|
||||
}
|
||||
|
||||
/* copysfile - copy string file to end of output file*/
|
||||
copysfile(fname)
|
||||
char *fname;
|
||||
{
|
||||
register int c;
|
||||
|
||||
close(sbuf.io_fd);
|
||||
if( fopen(fname,&sbuf,0) < 0 ) /* 3rd arg for versados */
|
||||
ferror("can't copy %s",fname);
|
||||
while( (c=getc(&sbuf)) > 0 )
|
||||
putc(c,&obuf);
|
||||
v6flush(&obuf);
|
||||
}
|
||||
|
||||
/* outword - output a word of data*/
|
||||
outword(w) /* word expression*/
|
||||
int w;
|
||||
{
|
||||
if( begseq )
|
||||
putchar(',');
|
||||
begseq++;
|
||||
printf("%d",w);
|
||||
}
|
||||
|
||||
/* outlong - output a long data*/
|
||||
outlong(l) /* returns - none*/
|
||||
long l; /* long data to output*/
|
||||
{
|
||||
outwdata();
|
||||
outword(l.hiword);
|
||||
outword(l.loword);
|
||||
outendseq();
|
||||
}
|
||||
|
||||
/* outfp - output floating point data*/
|
||||
outfp(l) /*[vlh] 3.4 returns - none*/
|
||||
long l; /* floating point data to output*/
|
||||
{
|
||||
outwdata();
|
||||
outword(l.hiword);
|
||||
outword(l.loword);
|
||||
outendseq();
|
||||
}
|
||||
|
||||
outendseq() /* returns - none*/
|
||||
{
|
||||
begseq = 0;
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* outtstr - output text string
|
||||
* This outputs a string to the string file, this is used wherever
|
||||
* you cannot output the string directly to data space, such as in
|
||||
* the middle of expressions.
|
||||
*/
|
||||
outtstr(lab)
|
||||
int lab;
|
||||
{
|
||||
char *savep;
|
||||
int sbol;
|
||||
|
||||
savep = obp; /*save to restore later...*/
|
||||
obp = &sbuf;
|
||||
sbol = bol;
|
||||
bol = 1;
|
||||
printf("\tL%d:",lab);
|
||||
outstr();
|
||||
obp = savep;
|
||||
bol = sbol;
|
||||
}
|
||||
|
||||
/* outstr - output a string as a sequence of bytes*/
|
||||
/* Outputs ".dc.b <byte1>,<byte2>,...,<0>*/
|
||||
outstr()
|
||||
{
|
||||
register char *s;
|
||||
register int i;
|
||||
|
||||
outbdata();
|
||||
for( s = cstr, i = cstrsize; i > 0; i-- )
|
||||
outword(*s++ & 0xff);
|
||||
outendseq();
|
||||
}
|
||||
|
||||
/*
|
||||
* putchar - handle outputting to intermediate or error files
|
||||
* This catches tabs to allow for the integration of the parser
|
||||
* and code generator into one pass. By merely throwing away the
|
||||
* tabs here, the output will be OK for the assembler.
|
||||
*/
|
||||
putchar(c)
|
||||
char c;
|
||||
{
|
||||
if( !obp )
|
||||
write(1,&c,1);
|
||||
else if( c == '\t' ) {
|
||||
if( bol ) /* not used && !onepass ) */
|
||||
putc('(',obp); /*for code generator*/
|
||||
}
|
||||
else {
|
||||
bol = (c == '\n');
|
||||
putc(c,obp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
#include "machine.h"
|
||||
/*
|
||||
* intermediate code operators
|
||||
* 0=>EOF, special operator
|
||||
*/
|
||||
#define EOF 0
|
||||
|
||||
/*1-59=>operators that generate code (entries in code gen optab)*/
|
||||
#define ADD 1
|
||||
#define SUB 2
|
||||
#define MULT 3
|
||||
#define DIV 4
|
||||
#define MOD 5
|
||||
#define RSH 6
|
||||
#define LSH 7
|
||||
#define AND 8
|
||||
#define OR 9
|
||||
#define XOR 10
|
||||
#define NOT 11
|
||||
#define UMINUS 12
|
||||
#define COMPL 13
|
||||
#define PREDEC 14
|
||||
#define PREINC 15
|
||||
#define POSTDEC 16
|
||||
#define POSTINC 17
|
||||
#define ASSIGN 18
|
||||
#define EQADD 19
|
||||
#define EQSUB 20
|
||||
#define EQMULT 21
|
||||
#define EQDIV 22
|
||||
#define EQMOD 23
|
||||
#define EQRSH 24
|
||||
#define EQLSH 25
|
||||
#define EQAND 26
|
||||
#define EQOR 27
|
||||
#define EQXOR 28
|
||||
#define FJSR 29
|
||||
#define EQUALS 30
|
||||
#define NEQUALS 31
|
||||
#define GREAT 32
|
||||
#define GREATEQ 33
|
||||
#define LESS 34
|
||||
#define LESSEQ 35
|
||||
#define INT2L 36
|
||||
#define LONG2I 37
|
||||
|
||||
/*machine dependent operators that generate code*/
|
||||
#define BTST 38
|
||||
#define LOAD 39
|
||||
#define LMULT 40
|
||||
#define LDIV 41
|
||||
#define LMOD 42
|
||||
#define LEQMULT 43
|
||||
#define LEQDIV 44
|
||||
#define LEQMOD 45
|
||||
#define EQADDR 46
|
||||
#define EQNOT 47
|
||||
#define EQNEG 48
|
||||
#define DOCAST 49
|
||||
|
||||
#define STASSIGN 50 /*[vlh]*/
|
||||
#define LONG2F 51 /*[vlh] 3.4*/
|
||||
#define FLOAT2L 52 /*[vlh] 3.4*/
|
||||
#define INT2F 53 /*[vlh] 3.4*/
|
||||
#define FLOAT2I 54 /*[vlh] 3.4*/
|
||||
#define LCGENOP 55 /*change if adding more operators...*/
|
||||
|
||||
/*intermediate code operators that do not generate code*/
|
||||
#define ADDR 60
|
||||
#define INDR 61
|
||||
#define LAND 62
|
||||
#define LOR 63
|
||||
#define QMARK 64
|
||||
#define COLON 65
|
||||
#define COMMA 66
|
||||
#define CINT 67
|
||||
#define CLONG 68
|
||||
#define SYMBOL 69
|
||||
#define AUTOINC 70
|
||||
#define AUTODEC 71
|
||||
#define CALL 72
|
||||
#define NACALL 73
|
||||
#define BFIELD 74
|
||||
#define IFGOTO 75
|
||||
#define INIT 76
|
||||
#define CFORREG 77
|
||||
#define DCLONG 78
|
||||
#define CFLOAT 79 /*[vlh] 3.4*/
|
||||
|
||||
/*operators local to parser*/
|
||||
#define CAST 80
|
||||
#define SEMI 81
|
||||
#define LCURBR 82
|
||||
#define RCURBR 83
|
||||
#define LBRACK 84
|
||||
#define RBRACK 85
|
||||
#define LPAREN 86
|
||||
#define RPAREN 87
|
||||
#define STRING 88
|
||||
#define RESWORD 89
|
||||
#define APTR 90
|
||||
#define PERIOD 91
|
||||
#define SIZEOF 92
|
||||
#define MPARENS 93
|
||||
#define FRETURN 94
|
||||
#define STACKEND 100
|
||||
|
||||
/*data types*/
|
||||
#define TYPELESS 0
|
||||
#define CHAR 1
|
||||
#define SHORT 2
|
||||
#define INT 3
|
||||
#define LONG 4
|
||||
#define UCHAR 5
|
||||
#define USHORT 6
|
||||
#define UNSIGNED 7
|
||||
#define ULONG 8
|
||||
#define FLOAT 9
|
||||
#define DOUBLE 10
|
||||
|
||||
/*data types local to parser*/
|
||||
#define STRUCT 11
|
||||
#define FRSTRUCT 12
|
||||
#define LLABEL 13
|
||||
|
||||
/*type flags and definitions*/
|
||||
#define TYPE 017
|
||||
#define SUPTYP 060
|
||||
#define ALLTYPE 077
|
||||
#define POINTER 020
|
||||
#define FUNCTION 040
|
||||
#define ARRAY 060
|
||||
#define SUTYPLEN 2
|
||||
|
||||
/*data registers*/
|
||||
#define DREG0 0
|
||||
#define DREG2 2
|
||||
#define DREG3 3
|
||||
#define DREG4 4
|
||||
#define DREG5 5
|
||||
#define DREG6 6
|
||||
#define DREG7 7
|
||||
#define AREG3 11
|
||||
#define AREG4 12
|
||||
#define AREG5 13
|
||||
|
||||
/*storage classes*/
|
||||
#define AUTO 1
|
||||
#define REGISTER 2
|
||||
#define EXTERNAL 3
|
||||
#define STATIC 4
|
||||
#define REGOFF 5
|
||||
#define EXTOFF 6
|
||||
#define STATOFF 7
|
||||
#define INDEXED 8
|
||||
|
||||
/*exclusively code generator storage classes*/
|
||||
#define CINDR 9
|
||||
#define CLINDR 10
|
||||
#define CFINDR 11 /* [vlh] 3.4 */
|
||||
|
||||
/*exclusively parser storage classes*/
|
||||
#define STRPROTO 9
|
||||
#define PDECLIST 10
|
||||
#define PARMLIST 11
|
||||
#define BFIELDCL 12
|
||||
#define UNELCL 13
|
||||
#define STELCL 14
|
||||
|
||||
|
||||
/*opinfo table bits*/
|
||||
#define OPPRI 077
|
||||
#define OPBIN 0100
|
||||
#define OPLVAL 0200
|
||||
#define OPREL 0400
|
||||
#define OPASSIGN 01000
|
||||
#define OPLWORD 02000
|
||||
#define OPRWORD 04000
|
||||
#define OPCOM 010000
|
||||
#define OPRAS 020000
|
||||
#define OPTERM 040000
|
||||
#define OPCONVS 0100000
|
||||
|
||||
/*68000 definitions*/
|
||||
#define PTRSIZE 4
|
||||
#define INTSIZE 2
|
||||
#define LONGSIZE 4
|
||||
#define SSIZE 8 /* chars per symbol */
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define TABC '\t' /* tab character */
|
||||
#define EOLC '\n' /* end of line character */
|
||||
#define BITSPBYTE 8
|
||||
|
||||
/*operator class priorities*/
|
||||
#define TRMPRI 0 /* terminal nodes */
|
||||
#define RPNPRI 1 /* ) and ] */
|
||||
#define CALPRI 2 /* in-stack call, ( or [ */
|
||||
#define COLPRI 3 /* init or case priority for : or , */
|
||||
#define STKPRI 4 /* priority of end of stack */
|
||||
#define COMPRI 5 /* normal priority for , */
|
||||
#define ASGPRI 6 /* =, +=, -=, *=, /=, %=, ... */
|
||||
#define QMKPRI 7 /* ?: */
|
||||
#define LORPRI 8 /* || */
|
||||
#define LNDPRI 9 /* && */
|
||||
#define ORPRI 10 /* |, ! */
|
||||
#define ANDPRI 11 /* & */
|
||||
#define EQLPRI 12 /* ==, != */
|
||||
#define RELPRI 13 /* >, <, >=, <= */
|
||||
#define SHFPRI 14 /* <<, >> */
|
||||
#define ADDPRI 15 /* +, - */
|
||||
#define MULPRI 16 /* *, /, % */
|
||||
#define UNOPRI 17 /* ++, --, &, *, -, ~, sizeof */
|
||||
#define LPNPRI 18 /* ., ->, [, (, function call */
|
||||
#define PSTPRI 19 /* in-stack post--, post++ */
|
||||
|
||||
struct io_buf {
|
||||
int io_fd;
|
||||
int io_nc;
|
||||
char *io_p;
|
||||
char io_b[512];
|
||||
};
|
||||
|
||||
#ifdef PDP11
|
||||
struct { short hiword; short loword; };
|
||||
#endif
|
||||
#ifdef MC68000
|
||||
struct { short hiword; short loword; };
|
||||
#endif
|
||||
#ifdef VAX
|
||||
struct { short loword; short hiword; };
|
||||
#endif
|
||||
|
||||
#define EXPSIZE 1024
|
||||
int exprarea[EXPSIZE];
|
||||
|
||||
/* v6io buffer declaration */
|
||||
#define BLEN 512
|
||||
|
||||
struct iobuf{
|
||||
int fildes;
|
||||
int nunused;
|
||||
char *xfree;
|
||||
char buff[BLEN];
|
||||
};
|
||||
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*
|
||||
C68 Parser - include file
|
||||
*/
|
||||
#include "icode.h"
|
||||
|
||||
/*symbol attribute fields*/
|
||||
#define SRESWORD 001 /*is symbol a reserved word?*/
|
||||
#define SGLOBAL 002 /*is symbol global?*/
|
||||
#define STYPEDEF 004 /*typedef declaration?*/
|
||||
#define SDEFINED 010 /*symbol defined?*/
|
||||
|
||||
/*reserved words*/
|
||||
#define R_AUTO 1
|
||||
#define R_BREAK 2
|
||||
#define R_CASE 3
|
||||
#define R_CHAR 4
|
||||
#define R_CONTINUE 5
|
||||
#define R_DO 6
|
||||
#define R_DEFAULT 7
|
||||
#define R_DOUBLE 8
|
||||
#define R_GOTO 9
|
||||
#define R_ELSE 10
|
||||
#define R_EXTERNAL 11
|
||||
#define R_FLOAT 12
|
||||
#define R_FOR 13
|
||||
#define R_IF 14
|
||||
#define R_INT 15
|
||||
#define R_LONG 16
|
||||
#define R_REGISTER 17
|
||||
#define R_RETURN 18
|
||||
#define R_SHORT 19
|
||||
#define R_SIZEOF 20
|
||||
#define R_STATIC 21
|
||||
#define R_STRUCT 22
|
||||
#define R_SWITCH 23
|
||||
#define R_TYPEDEF 24
|
||||
#define R_UNION 25
|
||||
#define R_UNSIGNED 26
|
||||
#define R_WHILE 27
|
||||
|
||||
/*
|
||||
* mixed-mode conversions, entries in 2-d array indexed by:
|
||||
* (int,unsn,long,doub,ptr)
|
||||
*/
|
||||
#define INT_CHAR 1
|
||||
#define UNSN_CHAR 1
|
||||
#define LONG_CHAR 1
|
||||
#define DOUB_CHAR 1
|
||||
#define PTR_CHAR 1
|
||||
#define INT_UNSN 0 /*no conversion is generated*/
|
||||
#define INT_LONG 2
|
||||
#define INT_DOUB 3
|
||||
#define INT_PTR 4
|
||||
#define UNSN_INT 0 /*no conversion is generated*/
|
||||
#define UNSN_LONG 6
|
||||
#define UNSN_DOUB 7
|
||||
#define UNSN_PTR 8
|
||||
#define LONG_INT 9
|
||||
#define LONG_UNSN 10
|
||||
#define LONG_DOUB 11
|
||||
#define LONG_PTR 12
|
||||
#define DOUB_INT 13
|
||||
#define DOUB_UNSN 14
|
||||
#define DOUB_LONG 15
|
||||
#define PTR_INT 16
|
||||
#define PTR_UNSN 17
|
||||
#define PTR_LONG 18
|
||||
#define PTR_PTR 19
|
||||
#define BADCONV 20
|
||||
|
||||
/* miscellaneous constants */
|
||||
#define OPSSIZE 40 /*operator stack size*/
|
||||
#define OPDSIZE 80 /*operand stack size*/
|
||||
#define HSIZE 517 /*hash table size, 3.4 made prime */
|
||||
#define SYMSIZE 1024 /*size to alloc for symbol structures*/
|
||||
#define SWSIZE 256 /*max no. of cases in a switch*/
|
||||
#define DSIZE 1000 /*dimension table size*/
|
||||
#define BITSPWORD 16 /*bits per word*/
|
||||
#define AREGLO 010 /*A reg flag*/
|
||||
#define HICREG 2 /*highest reg # used for code generation*/
|
||||
#define BITSPCHAR 8 /*bits per char*/
|
||||
#define CHRSPWORD 2 /*chars per word*/
|
||||
#define STRSIZE 300 /*max string length*/
|
||||
#define NFARGS 40 /*max no. of args to function*/
|
||||
#define NFRSTR 20 /*max no. of forward ref struct proto*/
|
||||
|
||||
/*symbol table node*/
|
||||
struct symbol {
|
||||
char s_attrib; /* defined, resword, global, typedef */
|
||||
char s_sc; /* auto, static, external, register */
|
||||
int s_type; /* 4bits specified, 2 bit fields for ptr... */
|
||||
int s_dp; /* index into dimension table */
|
||||
int s_ssp; /* dimension table/function arg table */
|
||||
int s_offset; /* offset inside of structure */
|
||||
char s_symbol[SSIZE]; /* symbol identifier, to SSIZE chars */
|
||||
struct symbol *s_struc; /* if struct, ptr to parent (sys III) */
|
||||
struct symbol *s_next; /* next symbol table entry */
|
||||
};
|
||||
|
||||
/*expression tree operator node*/
|
||||
struct tnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
struct tnode *t_left;
|
||||
struct tnode *t_right;
|
||||
};
|
||||
|
||||
/*expression tree node for symbol - only keeps location*/
|
||||
struct symnode {
|
||||
int t_op;
|
||||
int t_type; /*data type of symbol*/
|
||||
int t_dp; /*dimension pointer of symbol*/
|
||||
int t_ssp; /*structure size index to dtab*/
|
||||
int t_sc; /*storage class of symbol*/
|
||||
int t_offset; /*offset of symbol*/
|
||||
int t_label;
|
||||
};
|
||||
|
||||
/*expressioon tree node for external symbol - need to keep name*/
|
||||
struct extnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
int t_sc;
|
||||
int t_offset;
|
||||
int t_reg;
|
||||
int t_symbol[SSIZE]; /*symbol name*/
|
||||
};
|
||||
|
||||
/*expression tree node for integer constant*/
|
||||
struct conode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
int t_value; /*constant value*/
|
||||
};
|
||||
|
||||
struct lconode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
long t_lvalue; /*constant value*/
|
||||
};
|
||||
|
||||
struct swtch {
|
||||
int sw_label;
|
||||
int sw_value;
|
||||
} swtab[SWSIZE]=0;
|
||||
|
||||
/*operator and operand stack used by expr*/
|
||||
struct ops { /*operator stack*/
|
||||
int o_op; /*operator*/
|
||||
int o_pri; /*priority*/
|
||||
} opstack[OPSSIZE]=0, *opp=0;
|
||||
|
||||
char *opdstack[OPDSIZE]=0; /*operand stack*/
|
||||
char **opdp=0; /*operand stack pointer*/
|
||||
char *opap=0; /*ptr to next available loc in exprarea*/
|
||||
struct tnode *frp=0; /*pointer to function return info node*/
|
||||
int cswp=0; /*current low switch table index*/
|
||||
int clabel=0; /*continue label*/
|
||||
int blabel=0; /*break label*/
|
||||
int rlabel=0; /*return label*/
|
||||
int dlabel=0; /*default label*/
|
||||
int lineno=0; /*current line number of input*/
|
||||
int errcnt=0; /*count of errors*/
|
||||
int inclflag=0; /*in include file, don't incr line #'s*/
|
||||
int inclline=0; /*[vlh]line# in incl file for err rpting*/
|
||||
char inclfile[13]=0; /*[vlh]include filename for err rpting*/
|
||||
int equalstop=0; /*stop lex at '=', used for external init*/
|
||||
int commastop=0; /*stop parse @ comma(used for const expr)*/
|
||||
int colonstop=0; /*stop parse @ colon(used for case value)*/
|
||||
int instruct=0; /*set when in structure declaration*/
|
||||
int smember=0; /*set when seen . or ->*/
|
||||
int infunc=0; /*set when in function body*/
|
||||
int tdflag=0; /*declaration is a typedef proto*/
|
||||
char *tdp=0; /*points to typedef prototype*/
|
||||
int localsize=0; /*length of local variables*/
|
||||
int naregs=0; /*keeps track of ptr registers alloc'd*/
|
||||
int ndregs=0; /*keep track of data registers alloc'd*/
|
||||
int loadreg=0; /*need to load registers...*/
|
||||
int boffset=0; /*current bit offset in structure*/
|
||||
int eflag=0; /*[vlh] 3.4 IEEE floats */
|
||||
int fflag=0; /*[vlh] 3.4 FFP floats */
|
||||
int xflag=0; /*translate int's to long's*/
|
||||
int wflag=0; /*[vlh] don't generate warning mesgs*/
|
||||
int reducep=0; /*[vlh] if(procid); reduction*/
|
||||
int peektok=0; /*peeked at token*/
|
||||
|
||||
/*dimension table*/
|
||||
long dtab[DSIZE]=0; /* [vlh] 3.4 int => long */
|
||||
int cdp=0; /*next entry in dtab to alloc*/
|
||||
|
||||
/*lexical analyzer values*/
|
||||
int cvalue=0; /*current token value if keyword or CINT*/
|
||||
int cstrsize=0; /*current string size*/
|
||||
long clvalue=0; /*current token value if long constant*/
|
||||
struct symbol *csp=0; /*current token symbol ptr if SYMBOL*/
|
||||
char cstr[STRSIZE]=0; /*current token value if CSTRING*/
|
||||
struct symbol *dsp=0; /*declarator symbol pointer*/
|
||||
|
||||
/* -1 -> not instruct, 0 -> unnamed struct */
|
||||
struct symbol *strucptr[10]=0; /*[vlh] ptrs to struc symbols*/
|
||||
|
||||
/*function argument table, used to collect function parameters*/
|
||||
struct farg {
|
||||
struct symbol *f_sp;
|
||||
int f_offset;
|
||||
} fargtab[NFARGS]=0;
|
||||
|
||||
/*forward referenced structure prototype names*/
|
||||
struct symbol *frstab[NFRSTR]=0;
|
||||
int frstp=0;
|
||||
|
||||
/*output buffers for intermediate code and strings*/
|
||||
struct io_buf obuf=0, sbuf=0, ibuf=0, *obp=0;
|
||||
|
||||
#define stypedef(sp) (sp->s_attrib&STYPEDEF)
|
||||
#define walign(add) ((add+1)&(~1))
|
||||
#define array(type) ((type&SUPTYP)==ARRAY)
|
||||
#define function(type) ((type&SUPTYP)==FUNCTION)
|
||||
#define pointer(type) ((type&SUPTYP)==POINTER)
|
||||
#define notarray(type) ((type&SUPTYP)!=ARRAY)
|
||||
#define notfunction(type) ((type&SUPTYP)!=FUNCTION)
|
||||
#define notpointer(type) ((type&SUPTYP)!=POINTER)
|
||||
#define btype(type) (type&TYPE)
|
||||
#define suptype(type) (type&SUPTYP)
|
||||
#define alltype(type) (type&(SUPTYP|TYPE))
|
||||
#define asgop(op) ((opinfo[op]&OPASSIGN)!=0)
|
||||
#define relop(op) ((opinfo[op]&OPREL)!=0)
|
||||
#define lintegral(op) ((opinfo[op]&OPLWORD)!=0)
|
||||
#define rintegral(op) ((opinfo[op]&OPRWORD)!=0)
|
||||
#define rasop(op) ((opinfo[op]&OPRAS)!=0)
|
||||
#define binop(op) ((opinfo[op]&OPBIN)!=0)
|
||||
#define unaryop(op) ((opinfo[op]&OPBIN)==0)
|
||||
#define leaf(op) ((opinfo[op]&OPTERM)!=0)
|
||||
#define lvalop(op) ((opinfo[op]&OPLVAL)!=0)
|
||||
#define oppriority(op) (opinfo[op]&OPPRI)
|
||||
#define makeiop(op) (op|(0254<<8))
|
||||
/* checks for symbol with structure element storage class */
|
||||
#define isstel(tp) (tp->t_op==SYMBOL && (sesc(tp)))
|
||||
#define sesc(t) (t->t_sc==STELCL||t->t_sc==UNELCL||t->t_sc==BFIELDCL)
|
||||
/* peek at next token, if not read token put back, else delete */
|
||||
/* 1 if matched, 0 otherwise */
|
||||
#define peek(tok) ( (peektok=gettok()) == tok )
|
||||
|
||||
#define outcommon(sym,size) printf("\t.comm _%.8s,%ld\n",sym,size)
|
||||
#define outgoto(lab) if( lab > 0 ) printf("\tbra L%d\n",lab)
|
||||
/* change to text segment */
|
||||
#define outtext() printf("\t.text\n")
|
||||
/* change segment to bss */
|
||||
#define outbss() printf("\t.bss\n")
|
||||
/* output global symbol references */
|
||||
#define outextdef(sym) printf("\t.globl _%.8s\n",sym)
|
||||
/* outputs reserved memory [vlh] 3.4 %d => %ld */
|
||||
#define outresmem(size) printf("\t.ds.b %ld\n",size)
|
||||
/* output padding for word alignments */
|
||||
#define outpad() printf("\t.even\n")
|
||||
/* output long constant to assembler */
|
||||
#define outlcon(val) printf("\t.dc.l %d\n",val)
|
||||
/* output label constant */
|
||||
#define outclab(lab) printf("\t.dc.l L%d\n",lab)
|
||||
/* output a label */
|
||||
#define outlab(lab) printf("\tL%d:",lab)
|
||||
/* output function label */
|
||||
#define outflab(sym) printf("\t_%.8s:\n\t~~%.8s:\n",sym,sym)
|
||||
/* output data label */
|
||||
#define outdlab(sym) printf("\t_%.8s:\n",sym)
|
||||
|
||||
/*functions returning pointers*/
|
||||
char *expr();
|
||||
char *talloc();
|
||||
char *tnalloc();
|
||||
char *enalloc();
|
||||
char *snalloc();
|
||||
char *cnalloc();
|
||||
char *lcnalloc();
|
||||
char *fpcnalloc();
|
||||
char *popopd();
|
||||
char *cvopgen();
|
||||
char *arrayref();
|
||||
char *funcref();
|
||||
char *install();
|
||||
char *lookup();
|
||||
char *balpar();
|
||||
char *sbrk();
|
||||
|
||||
long initlist();
|
||||
long dsize();
|
||||
long psize();
|
||||
long dodecl();
|
||||
long dlist();
|
||||
long getdec();
|
||||
long gethex();
|
||||
long getoct();
|
||||
long getfp();
|
||||
long toieee();
|
||||
long toffp();
|
||||
|
||||
int inittype=0;
|
||||
int strassign=0;
|
||||
int begseq=0;
|
||||
|
||||
#define EXPSIZE 1024
|
||||
int exprarea[EXPSIZE]=0;
|
||||
|
||||
int opdontop=0;
|
||||
int pbchar=0;
|
||||
|
||||
struct symbol *symbols=0;
|
||||
struct symbol *symtab[HSIZE]=0;
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
int bol;
|
||||
|
||||
outinit(tp,type) /* returns - none*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
outexpr(tnalloc(INIT,type,0,0,tp));
|
||||
}
|
||||
|
||||
outcforreg(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
outexpr(tnalloc(CFORREG,tp->t_type,0,0,tp));
|
||||
}
|
||||
|
||||
outifgoto(tp,dir,lab)
|
||||
struct tnode *tp;
|
||||
int dir;
|
||||
int lab;
|
||||
{
|
||||
outexpr(tnalloc(IFGOTO,dir,lab,0,tp));
|
||||
}
|
||||
|
||||
outexpr(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( !bol )
|
||||
putchar('\n');
|
||||
printf(".%x\n",lineno);
|
||||
outtree(tp);
|
||||
}
|
||||
|
||||
outtree(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( !tp )
|
||||
return;
|
||||
printf("%x.%x",tp->t_op,tp->t_type);
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case CINT:
|
||||
printf(".%x\n",tp->t_value);
|
||||
break;
|
||||
|
||||
case CLONG:
|
||||
printf(".%x.%x\n",tp->t_lvalue.hiword,tp->t_lvalue.loword);
|
||||
break;
|
||||
|
||||
case CFLOAT: /*[vlh] 3.4*/
|
||||
printf(".%x.%x\n",tp->t_lvalue.hiword,tp->t_lvalue.loword);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
printf(".%x",tp->t_sc);
|
||||
if( tp->t_sc == EXTERNAL )
|
||||
printf(".%.8s\n",tp->t_symbol);
|
||||
else
|
||||
printf(".%x\n",tp->t_offset);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
putchar('\n');
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
case BFIELD:
|
||||
printf(".%x\n",tp->t_dp);
|
||||
outtree(tp->t_left);
|
||||
break;
|
||||
|
||||
default:
|
||||
putchar('\n');
|
||||
outtree(tp->t_left);
|
||||
if( binop(tp->t_op) )
|
||||
outtree(tp->t_right);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* snalloc - symbol node allocation*/
|
||||
/* Allocates a tree symbol node and sets the info in it*/
|
||||
char *snalloc(type,sc,off,dp,ssp) /* returns pointer to node alloc'ed*/
|
||||
int type; /* symbol type*/
|
||||
int sc; /* storage class*/
|
||||
int off; /* offset*/
|
||||
int dp; /* dimension pointer or other info*/
|
||||
int ssp; /* structure size pointer*/
|
||||
{
|
||||
register struct symnode *snp;
|
||||
|
||||
snp = talloc(sizeof(*snp));
|
||||
snp->t_op = SYMBOL;
|
||||
snp->t_sc = sc;
|
||||
snp->t_type = type;
|
||||
snp->t_dp = dp;
|
||||
snp->t_ssp = ssp;
|
||||
snp->t_offset = off;
|
||||
return(snp);
|
||||
}
|
||||
@@ -0,0 +1,827 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#define SOI '\01'
|
||||
#define STEL HSIZE/2
|
||||
|
||||
/*
|
||||
* the following are the cases within gettok, all other cases are
|
||||
* single character unambiguous tokens. Note that we need to take
|
||||
* special care not to interfere with the single character unambiguous
|
||||
* operators, this is why there is a gap between WHITSP and EXCLAM.
|
||||
*/
|
||||
#define BADC 0 /*bad character*/
|
||||
#define WHITSP 101 /*white space*/
|
||||
#define EXCLAM 102 /*exlamation point*/
|
||||
#define DQUOTE 103 /*double quote*/
|
||||
#define PERCNT 104 /*percent sign*/
|
||||
#define AMPER 105 /*ampersand*/
|
||||
#define SQUOTE 106 /*single quote*/
|
||||
#define STAR 107 /*asterisk or mult sign*/
|
||||
#define PLUS 108 /*plus sign*/
|
||||
#define MINUS 109 /*minus sign*/
|
||||
#define SLASH 110 /*divide sign*/
|
||||
#define DIGIT 111 /*0..9*/
|
||||
#define LCAROT 112 /*less than sign*/
|
||||
#define EQUAL 113 /*equals sign*/
|
||||
#define RCAROT 114 /*greater than*/
|
||||
#define ALPHA 115 /*a..z,A..Z and underbar*/
|
||||
#define CAROT 116 /*^*/
|
||||
#define BAR 117 /*vertical bar*/
|
||||
|
||||
char ctype[] {
|
||||
BADC, BADC, BADC, BADC, BADC, BADC, BADC, BADC,
|
||||
BADC, WHITSP, WHITSP, WHITSP, WHITSP, WHITSP, BADC, BADC,
|
||||
BADC, BADC, BADC, BADC, WHITSP, BADC, BADC, BADC,
|
||||
BADC, BADC, BADC, BADC, BADC, BADC, BADC, BADC,
|
||||
WHITSP, EXCLAM, DQUOTE, BADC, BADC, PERCNT, AMPER, SQUOTE,
|
||||
LPAREN, RPAREN, STAR, PLUS, COMMA, MINUS, PERIOD, SLASH,
|
||||
DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
|
||||
DIGIT, DIGIT, COLON, SEMI, LCAROT, EQUAL, RCAROT, QMARK,
|
||||
BADC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, LBRACK, BADC, RBRACK, CAROT, ALPHA,
|
||||
BADC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
||||
ALPHA, ALPHA, ALPHA, LCURBR, BAR, RCURBR, COMPL, BADC
|
||||
};
|
||||
|
||||
/*key word table*/
|
||||
struct resword {
|
||||
char *r_name;
|
||||
int r_value;
|
||||
} reswords[] {
|
||||
"auto", R_AUTO,
|
||||
"break", R_BREAK,
|
||||
"case", R_CASE,
|
||||
"char", R_CHAR,
|
||||
"continue", R_CONTINUE,
|
||||
"do", R_DO,
|
||||
"default", R_DEFAULT,
|
||||
"double", R_DOUBLE,
|
||||
"goto", R_GOTO,
|
||||
"else", R_ELSE,
|
||||
"extern", R_EXTERNAL,
|
||||
"float", R_FLOAT,
|
||||
"for", R_FOR,
|
||||
"if", R_IF,
|
||||
"int", R_INT,
|
||||
"long", R_LONG,
|
||||
"register", R_REGISTER,
|
||||
"return", R_RETURN,
|
||||
"short", R_SHORT,
|
||||
"sizeof", R_SIZEOF,
|
||||
"static", R_STATIC,
|
||||
"struct", R_STRUCT,
|
||||
"switch", R_SWITCH,
|
||||
"typedef", R_TYPEDEF,
|
||||
"union", R_UNION,
|
||||
"unsigned", R_UNSIGNED,
|
||||
"while", R_WHILE,
|
||||
0,
|
||||
};
|
||||
|
||||
#define SELFMOD 0200
|
||||
#define ASMASK 0177
|
||||
|
||||
/*
|
||||
* this table is used to check for an operator after an equals sign.
|
||||
* note that =-, =* and =& may all have an ambiguous meaning if not
|
||||
* followed by a space, this is checked for in gettok.
|
||||
*/
|
||||
char asmap[] {
|
||||
EQUALS, /*==*/
|
||||
EQADD, /*=+*/
|
||||
EQSUB|SELFMOD, /*=-*/
|
||||
EQMULT|SELFMOD, /*=**/
|
||||
EQDIV, /*=/*/
|
||||
EQOR, /*=|*/
|
||||
EQAND|SELFMOD, /*=&*/
|
||||
EQXOR, /*=^*/
|
||||
EQMOD, /*=%*/
|
||||
};
|
||||
|
||||
char escmap[] "\b\n\r\t";
|
||||
int pbchar; /*pushed back character*/
|
||||
struct symbol *symtab[HSIZE]; /*hash table*/
|
||||
struct symbol *symbols; /*pointer to next avail symbol buf*/
|
||||
int nsyms; /*number of symbol bufs in memory*/
|
||||
|
||||
/*
|
||||
* getdec - get a decimal number
|
||||
* Uses Horner's method to get decimal number. Note that
|
||||
* multiplication by 10 is cleverly programmed as two shifts and two
|
||||
* adds. This is because long multiplies are painful on both the
|
||||
* PDP-11 and 68000.
|
||||
*/
|
||||
long getdec() /* returns number*/
|
||||
{
|
||||
register long value;
|
||||
register char c;
|
||||
|
||||
for( value = 0; (c=ngetch()) >= '0' && c <= '9'; ) {
|
||||
value =<< 1; /*value = value*2*/
|
||||
value =+ value << 2; /*value*2 + value*8 = value*10*/
|
||||
value =+ (c-'0');
|
||||
}
|
||||
putback(c);
|
||||
return(value);
|
||||
}
|
||||
|
||||
#define BIAS 127L
|
||||
#define EXPSIZ 4
|
||||
#define FRACSIZ 20
|
||||
|
||||
long toieee();
|
||||
long toffp();
|
||||
float power10();
|
||||
|
||||
/*
|
||||
* getfp - get a floating point constant
|
||||
* we've already gotten the significant digits, now build a
|
||||
* floating point number with possible decimal digits and an
|
||||
* exponent, yields an ieee formated floating point number,
|
||||
* unless the fflag is on, then a ffp constant is generated.
|
||||
*/
|
||||
long
|
||||
getfp(significant)
|
||||
long significant;
|
||||
{
|
||||
register char c;
|
||||
register long places; /* decimal places */
|
||||
int esign;
|
||||
float exp, fraction, fp;
|
||||
|
||||
places = 0L; esign = 0; fraction = significant; exp = 0.0;
|
||||
if ((c = ngetch()) == '.') /* get decimal places */
|
||||
for( ; (c=ngetch()) >= '0' && c <= '9';) {
|
||||
fraction = fraction * 10.0;
|
||||
fraction = fraction + (c - '0');
|
||||
places++;
|
||||
}
|
||||
|
||||
if (c=='e' || c=='E') { /* exponent exists */
|
||||
esign = (peekis('-')) ? 1 : (peekis('+')) ? 0 : 0;
|
||||
for( ; (c=ngetch()) >= '0' && c <= '9'; ) {
|
||||
exp = exp * 10.0;
|
||||
exp = exp + (c - '0');
|
||||
}
|
||||
}
|
||||
|
||||
putback(c);
|
||||
if (esign)
|
||||
exp = -exp;
|
||||
places = exp - places;
|
||||
fp = fraction * power10(places);
|
||||
if (fflag)
|
||||
return( toffp(fp) );
|
||||
else
|
||||
return ( toieee(fp) );
|
||||
}
|
||||
|
||||
float
|
||||
power10(pwr) /* used by getfp, 10^pwr */
|
||||
long pwr;
|
||||
{
|
||||
float f;
|
||||
|
||||
if (pwr < 0L) /* negative power */
|
||||
for (f = 1.0; pwr < 0L; pwr++)
|
||||
f = f / 10.0;
|
||||
else /* positive power */
|
||||
for (f = 1.0; pwr > 0L; pwr--)
|
||||
f = f * 10.0;
|
||||
return(f);
|
||||
}
|
||||
|
||||
long
|
||||
toffp(f) /* converts current machine float to ffp rep */
|
||||
float f;
|
||||
{
|
||||
register long exp;
|
||||
register int sign, count;
|
||||
long l;
|
||||
|
||||
if (f == 0.0)
|
||||
return(0L);
|
||||
if (f < 0.0) {
|
||||
sign = 1;
|
||||
f = -f;
|
||||
}
|
||||
else
|
||||
sign = 0;
|
||||
exp = 0L;
|
||||
for( ; f >= 1.0; f = f / 2.0)
|
||||
exp++;
|
||||
for( ; f < 0.5; f = f * 2.0)
|
||||
exp--;
|
||||
f = f * 16777216.0; /* 2 ^ 24 */
|
||||
l = f;
|
||||
l =<< 8;
|
||||
if (sign)
|
||||
l =| 0x80;
|
||||
exp =+ 0x40;
|
||||
l =| (exp & 0x7f);
|
||||
return(l);
|
||||
}
|
||||
|
||||
long
|
||||
toieee(f) /* converts current machine float to ieee rep */
|
||||
float f;
|
||||
{
|
||||
register long exp;
|
||||
register int sign, count;
|
||||
long l;
|
||||
|
||||
if (f == 0.0)
|
||||
return(0L);
|
||||
if (f < 0.0) {
|
||||
sign = 1;
|
||||
f = -f;
|
||||
}
|
||||
else
|
||||
sign = 0;
|
||||
exp = 0L;
|
||||
for( ; f >= 2.0; f = f / 2.0)
|
||||
exp++;
|
||||
for( ; f < 1.0; f = f * 2.0)
|
||||
exp--;
|
||||
f = f - 1.0;
|
||||
f = f * 8388608.0; /* 2 ^ 23 */
|
||||
l = f;
|
||||
if (sign)
|
||||
l =| 0x80000000;
|
||||
exp = (exp + BIAS)<<23;
|
||||
l =| (exp & 0x7f800000);
|
||||
return(l);
|
||||
}
|
||||
|
||||
#define toupper(c) ((c) & ~32)
|
||||
/* gethex - get an hexidecimal number*/
|
||||
/* Uses Horner's method to get hexidecimal number*/
|
||||
long gethex() /* returns number*/
|
||||
{
|
||||
register long value;
|
||||
register char c, ch;
|
||||
|
||||
value = 0;
|
||||
while( 1 ) {
|
||||
if( (c=ngetch()) >= '0' && c <= '9' )
|
||||
c =- '0';
|
||||
else if((ch=toupper(c)) >= 'A' && ch <= 'F' ) /* [vlh] */
|
||||
c = ch - ('A'-10);
|
||||
else
|
||||
break;
|
||||
value = (value<<4) + c;
|
||||
}
|
||||
putback(c);
|
||||
return(value);
|
||||
}
|
||||
|
||||
/* getoct - get an octal number*/
|
||||
/* Uses Horner's method to get octal number*/
|
||||
long getoct(flag) /* returns number*/
|
||||
int flag; /* string flag 1=>in string, else 0*/
|
||||
{
|
||||
register long value;
|
||||
register char c;
|
||||
register int count;
|
||||
|
||||
count = 0;
|
||||
for( value = 0; (c=ngetch()) >= '0' && c <= '7'; ) {
|
||||
if( flag && ++count > 3 )
|
||||
break;
|
||||
value = (value<<3) + (c-'0');
|
||||
}
|
||||
putback(c);
|
||||
return(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* gettok - get next token from input
|
||||
* Checks pushed-packed token buffer, supresses / * * / comments,
|
||||
* folds multiple character special symbols into single word token.
|
||||
*/
|
||||
gettok() /* returns token type*/
|
||||
{
|
||||
register int c, nextc, i;
|
||||
register char *p;
|
||||
register long value;
|
||||
char sym[SSIZE];
|
||||
|
||||
if( peektok ) {
|
||||
i = peektok;
|
||||
peektok = 0;
|
||||
return(i);
|
||||
}
|
||||
while( (c=ngetch()) != EOF ) {
|
||||
switch(ctype[c]) {
|
||||
|
||||
case BADC: /*bad character*/
|
||||
error("invalid character");
|
||||
break;
|
||||
|
||||
case SEMI:
|
||||
cvalue = 0; /* [vlh] not reserved word... */
|
||||
default:
|
||||
return( ctype[c] );
|
||||
|
||||
case WHITSP: /*skip all white space*/
|
||||
break;
|
||||
|
||||
case EXCLAM: /*!= or !*/
|
||||
return( peekis('=') ? NEQUALS : NOT );
|
||||
|
||||
case DQUOTE: /*quoted string*/
|
||||
getstr(cstr,STRSIZE,'"');
|
||||
cvalue = nextlabel++;
|
||||
return(STRING);
|
||||
|
||||
case PERCNT: /*%= or %*/
|
||||
return( peekis('=') ? EQMOD : MOD );
|
||||
|
||||
case AMPER: /*&=, && or &*/
|
||||
return( peekis('=') ? EQAND : peekis('&') ? LAND : AND );
|
||||
|
||||
case SQUOTE: /*character constant*/
|
||||
getstr(cstr,STRSIZE,'\'');
|
||||
if( cstrsize > CHRSPWORD+1 ) {
|
||||
error("character constant too long");
|
||||
cstrsize = CHRSPWORD + 1;
|
||||
}
|
||||
cvalue = 0;
|
||||
for( p = cstr; --cstrsize > 0; ) {
|
||||
cvalue =<< BITSPCHAR;
|
||||
cvalue =| (*p++ & 0377);
|
||||
}
|
||||
return(CINT);
|
||||
|
||||
case STAR: /**= or **/
|
||||
return( peekis('=') ? EQMULT : MULT );
|
||||
|
||||
case PLUS: /*+=, ++ or +*/
|
||||
return( peekis('=') ? EQADD : peekis('+') ? PREINC : ADD );
|
||||
|
||||
case MINUS: /*-=, --, -> or -*/
|
||||
return( peekis('=') ? EQSUB : peekis('-') ? PREDEC :
|
||||
peekis('>') ? APTR : SUB );
|
||||
|
||||
case SLASH: /*/ *..* /, //..., /= or /*/
|
||||
if( peekis('*') ) {
|
||||
while( (c=ngetch()) != EOF )
|
||||
if( c == '*' && peekis('/') )
|
||||
break;
|
||||
if( c == EOF ) {
|
||||
error("no */ before EOF");
|
||||
return(EOF);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if( peekis('/') ) {
|
||||
while( (c=ngetch()) != EOF && c != EOLC )
|
||||
;
|
||||
continue;
|
||||
}
|
||||
return( peekis('=') ? EQDIV : DIV );
|
||||
|
||||
case DIGIT: /*number constant (long or reg)*/
|
||||
i = 0; /*flags if long constant*/
|
||||
if( c != '0' ) {
|
||||
putback(c);
|
||||
dofp:
|
||||
value = getdec();
|
||||
if ((c=ngetch())=='.' || c=='e' || c=='E') { /*[vlh] 3.4 */
|
||||
putback(c);
|
||||
clvalue = getfp(value);
|
||||
return(CFLOAT);
|
||||
}
|
||||
putback(c);
|
||||
if( value > 32767 || value < -32768 )
|
||||
i++;
|
||||
}
|
||||
else if( peekis('x') || peekis('X') ) {
|
||||
value = gethex();
|
||||
if( value < 0 || value >= 0x10000L )
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
if (peekis('.')) {
|
||||
putback('.');
|
||||
goto dofp;
|
||||
}
|
||||
value = getoct(0);
|
||||
if( value < 0 || value >= 0x10000L )
|
||||
i++;
|
||||
}
|
||||
if( peekis('l') || peekis('L') || i ) {
|
||||
clvalue = value;
|
||||
return(CLONG);
|
||||
}
|
||||
cvalue = value;
|
||||
return(CINT);
|
||||
|
||||
case LCAROT: /*<=, <<, <<= or <*/
|
||||
return( peekis('=') ? LESSEQ : peekis('<') ?
|
||||
(peekis('=') ? EQLSH : LSH) : LESS );
|
||||
|
||||
case EQUAL: /*==, =<<, =>>, =+, ..., =*/
|
||||
if( peekis('<') ) {
|
||||
if( peekis('<') )
|
||||
return(EQLSH);
|
||||
}
|
||||
else if( peekis('>') ) {
|
||||
if( peekis('>') )
|
||||
return(EQRSH);
|
||||
}
|
||||
else if( (i=index("=+-*/|&^%",(c=ngetch()))) >= 0 ) {
|
||||
i = asmap[i];
|
||||
if( i & SELFMOD ) {
|
||||
if( (nextc=ngetch()) != ' ' )
|
||||
if (!wflag) /*[vlh] old fashion initialization*/
|
||||
error("=%c assumed",c);
|
||||
putback(nextc);
|
||||
}
|
||||
return( i & ASMASK );
|
||||
}
|
||||
else
|
||||
putback(c);
|
||||
return(ASSIGN);
|
||||
|
||||
case RCAROT: /*>=, >>, >>= or >*/
|
||||
return( peekis('=') ? GREATEQ : peekis('>') ?
|
||||
(peekis('=') ? EQRSH : RSH) : GREAT );
|
||||
|
||||
case ALPHA: /*[A-Za-z][A-Za-z0-9]**/
|
||||
p = &sym[0];
|
||||
i = SSIZE;
|
||||
for(; ctype[c] == ALPHA || ctype[c] == DIGIT; c=ngetch(),i-- )
|
||||
if( i > 0 )
|
||||
*p++ = c;
|
||||
if( i > 0 )
|
||||
*p = '\0';
|
||||
putback(c);
|
||||
csp = lookup(sym);
|
||||
if( csp->s_attrib & SRESWORD ) {
|
||||
cvalue = csp->s_offset;
|
||||
return(RESWORD);
|
||||
}
|
||||
smember = 0;
|
||||
return(SYMBOL);
|
||||
|
||||
case CAROT: /*^= or ^*/
|
||||
return( peekis('=') ? EQXOR : XOR );
|
||||
|
||||
case BAR: /*|=, || or |*/
|
||||
return( peekis('=') ? EQOR : peekis('|') ? LOR : OR );
|
||||
|
||||
}
|
||||
}
|
||||
return(EOF);
|
||||
}
|
||||
|
||||
/*
|
||||
* peekis - peeks at next character for specific character
|
||||
* Gets next (possibly pushed back) character, if it matches
|
||||
* the given character 1 is returned, otherwise the character
|
||||
* is put back.
|
||||
*/
|
||||
peekis(tc) /* returns 1 if match, 0 otherwise*/
|
||||
int tc; /* test character*/
|
||||
{
|
||||
register int c;
|
||||
|
||||
if( (c=ngetch()) == tc )
|
||||
return(1);
|
||||
putback(c);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* ngetch - get a possibly pushed back character*/
|
||||
/* Checks pbchar variable, returns it if non-zero, handles counting*/
|
||||
/* of new lines and whether you are in an include or not.*/
|
||||
ngetch() /* returns character read or EOF*/
|
||||
{
|
||||
register int c;
|
||||
register char *ifile;
|
||||
|
||||
if( pbchar ) {
|
||||
c = pbchar;
|
||||
pbchar = 0;
|
||||
}
|
||||
else if( (c=getc(&ibuf)) == EOLC ) {
|
||||
if( inclflag )
|
||||
inclflag = 0;
|
||||
else
|
||||
lineno++;
|
||||
}
|
||||
else if( c == SOI) { /*[vlh]add incl filename & line # */
|
||||
inclflag++;
|
||||
ifile = &inclfile;
|
||||
while ((c=getc(&ibuf)) != SOI)
|
||||
*ifile++ = c&0377;
|
||||
*ifile = 0;
|
||||
inclline = getdec() & 077777;
|
||||
c = ' ';
|
||||
}
|
||||
else if( c < 0 )
|
||||
c = EOF;
|
||||
return(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* peekc - peek at the next non-whitespace character after token
|
||||
* This allows for the problem of having to look at two tokens
|
||||
* at once. The second token is always a semi-colon or colon,
|
||||
* so we only look at the single character, rather than going
|
||||
* thru gettok.
|
||||
*/
|
||||
peekc(tc) /* returns 1 if match, 0 otherwise*/
|
||||
int tc; /* character to look for*/
|
||||
{
|
||||
register int c;
|
||||
|
||||
while( ctype[(c=ngetch())] == WHITSP) ;
|
||||
if( c == tc )
|
||||
return(1);
|
||||
putback(c);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* putback - puts back a single character*/
|
||||
/* Checks pbchar for error condition.*/
|
||||
putback(c) /* returns - none*/
|
||||
int c;
|
||||
{
|
||||
if( pbchar )
|
||||
error("too many chars pushed back");
|
||||
else
|
||||
pbchar = c;
|
||||
}
|
||||
|
||||
/* getstr - get a quoted (single or double) character string*/
|
||||
/* Gets specified number of characters, handling escapes.*/
|
||||
getstr(str,nchars,endc) /* returns - none*/
|
||||
char *str; /* pointer to string buffer*/
|
||||
int nchars; /* max number of characters*/
|
||||
char endc; /* ending string character*/
|
||||
{
|
||||
register char *p;
|
||||
register int i;
|
||||
register int c;
|
||||
register int j;
|
||||
|
||||
cstrsize = 1;
|
||||
p = str;
|
||||
for( i = nchars; (c=ngetch()) != endc; i-- ) {
|
||||
if( c == EOF || c == EOLC ) {
|
||||
error("string cannot cross line");
|
||||
break;
|
||||
}
|
||||
if( c == '\\' ) {
|
||||
if( (c=ngetch()) >= '0' && c <= '7' ) {
|
||||
putback(c);
|
||||
if( (c=getoct(1)) < 0 || c > 255 ) {
|
||||
error("bad character constant");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if( (j=index("bnrt",c)) >= 0 )
|
||||
c = escmap[j];
|
||||
else if( c == EOLC ) /*escape followed by nl->ignore*/
|
||||
continue;
|
||||
}
|
||||
if( i > 0 ) { /*room left in string?*/
|
||||
cstrsize++;
|
||||
*p++ = c;
|
||||
}
|
||||
else if( !i ) /*only say error once...*/
|
||||
error("string too long");
|
||||
}
|
||||
if( i <= 0 ) /*string overflow?*/
|
||||
p--;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/* syminit - initialize the symbol table, install reswords*/
|
||||
/* Goes thru the resword table and installs them into the symbol*/
|
||||
/* table.*/
|
||||
syminit() /* returns - none*/
|
||||
{
|
||||
register struct resword *rp;
|
||||
|
||||
for( rp = &reswords[0]; rp->r_name != 0; rp++ )
|
||||
install(rp->r_name,SRESWORD|SDEFINED,rp->r_value);
|
||||
}
|
||||
|
||||
/* install - install a symbol in the symbol table*/
|
||||
/* Allocates a symbol entry, copies info into it and links it*/
|
||||
/* into the hash table chain.*/
|
||||
char *install(sym,attrib,offset) /* returns pointer to symbol struct*/
|
||||
char *sym; /* symbol to install*/
|
||||
int attrib; /* attribues of symbol*/
|
||||
int offset; /* symbol offset (resword value)*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
register int i;
|
||||
|
||||
while( !(sp=symbols) ) {
|
||||
if( !(sp=sbrk(SYMSIZE)) )
|
||||
ferror("symbol table overflow");
|
||||
for( i = SYMSIZE/(sizeof *symbols); --i >= 0; ) {
|
||||
sp->s_next = symbols;
|
||||
symbols = sp++;
|
||||
}
|
||||
}
|
||||
symbols = sp->s_next;
|
||||
sp->s_attrib = attrib;
|
||||
sp->s_sc = 0; sp->s_type = 0; sp->s_dp = 0; sp->s_ssp = 0;
|
||||
sp->s_offset = offset;
|
||||
sp->s_struc = (instruct) ? strucptr[smember+instruct] : 0;
|
||||
symcopy(sym,sp->s_symbol); /*copy symbol to symbol struct*/
|
||||
i = symhash(sym,instruct|smember); /*link into chain list*/
|
||||
sp->s_next = symtab[i];
|
||||
symtab[i] = sp;
|
||||
return(sp);
|
||||
}
|
||||
|
||||
/* lookup - looks up a symbol in symbol table*/
|
||||
/* Hashes symbol, then goes thru chain, if not found, then*/
|
||||
/* installs the symbol.*/
|
||||
char *lookup(sym) /* returns pointer to symbol buffer*/
|
||||
char *sym; /* pointer to symbol*/
|
||||
{
|
||||
register struct symbol *sp, *hold;
|
||||
register char *p;
|
||||
int exact; /* same name, diff type or offset */
|
||||
|
||||
p = sym;
|
||||
for( sp = symtab[symhash(p,0)]; sp != 0; sp = sp->s_next )
|
||||
if((sp->s_attrib&(SRESWORD|STYPEDEF)) && symequal(p,sp->s_symbol))
|
||||
return(sp);
|
||||
if (!(smember|instruct)) { /*[vlh]*/
|
||||
for( sp=symtab[symhash(p,0)]; sp!=0; sp=sp->s_next )
|
||||
if( symequal(p,sp->s_symbol) ) return(sp);
|
||||
}
|
||||
else { /* doing a declaration or an expression */
|
||||
hold = 0; exact = 0;
|
||||
for( sp=symtab[symhash(p,instruct|smember)]; sp!=0; sp=sp->s_next )
|
||||
if( symequal(p,sp->s_symbol) )
|
||||
if (symsame(sp,hold,&exact)) return(sp);
|
||||
else if (!hold && !exact) hold = sp;
|
||||
if (hold && !exact) return(hold);
|
||||
}
|
||||
return(install(p,0,0));
|
||||
}
|
||||
|
||||
/* freesyms - frees all local symbols at end of function declaration*/
|
||||
/* Searches thru symbol table, deleting all symbols marked as locals*/
|
||||
freesyms() /* returns - none*/
|
||||
{
|
||||
register int i, tinfo;
|
||||
register struct symbol *sp, *tp, *nextp, **htp;
|
||||
|
||||
for( htp = &symtab[0], i = HSIZE; --i >= 0; htp++ )
|
||||
for( tp = 0, sp = *htp; sp != 0; sp = nextp ) {
|
||||
nextp = sp->s_next;
|
||||
if( !(sp->s_attrib&SDEFINED) ) {
|
||||
error("undefined label: %.8s",sp->s_symbol);
|
||||
sp->s_attrib =| SDEFINED;
|
||||
}
|
||||
if( sp->s_attrib & (SGLOBAL|SRESWORD) )
|
||||
tp = sp;
|
||||
else {
|
||||
if( tp )
|
||||
tp->s_next = sp->s_next;
|
||||
else
|
||||
*htp = sp->s_next;
|
||||
sp->s_next = symbols;
|
||||
symbols = sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* chksyms - checks symbol table for undefined symbols, etc.*/
|
||||
/* Goes thru the symbol table checking for undeclared forward*/
|
||||
/* referenced structures, and outputs local symbols for debugger.*/
|
||||
chksyms() /* returns - none*/
|
||||
{
|
||||
register struct symbol **htp, *sp;
|
||||
register int i, sc;
|
||||
|
||||
for( htp = &symtab[0], i = HSIZE; --i >= 0; htp++ )
|
||||
for( sp = *htp; sp != 0; sp = sp->s_next ) {
|
||||
sc = sp->s_sc;
|
||||
if(sc!=0 && sp->s_ssp>=0 && (btype(sp->s_type))==FRSTRUCT) {
|
||||
sp->s_ssp = frstab[sp->s_ssp]->s_ssp; /* 3.4 ssp>0 */
|
||||
sp->s_type = (sp->s_type&~TYPE) | STRUCT;
|
||||
}
|
||||
if( sc == PDECLIST ) {
|
||||
error("not in parameter list: %.8s",sp->s_symbol);
|
||||
sp->s_sc = AUTO;
|
||||
}
|
||||
if( infunc )
|
||||
outlocal(sp->s_type,sp->s_sc,sp->s_symbol,sp->s_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* symhash - compute hash value for symbol*/
|
||||
/* Sums the symbols characters and takes that modulus the hash table*/
|
||||
/* size.*/
|
||||
symhash(sym,stel) /* returns hash value for symbol*/
|
||||
char *sym; /* pointer to symbol*/
|
||||
int stel; /* structure element flag*/
|
||||
{
|
||||
register char *p;
|
||||
register int hashval, i;
|
||||
|
||||
hashval = (stel ? STEL : 0 );
|
||||
for( p = sym, i = SSIZE; *p != '\0' && i > 0; i-- )
|
||||
hashval =+ *p++;
|
||||
return( hashval % HSIZE );
|
||||
}
|
||||
|
||||
/* symequal - check for symbol equality*/
|
||||
/* Does comparison between two symbols.*/
|
||||
symequal(sym1,sym2) /* returns 1 if equal, 0 otherwise*/
|
||||
char *sym1; /* pointer to first symbol*/
|
||||
char *sym2; /* pointer to second symbol*/
|
||||
{
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
for( p = sym1, q = sym2, i = SSIZE; *p == *q++; )
|
||||
if( *p++ == '\0' || --i == 0 )
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* symsame - symbol member same as declared */
|
||||
symsame(sp,hold,exact) /* [vlh] */
|
||||
struct symbol *sp, *hold;
|
||||
int *exact;
|
||||
{
|
||||
if (strucptr[smember+instruct])
|
||||
if (strucptr[smember+instruct]==sp->s_struc) return(1);
|
||||
if (hold)
|
||||
if (sp->s_type != hold->s_type || sp->s_offset != hold->s_offset)
|
||||
*exact = 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* symcopy - symbol copy*/
|
||||
/* Copies one symbol to another.*/
|
||||
symcopy(sym1,sym2) /* returns - none*/
|
||||
char *sym1; /* pointer to symbol to copy*/
|
||||
char *sym2; /* pointer to area to copy to*/
|
||||
{
|
||||
register char *p, *q;
|
||||
register int i;
|
||||
|
||||
for( p = sym1, q = sym2, i = SSIZE; --i >= 0; )
|
||||
*q++ = ( *p ? *p++ : '\0');
|
||||
}
|
||||
|
||||
/* index - find the index of a character in a string*/
|
||||
/* This is identical to Software Tools index.*/
|
||||
index(str,chr) /* returns index of c in str or -1*/
|
||||
char *str; /* pointer to string to search*/
|
||||
char chr; /* character to search for*/
|
||||
{
|
||||
register char *s;
|
||||
register int i;
|
||||
|
||||
for( s = str, i = 0; *s != '\0'; i++ )
|
||||
if( *s++ == chr )
|
||||
return(i);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* next - if next token matches given token, skip and return success*/
|
||||
/* This allows for clean parsing of declarations.*/
|
||||
next(tok) /* returns 1 if matched, 0 otherwise*/
|
||||
int tok;
|
||||
{
|
||||
register int token;
|
||||
|
||||
if( (token=gettok()) == tok )
|
||||
return(1);
|
||||
peektok = token;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* pbtok - put back the given token*/
|
||||
/* This merely sets the peektok variable*/
|
||||
pbtok(tok) /* returns - none*/
|
||||
int tok;
|
||||
{
|
||||
if( peektok )
|
||||
error("too many tokens pushed back");
|
||||
peektok = tok;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
$1lo68 -r -f $1 -unofloat 0$1s.o DECL.o EXPR.o ICODE.o INTERF.o LEX.o MAIN.o STMT.o TABL.o 0$1lib6.a 0$1libF.a 0$1clib
|
||||
era *.o
|
||||
era c068.rel
|
||||
ren c068.rel=c.out
|
||||
user 13!make $1
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
$ num
|
||||
DECL.C
|
||||
DECL.lis
|
||||
$ num
|
||||
EXPR.C
|
||||
EXPR.lis
|
||||
$ num
|
||||
ICODE.C
|
||||
ICODE.lis
|
||||
$ num
|
||||
INIT.C
|
||||
INIT.lis
|
||||
$ num
|
||||
INTERF.C
|
||||
INTERF.lis
|
||||
$ num
|
||||
LEX.C
|
||||
LEX.lis
|
||||
$ num
|
||||
MAIN.C
|
||||
MAIN.lis
|
||||
$ num
|
||||
STMT.C
|
||||
STMT.lis
|
||||
$ num
|
||||
TABL.C
|
||||
TABL.lis
|
||||
$ num
|
||||
VERSION.C
|
||||
VERSION.lis
|
||||
$ num
|
||||
ICODE.H
|
||||
ICODE.lst
|
||||
$ num
|
||||
MACHINE.H
|
||||
MACHINE.lst
|
||||
$ num
|
||||
PARSER.H
|
||||
PARSER.lst
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1*/ /* 68000 version */
|
||||
/*#define VAX 1*/ /* VAX Version */
|
||||
#define PDP11 1 /* PDP-11 Version*/
|
||||
/*#define CPM 1*/ /* CP/M Operating System*/
|
||||
#define UNIX 1 /* UNIX Operating System*/
|
||||
/*#define VMS 1*/ /* VMS Operating System*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
#define MC68000 1 /* 68000 version */
|
||||
/*#define VAX 1*/ /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
#define CPM 1 /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
/*#define VMS 1*/ /* VMS Operating System*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1*/ /* 68000 version */
|
||||
#define VAX 1 /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
/*#define CPM 1*/ /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
#define VMS 1 /* VMS Operating System*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1*/ /* 68000 version */
|
||||
#define VAX 1 /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
/*#define CPM 1*/ /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
#define VMS 1 /* VMS Operating System*/
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
char *version "@(#) c068 parser 4.0 - Feb 11, 1983";
|
||||
/*
|
||||
ALCYON C Compiler for the Motorola 68000 - Parser
|
||||
|
||||
Called from c68:
|
||||
|
||||
c068 source icode strings
|
||||
|
||||
source: input source code, preprocessed with comments stripped
|
||||
|
||||
icode: contains the intermediate code for the code generator,
|
||||
for a detailed explanaion see ../doc/icode.
|
||||
|
||||
strings: contains all the string constants.
|
||||
|
||||
The basic structure of the parser is as follows:
|
||||
|
||||
main main driver for parser
|
||||
syminit initializes symbol table
|
||||
doextdef external definition syntax
|
||||
getatt get type attributes
|
||||
dlist declaration list for structures/unions
|
||||
getatt recursive gettype call
|
||||
dodecl do one declaration
|
||||
declarator handle declarator syntax
|
||||
dodecl do one external declaraion
|
||||
initlist external initialization list
|
||||
cexpr constant expressions
|
||||
expr arithmetic expressions
|
||||
maketree build operator tree
|
||||
funcbody function body
|
||||
dlist declaration list
|
||||
stmt function statements
|
||||
stmt recursive stmt call
|
||||
expr arithmetic expressions
|
||||
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
int nextlabel 1;
|
||||
int lineno;
|
||||
char *exprp &exprarea[0];
|
||||
|
||||
/*
|
||||
* main - main routine for parser
|
||||
* Checks arguments, opens input and output files, does main loop
|
||||
* for external declarations and blocks.
|
||||
*/
|
||||
main(argc,argv) /* returns - none*/
|
||||
int argc; /* argument count*/
|
||||
char *argv[]; /* argument pointers*/
|
||||
{
|
||||
register char *q;
|
||||
register int i;
|
||||
|
||||
for( i = 4; i < argc; i++ ) {
|
||||
q = argv[i];
|
||||
if( *q++ != '-' )
|
||||
usage();
|
||||
while( 1 ) {
|
||||
switch( *q++ ) {
|
||||
|
||||
case 'F':
|
||||
case 'f':
|
||||
fflag++;
|
||||
continue;
|
||||
|
||||
case 'E':
|
||||
case 'e':
|
||||
eflag++;
|
||||
continue;
|
||||
|
||||
case 'W':
|
||||
case 'w':
|
||||
wflag++;
|
||||
continue;
|
||||
|
||||
case '\0':
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( argc < 4 )
|
||||
usage();
|
||||
if( fopen(argv[1],&ibuf,0) < 0 ) /* 3rd arg for versados */
|
||||
ferror("can't open %s",argv[i]);
|
||||
if( fcreat(argv[2],&obuf,0) < 0 || fcreat(argv[3],&sbuf,0) < 0 )
|
||||
ferror("temp creation error");
|
||||
obp = &obuf;
|
||||
lineno++;
|
||||
frstp = -1; /* [vlh] 3.4 - initialize only once */
|
||||
syminit();
|
||||
while( !peek(EOF) )
|
||||
doextdef();
|
||||
outeof();
|
||||
outdata();
|
||||
copysfile(argv[3]);
|
||||
exit(errcnt!=0);
|
||||
}
|
||||
|
||||
/* usage - output usage error message and die*/
|
||||
usage()
|
||||
{
|
||||
ferror("usage: c068 source icode str [-e] [-f] [-w]");
|
||||
}
|
||||
|
||||
/* error - report an error message*/
|
||||
/* outputs current line number and error message*/
|
||||
error(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* error message*/
|
||||
int x1, x2, x3, x4, x5, x6; /* args for printf*/
|
||||
{
|
||||
register char *savep;
|
||||
|
||||
savep = obp;
|
||||
obp = 0;
|
||||
errcnt++;
|
||||
if (!inclflag) {
|
||||
if( lineno )
|
||||
printf("* %d: ",lineno);
|
||||
}
|
||||
else /*[vlh] generate filename and approp line #*/
|
||||
printf("%s: * %d: ",inclfile,inclline);
|
||||
printf(s,x1,x2,x3,x4,x5,x6);
|
||||
printf("\n");
|
||||
obp = savep;
|
||||
}
|
||||
|
||||
/* ferror - fatal error*/
|
||||
/* Outputs error message and exits*/
|
||||
ferror(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* error message*/
|
||||
int x1, x2, x3, x4, x5, x6; /* args for printf*/
|
||||
{
|
||||
error(s,x1,x2,x3,x4,x5,x6);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
v6flush(v6buf)
|
||||
struct iobuf *v6buf;
|
||||
{
|
||||
register i;
|
||||
|
||||
i = BLEN - v6buf->nunused;
|
||||
v6buf->nunused = BLEN;
|
||||
v6buf->xfree = &(v6buf->buff[0]);
|
||||
if(write(v6buf->fildes,v6buf->xfree,i) != i)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
printf(string,a,b,c,d,e,f,g)
|
||||
char *string;
|
||||
int a,b,c,d,e,f,g;
|
||||
{
|
||||
char area[256];
|
||||
register char *p;
|
||||
|
||||
sprintf(area,string,a,b,c,d,e,f,g);
|
||||
for(p = &area[0]; *p; p++)
|
||||
putchar(*p);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
$1stat machine.h=rw
|
||||
$1pip machine.h=machine.68k
|
||||
|
||||
|
||||
$1cp68 -i 0$1 DECL.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic DECL.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u DECL.s
|
||||
era DECL.s
|
||||
|
||||
$1cp68 -i 0$1 EXPR.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic EXPR.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u EXPR.s
|
||||
era EXPR.s
|
||||
|
||||
$1cp68 -i 0$1 ICODE.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic ICODE.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u ICODE.s
|
||||
era ICODE.s
|
||||
|
||||
$1cp68 -i 0$1 INTERF.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic INTERF.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u INTERF.s
|
||||
era INTERF.s
|
||||
|
||||
$1cp68 -i 0$1 LEX.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic LEX.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u LEX.s
|
||||
era LEX.s
|
||||
|
||||
$1cp68 -i 0$1 MAIN.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic MAIN.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u MAIN.s
|
||||
era MAIN.s
|
||||
|
||||
$1cp68 -i 0$1 STMT.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic STMT.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u STMT.s
|
||||
era STMT.s
|
||||
|
||||
$1cp68 -i 0$1 TABL.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic TABL.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u TABL.s
|
||||
era TABL.s
|
||||
|
||||
$1cp68 -i 0$1 VERSION.c $1x.i
|
||||
$1c068 $1x.i $1x.ic $1x.st -f
|
||||
$1c168 $1x.ic VERSION.s -LD
|
||||
era $1x.i
|
||||
era $1x.ic
|
||||
era $1x.st
|
||||
$1as68 -s 0$1 -f $1 -l -u VERSION.s
|
||||
era VERSION.s
|
||||
|
||||
link $1
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*
|
||||
C68 Parser - include file
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <klib.h>
|
||||
#undef putchar
|
||||
#define putchar xputchar
|
||||
#undef ferror
|
||||
#define printf xprintf
|
||||
#include "icode.h"
|
||||
|
||||
/*symbol attribute fields*/
|
||||
#define SRESWORD 001 /*is symbol a reserved word?*/
|
||||
#define SGLOBAL 002 /*is symbol global?*/
|
||||
#define STYPEDEF 004 /*typedef declaration?*/
|
||||
#define SDEFINED 010 /*symbol defined?*/
|
||||
|
||||
/*reserved words*/
|
||||
#define R_AUTO 1
|
||||
#define R_BREAK 2
|
||||
#define R_CASE 3
|
||||
#define R_CHAR 4
|
||||
#define R_CONTINUE 5
|
||||
#define R_DO 6
|
||||
#define R_DEFAULT 7
|
||||
#define R_DOUBLE 8
|
||||
#define R_GOTO 9
|
||||
#define R_ELSE 10
|
||||
#define R_EXTERNAL 11
|
||||
#define R_FLOAT 12
|
||||
#define R_FOR 13
|
||||
#define R_IF 14
|
||||
#define R_INT 15
|
||||
#define R_LONG 16
|
||||
#define R_REGISTER 17
|
||||
#define R_RETURN 18
|
||||
#define R_SHORT 19
|
||||
#define R_SIZEOF 20
|
||||
#define R_STATIC 21
|
||||
#define R_STRUCT 22
|
||||
#define R_SWITCH 23
|
||||
#define R_TYPEDEF 24
|
||||
#define R_UNION 25
|
||||
#define R_UNSIGNED 26
|
||||
#define R_WHILE 27
|
||||
|
||||
/*
|
||||
* mixed-mode conversions, entries in 2-d array indexed by:
|
||||
* (int,unsn,long,doub,ptr)
|
||||
*/
|
||||
#define INT_CHAR 1
|
||||
#define UNSN_CHAR 1
|
||||
#define LONG_CHAR 1
|
||||
#define DOUB_CHAR 1
|
||||
#define PTR_CHAR 1
|
||||
#define INT_UNSN 0 /*no conversion is generated*/
|
||||
#define INT_LONG 2
|
||||
#define INT_DOUB 3
|
||||
#define INT_PTR 4
|
||||
#define UNSN_INT 0 /*no conversion is generated*/
|
||||
#define UNSN_LONG 6
|
||||
#define UNSN_DOUB 7
|
||||
#define UNSN_PTR 8
|
||||
#define LONG_INT 9
|
||||
#define LONG_UNSN 10
|
||||
#define LONG_DOUB 11
|
||||
#define LONG_PTR 12
|
||||
#define DOUB_INT 13
|
||||
#define DOUB_UNSN 14
|
||||
#define DOUB_LONG 15
|
||||
#define PTR_INT 16
|
||||
#define PTR_UNSN 17
|
||||
#define PTR_LONG 18
|
||||
#define PTR_PTR 19
|
||||
#define BADCONV 20
|
||||
|
||||
/* miscellaneous constants */
|
||||
#define OPSSIZE 40 /*operator stack size*/
|
||||
#define OPDSIZE 80 /*operand stack size*/
|
||||
#define HSIZE 517 /*hash table size, 3.4 made prime */
|
||||
#define SYMSIZE 1024 /*size to alloc for symbol structures*/
|
||||
#define SWSIZE 256 /*max no. of cases in a switch*/
|
||||
#define DSIZE 1000 /*dimension table size*/
|
||||
#define BITSPWORD 16 /*bits per word*/
|
||||
#define AREGLO 010 /*A reg flag*/
|
||||
#define HICREG 2 /*highest reg # used for code generation*/
|
||||
#define BITSPCHAR 8 /*bits per char*/
|
||||
#define CHRSPWORD 2 /*chars per word*/
|
||||
#define STRSIZE 300 /*max string length*/
|
||||
#define NFARGS 40 /*max no. of args to function*/
|
||||
#define NFRSTR 20 /*max no. of forward ref struct proto*/
|
||||
|
||||
/*symbol table node*/
|
||||
struct symbol {
|
||||
char s_attrib; /* defined, resword, global, typedef */
|
||||
char s_sc; /* auto, static, external, register */
|
||||
int s_type; /* 4bits specified, 2 bit fields for ptr... */
|
||||
int s_dp; /* index into dimension table */
|
||||
int s_ssp; /* dimension table/function arg table */
|
||||
int s_offset; /* offset inside of structure */
|
||||
char s_symbol[SSIZE]; /* symbol identifier, to SSIZE chars */
|
||||
struct symbol *s_struc; /* if struct, ptr to parent (sys III) */
|
||||
struct symbol *s_next; /* next symbol table entry */
|
||||
};
|
||||
|
||||
/*expression tree operator node*/
|
||||
struct tnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
struct tnode *t_left;
|
||||
struct tnode *t_right;
|
||||
};
|
||||
|
||||
/*expression tree node for symbol - only keeps location*/
|
||||
struct symnode {
|
||||
int t_op;
|
||||
int t_type; /*data type of symbol*/
|
||||
int t_dp; /*dimension pointer of symbol*/
|
||||
int t_ssp; /*structure size index to dtab*/
|
||||
int t_sc; /*storage class of symbol*/
|
||||
int t_offset; /*offset of symbol*/
|
||||
int t_label;
|
||||
};
|
||||
|
||||
/*expressioon tree node for external symbol - need to keep name*/
|
||||
struct extnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
int t_sc;
|
||||
int t_offset;
|
||||
int t_reg;
|
||||
int t_symbol[SSIZE]; /*symbol name*/
|
||||
};
|
||||
|
||||
/*expression tree node for integer constant*/
|
||||
struct conode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
int t_value; /*constant value*/
|
||||
};
|
||||
|
||||
struct lconode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_dp;
|
||||
int t_ssp;
|
||||
long t_lvalue; /*constant value*/
|
||||
};
|
||||
|
||||
struct swtch {
|
||||
int sw_label;
|
||||
int sw_value;
|
||||
} swtab[SWSIZE];
|
||||
|
||||
/*operator and operand stack used by expr*/
|
||||
struct ops { /*operator stack*/
|
||||
int o_op; /*operator*/
|
||||
int o_pri; /*priority*/
|
||||
} opstack[OPSSIZE], *opp;
|
||||
|
||||
char *opdstack[OPDSIZE]; /*operand stack*/
|
||||
char **opdp; /*operand stack pointer*/
|
||||
char *opap; /*ptr to next available loc in exprarea*/
|
||||
char *exprp; /*place to start building expression*/
|
||||
int opinfo[]; /*operator info table*/
|
||||
struct tnode *frp; /*pointer to function return info node*/
|
||||
int swp; /*current entry in switch table*/
|
||||
int cswp; /*current low switch table index*/
|
||||
int nextlabel; /*generates unique label numbers*/
|
||||
int clabel; /*continue label*/
|
||||
int blabel; /*break label*/
|
||||
int rlabel; /*return label*/
|
||||
int dlabel; /*default label*/
|
||||
int lineno; /*current line number of input*/
|
||||
int errcnt; /*count of errors*/
|
||||
int inclflag; /*in include file, don't incr line #'s*/
|
||||
int inclline; /*[vlh]line# in incl file for err rpting*/
|
||||
char inclfile[13]; /*[vlh]include filename for err rpting*/
|
||||
int equalstop; /*stop lex at '=', used for external init*/
|
||||
int commastop; /*stop parse @ comma(used for const expr)*/
|
||||
int colonstop; /*stop parse @ colon(used for case value)*/
|
||||
int instruct; /*set when in structure declaration*/
|
||||
int smember; /*set when seen . or ->*/
|
||||
int infunc; /*set when in function body*/
|
||||
int tdflag; /*declaration is a typedef proto*/
|
||||
char *tdp; /*points to typedef prototype*/
|
||||
int localsize; /*length of local variables*/
|
||||
int naregs; /*keeps track of ptr registers alloc'd*/
|
||||
int ndregs; /*keep track of data registers alloc'd*/
|
||||
int loadreg; /*need to load registers...*/
|
||||
int boffset; /*current bit offset in structure*/
|
||||
int eflag; /*[vlh] 3.4 IEEE floats */
|
||||
int fflag; /*[vlh] 3.4 FFP floats */
|
||||
int xflag; /*translate int's to long's*/
|
||||
int wflag; /*[vlh] don't generate warning mesgs*/
|
||||
int reducep; /*[vlh] if(procid); reduction*/
|
||||
int peektok; /*peeked at token*/
|
||||
|
||||
/*dimension table*/
|
||||
long dtab[DSIZE]; /* [vlh] 3.4 int => long */
|
||||
int cdp; /*next entry in dtab to alloc*/
|
||||
|
||||
/*lexical analyzer values*/
|
||||
int cvalue; /*current token value if keyword or CINT*/
|
||||
int cstrsize; /*current string size*/
|
||||
long clvalue; /*current token value if long constant*/
|
||||
struct symbol *csp; /*current token symbol ptr if SYMBOL*/
|
||||
char cstr[STRSIZE]; /*current token value if CSTRING*/
|
||||
struct symbol *dsp; /*declarator symbol pointer*/
|
||||
|
||||
/* -1 -> not instruct, 0 -> unnamed struct */
|
||||
struct symbol *strucptr[10]; /*[vlh] ptrs to struc symbols*/
|
||||
|
||||
/*function argument table, used to collect function parameters*/
|
||||
struct farg {
|
||||
struct symbol *f_sp;
|
||||
int f_offset;
|
||||
} fargtab[NFARGS];
|
||||
|
||||
/*forward referenced structure prototype names*/
|
||||
struct symbol *frstab[NFRSTR];
|
||||
int frstp;
|
||||
|
||||
/*output buffers for intermediate code and strings*/
|
||||
struct io_buf obuf, sbuf, ibuf, *obp;
|
||||
|
||||
#define stypedef(sp) (sp->s_attrib&STYPEDEF)
|
||||
#define walign(add) ((add+1)&(~1))
|
||||
#define array(type) ((type&SUPTYP)==ARRAY)
|
||||
#define function(type) ((type&SUPTYP)==FUNCTION)
|
||||
#define pointer(type) ((type&SUPTYP)==POINTER)
|
||||
#define notarray(type) ((type&SUPTYP)!=ARRAY)
|
||||
#define notfunction(type) ((type&SUPTYP)!=FUNCTION)
|
||||
#define notpointer(type) ((type&SUPTYP)!=POINTER)
|
||||
#define btype(type) (type&TYPE)
|
||||
#define suptype(type) (type&SUPTYP)
|
||||
#define alltype(type) (type&(SUPTYP|TYPE))
|
||||
#define asgop(op) ((opinfo[op]&OPASSIGN)!=0)
|
||||
#define relop(op) ((opinfo[op]&OPREL)!=0)
|
||||
#define lintegral(op) ((opinfo[op]&OPLWORD)!=0)
|
||||
#define rintegral(op) ((opinfo[op]&OPRWORD)!=0)
|
||||
#define rasop(op) ((opinfo[op]&OPRAS)!=0)
|
||||
#define binop(op) ((opinfo[op]&OPBIN)!=0)
|
||||
#define unaryop(op) ((opinfo[op]&OPBIN)==0)
|
||||
#define leaf(op) ((opinfo[op]&OPTERM)!=0)
|
||||
#define lvalop(op) ((opinfo[op]&OPLVAL)!=0)
|
||||
#define oppriority(op) (opinfo[op]&OPPRI)
|
||||
#define makeiop(op) (op|(0254<<8))
|
||||
/* checks for symbol with structure element storage class */
|
||||
#define isstel(tp) (tp->t_op==SYMBOL && (sesc(tp)))
|
||||
#define sesc(t) (t->t_sc==STELCL||t->t_sc==UNELCL||t->t_sc==BFIELDCL)
|
||||
/* peek at next token, if not read token put back, else delete */
|
||||
/* 1 if matched, 0 otherwise */
|
||||
#define peek(tok) ( (peektok=gettok()) == tok )
|
||||
|
||||
#define outcommon(sym,size) printf("\t.comm _%.8s,%ld\n",sym,size)
|
||||
#define outgoto(lab) if( lab > 0 ) printf("\tbra L%d\n",lab)
|
||||
/* change to text segment */
|
||||
#define outtext() printf("\t.text\n")
|
||||
/* change segment to bss */
|
||||
#define outbss() printf("\t.bss\n")
|
||||
/* output global symbol references */
|
||||
#define outextdef(sym) printf("\t.globl _%.8s\n",sym)
|
||||
/* outputs reserved memory [vlh] 3.4 %d => %ld */
|
||||
#define outresmem(size) printf("\t.ds.b %ld\n",size)
|
||||
/* output padding for word alignments */
|
||||
#define outpad() printf("\t.even\n")
|
||||
/* output long constant to assembler */
|
||||
#define outlcon(val) printf("\t.dc.l %d\n",val)
|
||||
/* output label constant */
|
||||
#define outclab(lab) printf("\t.dc.l L%d\n",lab)
|
||||
/* output a label */
|
||||
#define outlab(lab) printf("\tL%d:",lab)
|
||||
/* output function label */
|
||||
#define outflab(sym) printf("\t_%.8s:\n\t~~%.8s:\n",sym,sym)
|
||||
/* output data label */
|
||||
#define outdlab(sym) printf("\t_%.8s:\n",sym)
|
||||
|
||||
/*functions returning pointers*/
|
||||
char *expr();
|
||||
char *talloc();
|
||||
char *tnalloc();
|
||||
char *enalloc();
|
||||
char *snalloc();
|
||||
char *cnalloc();
|
||||
char *lcnalloc();
|
||||
char *fpcnalloc();
|
||||
char *popopd();
|
||||
char *cvopgen();
|
||||
char *arrayref();
|
||||
char *funcref();
|
||||
char *install();
|
||||
char *lookup();
|
||||
char *balpar();
|
||||
char *sbrk();
|
||||
|
||||
long initlist();
|
||||
long dsize();
|
||||
long psize();
|
||||
long dodecl();
|
||||
long dlist();
|
||||
long getdec();
|
||||
long gethex();
|
||||
long getoct();
|
||||
long getfp();
|
||||
long toieee();
|
||||
long toffp();
|
||||
@@ -0,0 +1,16 @@
|
||||
e:send DECL.C
|
||||
e:send EXPR.C
|
||||
e:send ICODE.C
|
||||
e:send INTERF.C
|
||||
e:send LEX.C
|
||||
e:send MAIN.C
|
||||
e:send STMT.C
|
||||
e:send TABL.C
|
||||
e:send VERSION.C
|
||||
e:send ICODE.H
|
||||
e:send PARSER.H
|
||||
e:send MACHINE.68K
|
||||
e:send LINK.SUB
|
||||
e:send MAKE.SUB
|
||||
e:send MACHINE.H
|
||||
e:send SEND12.SU
|
||||
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#define labgen(l,sl) sl=l;l=nextlabel++;
|
||||
int swp -1;
|
||||
|
||||
|
||||
/* stmt - process a single statement*/
|
||||
stmt() /* returns - none*/
|
||||
{
|
||||
register int token, lab, i;
|
||||
register struct tnode *tp;
|
||||
register char *p;
|
||||
|
||||
while( 1 ) {
|
||||
switch(token=gettok()) {
|
||||
|
||||
case LCURBR: /*handle { ... }*/
|
||||
while( !next(EOF) ) {
|
||||
if( next(RCURBR) )
|
||||
return;
|
||||
stmt();
|
||||
}
|
||||
case EOF:
|
||||
error("{ not matched by }");
|
||||
case SEMI: /*null statement*/
|
||||
return;
|
||||
|
||||
case RCURBR:
|
||||
pbtok(token);
|
||||
return;
|
||||
|
||||
case SYMBOL: /*symbol: statement*/
|
||||
if( peekc(':') ) {
|
||||
dolabel();
|
||||
continue;
|
||||
}
|
||||
default: /*anything else...*/
|
||||
pbtok(token);
|
||||
outexpr(expr());
|
||||
break;
|
||||
|
||||
case RESWORD:
|
||||
switch(cvalue) {
|
||||
|
||||
case R_BREAK:
|
||||
lab = brklabel();
|
||||
outgoto(lab); /*branch to break label*/
|
||||
break;
|
||||
|
||||
case R_CASE:
|
||||
docase();
|
||||
continue;
|
||||
|
||||
case R_CONTINUE:
|
||||
lab = contlabel(); /*branch to continue label*/
|
||||
outgoto(lab);
|
||||
break;
|
||||
|
||||
case R_DEFAULT:
|
||||
dodefault();
|
||||
continue;
|
||||
|
||||
case R_DO:
|
||||
dodo();
|
||||
break;
|
||||
|
||||
case R_FOR:
|
||||
dofor();
|
||||
return;
|
||||
|
||||
case R_GOTO:
|
||||
lab = gotolabel();
|
||||
outgoto(lab);
|
||||
break;
|
||||
|
||||
case R_IF:
|
||||
doif();
|
||||
return;
|
||||
|
||||
case R_RETURN:
|
||||
doreturn();
|
||||
break;
|
||||
|
||||
case R_SWITCH:
|
||||
doswitch();
|
||||
return;
|
||||
|
||||
case R_WHILE:
|
||||
dowhile();
|
||||
return;
|
||||
|
||||
default:
|
||||
synerr("invalid keyword");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( !next(SEMI) )
|
||||
synerr("missing semicolon");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* balpar - handle expression within parenthesis for while and if*/
|
||||
/* Merely checks for left and right parens and builds expression.*/
|
||||
char *balpar() /* returns pointer to expression*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
if( next(LPAREN) ) {
|
||||
reducep = 1;
|
||||
tp = expr();
|
||||
reducep = 0;
|
||||
if( next(RPAREN) )
|
||||
return(tp);
|
||||
}
|
||||
synerr("parenthesized expression syntax");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* synerr - syntax error*/
|
||||
/* Outputs error message and tries to resyncronize input.*/
|
||||
synerr(s,x1,x2,x3,x4,x5,x6) /* returns - none*/
|
||||
char *s; /* printf format string*/
|
||||
int x1, x2, x3, x4, x5, x6; /* printf arguments*/
|
||||
{
|
||||
register int token;
|
||||
|
||||
error(s,x1,x2,x3,x4,x5,x6);
|
||||
while( (token=gettok()) != SEMI && token != EOF && token != LCURBR &&
|
||||
token != RCURBR )
|
||||
;
|
||||
pbtok(token);
|
||||
}
|
||||
|
||||
/* gotolabel - gets label id for goto*/
|
||||
/* This is used for both: goto symbol and if(...)goto symbol*/
|
||||
gotolabel() /* returns 0 if not, else label id*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
if( !next(SYMBOL) )
|
||||
synerr("expected label");
|
||||
else {
|
||||
sp = csp;
|
||||
if( !(sp->s_sc) ) {
|
||||
sp->s_type = LLABEL;
|
||||
if( !sp->s_offset )
|
||||
sp->s_offset = nextlabel++;
|
||||
}
|
||||
if( (!sp->s_sc || sp->s_sc == STATIC ) && sp->s_type == LLABEL )
|
||||
return(sp->s_offset);
|
||||
synerr("invalid label");
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* dolabel - do statement label*/
|
||||
/* Checks current symbol for already being defined, then sets*/
|
||||
/* symbol attributes for label.*/
|
||||
dolabel() /* returns - none*/
|
||||
{
|
||||
register struct symbol *sp;
|
||||
|
||||
sp = csp;
|
||||
if( sp->s_sc )
|
||||
error("label redeclaration: %.8s",sp->s_symbol);
|
||||
else {
|
||||
sp->s_attrib =| SDEFINED;
|
||||
sp->s_sc = STATIC;
|
||||
sp->s_type = LLABEL;
|
||||
if( !sp->s_offset )
|
||||
sp->s_offset = nextlabel++;
|
||||
outlab(sp->s_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* brklabel - generate break label*/
|
||||
/* Checks if break label is undefined, and if so, generates message*/
|
||||
brklabel() /* returns label number*/
|
||||
{
|
||||
if( !blabel )
|
||||
error("invalid break statement");
|
||||
return(blabel);
|
||||
}
|
||||
|
||||
/* contlabel - generate continue label*/
|
||||
/* Checks if continue label is undefined, and if so, generates message*/
|
||||
contlabel() /* returns label number*/
|
||||
{
|
||||
if( !clabel )
|
||||
error("invalid continue statement");
|
||||
return(clabel);
|
||||
}
|
||||
|
||||
/* docase - handles: case constant : statement*/
|
||||
/* Checks for being in a switch statement, adds entry to switch table*/
|
||||
docase() /* returns - none*/
|
||||
{
|
||||
register int value, lab;
|
||||
|
||||
colonstop++;
|
||||
value = cexpr(); /*get case value*/
|
||||
colonstop--;
|
||||
if( !next(COLON) ) /*check for colon*/
|
||||
synerr("missing colon");
|
||||
if( swp < 0 )
|
||||
error("case not inside a switch block");
|
||||
else if( swp >= (SWSIZE-1) )
|
||||
error("too many cases in switch");
|
||||
else {
|
||||
addswitch(&swtab[cswp],swp-cswp,value,lab=nextlabel++);
|
||||
outlab(lab);
|
||||
swp++;
|
||||
}
|
||||
}
|
||||
|
||||
/* dodefault - handles: default : statement*/
|
||||
/* Checks for colon and being in a switch statement*/
|
||||
dodefault() /* returns - none*/
|
||||
{
|
||||
if( !next(COLON) )
|
||||
error("missing colon");
|
||||
if( swp < 0 )
|
||||
error("default not inside a switch block");
|
||||
else {
|
||||
dlabel = nextlabel++; /*allocate default label*/
|
||||
outlab(dlabel); /*output default label*/
|
||||
}
|
||||
}
|
||||
|
||||
/* dodo - handles: do statement while ( expression )*/
|
||||
dodo() /* returns - none*/
|
||||
{
|
||||
register int lab, saveblab, saveclab;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
lab = nextlabel++;
|
||||
outlab(lab); /*branch back to here*/
|
||||
stmt(); /*do statement*/
|
||||
outlab(clabel); /*continue label*/
|
||||
if( !nextrw(R_WHILE) ) {
|
||||
error("missing while"); /*only advisory...*/
|
||||
outgoto(lab);
|
||||
}
|
||||
else
|
||||
outifgoto(balpar(),TRUE,lab); /*while expression*/
|
||||
outlab(blabel); /*break label*/
|
||||
blabel = saveblab; /*restore labels*/
|
||||
clabel = saveclab;
|
||||
}
|
||||
|
||||
/*
|
||||
* dofor - handle: for ( expression ; expression ; expression ) statement
|
||||
* Hard part is handling re-initialization expression, which is
|
||||
* parsed and saved, then the statement is parsed, then the reinit
|
||||
* clause expression tree is output.
|
||||
*/
|
||||
dofor() /* returns - none*/
|
||||
{
|
||||
register int lab, saveblab, saveclab, reinit, clineno;
|
||||
register char *savep;
|
||||
register struct tnode *tp;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
if( !next(LPAREN) ) {
|
||||
forerr:
|
||||
synerr("invalid for statement");
|
||||
return;
|
||||
}
|
||||
if( !next(SEMI) ) { /*do init expression*/
|
||||
outexpr(expr());
|
||||
if( !next(SEMI) )
|
||||
goto forerr;
|
||||
}
|
||||
outlab(clabel); /*branch back to here*/
|
||||
if( !next(SEMI) ) { /*do for condition*/
|
||||
outifgoto(expr(),FALSE,blabel);
|
||||
if( !next(SEMI) )
|
||||
goto forerr;
|
||||
}
|
||||
if( next(RPAREN) ) { /*no re-init - easy case*/
|
||||
stmt(); /*output statement*/
|
||||
outgoto(clabel); /*output continue label*/
|
||||
}
|
||||
else { /*there is a re-init clause*/
|
||||
labgen(clabel,lab);
|
||||
savep = exprp;
|
||||
tp = expr(); /*save re-init tree until done*/
|
||||
exprp = opap; /*remember until reinit is output*/
|
||||
reinit = lineno;
|
||||
if( !next(RPAREN) )
|
||||
goto forerr;
|
||||
stmt(); /*do statment*/
|
||||
clineno = lineno;
|
||||
lineno = reinit;
|
||||
outlab(clabel); /*we branch to here for reinit*/
|
||||
outexpr(tp); /*output re-init clause*/
|
||||
exprp = savep;
|
||||
lineno = clineno;
|
||||
outgoto(lab); /*branch back to top of loop*/
|
||||
}
|
||||
outlab(blabel); /*break to here*/
|
||||
blabel = saveblab;
|
||||
clabel = saveclab; /*restore labels*/
|
||||
}
|
||||
|
||||
/* doif - handles: if ( expression ) statement [ else statement ]*/
|
||||
/* Handles special cases for goto, break, continue and return.*/
|
||||
doif() /* returns - none*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
register int elselab, exitlab;
|
||||
|
||||
tp = balpar(); /*if( expr )...*/
|
||||
exitlab = 0;
|
||||
if( nextrw(R_GOTO) )
|
||||
exitlab = gotolabel();
|
||||
else if( nextrw(R_BREAK) )
|
||||
exitlab = brklabel();
|
||||
else if( nextrw(R_CONTINUE) )
|
||||
exitlab = contlabel();
|
||||
else if( nextrw(R_RETURN) ) {
|
||||
if( peekc(';') ) {
|
||||
exitlab = rlabel;
|
||||
putback(';');
|
||||
}
|
||||
else
|
||||
pbtok(RESWORD);
|
||||
}
|
||||
if( exitlab ) { /*easy goto, do branch if true*/
|
||||
outifgoto(tp,TRUE,exitlab);
|
||||
if( !next(SEMI) )
|
||||
synerr("missing semicolon");
|
||||
if( nextrw(R_ELSE) ) /*else clause, just output it*/
|
||||
stmt();
|
||||
}
|
||||
else { /*hard goto, branch over statement*/
|
||||
elselab = nextlabel++;
|
||||
outifgoto(tp,FALSE,elselab);
|
||||
stmt();
|
||||
if( nextrw(R_ELSE) ) {
|
||||
exitlab = nextlabel++; /*branches over else clause*/
|
||||
outgoto(exitlab); /*branch out of then clause*/
|
||||
outlab(elselab); /*label to start else clause*/
|
||||
stmt(); /*else statement*/
|
||||
outlab(exitlab);
|
||||
}
|
||||
else
|
||||
outlab(elselab); /*no else, just branch out*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* doreturn - handles: return [ expression ] ;
|
||||
* Expression is the hard part, must create an assignment expression
|
||||
* to assign expression to the type of the function, then get it
|
||||
* loaded into a specific register.
|
||||
*/
|
||||
doreturn() /* returns - none*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
if( !peekc(';') ) /*need to compute return?*/
|
||||
outforreg(FRETURN,frp,expr());
|
||||
else
|
||||
putback(';');
|
||||
outgoto(rlabel); /*branch to the return label*/
|
||||
}
|
||||
|
||||
/*
|
||||
* doswitch - handles: switch ( expression ) statement
|
||||
* Evaluates the expression, forces the result into a known register
|
||||
* collects the case statements in swtab, then outputs the switch
|
||||
* operator and switch cases.
|
||||
*/
|
||||
doswitch() /* returns - none*/
|
||||
{
|
||||
register int saveblab, swlab, savedlab, saveswp, i;
|
||||
register struct tnode *tp;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
tp = balpar();
|
||||
integral(tp,-1); /*must be integral type result*/
|
||||
outforreg(ASSIGN,snalloc(INT,AUTO,0,0,0),tp);
|
||||
saveswp = swp; /*remember old switch pointer*/
|
||||
if( saveswp < 0 )
|
||||
swp++;
|
||||
i = cswp;
|
||||
cswp = swp; /*remember real first entry*/
|
||||
swlab = nextlabel++;
|
||||
outgoto(swlab); /*branch to switch code*/
|
||||
savedlab = dlabel;
|
||||
dlabel = 0;
|
||||
stmt(); /*do switch statement*/
|
||||
outgoto(blabel); /*output branch just in case*/
|
||||
outlab(swlab); /*here we now do the switch code*/
|
||||
if( !dlabel )
|
||||
dlabel = blabel;
|
||||
outswitch(swp-cswp,dlabel,&swtab[cswp]);
|
||||
outlab(blabel); /*break to here*/
|
||||
cswp = i;
|
||||
swp = saveswp;
|
||||
blabel = saveblab;
|
||||
dlabel = savedlab;
|
||||
}
|
||||
|
||||
/* dowhile - handles: while ( expression ) statement*/
|
||||
/* This is fairly straight-forward.*/
|
||||
dowhile() /* returns - none*/
|
||||
{
|
||||
register int saveclab, saveblab;
|
||||
|
||||
labgen(blabel,saveblab);
|
||||
labgen(clabel,saveclab);
|
||||
outlab(clabel); /*continue label*/
|
||||
outifgoto(balpar(),FALSE,blabel); /*condition clause*/
|
||||
stmt(); /*statement*/
|
||||
outgoto(clabel); /*branch back to top of loop*/
|
||||
outlab(blabel); /*break to here*/
|
||||
blabel = saveblab;
|
||||
clabel = saveclab; /*restore labels*/
|
||||
}
|
||||
|
||||
/* nextrw - is next token the specified reserved word?*/
|
||||
nextrw(rw) /* returns 1 if match, 0 otherwise*/
|
||||
int rw; /* reserved word to match*/
|
||||
{
|
||||
register int token;
|
||||
|
||||
if( (token=gettok()) != RESWORD || cvalue != rw ) {
|
||||
pbtok(token);
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* addswitch - add an entry into current switch table, bubble sorting
|
||||
* This makes it easier on the code generator and also checks for
|
||||
* duplicate labels at the "right" time.
|
||||
*/
|
||||
addswitch(sp,ncases,nval,nlab) /* returns - none*/
|
||||
struct swtch *sp; /* switch table pointer*/
|
||||
int ncases; /* number of cases in switch*/
|
||||
int nval; /* new value*/
|
||||
int nlab; /* new label*/
|
||||
{
|
||||
register struct swtch *nswp, *s;
|
||||
register int temp, i;
|
||||
|
||||
nswp = &sp[ncases];
|
||||
nswp->sw_value = nval;
|
||||
nswp->sw_label = nlab;
|
||||
s = nswp--;
|
||||
for( ; --ncases >= 0; s--, nswp-- ) {
|
||||
if( s->sw_value == nswp->sw_value )
|
||||
error("duplicate case value");
|
||||
if( s->sw_value < nswp->sw_value ) {
|
||||
temp = s->sw_value;
|
||||
s->sw_value = nswp->sw_value;
|
||||
nswp->sw_value = temp;
|
||||
temp = s->sw_label;
|
||||
s->sw_label = nswp->sw_label;
|
||||
nswp->sw_label = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* outforreg - generate assignment for switch and return*/
|
||||
outforreg(op,ltp,rtp) /*returns - none*/
|
||||
int op; /*operator for build tree*/
|
||||
struct tnode *ltp; /*left expression tree*/
|
||||
struct tnode *rtp; /*right expression tree*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
opp = opstack;
|
||||
opdp = opdstack;
|
||||
pushopd(ltp);
|
||||
pushopd(rtp);
|
||||
maketree(op);
|
||||
if( tp = popopd() )
|
||||
outcforreg(tp->t_right);
|
||||
opp = opdp = 0;
|
||||
}
|
||||
|
||||
/* outassign - generate assignment for function args*/
|
||||
outassign(ltp,rtp) /*returns - none*/
|
||||
struct tnode *ltp; /*left expression tree*/
|
||||
struct tnode *rtp; /*right expression tree*/
|
||||
{
|
||||
opp = opstack;
|
||||
opdp = opdstack;
|
||||
pushopd(ltp);
|
||||
pushopd(rtp);
|
||||
maketree(ASSIGN);
|
||||
outexpr(popopd());
|
||||
opp = opdp = 0;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#define ASGOP OPRAS|OPASSIGN|OPLVAL|OPBIN
|
||||
|
||||
/*info on operators:*/
|
||||
/*000077-- OPPRI - priority*/
|
||||
/*000100-- OPBIN - binary operator*/
|
||||
/*000200-- OPLVAL - left operand must be lvalue*/
|
||||
/*000400-- OPREL - relational operator*/
|
||||
/*001000-- OPASSIGN - assignment operator*/
|
||||
/*002000-- OPLWORD - int required on left*/
|
||||
/*004000-- OPRWORD - int required on right*/
|
||||
/*010000-- OPCOM commutative*/
|
||||
/*020000-- OPRAS - right associative*/
|
||||
/*040000-- OPTERM - termination node*/
|
||||
/*100000 - OPCONVS - conversion operator*/
|
||||
int opinfo[] {
|
||||
TRMPRI, /*EOF*/
|
||||
ADDPRI|OPCOM|OPBIN, /*ADD - expr + expr*/
|
||||
ADDPRI|OPBIN, /*SUB - expr - expr*/
|
||||
MULPRI|OPCOM|OPBIN, /*MULT - expr * expr*/
|
||||
MULPRI|OPBIN, /*DIV - expr / expr*/
|
||||
MULPRI|OPBIN, /*MOD - expr % expr*/
|
||||
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*RSH - expr >> expr*/
|
||||
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*LSH - expr << expr*/
|
||||
ANDPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*AND - expr & expr*/
|
||||
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*OR - expr | expr*/
|
||||
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*XOR - expr ^ expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*NOT - ! expr*/
|
||||
UNOPRI|OPRAS, /*UMINUS - - expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*COMPL - ~ expr*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREDEC - --lvalue*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREINC - ++lvalue*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTDEC - lvalue--*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTINC - lvalue++*/
|
||||
ASGPRI|ASGOP, /*ASSIGN - lvalue = expr*/
|
||||
ASGPRI|ASGOP, /*EQADD - lvalue += expr*/
|
||||
ASGPRI|ASGOP, /*EQSUB - lvalue -= expr*/
|
||||
ASGPRI|ASGOP, /*EQMULT - lvalue *= expr*/
|
||||
ASGPRI|ASGOP, /*EQDIV - lvalue /= expr*/
|
||||
ASGPRI|ASGOP, /*EQMOD - lvalue %= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQRSH - lvalue >>= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQLSH - lvalue <<= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQAND - lvalue &= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQOR - lvalue |= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQXOR - lvalue ^= expr*/
|
||||
TRMPRI, /*FJSR - generate function jsr*/
|
||||
EQLPRI|OPREL|OPBIN, /*EQUALS - expr == expr*/
|
||||
EQLPRI|OPREL|OPBIN, /*NEQUALS - expr != expr*/
|
||||
RELPRI|OPREL|OPBIN, /*GREAT - expr > expr*/
|
||||
RELPRI|OPREL|OPBIN, /*GREATEQ - expr >= expr*/
|
||||
RELPRI|OPREL|OPBIN, /*LESS - expr < expr*/
|
||||
RELPRI|OPREL|OPBIN, /*LESSEQ - expr <= expr*/
|
||||
TRMPRI|OPCONVS, /*INT2L*/
|
||||
TRMPRI|OPCONVS, /*LONG2I*/
|
||||
TRMPRI|OPBIN, /*BTST*/
|
||||
TRMPRI, /*LOAD*/
|
||||
TRMPRI|OPBIN, /*LMULT*/
|
||||
TRMPRI|OPBIN, /*LDIV*/
|
||||
TRMPRI|OPBIN, /*LMOD*/
|
||||
TRMPRI|OPBIN, /*LEQMULT*/
|
||||
TRMPRI|OPBIN, /*LEQDIV*/
|
||||
TRMPRI|OPBIN, /*LEQMOD*/
|
||||
TRMPRI|ASGOP, /*EQADDR*/
|
||||
TRMPRI, /*EQNOT*/
|
||||
TRMPRI, /*EQNEG*/
|
||||
TRMPRI|OPBIN, /*DOCAST*/
|
||||
ASGPRI|ASGOP, /*STASSIGN [vlh]*/
|
||||
TRMPRI|OPCONVS, /*LONG2F [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*FLOAT2L [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*INT2F [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*FLOAT2F [vlh] 3.4*/
|
||||
TRMPRI, /*unused - 55*/
|
||||
TRMPRI, /*unused - 56*/
|
||||
TRMPRI, /*unused - 57*/
|
||||
TRMPRI, /*unused - 58*/
|
||||
TRMPRI, /*unused - 59*/
|
||||
UNOPRI|OPRAS|OPLVAL, /*ADDR - & expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*INDR - * expr*/
|
||||
LNDPRI|OPBIN, /*LAND - expr && expr*/
|
||||
LORPRI|OPBIN, /*LOR - expr || expr*/
|
||||
QMKPRI|OPRAS|OPBIN, /*QMARK - expr ? expr : expr*/
|
||||
QMKPRI|OPRAS|OPBIN, /*COLON*/
|
||||
COMPRI|OPBIN, /*COMMA*/
|
||||
TRMPRI|OPTERM, /*CINT*/
|
||||
TRMPRI|OPTERM, /*CLONG*/
|
||||
TRMPRI|OPTERM, /*SYMBOL*/
|
||||
TRMPRI|OPTERM, /*AUTOINC*/
|
||||
TRMPRI|OPTERM, /*AUTODEC*/
|
||||
LPNPRI|OPBIN, /*CALL - call with arguments*/
|
||||
LPNPRI, /*NACALL - no argument call*/
|
||||
TRMPRI, /*BFIELD - field selection*/
|
||||
TRMPRI, /*IFGOTO*/
|
||||
TRMPRI, /*INIT*/
|
||||
TRMPRI, /*CFORREG*/
|
||||
TRMPRI, /*unused - 78*/
|
||||
TRMPRI|OPTERM, /*CFLOAT [vlh] 3.4*/
|
||||
UNOPRI|OPRAS|OPASSIGN|OPBIN, /*CAST*/
|
||||
TRMPRI, /*SEMI*/
|
||||
TRMPRI, /*LCURBR - {*/
|
||||
TRMPRI, /*RCURBR - }*/
|
||||
LPNPRI, /*LBRACK - [*/
|
||||
RPNPRI, /*RBRACK - ]*/
|
||||
LPNPRI, /*LPAREN - )*/
|
||||
RPNPRI, /*RPAREN - )*/
|
||||
TRMPRI|OPTERM, /*STRING*/
|
||||
TRMPRI, /*RESWORD*/
|
||||
LPNPRI|OPBIN, /*APTR - expr -> symbol*/
|
||||
LPNPRI|OPBIN, /*PERIOD - expr . symbol*/
|
||||
UNOPRI|OPRAS, /*SIZEOF - sizeof expr*/
|
||||
LPNPRI|OPBIN, /*MPARENS - matching parens ()*/
|
||||
UNOPRI|OPRAS|OPASSIGN|OPBIN, /*FRETURN*/
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
e:vax DECL.C s
|
||||
e:vax EXPR.C s
|
||||
e:vax ICODE.C s
|
||||
e:vax INTERF.C s
|
||||
e:vax LEX.C s
|
||||
e:vax MAIN.C s
|
||||
e:vax STMT.C s
|
||||
e:vax TABL.C s
|
||||
e:vax VERSION.C s
|
||||
e:vax ICODE.H s
|
||||
e:vax PARSER.H s
|
||||
e:vax MACHINE.68K s
|
||||
e:vax LINK.SUB s
|
||||
e:vax MAKE.SUB s
|
||||
e:vax MACHINE.H s
|
||||
e:vax SEND12.SUB s
|
||||
@@ -0,0 +1 @@
|
||||
char *compiled "@(#) parser - Thu Feb 10 13:02 1983";
|
||||
@@ -0,0 +1,18 @@
|
||||
$ parser
|
||||
$ set noon
|
||||
$ !
|
||||
$ ! C068 make file for VMS
|
||||
$ !
|
||||
$ copy machine.vax machine.h
|
||||
$ pur machine.h
|
||||
$ cx DECL
|
||||
$ cx EXPR
|
||||
$ cx ICODE
|
||||
$ cx INIT
|
||||
$ cx INTERF
|
||||
$ cx LEX
|
||||
$ cx MAIN
|
||||
$ cx STMT
|
||||
$ cx TABL
|
||||
$ cx VERSION
|
||||
$ clink DECL,EXPR,ICODE,INTERF,LEX,MAIN,STMT,TABL,init,version,lib:klib/lib c068
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <klib.h>
|
||||
#undef putchar
|
||||
#define putchar xputchar
|
||||
#undef ferror
|
||||
#define ferror xferror
|
||||
#define printf xprintf
|
||||
#include "icode.h"
|
||||
|
||||
char brtab[][2];
|
||||
int invrel[];
|
||||
int swaprel[];
|
||||
char *strtab[];
|
||||
char null[];
|
||||
|
||||
/*operator tree node for unary and binary operators*/
|
||||
struct tnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*data type of result*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
struct tnode *t_left; /*left sub-tree*/
|
||||
struct tnode *t_right; /*right sub-tree (undefined if unary)*/
|
||||
};
|
||||
|
||||
/*constant terminal node*/
|
||||
struct conode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_value; /*value or label number*/
|
||||
};
|
||||
|
||||
struct lconode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
long t_lvalue; /*value or label number*/
|
||||
};
|
||||
|
||||
/*local symbol terminal node*/
|
||||
struct symnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*symbol data type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_sc; /*storage class*/
|
||||
int t_offset; /*register offset*/
|
||||
int t_reg; /*register number*/
|
||||
int t_label; /*label number if static*/
|
||||
};
|
||||
|
||||
/*external symbol reference node*/
|
||||
struct extnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*symbol data type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_sc; /*storage class*/
|
||||
int t_offset; /*register offset*/
|
||||
int t_reg; /*register number*/
|
||||
char t_symbol[SSIZE]; /*symbol name*/
|
||||
};
|
||||
|
||||
/*68000 special - indexed symbol node*/
|
||||
/*this is used to generate a An(off,Xn.type) address*/
|
||||
struct indexnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_su;
|
||||
int t_ssp;
|
||||
int t_sc;
|
||||
int t_offset;
|
||||
int t_reg;
|
||||
int t_xreg;
|
||||
int t_xtype;
|
||||
};
|
||||
|
||||
int lflag;
|
||||
int dflag;
|
||||
int mflag;
|
||||
int cflag;
|
||||
int eflag;
|
||||
int fflag;
|
||||
int oflag;
|
||||
struct io_buf ibuf, obuf;
|
||||
int lineno;
|
||||
int naregs;
|
||||
int ndregs;
|
||||
int errcnt;
|
||||
int opinfo[];
|
||||
int nextlabel;
|
||||
char null[];
|
||||
char optab[][6];
|
||||
char *mnemonics[];
|
||||
char *codeskels[];
|
||||
int stacksize;
|
||||
|
||||
char *tnalloc();
|
||||
char *snalloc();
|
||||
char *cenalloc();
|
||||
char *xnalloc();
|
||||
char *talloc();
|
||||
char *cnalloc();
|
||||
char *lcnalloc();
|
||||
char *fpcnalloc();
|
||||
char *canon();
|
||||
char *commute();
|
||||
char *constant();
|
||||
char *match();
|
||||
char *addptree();
|
||||
char *fixbfield();
|
||||
char *coffset();
|
||||
char *tcopy();
|
||||
|
||||
#define wallign(add) ((add+1)&(~1))
|
||||
#define array(type) ((type&SUPTYP)==ARRAY)
|
||||
#define function(type) ((type&SUPTYP)==FUNCTION)
|
||||
#define pointer(type) ((type&SUPTYP)==POINTER)
|
||||
#define notarray(type) ((type&SUPTYP)!=ARRAY)
|
||||
#define notfunction(type) ((type&SUPTYP)!=FUNCTION)
|
||||
#define notpointer(type) ((type&SUPTYP)!=POINTER)
|
||||
#define isfloat(type) (type==FLOAT)
|
||||
#define btype(type) (type&TYPE)
|
||||
#define suptype(type) (type&SUPTYP)
|
||||
#define alltype(type) (type&(SUPTYP|TYPE))
|
||||
#define asgop(op) ((opinfo[op]&OPASSIGN)!=0)
|
||||
#define relop(op) ((opinfo[op]&OPREL)!=0)
|
||||
#define lintegral(op) ((opinfo[op]&OPLWORD)!=0)
|
||||
#define rintegral(op) ((opinfo[op]&OPRWORD)!=0)
|
||||
#define rasop(op) ((opinfo[op]&OPRAS)!=0)
|
||||
#define binop(op) ((opinfo[op]&OPBIN)!=0)
|
||||
#define unaryop(op) ((opinfo[op]&(OPBIN|OPTERM))==0)
|
||||
#define leafop(op) ((opinfo[op]&OPTERM)!=0)
|
||||
#define notleafop(op) ((opinfo[op]&OPTERM)==0)
|
||||
#define lvalop(op) ((opinfo[op]&OPLVAL)!=0)
|
||||
#define oppriority(op) (opinfo[op]&OPPRI)
|
||||
#define commop(op) ((opinfo[op]&OPCOM)!=0)
|
||||
#define convop(op) ((opinfo[op]&OPCONVS)!=0)
|
||||
#define notconvop(op) ((opinfo[op]&OPCONVS)==0)
|
||||
#define max(a,b) (a>b?a:b)
|
||||
#define min(a,b) (a<b?a:b)
|
||||
|
||||
#define QUICKVAL 8
|
||||
#define LEP 14
|
||||
#define FORCC 1
|
||||
#define FOREFF 2
|
||||
#define FORSTACK 3
|
||||
#define FORCREG 4
|
||||
#define FORSP 5
|
||||
#define FORREG 4
|
||||
#define HICREG 2
|
||||
#define NCREGS 3
|
||||
#define AREGLO 8
|
||||
#define IMMED 1
|
||||
#define NOTIMMED 0
|
||||
#define NOTLOFFSET 0
|
||||
|
||||
/* one line routines turned into defines [vlh] for speed */
|
||||
|
||||
/*outgoto - output "bra L[labno]"*/
|
||||
#define outgoto(lab) if (lab>0) printf("bra L%d\n",lab)
|
||||
/*outlab - output "L[labno]:"*/
|
||||
#define outlab(lab) if (lab>0) printf("L%d:",lab)
|
||||
|
||||
/*outext - output register sign extension*/
|
||||
#define outext(reg) printf("ext.l R%d\n",reg)
|
||||
/*outuext - output unsigned to long register extension*/
|
||||
#define outuext(reg) printf("swap R%d\nclr R%d\nswap R%d\n",reg,reg,reg)
|
||||
/*outswap - output swap register instruction*/
|
||||
#define outswap(reg) printf("swap R%d\n",reg)
|
||||
/*outaddr - output "add [type] R1 R2" instruction*/
|
||||
#define outaddr(r1,r2,tp) outrr("add",r1,r2,(tp))
|
||||
/*outccsave - ouput instruction to move cc's to register*/
|
||||
#define outccsave(reg) printf("move sr,R%d\n",reg)
|
||||
/*outccrestore - output instruction to restore cc's from register*/
|
||||
#define outccrestore(reg) printf("move R%d,ccr\n",reg)
|
||||
/*basetype - get the btype info sans unsigned*/
|
||||
#define basetype(type) ((type==UNSIGNED) ? INT : type)
|
||||
#define unsign(type) ((type) == UNSIGNED)
|
||||
#define longorptr(type) (type==LONG || (type&SUPTYP))
|
||||
#define unorptr(type) (type==UNSIGNED || (type&SUPTYP))
|
||||
#define dreg(reg) ((reg) & (~AREGLO))
|
||||
#define areg(reg) ((reg) | AREGLO)
|
||||
#define isareg(reg) ((reg) >= AREGLO)
|
||||
#define isdreg(reg) ((reg) < AREGLO)
|
||||
#define isreg(tp) ((tp)->t_op == SYMBOL && (tp)->t_sc == REGISTER)
|
||||
@@ -0,0 +1,756 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
|
||||
/* scodegen - over-all code generation for expression*/
|
||||
/* Picks off post-fix ++, --.*/
|
||||
scodegen(tp,cookie,reg) /* returns register result is in*/
|
||||
struct tnode *tp;
|
||||
int cookie;
|
||||
int reg;
|
||||
{
|
||||
struct tnode *clist[20];
|
||||
struct tnode **clp;
|
||||
register struct tnode **cp;
|
||||
register int r;
|
||||
register int ccflag;
|
||||
register struct tnode *rtp;
|
||||
|
||||
if( tp->t_op == COMMA ) {
|
||||
scodegen(tp->t_left,FOREFF,reg);
|
||||
return(scodegen(tp->t_right,cookie,reg));
|
||||
}
|
||||
ccflag = 0;
|
||||
clp = clist;
|
||||
tp = addptree(tp,&clp);
|
||||
if( clp > clist ) {
|
||||
/*
|
||||
* post ++, -- in tree. We need to compile the tree post operators
|
||||
* then generate code to do the post operators, then do any fix up of
|
||||
* condition codes since the Stupid 68000 architect was a nimnul.
|
||||
*/
|
||||
if( cookie == FORCC ) {
|
||||
/*
|
||||
* here we make the observation that if we are comparing something with
|
||||
* zero OR the top operator of the tree is not a comparison operator,
|
||||
* we can compile the tree to a register, and then set the condition
|
||||
* codes OK with a tst instruction at the end.
|
||||
*/
|
||||
if( relop(tp->t_op) ) {
|
||||
if( (rtp=constant(tp->t_right)) && !rtp->t_value ) {
|
||||
ccflag = 1;
|
||||
tp = tp->t_left;
|
||||
cookie = FORREG;
|
||||
}
|
||||
else
|
||||
ccflag = 2;
|
||||
}
|
||||
else {
|
||||
ccflag = 1;
|
||||
cookie = FORREG;
|
||||
}
|
||||
}
|
||||
}
|
||||
r = codegen(tp,cookie,reg);
|
||||
if( clp > clist ) {
|
||||
if( ccflag == 2 )
|
||||
outccsave(r);
|
||||
for( cp = clist; cp < clp; cp++ )
|
||||
codegen(*cp,FOREFF,r+1);
|
||||
if( ccflag == 1 )
|
||||
outcmp0(r,tp);
|
||||
else if( ccflag == 2 )
|
||||
outccrestore(r);
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* addptree - prune off postfix ++, -- from expression tree*/
|
||||
/* This prunes off ++, -- and collects those expressions for*/
|
||||
/* scodegen.*/
|
||||
char *addptree(tp,clp) /* returns pointer to pruned tree*/
|
||||
struct tnode *tp;
|
||||
struct tnode ***clp;
|
||||
{
|
||||
register int op;
|
||||
|
||||
op = tp->t_op;
|
||||
if( leafop(op) || op == QMARK ) /* [vlh] 4.0 QMARK... */
|
||||
return(tp);
|
||||
if( op == POSTINC || op == POSTDEC ) {
|
||||
*(*clp)++ = tp;
|
||||
return( tcopy(tp->t_left) );
|
||||
}
|
||||
if( binop(op) )
|
||||
tp->t_right = addptree(tp->t_right,clp);
|
||||
tp->t_left = addptree(tp->t_left,clp);
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* codegen - generate code for expression*/
|
||||
/* This calls up rcodegen, which prunes off any special register*/
|
||||
/* optimization code, then calls ucodegen (unrecursive) code*/
|
||||
/* generation.*/
|
||||
codegen(tp,cookie,reg) /* returns reg result is in*/
|
||||
struct tnode *tp; /* tree pointer*/
|
||||
int cookie; /* code generation goals*/
|
||||
int reg; /* first available register*/
|
||||
{
|
||||
register int size, savestk, ssize, r, i, scookie;
|
||||
register struct tnode *rtp;
|
||||
|
||||
#ifndef NODEBUG
|
||||
if( cflag )
|
||||
printf("codegen op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg);
|
||||
#endif
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case CALL:
|
||||
case NACALL:
|
||||
ssize = 0;
|
||||
savestk = stacksize;
|
||||
if( tp->t_left->t_op != SYMBOL )
|
||||
stacksize++;
|
||||
if( tp->t_op == CALL ) {
|
||||
rtp = tp->t_right;
|
||||
while( rtp->t_op == COMMA ) {
|
||||
ssize =+ dofarg(rtp->t_right);
|
||||
rtp = rtp->t_left;
|
||||
}
|
||||
ssize =+ dofarg(rtp);
|
||||
}
|
||||
tp->t_op = FJSR; /*generate JSR (unary op)*/
|
||||
codegen(tp,FORREG,reg);
|
||||
popstack(ssize);
|
||||
stacksize = savestk;
|
||||
fixresult(tp,cookie,0);
|
||||
return(0); /*result in R0*/
|
||||
|
||||
case COMMA:
|
||||
codegen(tp->t_left,FOREFF,reg);
|
||||
return(codegen(tp->t_right,cookie,reg));
|
||||
|
||||
case AND:
|
||||
if( cookie == FORCC && (i=isonebit(tp->t_right)) >= 0 &&
|
||||
(i=dobitadd(tp->t_left,i)) >= 0 ) {
|
||||
if( convop(tp->t_right->t_op) )
|
||||
tp->t_right = tp->t_right->t_left;
|
||||
tp->t_right->t_value = i;
|
||||
tp->t_op = BTST;
|
||||
tp = canon(tp);
|
||||
sucomp(tp,reg,1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( rcodegen(&tp,cookie,reg) ) {
|
||||
if( cookie == FORCC && tp->t_op == SYMBOL && tp->t_sc == REGISTER
|
||||
&& isdreg(tp->t_reg))
|
||||
return(reg);
|
||||
}
|
||||
r = ucodegen(tp,cookie,reg);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* fixresult - fix result of code generation*/
|
||||
fixresult(tp,cookie,reg) /* returns - none*/
|
||||
struct tnode *tp;
|
||||
int cookie; /* wanted this cookie*/
|
||||
int reg;
|
||||
{
|
||||
#ifndef NODEBUG
|
||||
if (cflag)
|
||||
printf("fixresult cookie=%d reg=%d op=%d\n",cookie,reg,tp->t_op);
|
||||
#endif
|
||||
switch( cookie ) {
|
||||
|
||||
case FORCC:
|
||||
outcmp0(reg,tp);
|
||||
break;
|
||||
|
||||
case FORSP:
|
||||
case FORSTACK:
|
||||
stacksize++;
|
||||
outrpush(reg,tp,cookie==FORSTACK);
|
||||
break;
|
||||
|
||||
}
|
||||
return(reg);
|
||||
}
|
||||
|
||||
/* ucodegen - generate code for tree given cookie and starting register*/
|
||||
/* Handles the matching of the expression tree node with the*/
|
||||
/* corresponding code generation table. When a match is found,*/
|
||||
/* expand is called to expand the code skeleton macro.*/
|
||||
ucodegen(tp,cookie,reg) /* returns reg result is in*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int cookie; /* (FORCC,FOREFF,FORREG,FORSTACK)*/
|
||||
int reg; /* first available register*/
|
||||
{
|
||||
register int r;
|
||||
register char *p;
|
||||
|
||||
#ifndef NODEBUG
|
||||
if(cflag)
|
||||
putexpr("ucodegen",tp);
|
||||
#endif
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case STASSIGN: /*[vlh]*/
|
||||
outstrcpy(codegen(tp->t_left,FORREG,areg(reg)),
|
||||
codegen(tp->t_right,FORREG,areg(reg+1)), tp->t_type);
|
||||
return(reg);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
if( cookie == FOREFF )
|
||||
return(reg);
|
||||
break;
|
||||
|
||||
case LSH:
|
||||
if( (isareg(reg)) && (p=constant(tp->t_right)) &&
|
||||
!(unsign(tp->t_left->t_type)) &&
|
||||
(p->t_value == 1 || p->t_value == 2) ) {
|
||||
r = codegen(tp->t_left,FORREG,reg);
|
||||
outmovr(r,reg,tp->t_left);
|
||||
if( p->t_value == 2 )
|
||||
outaddr(reg,reg,tp);
|
||||
outaddr(reg,reg,tp);
|
||||
fixresult(tp,cookie,reg);
|
||||
return(reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case EQMULT:
|
||||
case EQDIV:
|
||||
case LEQMULT:
|
||||
case LEQDIV:
|
||||
case EQMOD:
|
||||
case LEQMOD:
|
||||
case EQRSH:
|
||||
case EQLSH:
|
||||
case EQAND:
|
||||
case EQOR:
|
||||
case EQXOR:
|
||||
if( indexreg(tp->t_left) ) {
|
||||
reg = dreg(reg);
|
||||
outmovr(r=tp->t_left->t_reg,reg,tp);
|
||||
tp->t_left->t_reg = reg;
|
||||
codegen(tp,cookie,reg+1);
|
||||
outmovr(reg,r,tp);
|
||||
return(reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case ADD:
|
||||
case EQADD:
|
||||
if( (p=constant(tp->t_right)) && p->t_value < 0 &&
|
||||
p->t_value >= -QUICKVAL ) {
|
||||
p->t_value = - p->t_value;
|
||||
tp->t_op =+ (SUB-ADD);
|
||||
}
|
||||
break;
|
||||
}
|
||||
sucomp(tp,reg,1);
|
||||
if( (r=loadexpr(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( (r=cqmark(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( (r=hardrel(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( cookie == FORCC && (p=match(tp,FOREFF,reg)) != 0 ) {
|
||||
r = expand(tp,FOREFF,reg,p);
|
||||
if( asgop(tp->t_op) && indexreg(tp->t_left) )
|
||||
outcmp0(tp->t_left->t_reg,tp->t_left);
|
||||
}
|
||||
else if( p = match(tp,cookie,reg) )
|
||||
r = expand(tp,cookie,reg,p);
|
||||
else if( cookie != FORREG )
|
||||
r = fixresult(tp,cookie,ucodegen(tp,FORREG,reg));
|
||||
else
|
||||
error("no code table for %d",tp->t_op);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* outstrcpy - output structure copy */
|
||||
outstrcpy(lr,rr,size) /*[vlh]*/
|
||||
int lr, rr; /* left register, right register */
|
||||
int size; /* structure size to copy */
|
||||
{
|
||||
register int lab;
|
||||
lab = nextlabel++;
|
||||
printf("move #%d,r%d\n",(size/2)-1,dreg(lr));
|
||||
outlab(lab);
|
||||
printf("move (r%d)+,(r%d)+\ndbra r%d,L%d\n",rr,lr,dreg(lr),lab);
|
||||
}
|
||||
|
||||
/* loadexpr - load an addressable expression into a register*/
|
||||
/* This checks for any possible usage of the register indexed*/
|
||||
/* addressing mode. Note that this relies on the good graces of the*/
|
||||
/* load code skeletons not to muck up the compiler registers before*/
|
||||
/* loading an addressable expression...*/
|
||||
loadexpr(tp,cookie,reg) /* returns register loaded or -1*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int reg; /* register to load*/
|
||||
{
|
||||
register struct tnode *rtp, *ltp, *xtp, *atp;
|
||||
register int off, r, type, nr, ar, xr, xt;
|
||||
|
||||
if( tp->t_op == INDR || LOADABLE(tp) ) {
|
||||
type = tp->t_type;
|
||||
if( tp->t_op == INDR && (ltp=tp->t_left)->t_op == ADD ) {
|
||||
rtp = ltp->t_right;
|
||||
ltp = ltp->t_left;
|
||||
off = 0;
|
||||
if( rtp->t_op == CINT && ((off=rtp->t_value) < -128 ||
|
||||
off > 127 || ltp->t_op != ADD ) ) {
|
||||
tp = snalloc(type,AUTO,off,0,0);
|
||||
if( indexreg(ltp) )
|
||||
tp->t_reg = ltp->t_reg;
|
||||
else {
|
||||
r = codegen(ltp,FORREG,areg(reg));
|
||||
if( isdreg(r) )
|
||||
outmovr(r,areg(r),ltp);
|
||||
tp->t_reg = areg(r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( rtp->t_op == CINT ) {
|
||||
rtp = ltp->t_right;
|
||||
ltp = ltp->t_left;
|
||||
}
|
||||
if(indexreg(rtp) || (!(indexreg(ltp)) && (isreg(rtp)))) {
|
||||
xtp = ltp;
|
||||
ltp = rtp;
|
||||
rtp = xtp;
|
||||
}
|
||||
xtp = atp = 0;
|
||||
if( indexreg(ltp) ) {
|
||||
ar = ltp->t_reg;
|
||||
if( (isreg(rtp)) && rtp->t_type != CHAR ) {
|
||||
xr = rtp->t_reg;
|
||||
xt = rtp->t_type;
|
||||
}
|
||||
else
|
||||
xtp = rtp;
|
||||
}
|
||||
else if( (isreg(ltp)) && ltp->t_type != CHAR &&
|
||||
(lflag || rtp->t_op != ADDR) ) {
|
||||
xr = ltp->t_reg;
|
||||
xt = ltp->t_type;
|
||||
atp = rtp;
|
||||
}
|
||||
else if( rtp->t_op == ADDR ) {
|
||||
atp = ltp;
|
||||
xtp = rtp;
|
||||
}
|
||||
else {
|
||||
atp = rtp;
|
||||
xtp = ltp;
|
||||
}
|
||||
nr = 0;
|
||||
if( atp )
|
||||
nr++;
|
||||
if( xtp && (xtp->t_op != ADDR || lflag ) )
|
||||
nr++;
|
||||
if( dreg(nr+reg) <= HICREG ) {
|
||||
r = reg;
|
||||
if( atp ) {
|
||||
ar = codegen(atp,FORREG,areg(r));
|
||||
if( isdreg(ar) ) {
|
||||
outmovr(ar,areg(ar),atp);
|
||||
ar = areg(ar);
|
||||
}
|
||||
r++;
|
||||
}
|
||||
if( xtp && xtp->t_op == ADDR && !lflag ) {
|
||||
tp = xtp->t_left;
|
||||
tp->t_sc =+ (EXTOFF-EXTERNAL);
|
||||
tp->t_offset =+ off;
|
||||
tp->t_reg = ar;
|
||||
}
|
||||
else {
|
||||
if( xtp ) {
|
||||
xr = codegen(xtp,FORREG,areg(r));
|
||||
xt = xtp->t_type;
|
||||
}
|
||||
tp = xnalloc(type,ar,off,xr,xt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (isareg(reg)) && tp->t_type == CHAR )
|
||||
reg = dreg(reg);
|
||||
tp = tnalloc(LOAD,tp->t_type,SU_EASY,0,tp,null);
|
||||
return( codegen(tp,cookie,reg) );
|
||||
}
|
||||
return(-1);
|
||||
|
||||
}
|
||||
|
||||
/* coffset - check offset for addressable node*/
|
||||
char *coffset(tp) /* returns ptr to const off node*/
|
||||
struct tnode *tp; /* pointer to node*/
|
||||
{
|
||||
register struct tnode *rtp;
|
||||
|
||||
if( tp->t_op == ADD ) {
|
||||
rtp = tp->t_right;
|
||||
if( rtp->t_op == CINT )
|
||||
return(rtp);
|
||||
if(!lflag) {
|
||||
if( rtp->t_op == ADDR )
|
||||
return(rtp->t_left);
|
||||
rtp = tp->t_left;
|
||||
if( rtp->t_op == ADDR ) {
|
||||
tp->t_left = tp->t_right;
|
||||
tp->t_right = rtp;
|
||||
return(rtp->t_left);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* hardrel - do relationals returning a value*/
|
||||
hardrel(tp,cookie,reg) /* returns reg or -1*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int cookie; /* cookie for code generation*/
|
||||
int reg; /* low register*/
|
||||
{
|
||||
char *p;
|
||||
int op, lab1, lab2;
|
||||
|
||||
if( cookie != FORCC && (relop(op=tp->t_op) || op == LOR ||
|
||||
op == LAND || op == NOT) ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(tp,TRUE,lab1,reg);
|
||||
p = canon(cnalloc(INT,0));
|
||||
codegen(p,cookie,reg);
|
||||
lab2 = nextlabel++;
|
||||
outgoto(lab2);
|
||||
outlab(lab1);
|
||||
p = canon(cnalloc(INT,1));
|
||||
codegen(p,cookie,reg);
|
||||
outlab(lab2);
|
||||
return(reg);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* cqmark - compile question mark operator*/
|
||||
/* This does the compilation of the question mark operator.*/
|
||||
cqmark(tp,cookie,reg) /* returns reg or -1*/
|
||||
struct tnode *tp;
|
||||
int cookie;
|
||||
int reg;
|
||||
{
|
||||
register int lab1, lab2, savestk, r;
|
||||
|
||||
if( tp->t_op == QMARK && cookie != FORCC ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(tp->t_left,FALSE,lab1,reg);
|
||||
savestk = stacksize;
|
||||
r = scodegen(tp->t_right->t_left,cookie,reg); /* [mc] 4.0 */
|
||||
outmovr(r,reg,tp);
|
||||
stacksize = savestk;
|
||||
outgoto(lab2=nextlabel++);
|
||||
outlab(lab1);
|
||||
r = scodegen(tp->t_right->t_right,cookie,reg); /* [mc] 4.0 */
|
||||
outmovr(r,reg,tp);
|
||||
outlab(lab2);
|
||||
return(reg);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* condbr - handle conditional branch code generation*/
|
||||
/* This handles the conditional branch code generation, handling*/
|
||||
/* the special cases for constants, ||, &&, ! and generating the*/
|
||||
/* correct conditional branch instruction.*/
|
||||
condbr(tp,dir,lab,reg)
|
||||
struct tnode *tp;
|
||||
int dir;
|
||||
int lab;
|
||||
int reg;
|
||||
{
|
||||
register struct tnode *ltp, *rtp;
|
||||
register int lab1, optype, op, subdir;
|
||||
|
||||
ltp = tp->t_left;
|
||||
if( binop(op=tp->t_op) )
|
||||
rtp = tp->t_right;
|
||||
subdir = dir; /*set up for LOR*/
|
||||
switch( op ) {
|
||||
|
||||
case CINT:
|
||||
if( !tp->t_value ) {
|
||||
if( dir == FALSE )
|
||||
outgoto(lab);
|
||||
}
|
||||
else if( dir != FALSE )
|
||||
outgoto(lab);
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
condbr(ltp,!dir,lab,reg);
|
||||
break;
|
||||
|
||||
case LAND:
|
||||
dir = !dir;
|
||||
case LOR:
|
||||
if( dir == FALSE ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(ltp,!subdir,lab1,reg);
|
||||
condbr(rtp,subdir,lab,reg);
|
||||
outlab(lab1);
|
||||
}
|
||||
else {
|
||||
condbr(ltp,subdir,lab,reg);
|
||||
condbr(rtp,subdir,lab,reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMA:
|
||||
scodegen(tp->t_left,FOREFF,reg);
|
||||
condbr(tp->t_right,dir,lab,reg);
|
||||
break;
|
||||
|
||||
default:
|
||||
if( op == NEQUALS && ltp->t_op == PREDEC &&
|
||||
isdreg(ltp->t_left->t_reg) && ltp->t_left->t_type == INT &&
|
||||
rtp->t_op == CINT && rtp->t_value == -1 ) {
|
||||
outdbra(ltp->t_left->t_reg,lab);
|
||||
break;
|
||||
}
|
||||
if( relop(op) && ltp->t_op == AUTOINC && rtp->t_op == AUTOINC &&
|
||||
ltp->t_type == rtp->t_type )
|
||||
outcmpm(tp);
|
||||
else
|
||||
scodegen(tp,FORCC,reg);
|
||||
optype = 0;
|
||||
if( relop(op) ) {
|
||||
if( unorptr(ltp->t_type) || unorptr(rtp->t_type) )
|
||||
optype =+ 1;
|
||||
}
|
||||
else
|
||||
op = NEQUALS;
|
||||
if(!dir)
|
||||
op = invrel[op-EQUALS];
|
||||
optype = brtab[op-EQUALS][optype];
|
||||
printf("%s L%d\n",mnemonics[optype],lab);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rcodegen(tpp,cookie,reg) /* returns changed flag*/
|
||||
struct tnode **tpp; /* pointer to tree*/
|
||||
int cookie; /* code generation cookie*/
|
||||
int reg; /* register to use for code*/
|
||||
{
|
||||
register int change, op;
|
||||
register struct tnode *tp;
|
||||
|
||||
tp = *tpp;
|
||||
op = tp->t_op;
|
||||
change = 0;
|
||||
if( notleafop(op) && op != COMMA ) {
|
||||
change =+ rcodegen(&tp->t_left,cookie,reg);
|
||||
if( binop(op) )
|
||||
change =+ rcodegen(&tp->t_right,cookie,reg);
|
||||
change =+ rcgen(tpp,cookie,reg);
|
||||
}
|
||||
if( change )
|
||||
*tpp = canon(*tpp);
|
||||
return(change);
|
||||
}
|
||||
|
||||
rcgen(tpp,cookie,reg) /* returns changed flag*/
|
||||
struct tnode **tpp; /* pointer to tree*/
|
||||
int cookie; /* code generation goals*/
|
||||
int reg; /* register to use*/
|
||||
{
|
||||
register struct tnode *tp, *p, *ltp, *rtp;
|
||||
register int op, change;
|
||||
|
||||
change = 0;
|
||||
for( tp = *tpp ; binop(op=tp->t_op); *tpp=tp=canon(tp), change++ ) {
|
||||
ltp = tp->t_left;
|
||||
if( ltp->t_op != SYMBOL )
|
||||
break;
|
||||
rtp = tp->t_right;
|
||||
switch( op ) {
|
||||
|
||||
case ASSIGN:
|
||||
if( ltp->t_sc != REGISTER )
|
||||
return(change);
|
||||
switch( rtp->t_op ) {
|
||||
|
||||
case MULT:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case AND:
|
||||
case OR:
|
||||
case XOR:
|
||||
case LSH:
|
||||
case RSH:
|
||||
if( isareg(ltp->t_reg) )
|
||||
return(change);
|
||||
case ADD:
|
||||
case SUB:
|
||||
p = rtp->t_right;
|
||||
if(NOTADDRESSABLE(ltp) || !noref(rtp->t_right,ltp->t_reg))
|
||||
return(change);
|
||||
p = rtp->t_left;
|
||||
if( p->t_op != SYMBOL || p->t_sc != REGISTER ||
|
||||
p->t_reg != ltp->t_reg ) {
|
||||
tp->t_right = p;
|
||||
#ifndef NODEBUG
|
||||
if( cflag > 1 )
|
||||
putexpr("rcgen",tp);
|
||||
#endif
|
||||
codegen(tp,FOREFF,reg);
|
||||
}
|
||||
tp->t_right = rtp->t_right;
|
||||
tp->t_op = rtp->t_op + (EQADD-ADD);
|
||||
continue;
|
||||
}
|
||||
case EQLSH:
|
||||
case EQRSH:
|
||||
if( ltp->t_sc != REGISTER )
|
||||
return(change);
|
||||
case EQADD:
|
||||
case EQSUB:
|
||||
case EQAND:
|
||||
case EQOR:
|
||||
case EQXOR:
|
||||
if( ltp->t_type == CHAR )
|
||||
return(change);
|
||||
#ifndef NODEBUG
|
||||
if( cflag > 1 )
|
||||
putexpr("rcgen",tp);
|
||||
#endif
|
||||
ucodegen(tp,FOREFF,reg);
|
||||
tp = ltp;
|
||||
continue;
|
||||
|
||||
case PREDEC:
|
||||
case PREINC:
|
||||
if( cookie == FORCC || ltp->t_type == CHAR )
|
||||
return(change);
|
||||
ucodegen(tp,FOREFF,reg);
|
||||
tp = ltp;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return(change);
|
||||
}
|
||||
|
||||
noref(tp,reg) /* 4.0 change */
|
||||
struct tnode *tp; /* returns 1 if no reference in tree to reg */
|
||||
int reg;
|
||||
{
|
||||
if ( leafop(tp->t_op) ) {
|
||||
if (tp->t_op == SYMBOL && tp->t_sc == REGISTER && tp->t_reg == reg)
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
if ( !noref(tp->t_left,reg) )
|
||||
return(0);
|
||||
if (binop(tp->t_op))
|
||||
return( noref(tp->t_right,reg) );
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* cdsize - compute size of data item*/
|
||||
cdsize(tp) /* returns data size in bytes*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
register int type;
|
||||
|
||||
type = tp->t_type;
|
||||
if( suptype(type) )
|
||||
return(PTRSIZE);
|
||||
switch( type ) {
|
||||
|
||||
case CHAR:
|
||||
case INT:
|
||||
case UNSIGNED:
|
||||
return(INTSIZE);
|
||||
|
||||
case LONG:
|
||||
case FLOAT: /* [vlh] 3.4 */
|
||||
return(LONGSIZE);
|
||||
}
|
||||
error("cdsize: invalid type %d",type);
|
||||
return(0);
|
||||
}
|
||||
|
||||
dofarg(tp) /* returns number of bytes pushed*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
{
|
||||
register int nb;
|
||||
|
||||
nb = 0;
|
||||
if( tp->t_op == SYMBOL && tp->t_sc == STRUCT )
|
||||
error("structure operation not implemented");
|
||||
else if( stacksize ) {
|
||||
codegen(tp,FORSTACK,0);
|
||||
nb = cdsize(tp);
|
||||
}
|
||||
else
|
||||
codegen(tp,FORSP,0);
|
||||
return( nb );
|
||||
}
|
||||
|
||||
/* dobitadd - do bit operation address checking and fixup*/
|
||||
dobitadd(tp,bitno) /* returns -1 if can't or bitno*/
|
||||
struct tnode *tp;
|
||||
int bitno;
|
||||
{
|
||||
register int offset;
|
||||
|
||||
if( tp->t_type == CHAR )
|
||||
offset = 0;
|
||||
else
|
||||
offset = cdsize(tp) - (bitno/BITSPBYTE) - 1;
|
||||
if( tp->t_op == SYMBOL ) {
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
case REGISTER:
|
||||
if( isdreg(tp->t_reg) )
|
||||
return(bitno);
|
||||
default:
|
||||
return(-1);
|
||||
|
||||
case EXTERNAL:
|
||||
case STATIC:
|
||||
case REGOFF:
|
||||
case STATOFF:
|
||||
case EXTOFF:
|
||||
tp->t_offset =+ offset;
|
||||
return( bitno % BITSPBYTE );
|
||||
}
|
||||
}
|
||||
else if( tp->t_op == INDR ) {
|
||||
tp->t_left = tnalloc(ADD,tp->t_left->t_type,0,0,tp->t_left,
|
||||
cnalloc(INT,offset));
|
||||
return( bitno % BITSPBYTE );
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
isonebit(tp) /* returns -1 if not 1 bit, else bitno*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
{
|
||||
if( tp = constant(tp) )
|
||||
return( onebit(tp->t_value) );
|
||||
return(-1);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 1981
|
||||
Alcyon Corporation
|
||||
8474 Commerce Av.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*built-in literals*/
|
||||
#define MOV 128
|
||||
#define MOVL 129
|
||||
#define JSR 130
|
||||
#define CLR 131
|
||||
#define CLRL 132
|
||||
#define EXTW 133
|
||||
#define EXTL 134
|
||||
#define LEA 135
|
||||
#define STK 136
|
||||
|
||||
/*built-in macros*/
|
||||
#define TREE 141
|
||||
#define LEFT 142
|
||||
#define RIGHT 143
|
||||
#define LOFFSET 144
|
||||
#define ROFFSET 145
|
||||
#define LADDR 146
|
||||
#define RADDR 147
|
||||
#define CR 148
|
||||
#define NR 149
|
||||
#define CAR 150
|
||||
#define NAR 151
|
||||
#define TLEFT 152
|
||||
#define TRIGHT 153
|
||||
#define TEITHER 154
|
||||
#define TLEFTL 155
|
||||
#define OP 156
|
||||
#define AOP 157
|
||||
#define MODSWAP 158
|
||||
#define EXL 159
|
||||
#define EXLR 160
|
||||
#define EXLRN 161
|
||||
#define EXRL 162
|
||||
#define EXRLN 163
|
||||
#define PSH 164
|
||||
#define POP 165
|
||||
#define POP8 166
|
||||
#define OPCALL 167
|
||||
#define POP4 169
|
||||
#define LADDRP 168
|
||||
|
||||
/*modifiers for compiling sub-trees*/
|
||||
#define S_INDR 1 /*indirection*/
|
||||
#define S_STACK 2 /*onto stack*/
|
||||
#define S_FORCC 4 /*set condition codes*/
|
||||
#define S_NEXT 8 /*into next register*/
|
||||
|
||||
/*Sethy-Ullman values*/
|
||||
#define SU_ZERO 0x000 /*zero*/
|
||||
#define SU_ONE 0x100 /*one*/
|
||||
#define SU_SMALL 0x200 /*constant between 1 and 8*/
|
||||
#define SU_QUICK 0x300 /*quick constant between -128 and 127*/
|
||||
#define SU_CONST 0x400 /*any constant*/
|
||||
#define SU_AREG 0x500 /*A register*/
|
||||
#define SU_REG 0x600 /*register*/
|
||||
#define SU_ADDR 0x700 /*addressable*/
|
||||
#define SU_XREG 0x800 /*A register used as data...*/
|
||||
#define SU_EASY 0x900 /*easy*/
|
||||
#define SU_HARD 0xa00 /*hard*/
|
||||
#define SU_VHARD 0xb00 /*very hard ... function calls, etc.*/
|
||||
#define SU_ANY 0xf00 /*anything*/
|
||||
#define ADDRESSABLE(x) (x->t_su<=SU_ADDR)
|
||||
#define NOTADDRESSABLE(x) (x->t_su>SU_ADDR)
|
||||
#define LOADABLE(x) (x->t_su<=SU_XREG)
|
||||
|
||||
/*flag byte (operand type):*/
|
||||
#define T_CHAR 1 /*char only*/
|
||||
#define T_SHORT 2 /*short*/
|
||||
#define T_INT 3 /*int only*/
|
||||
#define T_LONG 4 /*long*/
|
||||
#define T_UCHAR 5 /*unsigned char*/
|
||||
#define T_USHORT 6 /*unsigned short*/
|
||||
#define T_UNSN 7 /*unsigned int*/
|
||||
#define T_ULONG 8 /*unsigned long*/
|
||||
#define T_FLOAT 9 /*float*/
|
||||
#define T_DOUB 10 /*double*/
|
||||
#define T_ANY 11 /*int or word (implied)*/
|
||||
#define T_INDR 0x10 /*pointer type (bit)*/
|
||||
|
||||
struct skeleton {
|
||||
int sk_left;
|
||||
int sk_right;
|
||||
char *sk_def;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
#include "machine.h"
|
||||
/*
|
||||
* intermediate code operators
|
||||
* 0=>EOF, special operator
|
||||
*/
|
||||
#define EOF 0
|
||||
|
||||
/*1-59=>operators that generate code (entries in code gen optab)*/
|
||||
#define ADD 1
|
||||
#define SUB 2
|
||||
#define MULT 3
|
||||
#define DIV 4
|
||||
#define MOD 5
|
||||
#define RSH 6
|
||||
#define LSH 7
|
||||
#define AND 8
|
||||
#define OR 9
|
||||
#define XOR 10
|
||||
#define NOT 11
|
||||
#define UMINUS 12
|
||||
#define COMPL 13
|
||||
#define PREDEC 14
|
||||
#define PREINC 15
|
||||
#define POSTDEC 16
|
||||
#define POSTINC 17
|
||||
#define ASSIGN 18
|
||||
#define EQADD 19
|
||||
#define EQSUB 20
|
||||
#define EQMULT 21
|
||||
#define EQDIV 22
|
||||
#define EQMOD 23
|
||||
#define EQRSH 24
|
||||
#define EQLSH 25
|
||||
#define EQAND 26
|
||||
#define EQOR 27
|
||||
#define EQXOR 28
|
||||
#define FJSR 29
|
||||
#define EQUALS 30
|
||||
#define NEQUALS 31
|
||||
#define GREAT 32
|
||||
#define GREATEQ 33
|
||||
#define LESS 34
|
||||
#define LESSEQ 35
|
||||
#define INT2L 36
|
||||
#define LONG2I 37
|
||||
|
||||
/*machine dependent operators that generate code*/
|
||||
#define BTST 38
|
||||
#define LOAD 39
|
||||
#define LMULT 40
|
||||
#define LDIV 41
|
||||
#define LMOD 42
|
||||
#define LEQMULT 43
|
||||
#define LEQDIV 44
|
||||
#define LEQMOD 45
|
||||
#define EQADDR 46
|
||||
#define EQNOT 47
|
||||
#define EQNEG 48
|
||||
#define DOCAST 49
|
||||
|
||||
#define STASSIGN 50 /*[vlh]*/
|
||||
#define LONG2F 51 /*[vlh] 3.4*/
|
||||
#define FLOAT2L 52 /*[vlh] 3.4*/
|
||||
#define INT2F 53 /*[vlh] 3.4*/
|
||||
#define FLOAT2I 54 /*[vlh] 3.4*/
|
||||
#define LCGENOP 55 /*change if adding more operators...*/
|
||||
|
||||
/*intermediate code operators that do not generate code*/
|
||||
#define ADDR 60
|
||||
#define INDR 61
|
||||
#define LAND 62
|
||||
#define LOR 63
|
||||
#define QMARK 64
|
||||
#define COLON 65
|
||||
#define COMMA 66
|
||||
#define CINT 67
|
||||
#define CLONG 68
|
||||
#define SYMBOL 69
|
||||
#define AUTOINC 70
|
||||
#define AUTODEC 71
|
||||
#define CALL 72
|
||||
#define NACALL 73
|
||||
#define BFIELD 74
|
||||
#define IFGOTO 75
|
||||
#define INIT 76
|
||||
#define CFORREG 77
|
||||
#define DCLONG 78
|
||||
#define CFLOAT 79 /*[vlh] 3.4*/
|
||||
|
||||
/*operators local to parser*/
|
||||
#define CAST 80
|
||||
#define SEMI 81
|
||||
#define LCURBR 82
|
||||
#define RCURBR 83
|
||||
#define LBRACK 84
|
||||
#define RBRACK 85
|
||||
#define LPAREN 86
|
||||
#define RPAREN 87
|
||||
#define STRING 88
|
||||
#define RESWORD 89
|
||||
#define APTR 90
|
||||
#define PERIOD 91
|
||||
#define SIZEOF 92
|
||||
#define MPARENS 93
|
||||
#define FRETURN 94
|
||||
#define STACKEND 100
|
||||
|
||||
/*data types*/
|
||||
#define TYPELESS 0
|
||||
#define CHAR 1
|
||||
#define SHORT 2
|
||||
#define INT 3
|
||||
#define LONG 4
|
||||
#define UCHAR 5
|
||||
#define USHORT 6
|
||||
#define UNSIGNED 7
|
||||
#define ULONG 8
|
||||
#define FLOAT 9
|
||||
#define DOUBLE 10
|
||||
|
||||
/*data types local to parser*/
|
||||
#define STRUCT 11
|
||||
#define FRSTRUCT 12
|
||||
#define LLABEL 13
|
||||
|
||||
/*type flags and definitions*/
|
||||
#define TYPE 017
|
||||
#define SUPTYP 060
|
||||
#define ALLTYPE 077
|
||||
#define POINTER 020
|
||||
#define FUNCTION 040
|
||||
#define ARRAY 060
|
||||
#define SUTYPLEN 2
|
||||
|
||||
/*data registers*/
|
||||
#define DREG0 0
|
||||
#define DREG2 2
|
||||
#define DREG3 3
|
||||
#define DREG4 4
|
||||
#define DREG5 5
|
||||
#define DREG6 6
|
||||
#define DREG7 7
|
||||
#define AREG3 11
|
||||
#define AREG4 12
|
||||
#define AREG5 13
|
||||
|
||||
/*storage classes*/
|
||||
#define AUTO 1
|
||||
#define REGISTER 2
|
||||
#define EXTERNAL 3
|
||||
#define STATIC 4
|
||||
#define REGOFF 5
|
||||
#define EXTOFF 6
|
||||
#define STATOFF 7
|
||||
#define INDEXED 8
|
||||
|
||||
/*exclusively code generator storage classes*/
|
||||
#define CINDR 9
|
||||
#define CLINDR 10
|
||||
#define CFINDR 11 /* [vlh] 3.4 */
|
||||
|
||||
/*exclusively parser storage classes*/
|
||||
#define STRPROTO 9
|
||||
#define PDECLIST 10
|
||||
#define PARMLIST 11
|
||||
#define BFIELDCL 12
|
||||
#define UNELCL 13
|
||||
#define STELCL 14
|
||||
|
||||
|
||||
/*opinfo table bits*/
|
||||
#define OPPRI 077
|
||||
#define OPBIN 0100
|
||||
#define OPLVAL 0200
|
||||
#define OPREL 0400
|
||||
#define OPASSIGN 01000
|
||||
#define OPLWORD 02000
|
||||
#define OPRWORD 04000
|
||||
#define OPCOM 010000
|
||||
#define OPRAS 020000
|
||||
#define OPTERM 040000
|
||||
#define OPCONVS 0100000
|
||||
|
||||
/*68000 definitions*/
|
||||
#define PTRSIZE 4
|
||||
#define INTSIZE 2
|
||||
#define LONGSIZE 4
|
||||
#define SSIZE 8 /* chars per symbol */
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define TABC '\t' /* tab character */
|
||||
#define EOLC '\n' /* end of line character */
|
||||
#define BITSPBYTE 8
|
||||
|
||||
/*operator class priorities*/
|
||||
#define TRMPRI 0 /* terminal nodes */
|
||||
#define RPNPRI 1 /* ) and ] */
|
||||
#define CALPRI 2 /* in-stack call, ( or [ */
|
||||
#define COLPRI 3 /* init or case priority for : or , */
|
||||
#define STKPRI 4 /* priority of end of stack */
|
||||
#define COMPRI 5 /* normal priority for , */
|
||||
#define ASGPRI 6 /* =, +=, -=, *=, /=, %=, ... */
|
||||
#define QMKPRI 7 /* ?: */
|
||||
#define LORPRI 8 /* || */
|
||||
#define LNDPRI 9 /* && */
|
||||
#define ORPRI 10 /* |, ! */
|
||||
#define ANDPRI 11 /* & */
|
||||
#define EQLPRI 12 /* ==, != */
|
||||
#define RELPRI 13 /* >, <, >=, <= */
|
||||
#define SHFPRI 14 /* <<, >> */
|
||||
#define ADDPRI 15 /* +, - */
|
||||
#define MULPRI 16 /* *, /, % */
|
||||
#define UNOPRI 17 /* ++, --, &, *, -, ~, sizeof */
|
||||
#define LPNPRI 18 /* ., ->, [, (, function call */
|
||||
#define PSTPRI 19 /* in-stack post--, post++ */
|
||||
|
||||
struct io_buf {
|
||||
int io_fd;
|
||||
int io_nc;
|
||||
char *io_p;
|
||||
char io_b[512];
|
||||
};
|
||||
|
||||
#ifdef PDP11
|
||||
struct { short hiword; short loword; };
|
||||
#endif
|
||||
#ifdef MC68000
|
||||
struct { short hiword; short loword; };
|
||||
#endif
|
||||
#ifdef VAX
|
||||
struct { short loword; short hiword; };
|
||||
#endif
|
||||
|
||||
#define EXPSIZE 1024
|
||||
int exprarea[EXPSIZE];
|
||||
|
||||
/* v6io buffer declaration */
|
||||
#define BLEN 512
|
||||
|
||||
struct iobuf{
|
||||
int fildes;
|
||||
int nunused;
|
||||
char *xfree;
|
||||
char buff[BLEN];
|
||||
};
|
||||
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
|
||||
char null[]=0;
|
||||
#define SSIZE 8 /* chars per symbol */
|
||||
|
||||
/*operator tree node for unary and binary operators*/
|
||||
struct tnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*data type of result*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
struct tnode *t_left; /*left sub-tree*/
|
||||
struct tnode *t_right; /*right sub-tree (undefined if unary)*/
|
||||
};
|
||||
|
||||
/*constant terminal node*/
|
||||
struct conode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_value; /*value or label number*/
|
||||
};
|
||||
|
||||
struct lconode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
long t_lvalue; /*value or label number*/
|
||||
};
|
||||
|
||||
/*local symbol terminal node*/
|
||||
struct symnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*symbol data type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_sc; /*storage class*/
|
||||
int t_offset; /*register offset*/
|
||||
int t_reg; /*register number*/
|
||||
int t_label; /*label number if static*/
|
||||
};
|
||||
|
||||
/*external symbol reference node*/
|
||||
struct extnode {
|
||||
int t_op; /*operator*/
|
||||
int t_type; /*symbol data type*/
|
||||
int t_su; /*Sethy-Ullman number*/
|
||||
int t_ssp;
|
||||
int t_sc; /*storage class*/
|
||||
int t_offset; /*register offset*/
|
||||
int t_reg; /*register number*/
|
||||
char t_symbol[SSIZE]; /*symbol name*/
|
||||
};
|
||||
|
||||
/*68000 special - indexed symbol node*/
|
||||
/*this is used to generate a An(off,Xn.type) address*/
|
||||
struct indexnode {
|
||||
int t_op;
|
||||
int t_type;
|
||||
int t_su;
|
||||
int t_ssp;
|
||||
int t_sc;
|
||||
int t_offset;
|
||||
int t_reg;
|
||||
int t_xreg;
|
||||
int t_xtype;
|
||||
};
|
||||
|
||||
int lflag=0;
|
||||
int dflag=0;
|
||||
int mflag=0;
|
||||
int cflag=0;
|
||||
int eflag=0;
|
||||
int fflag=0;
|
||||
int oflag=0;
|
||||
int lineno=0;
|
||||
int naregs=0;
|
||||
int ndregs=0;
|
||||
int errcnt=0;
|
||||
int stacksize=0;
|
||||
|
||||
char *tnalloc();
|
||||
char *snalloc();
|
||||
char *cenalloc();
|
||||
char *xnalloc();
|
||||
char *talloc();
|
||||
char *cnalloc();
|
||||
char *lcnalloc();
|
||||
char *fpcnalloc();
|
||||
char *canon();
|
||||
char *commute();
|
||||
char *constant();
|
||||
char *match();
|
||||
char *addptree();
|
||||
char *fixbfield();
|
||||
char *coffset();
|
||||
char *tcopy();
|
||||
|
||||
#define wallign(add) ((add+1)&(~1))
|
||||
#define array(type) ((type&SUPTYP)==ARRAY)
|
||||
#define function(type) ((type&SUPTYP)==FUNCTION)
|
||||
#define pointer(type) ((type&SUPTYP)==POINTER)
|
||||
#define notarray(type) ((type&SUPTYP)!=ARRAY)
|
||||
#define notfunction(type) ((type&SUPTYP)!=FUNCTION)
|
||||
#define notpointer(type) ((type&SUPTYP)!=POINTER)
|
||||
#define isfloat(type) (type==FLOAT)
|
||||
#define btype(type) (type&TYPE)
|
||||
#define suptype(type) (type&SUPTYP)
|
||||
#define alltype(type) (type&(SUPTYP|TYPE))
|
||||
#define asgop(op) ((opinfo[op]&OPASSIGN)!=0)
|
||||
#define relop(op) ((opinfo[op]&OPREL)!=0)
|
||||
#define lintegral(op) ((opinfo[op]&OPLWORD)!=0)
|
||||
#define rintegral(op) ((opinfo[op]&OPRWORD)!=0)
|
||||
#define rasop(op) ((opinfo[op]&OPRAS)!=0)
|
||||
#define binop(op) ((opinfo[op]&OPBIN)!=0)
|
||||
#define unaryop(op) ((opinfo[op]&(OPBIN|OPTERM))==0)
|
||||
#define leafop(op) ((opinfo[op]&OPTERM)!=0)
|
||||
#define notleafop(op) ((opinfo[op]&OPTERM)==0)
|
||||
#define lvalop(op) ((opinfo[op]&OPLVAL)!=0)
|
||||
#define oppriority(op) (opinfo[op]&OPPRI)
|
||||
#define commop(op) ((opinfo[op]&OPCOM)!=0)
|
||||
#define convop(op) ((opinfo[op]&OPCONVS)!=0)
|
||||
#define notconvop(op) ((opinfo[op]&OPCONVS)==0)
|
||||
#define max(a,b) (a>b?a:b)
|
||||
#define min(a,b) (a<b?a:b)
|
||||
|
||||
#define QUICKVAL 8
|
||||
#define LEP 14
|
||||
#define FORCC 1
|
||||
#define FOREFF 2
|
||||
#define FORSTACK 3
|
||||
#define FORCREG 4
|
||||
#define FORSP 5
|
||||
#define FORREG 4
|
||||
#define HICREG 2
|
||||
#define NCREGS 3
|
||||
#define AREGLO 8
|
||||
#define IMMED 1
|
||||
#define NOTIMMED 0
|
||||
#define NOTLOFFSET 0
|
||||
|
||||
/* one line routines turned into defines [vlh] for speed */
|
||||
|
||||
/*outgoto - output "bra L[labno]"*/
|
||||
#define outgoto(lab) if (lab>0) printf("bra L%d\n",lab)
|
||||
/*outlab - output "L[labno]:"*/
|
||||
#define outlab(lab) if (lab>0) printf("L%d:",lab)
|
||||
|
||||
/*outext - output register sign extension*/
|
||||
#define outext(reg) printf("ext.l R%d\n",reg)
|
||||
/*outuext - output unsigned to long register extension*/
|
||||
#define outuext(reg) printf("swap R%d\nclr R%d\nswap R%d\n",reg,reg,reg)
|
||||
/*outswap - output swap register instruction*/
|
||||
#define outswap(reg) printf("swap R%d\n",reg)
|
||||
/*outaddr - output "add [type] R1 R2" instruction*/
|
||||
#define outaddr(r1,r2,tp) outrr("add",r1,r2,(tp))
|
||||
/*outccsave - ouput instruction to move cc's to register*/
|
||||
#define outccsave(reg) printf("move sr,R%d\n",reg)
|
||||
/*outccrestore - output instruction to restore cc's from register*/
|
||||
#define outccrestore(reg) printf("move R%d,ccr\n",reg)
|
||||
/*basetype - get the btype info sans unsigned*/
|
||||
#define basetype(type) ((type==UNSIGNED) ? INT : type)
|
||||
#define unsign(type) ((type) == UNSIGNED)
|
||||
#define longorptr(type) (type==LONG || (type&SUPTYP))
|
||||
#define unorptr(type) (type==UNSIGNED || (type&SUPTYP))
|
||||
#define dreg(reg) ((reg) & (~AREGLO))
|
||||
#define areg(reg) ((reg) | AREGLO)
|
||||
#define isareg(reg) ((reg) >= AREGLO)
|
||||
#define isdreg(reg) ((reg) < AREGLO)
|
||||
#define isreg(tp) ((tp)->t_op == SYMBOL && (tp)->t_sc == REGISTER)
|
||||
|
||||
/*
|
||||
* intermediate code operators
|
||||
* 0=>EOF, special operator
|
||||
*/
|
||||
#define EOF 0
|
||||
|
||||
/*1-59=>operators that generate code (entries in code gen optab)*/
|
||||
#define ADD 1
|
||||
#define SUB 2
|
||||
#define MULT 3
|
||||
#define DIV 4
|
||||
#define MOD 5
|
||||
#define RSH 6
|
||||
#define LSH 7
|
||||
#define AND 8
|
||||
#define OR 9
|
||||
#define XOR 10
|
||||
#define NOT 11
|
||||
#define UMINUS 12
|
||||
#define COMPL 13
|
||||
#define PREDEC 14
|
||||
#define PREINC 15
|
||||
#define POSTDEC 16
|
||||
#define POSTINC 17
|
||||
#define ASSIGN 18
|
||||
#define EQADD 19
|
||||
#define EQSUB 20
|
||||
#define EQMULT 21
|
||||
#define EQDIV 22
|
||||
#define EQMOD 23
|
||||
#define EQRSH 24
|
||||
#define EQLSH 25
|
||||
#define EQAND 26
|
||||
#define EQOR 27
|
||||
#define EQXOR 28
|
||||
#define FJSR 29
|
||||
#define EQUALS 30
|
||||
#define NEQUALS 31
|
||||
#define GREAT 32
|
||||
#define GREATEQ 33
|
||||
#define LESS 34
|
||||
#define LESSEQ 35
|
||||
#define INT2L 36
|
||||
#define LONG2I 37
|
||||
|
||||
/*machine dependent operators that generate code*/
|
||||
#define BTST 38
|
||||
#define LOAD 39
|
||||
#define LMULT 40
|
||||
#define LDIV 41
|
||||
#define LMOD 42
|
||||
#define LEQMULT 43
|
||||
#define LEQDIV 44
|
||||
#define LEQMOD 45
|
||||
#define EQADDR 46
|
||||
#define EQNOT 47
|
||||
#define EQNEG 48
|
||||
#define DOCAST 49
|
||||
|
||||
#define STASSIGN 50 /*[vlh]*/
|
||||
#define LONG2F 51 /*[vlh] 3.4*/
|
||||
#define FLOAT2L 52 /*[vlh] 3.4*/
|
||||
#define INT2F 53 /*[vlh] 3.4*/
|
||||
#define FLOAT2I 54 /*[vlh] 3.4*/
|
||||
#define LCGENOP 55 /*change if adding more operators...*/
|
||||
|
||||
/*intermediate code operators that do not generate code*/
|
||||
#define ADDR 60
|
||||
#define INDR 61
|
||||
#define LAND 62
|
||||
#define LOR 63
|
||||
#define QMARK 64
|
||||
#define COLON 65
|
||||
#define COMMA 66
|
||||
#define CINT 67
|
||||
#define CLONG 68
|
||||
#define SYMBOL 69
|
||||
#define AUTOINC 70
|
||||
#define AUTODEC 71
|
||||
#define CALL 72
|
||||
#define NACALL 73
|
||||
#define BFIELD 74
|
||||
#define IFGOTO 75
|
||||
#define INIT 76
|
||||
#define CFORREG 77
|
||||
#define DCLONG 78
|
||||
#define CFLOAT 79 /*[vlh] 3.4*/
|
||||
|
||||
/*operators local to parser*/
|
||||
#define CAST 80
|
||||
#define SEMI 81
|
||||
#define LCURBR 82
|
||||
#define RCURBR 83
|
||||
#define LBRACK 84
|
||||
#define RBRACK 85
|
||||
#define LPAREN 86
|
||||
#define RPAREN 87
|
||||
#define STRING 88
|
||||
#define RESWORD 89
|
||||
#define APTR 90
|
||||
#define PERIOD 91
|
||||
#define SIZEOF 92
|
||||
#define MPARENS 93
|
||||
#define FRETURN 94
|
||||
#define STACKEND 100
|
||||
|
||||
/*data types*/
|
||||
#define TYPELESS 0
|
||||
#define CHAR 1
|
||||
#define SHORT 2
|
||||
#define INT 3
|
||||
#define LONG 4
|
||||
#define UCHAR 5
|
||||
#define USHORT 6
|
||||
#define UNSIGNED 7
|
||||
#define ULONG 8
|
||||
#define FLOAT 9
|
||||
#define DOUBLE 10
|
||||
|
||||
/*data types local to parser*/
|
||||
#define STRUCT 11
|
||||
#define FRSTRUCT 12
|
||||
#define LLABEL 13
|
||||
|
||||
/*type flags and definitions*/
|
||||
#define TYPE 017
|
||||
#define SUPTYP 060
|
||||
#define ALLTYPE 077
|
||||
#define POINTER 020
|
||||
#define FUNCTION 040
|
||||
#define ARRAY 060
|
||||
#define SUTYPLEN 2
|
||||
|
||||
/*data registers*/
|
||||
#define DREG0 0
|
||||
#define DREG2 2
|
||||
#define DREG3 3
|
||||
#define DREG4 4
|
||||
#define DREG5 5
|
||||
#define DREG6 6
|
||||
#define DREG7 7
|
||||
#define AREG3 11
|
||||
#define AREG4 12
|
||||
#define AREG5 13
|
||||
|
||||
/*storage classes*/
|
||||
#define AUTO 1
|
||||
#define REGISTER 2
|
||||
#define EXTERNAL 3
|
||||
#define STATIC 4
|
||||
#define REGOFF 5
|
||||
#define EXTOFF 6
|
||||
#define STATOFF 7
|
||||
#define INDEXED 8
|
||||
|
||||
/*exclusively code generator storage classes*/
|
||||
#define CINDR 9
|
||||
#define CLINDR 10
|
||||
#define CFINDR 11 /* [vlh] 3.4 */
|
||||
|
||||
/*exclusively parser storage classes*/
|
||||
#define STRPROTO 9
|
||||
#define PDECLIST 10
|
||||
#define PARMLIST 11
|
||||
#define BFIELDCL 12
|
||||
#define UNELCL 13
|
||||
#define STELCL 14
|
||||
|
||||
|
||||
/*opinfo table bits*/
|
||||
#define OPPRI 077
|
||||
#define OPBIN 0100
|
||||
#define OPLVAL 0200
|
||||
#define OPREL 0400
|
||||
#define OPASSIGN 01000
|
||||
#define OPLWORD 02000
|
||||
#define OPRWORD 04000
|
||||
#define OPCOM 010000
|
||||
#define OPRAS 020000
|
||||
#define OPTERM 040000
|
||||
#define OPCONVS 0100000
|
||||
|
||||
/*68000 definitions*/
|
||||
#define PTRSIZE 4
|
||||
#define INTSIZE 2
|
||||
#define LONGSIZE 4
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define TABC '\t' /* tab character */
|
||||
#define EOLC '\n' /* end of line character */
|
||||
#define BITSPBYTE 8
|
||||
|
||||
/*operator class priorities*/
|
||||
#define TRMPRI 0 /* terminal nodes */
|
||||
#define RPNPRI 1 /* ) and ] */
|
||||
#define CALPRI 2 /* in-stack call, ( or [ */
|
||||
#define COLPRI 3 /* init or case priority for : or , */
|
||||
#define STKPRI 4 /* priority of end of stack */
|
||||
#define COMPRI 5 /* normal priority for , */
|
||||
#define ASGPRI 6 /* =, +=, -=, *=, /=, %=, ... */
|
||||
#define QMKPRI 7 /* ?: */
|
||||
#define LORPRI 8 /* || */
|
||||
#define LNDPRI 9 /* && */
|
||||
#define ORPRI 10 /* |, ! */
|
||||
#define ANDPRI 11 /* & */
|
||||
#define EQLPRI 12 /* ==, != */
|
||||
#define RELPRI 13 /* >, <, >=, <= */
|
||||
#define SHFPRI 14 /* <<, >> */
|
||||
#define ADDPRI 15 /* +, - */
|
||||
#define MULPRI 16 /* *, /, % */
|
||||
#define UNOPRI 17 /* ++, --, &, *, -, ~, sizeof */
|
||||
#define LPNPRI 18 /* ., ->, [, (, function call */
|
||||
#define PSTPRI 19 /* in-stack post--, post++ */
|
||||
|
||||
struct io_buf {
|
||||
int io_fd;
|
||||
int io_nc;
|
||||
char *io_p;
|
||||
char io_b[512];
|
||||
};
|
||||
struct { int hiword; int loword; };
|
||||
#define EXPSIZE 1024
|
||||
int exprarea[EXPSIZE]=0;
|
||||
|
||||
/* v6io buffer declaration */
|
||||
#define BLEN 512
|
||||
|
||||
struct iobuf {
|
||||
int fildes;
|
||||
int nunused;
|
||||
char *xfree;
|
||||
char buff[BLEN];
|
||||
};
|
||||
struct io_buf ibuf={0}, obuf={0};
|
||||
int bol=0;
|
||||
int errflg=0;
|
||||
int level=0;
|
||||
int onepass=0;
|
||||
char *opap=0;
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
int bol;
|
||||
int onepass;
|
||||
|
||||
/* outexpr - output expression*/
|
||||
outexpr(tp) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree node*/
|
||||
{
|
||||
if( dflag )
|
||||
outline();
|
||||
if( exprok(tp) )
|
||||
scodegen(canon(tp),FOREFF,0);
|
||||
}
|
||||
|
||||
outifgoto(tp,dir,lab)
|
||||
struct tnode *tp;
|
||||
int dir;
|
||||
int lab;
|
||||
{
|
||||
if( dflag )
|
||||
outline();
|
||||
if( exprok(tp) )
|
||||
condbr(canon(tp),dir,lab,0);
|
||||
}
|
||||
|
||||
outcforreg(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( dflag )
|
||||
outline();
|
||||
if( exprok(tp) )
|
||||
outmovr(scodegen(canon(tp),FORREG,0),0,tp);
|
||||
}
|
||||
|
||||
outinit(tp) /* returns - none*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
register int typeout;
|
||||
|
||||
if( dflag )
|
||||
outline();
|
||||
if( exprok(tp) ) {
|
||||
typeout = tp->t_type;
|
||||
tp = canon(tp);
|
||||
if( tp->t_op == ADDR )
|
||||
tp = tp->t_left;
|
||||
if( tp->t_op == CINT || tp->t_op == SYMBOL ) {
|
||||
if( tp->t_op != CINT )
|
||||
printf(".dc.l ");
|
||||
else {
|
||||
printf(".dc");
|
||||
outtype(typeout);
|
||||
putchar(' ');
|
||||
}
|
||||
outaexpr(tp,NOTIMMED); /* [vlh] 4.0 not immed... */
|
||||
}
|
||||
else
|
||||
error("invalid initialization");
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
/* snalloc - code generator symbol node allocation*/
|
||||
/* This might be coalesced into parser snalloc.*/
|
||||
char *snalloc(type,sc,offset,dp,ssp) /* returns ptr to node alloced*/
|
||||
int type; /* type of symbol*/
|
||||
int sc; /* storage class*/
|
||||
int offset; /* offset from Local Environment Ptr*/
|
||||
int dp; /*for compatability with parser*/
|
||||
int ssp; /*for compatability with parser*/
|
||||
{
|
||||
register struct symnode *sp;
|
||||
|
||||
sp = talloc(sizeof(*sp));
|
||||
sp->t_op = SYMBOL;
|
||||
sp->t_type = type;
|
||||
sp->t_su = dp;
|
||||
sp->t_ssp = ssp;
|
||||
sp->t_sc = sc;
|
||||
switch( sc ) {
|
||||
|
||||
case STATIC:
|
||||
sp->t_offset = 0;
|
||||
sp->t_reg = 0;
|
||||
sp->t_label = offset;
|
||||
break;
|
||||
|
||||
case REGISTER:
|
||||
sp->t_offset = 0;
|
||||
sp->t_reg = offset;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
|
||||
case AUTO:
|
||||
sp->t_sc = REGOFF;
|
||||
sp->t_offset = offset;
|
||||
sp->t_reg = LEP;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
sp->t_offset = offset;
|
||||
sp->t_reg = 0;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
}
|
||||
return(sp);
|
||||
}
|
||||
|
||||
exprok(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( tp < exprarea || tp > &exprarea[EXPSIZE] )
|
||||
return(0);
|
||||
if( leafop(tp->t_op) )
|
||||
return(1);
|
||||
if( binop(tp->t_op) && !exprok(tp->t_right) )
|
||||
return(0);
|
||||
return( exprok(tp->t_left) );
|
||||
}
|
||||
|
||||
outline()
|
||||
{
|
||||
if( onepass && !bol )
|
||||
putchar('\n');
|
||||
printf("*line %d\n",lineno);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
ren u.o=util.o
|
||||
ren t.o=tabl.o
|
||||
ren c.o=codegen.o
|
||||
ren i.o=interf.o
|
||||
ren m.o=main.o
|
||||
ren p.o=putexpr.o
|
||||
$1lo68 -r -f $1 -unofloat 0$1s.o canon.o c.o cskels.o i.o m.o optab.o p.o smatch.o sucomp.o t.o u.o 0$1lib6.a 0$1clib
|
||||
era c168.rel
|
||||
ren c168.rel=c.out
|
||||
era *.o
|
||||
|
||||
user 0!make $1
|
||||
@@ -0,0 +1,51 @@
|
||||
$ num
|
||||
CANON.C
|
||||
CANON.lis
|
||||
$ num
|
||||
CODEGEN.C
|
||||
CODEGEN.lis
|
||||
$ num
|
||||
CSKELS.C
|
||||
CSKELS.lis
|
||||
$ num
|
||||
INIT.C
|
||||
INIT.lis
|
||||
$ num
|
||||
INTERF.C
|
||||
INTERF.lis
|
||||
$ num
|
||||
MAIN.C
|
||||
MAIN.lis
|
||||
$ num
|
||||
OPTAB.C
|
||||
OPTAB.lis
|
||||
$ num
|
||||
PUTEXPR.C
|
||||
PUTEXPR.lis
|
||||
$ num
|
||||
SMATCH.C
|
||||
SMATCH.lis
|
||||
$ num
|
||||
SUCOMP.C
|
||||
SUCOMP.lis
|
||||
$ num
|
||||
TABL.C
|
||||
TABL.lis
|
||||
$ num
|
||||
UTIL.C
|
||||
UTIL.lis
|
||||
$ num
|
||||
VERSION.C
|
||||
VERSION.lis
|
||||
$ num
|
||||
CGEN.H
|
||||
CGEN.lst
|
||||
$ num
|
||||
CSKEL.H
|
||||
CSKEL.lst
|
||||
$ num
|
||||
ICODE.H
|
||||
ICODE.lst
|
||||
$ num
|
||||
MACHINE.H
|
||||
MACHINE.lst
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1*/ /* 68000 version */
|
||||
/*#define VAX 1*/ /* VAX Version */
|
||||
#define PDP11 1 /* PDP-11 Version*/
|
||||
/*#define CPM 1*/ /* CP/M Operating System*/
|
||||
#define UNIX 1 /* UNIX Operating System*/
|
||||
/*#define VMS 1*/ /* VMS Operating System*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
#define MC68000 1 /* 68000 version */
|
||||
/*#define VAX 1*/ /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
#define CPM 1 /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
/*#define VMS 1*/ /* VMS Operating System*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Use this file to determine what kind of machine you want the
|
||||
* Alcyon stuff to run on ....
|
||||
*/
|
||||
/*#define MC68000 1*/ /* 68000 version */
|
||||
#define VAX 1 /* VAX Version */
|
||||
/*#define PDP11 1*/ /* PDP-11 Version*/
|
||||
/*#define CPM 1*/ /* CP/M Operating System*/
|
||||
/*#define UNIX 1*/ /* UNIX Operating System*/
|
||||
#define VMS 1 /* VMS Operating System*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user