page@swan.ulowell.edu (Bob Page) (03/08/89)
Submitted-by: monty@brahms.Berkeley.EDU (Joe Montgomery) Posting-number: Volume 89, Issue 31 Archive-name: languages/zc.4 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # out.c # p2.c # pre.c # subs.c # tok.c # This archive created: Tue Mar 7 21:51:34 1989 cat << \SHAR_EOF > out.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * out.c * * Revised: Dec 1988 Joe Montgomery * * Revised out.c to use MOTOROLA assembly directives in order * to be compatible with C.Gibbs a68k assembler & blink * Added END statement * Changed .comm label,size to label DC.x 0 * * other modules: * Revised main.c to use Amiga File System Naming Conventions * Added ?,C,F switches. ? help * C force data,bss into Chip memory * F force data,bss into Fast memory * Revised d2.c so that externs are declared as XREF ----- * * Revised g2.c & gen.c to declare all called functions XREF * (will need to change this to declare only external functions) * * All changes labeled JMM * * Code generation output routines. */ #include <stdio.h> #include "param.h" #include "nodes.h" #include "flags.h" #include "bstok.h" #include "tytok.h" #include "gen.h" #ifdef dLibs #include <ctype.h> #endif #if MMCC overlay "pass2" #endif #if CC68 FILE *fopen(); #endif #if NEEDBUF char my_obuf[BUFSIZ]; #endif #define T_SEG 0 #define D_SEG 1 #define B_SEG 2 #define TO_TEXT to_seg(T_SEG) #define TO_DATA to_seg(D_SEG) #define TO_BSS to_seg(B_SEG) #define isareg(np) ((np)->g_token == REGVAR && (np)->g_rno >= AREG) extern FILE *output; /*JMM added -O switch to allow user to specify output file */ char *outfilename,*errorfile; extern int nmerrors; static int in_seg; static int lblnum; static int dat_size; /* called to open output file. We've only just begun */ out_start(s) char *s; { char *scopy(), *outs; register int len; /* JMM added -O switch to allow user to specify output file */ if(outfilename) outs = scopy(outfilename); else outs = scopy(s); len = strlen(outs); /* JMM add -O switch */ if(outfilename){ output = fopen(outs,"w"); if(output == NULL ) fatals("Cant open",outs); } else if ( len >= 2 && outs[len-2] == '.' && tolower(outs[len-1]) == 'c' ) { outs[len-1] = 's'; output = fopen(outs, "w"); if (output == NULL) fatals("Cant open", outs); #if NEEDBUF setbuf(output, my_obuf); #endif } else output = stdout; sfree(outs); in_seg = -1; lblnum = 0; dat_size = 0; } /* closes output file. All done */ static char seterrorbuf[50]; out_end() { char *outs; extern char *scopy(); FILE *err; fprintf(output, "\tEND \n"); if (output != stdout) fclose(output); if( ( errorfile != NULL) ){ outs = scopy((char *) errorfile ); err = fopen(outs,"w"); if(err == NULL ) fatals("Cant open",outs); fprintf(err,"%d",nmerrors); close(err); sfree(outs); } } /* Assembler segment Directives */ static char *sg_go[] = { "CODE CODE", /* .text segment ?same as code segment? */ "DATA DATA", /* .data segment */ "BSS BSS" /* .bss segment */ }; /* JMM added ability to force Data,BSS into either Chip or Fast */ short usefastmemory,usechipmemory; static char *chipsg_go[] = { "CODE CODE", /* .text segment ?same as code segment? */ "DATA CHIPDATA CHIP", /* .data segment */ "BSS CHIPBSS CHIP" /* .bss segment */ }; static char *fastsg_go[] = { "CODE CODE", /* .text segment ?same as code segment? */ "DATA FASTDATA FAST", /* .data segment */ "BSS FASTBSS FAST" /* .bss segment */ }; /* extern directive, global directive */ char externdir[]="\tXREF \t"; char globaldir[]="\tXDEF \t"; char externfuncdir[]="\tXREF \t"; to_text() { TO_TEXT; /* to_seg(0) *//* fprintf(output," .text ") */ } to_seg(sg) { char *segment; /* JMM modified to_seg to force data,bss into either CHIP or FAST */ if (sg == in_seg) return; if(usechipmemory)segment =(char *) chipsg_go[sg]; else if(usefastmemory) segment = (char *)fastsg_go[sg]; else segment =(char *) sg_go[sg]; fprintf(output, "\t%s\n", segment); in_seg = sg; } /* JMM ? output a long ? */ o_aln(x) { if (x && (dat_size & 1)) { dat_size++; TO_DATA; /* data segment */ fprintf(output, "\tCNOP 0,2\n");/* was .even */ } } char *rnms[] = { "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", }; /* return string containing register name */ char *regnm(n) { return rnms[n]; } /* define constant of length n */ char * init_str(n) int n; { char *s; switch (n) { case 1: s = "DC.B"; break; case 2: s = "DC.W"; break; default: s = "DC.L"; break; } return s; } tlen(n) { switch (n) { case 1: return 'b'; case 2: return 'w'; default: return 'l'; } } /* JMM ? output init node pointer * * output predefined values for variable ? */ o_vinit(tp, xp) NODEP tp, xp; /* Node pointers */ { /* .dc.b t_size 1 * .dc.w 2 * .dc.l 3 or greater */ fprintf(output, "\t%s\t", init_str((int)tp->t_size)); dat_size += tp->t_size; p2_expr(&xp); asn_chk(tp, xp); to_init(xp, tp); fputc('\n', output); } to_init(np, typ) NODEP np, typ; { NODEP tp; tp = allocnode(); tp->e_token = TCONV; tp->n_tptr = typ; tp->n_flags |= N_COPYT; tp->n_left = np; tp->e_type = E_UNARY; strcpy(tp->n_name, "i cast"); genx(tp, FORINIT); } /* output move.x #(a6),rn where x=b,w,l , rn=a0-a7 or d0-d7*/ out_argreg(np) NODEP np; { fprintf(output, "\tmove.%c\t%d(a6),%s\n", tlen((int)np->n_tptr->t_size), (int)np->e_offs, regnm(np->e_rno)); } extern int pflag; /* JMM ? output label ? makes function labels etc */ out_fstart(np) NODEP np; { TO_TEXT; /* code segment */ if (np->e_sc != K_STATIC) { /* JMM changed to output XDEF name */ fprintf(output, globaldir); und_nnm(np); /* output _XXXXX where XXXXX is name of variable */ fputc('\n', output); } und_nnm(np); fprintf(output, ":\n"); if (pflag) { int tlab = new_lbl(); TO_BSS; fprintf(output, "L%d:\tDS.L\t1\n", tlab); TO_TEXT; fprintf(output, "\tmove.l\t#"); und_nnm(np); fprintf(output, ",a0\n"); fprintf(output, "\tmove.l\t#L%d,a1\n", tlab); fprintf(output,"\tXREF \tmcount\n"); fprintf(output,"; Calling profiler \n"); fprintf(output, "\tjsr\tmcount\n"); } } static char rbuf[30]; char * regstr(regs) { int lod, hid, loa, hia; register i; char *bp = rbuf; lod = 999; hid = -1; for (i=DRV_START; i<=DRV_END; i++) if (regs & (1<<i)) { if (i < lod) lod = i; if (i > hid) hid = i; } loa = 999; hia = -1; for (i=ARV_START; i<=ARV_END; i++) if (regs & (1<<i)) { if (i < loa) loa = i; if (i > hia) hia = i; } if (lod < 999) { if (lod != hid) sprintf(bp, "d%d-d%d", lod, hid); else sprintf(bp, "d%d", lod); if (loa < 999) { bp += strlen(rbuf); *bp++ = '/'; } } if (loa < 999) { if (loa != hia) sprintf(bp, "a%d-a%d", loa-AREG, hia-AREG); else sprintf(bp, "a%d", loa-AREG); } return rbuf; } out_fend(regs, lsize) long lsize; { if (lsize < 0x7fff) fprintf(output, "\tlink\ta6,#-%d\n", (int)lsize); else fprintf(output, "\tlink\ta6,#0\n\tsub.l\t#%ld,sp\n", lsize); if (regs) fprintf(output, "\tmovem.l\t%s,-(sp)\n", regstr(regs)); } out_fret(regs, strl) { if (regs) fprintf(output, "\tmovem.l\t(sp)+,%s\n", regstr(regs)); if (strl) fprintf(output, "\tmove.l\t#L%d,a0\n", strl); fprintf(output, "\tunlk\ta6\n\trts\n"); } out_fs(strl, size) long size; { TO_BSS; def_lbl(strl); fprintf(output, "\tDS.W \t%ld\n", size/2); } /* ? output global variables ? */ out_gv(np, isbss) register NODEP np; { long sz; char c; if (np->e_sc == K_STATIC) { np->e_offs = lblnum++; } /* JMM ? added part to print out XREF statement for a68k ? */ if (np->e_sc == K_EXTERN) { to_seg(isbss ? B_SEG : D_SEG); /*if (np->e_sc != K_STATIC) { */ fprintf(output, externdir); out_nm(np); fputc('\n', output); /* } */ } if (np->e_sc != K_EXTERN) { to_seg(isbss ? B_SEG : D_SEG); if (np->e_sc != K_STATIC) { fprintf(output, globaldir); out_nm(np); fputc('\n', output); } if (isbss) { if (np->e_sc == K_STATIC) { out_nm(np); sz = np->n_tptr->t_size; c = 'b'; if (np->n_tptr->t_aln) { c = 'w'; sz /= 2; } fprintf(output, ":\tDS.%c\t%ld\n", c, sz); } else { out_nm(np); sz = np->n_tptr->t_size; if (sz & 1) sz++; /* ALCYON hack */ fprintf(output, ":\t DS.%c 0 \n", tlen(sz) ); sz -= 4; while (sz > 0){ fprintf(output,"\t DS.W 0\n"); sz -= 2; } /* fprintf(output, "\t.comm\t"); * out_nm(np); * sz = np->n_tptr->t_size; * if (sz & 1) sz++; /* ALCYON hack * / * fprintf(output, ",%ld\n", sz); */ } } else { out_nm(np); fprintf(output, ":\n"); } } } new_lbl() { return lblnum++; } def_lbl(l) { fprintf(output, "L%d:\n", l); } out_br(l) { if (l < 0) error("bad branch"); else fprintf(output, "\tbra\tL%d\n", l); } static char *bnm[] = { "", "beq", "bne", "blt", "bge", "ble", "bgt", "bra", "nop", "bcs", "bcc", "bls", "bhi" }; out_b(key, l) { if (key != B_NO) fprintf(output, "\t%s\tL%d\n", bnm[key], l); } out_bnol(key) { fprintf(output, "\t%s\t", bnm[key]); } out_d0cmp(x) { fprintf(output, "\tcmp.w\t#%d,d0\n", x); } out_d0sub(x) { fprintf(output, "\tsub.w\t#%d,d0\n", x); } out_tlbl(l) { fprintf(output, "\tDC.L\tL%d\n", l); } out_tsw() { fprintf(output, "\text.l\td0\n"); fprintf(output, "\tasl.l\t#2,d0\n"); fprintf(output, "\tmove.l\t4(pc,d0.l),a0\n"); fprintf(output, "\tjmp\t(a0)\n"); } out_nm(np) NODEP np; { if (np->e_sc == K_STATIC) fprintf(output, "L%d", (int)np->e_offs); else und_nnm(np); } externfuncref(np) NODEP np; { if ( np->e_sc != K_STATIC){ fprintf(output, externfuncdir); fput_nnm(np->n_left); fprintf(output,"\n"); } } out_zi(tp) NODEP tp; { char *s; /* switch (tp->t_token) { case K_FLOAT: fprintf(output, "\t.float\t0.0\n"); return; case K_DOUBLE: fprintf(output, "\t.double\t0.0\n"); return; } */ dat_size += tp->t_size; s = init_str((int)tp->t_size); fprintf(output, "\t%s\t0\n", s); } o_nz(sz, aln) long sz; { dat_size += sz; if (aln) { if (sz & 1) fprintf(output, "\tDS.B\t1\n"); sz >>= 1; fprintf(output, "\tDS.W\t%ld\n", sz); } else { fprintf(output, "\tDS.B\t%ld\n", sz); } } dumpstrs(np) NODEP np; { TO_DATA; more: if (np == NULL) return; fprintf(output, "L%d:", (int)np->g_offs); out_scon(np); np = np->n_next; goto more; } int see_esc; out_scon(np) NODEP np; { int len = 0; if (np == NULL) return 0; see_esc = 0; more: if (np->n_name[0]) { fprintf(output, "\tDC.B\t"); len += out_str(np->n_name); putc('\n', output); } np = np->n_nmx; if (np) goto more; fprintf(output, "\tDC.B\t0\n"); len++; dat_size += len; return len; } out_str(s) char *s; { int len; register c; len = 0; for ( ; c = *s; s++) { if (see_esc) { /* allow null */ c--; see_esc = 0; } else if (c == 1) { see_esc = 1; continue; } if (len) putc(',', output); out_1c(c); len++; } return len; } out_asm(np) NODEP np; { putc('\t', output); more: fprintf(output, "%s", np->n_name); /* no \0 or \1 please! */ np = np->n_nmx; if (np) goto more; putc('\n', output); } /* Output underscore name */ und_nnm(np) NODEP np; { fputc('_', output); fput_nnm(np); } out_1c(c) char c; { fprintf(output, "$%x", c & 0xff); } outcode(np) register NODEP np; { NODEP tp; if (np == NULL) return; switch (np->g_type) { case EV_NONE: break; case EV_RL: outcode(np->n_right); outsub(np->g_betw, np); /* fall through */ case EV_LEFT: outcode(np->n_left); break; case EV_LR: case EV_LRSEP: outcode(np->n_left); outsub(np->g_betw, np); /* fall through */ case EV_RIGHT: outcode(np->n_right); break; default: printf("bad eval %d ", np->g_type); } if (np->n_flags & N_COPYT) /* g_code is a char * */ outsub(np->g_code, np); else /* g_code is a list of nodes */ for (tp=np->g_code; tp != NULL; tp = tp->g_code) outsub(tp->n_name, np); } outsub(cp, np) register char *cp; register NODEP np; { register char c; if (cp == NULL) return; while (c = *cp++) if (c == '<') out_let(*cp++, np->n_left); else if (c == '>') out_let(*cp++, np->n_right); else if (c == '\'') { c = *cp++; fputc(c, output); } else if (c == 'L') seelab(*cp++, np); else if (c == 'R') seereg(np, *cp++); else if (c >= 'A' && c <= 'Z') { out_let(c, np); } else fputc(c, output); } seereg(np, c) NODEP np; { int i; switch (c) { case '0': i = np->g_rno; break; case '1': i = np->g_r1; break; case '2': i = np->g_r2; break; } fprintf(output, regnm(i)); } out_let(c, np) register NODEP np; { int i; switch (c) { case 'A': if (np->g_flags & IMMEDID) fputc('#', output); out_a(np, output); break; case 'F': /* branch if false */ i = cctok(np); i = (i&1) ? i+1 : i-1; /* reverse truth */ out_bnol(i); break; case 'K': fprintf(output, "%ld", np->g_bsize); break; case 'N': fprintf(output, "%s", np->n_name); break; case 'O': fprintf(output, "%ld", np->g_offs); break; case 'Q': if (np->g_flags & IMMEDID) { warn("constant test expr"); if (np->g_token == ICON && np->g_offs == 0) fprintf(output, "\tor\t#$FF,ccr\n"); else fprintf(output, "\tand\t#0,ccr\n"); return; } fprintf(output, "\t%s.%c\t", isareg(np) ? "cmp" : "tst", tlen(np->g_sz)); if (isareg(np)) fprintf(output, "#0,"); out_let('A', np); fputc('\n', output); break; case 'S': fputc(tlen(np->g_sz), output); break; case 'T': /* branch if true */ out_bnol(cctok(np)); break; case 'U': fputc(np->g_ty == ET_U ? 'u' : 's', output); break; case 'W': /* field width 1's */ fprintf(output, "$%x", ones(np->g_fldw)); break; case 'X': /* ~(W << offset) */ fprintf(output, "$%x", ~(ones(np->g_fldw)<<np->g_fldo)); break; case 'Y': /* field offset */ fprintf(output, "%d", np->g_fldo); break; case 'Z': /* field offset - 8 */ fprintf(output, "%d", np->g_fldo - 8); break; default: printf("bad out_let %c ", c); } } out_a(np, fd) register NODEP np; FILE *fd; { int offs = np->g_offs; switch (np->g_token) { case ICON: fprintf(fd, "%ld", np->g_offs); break; case FCON: /* works for ALCYON C */ /* otherwise depends on floating internal format */ fprintf(fd, "$%lx", np->g_offs); break; case ONAME: while (np->g_flags & (CHILDNM|RCHILDNM)) { np = (np->g_flags & CHILDNM) ? np->n_left : np->n_right; } qput_nnm(np, fd); if (offs) fprintf(fd, offs > 0 ? "+%d" : "%d", offs); break; case PUSHER: fprintf(fd, "(sp)+"); break; case OREG: if (offs) fprintf(fd, "%d", offs); fprintf(fd, "(%s)", regnm(np->g_rno)); break; case REGVAR: fprintf(fd, regnm(np->g_rno)); break; case ',': fputc(',', fd); /* for debug */ break; default: if (np->g_token >= BR_TOK) { fprintf(fd, "B_%s", bnm[np->g_token - BR_TOK]); break; } printf("? tok %d ", np->g_token); } } seelab(c, np) char c; NODEP np; { c -= '1'; fprintf(output, "L%d", (int)np->g_bsize+c); } ones(n) { return (1 << n) - 1; } SHAR_EOF cat << \SHAR_EOF > p2.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * p2.c * * Expression tree routines. * * Constant folding, typing of nodes, simple transformations. */ #include <stdio.h> #include "param.h" #include "tok.h" #include "nodes.h" #include "cookie.h" #if MMCC overlay "pass2" #endif extern int xflags[]; #define debug xflags['t'-'a'] extern nmerrors; NODEP bas_type(); do_expr(np, cookie) NODE *np; { if (np == NULL) return; /* include if want only one error at a time if (nmerrors) { freenode(np); return; } */ p2_expr(&np); genx(np, cookie); } p2_expr(npp) NODEP *npp; { NODEP np = *npp; if (np == NULL) return; if (debug > 1) { printf("P2 enter"); printnode(np); } confold(npp,0); np = *npp; form_types(np); if (debug) { printf("p2_expr"); printnode(np); } return; } form_types(np) NODEP np; { if (np == NULL) return; switch (np->e_type) { case E_SPEC: switch (np->e_token) { /* special cases */ case '.': case ARROW: form_types(np->n_left); sel_type(np); return; case '(': if (np->n_right) { form_types(np->n_right); /* args */ np->e_type = E_BIN; } else np->e_type = E_UNARY; fun_type(np); return; } /* fall through */ case E_BIN: form_types(np->n_left); form_types(np->n_right); b_types(np); break; case E_UNARY: form_types(np->n_left); u_types(np); break; case E_LEAF: l_types(np); break; } } /* (fun) (args) */ fun_type(np) NODEP np; { NODEP lp, typ; NODEP allsyms(), new_fun(); lp = np->n_left; if (lp->e_token == ID) { /* may be new ID */ typ = allsyms(lp); if (typ == NULL) typ = new_fun(lp); typ = typ->n_tptr; lp->n_tptr = typ; lp->n_flags |= N_COPYT; } else { form_types(lp); typ = lp->n_tptr; } if (typ->t_token != '(') { /* fun ret ? */ error("call non-fun"); goto bad; } typ = typ->n_tptr; goto good; bad: typ = bas_type(K_INT); good: np->n_tptr = typ; np->n_flags |= N_COPYT; } /* (struct|union) (. or ->) ID */ sel_type(xp) NODEP xp; { NODEP np, sup; int tok; NODEP rv; NODEP llook(); np = xp->n_right; sup = xp->n_left->n_tptr; tok = xp->e_token; /* already checked that np->e_token == ID */ if (tok == ARROW) { if (sup->t_token != STAR) { error("(non pointer)->"); goto bad; } sup = sup->n_tptr; } if (sup->t_token != K_STRUCT && sup->t_token != K_UNION) { error("select non-struct"); goto bad; } rv = llook(sup->n_right, np); if (rv == NULL) { error("? member ID"); goto bad; } xp->e_offs = rv->e_offs; if (rv->e_fldw) { xp->e_fldw = rv->e_fldw; xp->e_fldo = rv->e_fldo; } rv = rv->n_tptr; goto good; bad: rv = bas_type(K_INT); good: xp->n_tptr = rv; xp->n_flags |= N_COPYT; /* change to UNARY op */ xp->e_type = E_UNARY; freenode(np); xp->n_right = NULL; /* change ARY OF to PTR TO */ if (rv->t_token == '[') see_array(xp); } l_types(np) register NODE *np; { NODEP allsyms(); register NODE *tp; switch (np->e_token) { case ID: /* already did see_id */ if (np->n_tptr->t_token == '[') /* change to &ID */ see_array(np); return; case ICON: tp = bas_type(icon_ty(np)); break; case FCON: tp = bas_type(K_DOUBLE); break; case SCON: tp = bas_type(SCON); break; default: errors("Weird leaf",np->n_name); bad: tp = bas_type(K_INT); } np->n_tptr = tp; np->n_flags |= N_COPYT; } u_types(np) NODEP np; { NODEP tp; NODEP lp = np->n_left; NODEP normalty(); tp = lp->n_tptr; /* default */ switch (np->e_token) { case DOUBLE '+': case DOUBLE '-': case POSTINC: case POSTDEC: mustlval(lp); mustty(lp, R_SCALAR); if (tp->t_token == STAR) np->e_offs = tp->n_tptr->t_size; else np->e_offs = 1; break; case STAR: if (mustty(lp, R_POINTER)) goto bad; tp = tp->n_tptr; np->n_tptr = tp; np->n_flags |= N_COPYT; /* Ary of to Ptr to */ if (tp->t_token == '[') see_array(np); return; case UNARY '&': mustlval(lp); tp = allocnode(); tp->n_tptr = lp->n_tptr; tp->n_flags |= N_COPYT; tp->t_token = STAR; sprintf(tp->n_name, "Ptr to"); tp->t_size = SIZE_P; np->n_tptr = tp; return; /* no COPYT */ case UNARY '-': mustty(lp, R_ARITH); tp = normalty(lp, NULL); break; case TCONV: mustty(lp, R_SCALAR); if (np->n_tptr->t_token != K_VOID) mustty(np, R_SCALAR); return; /* type already specified */ case '!': mustty(lp, R_SCALAR); tp = bas_type(K_INT); break; case '~': mustty(lp, R_INTEGRAL); tp = normalty(lp, NULL); break; default: error("bad unary type"); bad: tp = bas_type(K_INT); } np->n_tptr = tp; np->n_flags |= N_COPYT; } b_types(np) NODEP np; { NODEP tp; NODEP lp, rp; NODEP normalty(), addty(), colonty(); int op; op = np->e_token; if (isassign(op)) { mustlval(np->n_left); op -= (ASSIGN 0); } lp = np->n_left; rp = np->n_right; tp = bas_type(K_INT); switch (op) { case '*': case '/': mustty(lp, R_ARITH); mustty(rp, R_ARITH); tp = normalty(lp,rp); break; case '%': case '&': case '|': case '^': mustty(lp, R_INTEGRAL); mustty(rp, R_INTEGRAL); tp = normalty(lp,rp); break; case '+': case '-': mustty(lp, R_SCALAR); mustty(rp, R_SCALAR); tp = addty(np); break; case DOUBLE '<': case DOUBLE '>': mustty(lp, R_INTEGRAL); mustty(rp, R_INTEGRAL); tp = normalty(lp, NULL); break; case '<': case '>': case LTEQ: case GTEQ: case DOUBLE '=': case NOTEQ: mustty(lp, R_SCALAR); mustty(rp, R_SCALAR); chkcmp(np); break; /* INT */ case DOUBLE '&': case DOUBLE '|': mustty(lp, R_SCALAR); mustty(rp, R_SCALAR); break; /* INT */ case '?': mustty(lp, R_SCALAR); tp = rp->n_tptr; break; case ':': if (same_type(lp->n_tptr, rp->n_tptr)) { tp = lp->n_tptr; break; } mustty(lp, R_SCALAR); mustty(rp, R_SCALAR); tp = colonty(np); break; case '=': mustlval(lp); mustty(lp, R_ASSN); asn_chk(lp->n_tptr, rp); tp = lp->n_tptr; break; case ',': tp = rp->n_tptr; break; default: error("bad binary type"); bad: tp = bas_type(K_INT); } if (isassign(np->e_token)) { /* ignore normal result -- result is left type */ tp = lp->n_tptr; } np->n_tptr = tp; np->n_flags |= N_COPYT; } long conlval(np) NODEP np; { long i; confold(&np,0); if (np->e_token == ICON) { i = np->e_ival; freenode(np); return i; } error("need const expr"); return 0; } conxval(np) NODEP np; { return (int)conlval(np); } confold(npp,spec) NODEP *npp; { NODEP np; NODEP tp, onp; int tok,spl,spr; long l; np = *npp; if (np == NULL) return; switch (np->e_type) { case E_LEAF: lcanon(np,spec); return; case E_UNARY: confold(&np->n_left,0); ucanon(np); return; case E_BIN: confold(&np->n_left,0); confold(&np->n_right,0); if (np->e_token == '?') { tok = np->n_left->e_token; if (tok != ICON) return; l = np->n_left->e_ival; onp = np; tp = np->n_right; /* ':' node */ if (l) { /* take true side */ np = tp->n_left; tp->n_left = NULL; } else { /* take false side */ np = tp->n_right; tp->n_right = NULL; } freenode(onp); *npp = np; return; } bcanon(np); if (np->e_flags & C_AND_A) b_assoc(np); return; case E_SPEC: tok = np->e_token; spl = spr = 0; switch (tok) { case '(': spl = tok; /* new name allowed */ break; case '.': case ARROW: spr = tok; /* look in struct sym.tab. */ break; } confold(&np->n_left,spl); confold(&np->n_right,spr); return; } } newicon(np,x,nf) NODE *np; long x; { np->e_token = ICON; np->e_ival = x; np->e_flags = nf; sprintf(np->n_name, "%ld", x); np->e_type = E_LEAF; if (np->n_left) { freenode(np->n_left); np->n_left = NULL; } if (np->n_right) { freenode(np->n_right); np->n_right = NULL; } } newfcon(np,x,nf) NODE *np; double x; { np->e_token = FCON; np->e_fval = x; np->e_flags = nf; sprintf(np->n_name, FLTFORM, x); np->e_type = E_LEAF; if (np->n_left) { freenode(np->n_left); np->n_left = NULL; } if (np->n_right) { freenode(np->n_right); np->n_right = NULL; } } /* LEAF */ /* sptok is token if E_SPEC node is parent and dont want to look at ID yet */ lcanon(np,sptok) NODE *np; { NODE *tp; NODEP allsyms(); long x; if (np->e_token == ID) { if (sptok) return; see_id(np); return; } if (np->e_token == TSIZEOF) { tp = np->n_tptr; x = tp->t_size; np->n_tptr = NULL; if ((np->n_flags & N_COPYT) == 0) freenode(tp); newicon(np, x, 0); } } /* UNARY */ ucanon(np) NODE *np; { NODE *tp; long x,l; int lflags = 0; if (np->e_token == K_SIZEOF) { tp = np->n_left; confold(&tp,0); form_types(tp); tp = tp->n_tptr; x = tp->t_size; goto out; } if (np->n_left->e_token == FCON) { if (np->e_token == UNARY '-') newfcon(np, -(np->n_left->e_fval)); return; } if (np->n_left->e_token != ICON) return; l = np->n_left->e_ival; lflags = np->n_left->e_flags; switch (np->e_token) { case UNARY '-': x = -l; break; case '~': x = ~l; break; case '!': x = !l; break; default: return; } out: newicon(np, x, lflags); } bcanon(np) register NODE *np; { int ltok, rtok; double l,r; NODEP tp; ltok = np->n_left->e_token; rtok = np->n_right->e_token; if (ltok != ICON && ltok != FCON) return; if (rtok != ICON && rtok != FCON) { /* left is ?CON, right is not */ if (np->e_flags & (C_AND_A|C_NOT_A)) { /* reverse sides - put CON on right */ tp = np->n_left; np->n_left = np->n_right; np->n_right = tp; if (np->e_flags & C_NOT_A) swt_op(np); } return; } if (ltok == ICON && rtok == ICON) { b2i(np); return; } if (ltok == FCON) l = np->n_left->e_fval; else l = (double)np->n_left->e_ival; if (rtok == FCON) r = np->n_right->e_fval; else r = (double)np->n_right->e_ival; b2f(np,l,r); } /* canon for assoc. & comm. op */ /* this code will almost never be executed, but it was fun. */ b_assoc(np) NODEP np; { NODEP lp, rp; int tok; lp = np->n_left; if (lp->e_token != np->e_token) return; /* left is same op as np */ rp = np->n_right; tok = lp->n_right->e_token; if (tok != ICON && tok != FCON) return; /* left.right is ?CON */ tok = rp->e_token; if (tok == ICON || tok == FCON) { /* have 2 CONS l.r and r -- put together on r */ NODEP ep; ep = lp->n_left; np->n_left = ep; np->n_right = lp; lp->n_left = rp; /* can now fold 2 CONS */ bcanon(lp); } else { /* have 1 CON at l.r -- move to top right */ NODEP kp; kp = lp->n_right; lp->n_right = rp; np->n_right = kp; } } /* switch pseudo-commutative op */ swt_op(np) NODEP np; { int newtok; switch (np->e_token) { case LTEQ: newtok = '>'; break; case GTEQ: newtok = '<'; break; case '<': newtok = GTEQ; break; case '>': newtok = LTEQ; break; default: return; } np->e_token = newtok; } /* BINARY 2 ICON's */ b2i(np) register NODE *np; { register long l,r,x; int newflags,lflags; newflags = 0; r = np->n_right->e_ival; newflags = np->n_right->e_flags; l = np->n_left->e_ival; lflags = np->n_left->e_flags; newflags = newflags>lflags ? newflags : lflags; switch (np->e_token) { case '+': x = l+r; break; case '-': x = l-r; break; case '*': x = l*r; break; case '/': x = l/r; break; case '%': x = l%r; break; case '>': x = l>r; break; case '<': x = l<r; break; case LTEQ: x = l>=r; break; case GTEQ: x = l<=r; break; case DOUBLE '=': x = l==r; break; case NOTEQ: x = l!=r; break; case '&': x = l&r; break; case '|': x = l|r; break; case '^': x = l^r; break; case DOUBLE '<': x = l<<r; break; case DOUBLE '>': x = l>>r; break; default: return; } newicon(np, x, newflags); } /* BINARY 2 FCON's */ b2f(np,l,r) register NODE *np; double l,r; { register double x; int ix, isint; isint = 0; switch (np->e_token) { case '+': x = l+r; break; case '-': x = l-r; break; case '*': x = l*r; break; case '/': x = l/r; break; case '>': ix = l>r; isint++; break; case '<': ix = l<r; isint++; break; case LTEQ: ix = l>=r; isint++; break; case GTEQ: ix = l<=r; isint++; break; case DOUBLE '=': ix = l==r; isint++; break; case NOTEQ: ix = l!=r; isint++; break; default: return; } if (isint) newicon(np, (long)ix, 0); else newfcon(np, x); } same_type(a,b) register NODE *a, *b; { more: if (a == b) return 1; if (a == NULL || b == NULL) return 0; if (a->t_token != b->t_token) return 0; if (a->t_token != STAR && a->t_size != b->t_size) return 0; a = a->n_tptr; b = b->n_tptr; goto more; } see_id(np) NODEP np; { NODEP tp; NODEP allsyms(), def_type(); tp = allsyms(np); if (tp == NULL) { errorn("undefined:", np); tp = def_type(); goto out; } switch (tp->e_sc) { case ENUM_SC: newicon(np, tp->e_ival, 0); return; case K_REGISTER: np->e_rno = tp->e_rno; /* fall through */ default: np->e_sc = tp->e_sc; np->e_offs = tp->e_offs; tp = tp->n_tptr; } out: np->n_tptr = tp; np->n_flags |= N_COPYT; /* special conversions */ if (tp->t_token == '(') insptrto(np); } insptrto(np) NODEP np; { NODEP op, copyone(); op = copyone(np); np->n_left = op; np->e_token = UNARY '&'; np->e_type = E_UNARY; strcpy(np->n_name, "&fun"); np->n_flags &= ~N_COPYT; } /* np points to ID or STAR or '.' node tptr is a COPY tptr token is '[' */ see_array(np) NODEP np; { NODEP tp, copyone(); tp = copyone(np); tp->n_left = np->n_left; tp->n_tptr = tp->n_tptr->n_tptr; np->n_left = tp; np->e_token = UNARY '&'; np->e_type = E_UNARY; strcpy(np->n_name, "&ary"); arytoptr(np); /* leave old size np->n_tptr->t_size = SIZE_P; */ } SHAR_EOF cat << \SHAR_EOF > pre.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * pre.c * * preprocessor for the compiler * * Handles all preprocessor (#) commands and * looks up keywords * * Interface: * getnode() returns next "token node" */ #include <stdio.h> #include "param.h" #include "tok.h" #include "nodes.h" #if CC68 FILE *fopenb(); #define fopen fopenb #endif NODE *deflist[NHASH]; extern struct tok curtok; extern char curstr[]; #define TK_SEENL 1 /* want to see NL token */ #define TK_SEEWS 2 /* want to see WS token */ #define TK_ONLY1 4 /* only want 1st token on line */ #define TK_LTSTR 8 /* '<' starts a string */ #define TK_NOESC 16 /* dont do '\' escapes in string */ extern int tk_flags, sawnl; NODE *holdtok; extern lineno; extern char *inname; extern FILE *input; int iflevel, iftruth, ifnest; NODE *hlook(), *llook(); NODEP tok_to_node(); NODE *copylist(); #ifdef DEBUG extern int oflags[]; #define debugd oflags['d'-'a'] #define debugt oflags['t'-'a'] #endif NODEP hi_node() { register NODEP rv; /* node from hold queue ? */ if (holdtok) { #ifdef DEBUG if (debugd > 2) { printf("Holdqueue"); printnode(holdtok); } #endif rv = holdtok; holdtok = rv->n_next; rv->n_next = NULL; return rv; } /* node from input */ again: while (iflevel && !iftruth) skiplines(); if (nxttok()==0) return NULL; if (curtok.tnum == '#') { dopound(0); goto again; } rv = tok_to_node(); return rv; } NODEP getnode() { register NODEP rv; NODEP dp; again: rv = hi_node(); if (rv == NULL) { rv = allocnode(); rv->e_token = EOFTOK; strcpy(rv->n_name, "*EOF*"); } else if (rv->e_token == ID) { if ((dp = hlook(deflist, rv)) != NULL) { expand(dp); freenode(rv); goto again; } else kw_tok(rv); } #ifdef DEBUG if (debugt) { putchar('['); put_nnm(rv); printf("] "); } #endif return rv; } skiplines() { for (;;) { if (nxttok()== 0) return; if (curtok.tnum == '#') { dopound(1); return; } tk_flags |= TK_ONLY1; } } static defnargs; p_def() { NODE *args; NODE *val; NODE *def; NODE *def_rgs(), *def_val(); defnargs = -1; args = NULL; val = NULL; nxttok(); if (curtok.tnum != ID) { error("bad #define"); goto flush; } def = tok_to_node(); tk_flags |= TK_SEEWS; nxttok(); switch (curtok.tnum) { case '(': defnargs = 0; args = def_rgs(); case WS: goto getval; case NL: goto dodef; default: error("bad #define"); goto flush; } getval: val = def_val(); dodef: def->e_ival = defnargs; define(def, val, args); flush: ; } optdef(s) char *s; { NODEP val; NODEP def; NODEP id_tok(), def_val(); char *as, *strchr(); as = strchr(s, '='); if (as) *as++ = 0; else as = "1"; defnargs = -1; val = NULL; def = id_tok(s); chr_push(as); tk_flags |= TK_SEENL; val = def_val(); tk_flags = 0; def->e_ival = defnargs; define(def, val, NULL); } optundef(s) char *s; { NODEP np, tp, id_tok(); np = id_tok(s); tp = hlook(deflist, np); if (tp != NULL) tp->n_name[0] = '#'; freenode(np); } samedef(p1, p2) NODEP p1, p2; { if (p1->e_ival != p2->e_ival) return 0; return same_list(p1->n_right, p2->n_right); } same_list(p1, p2) NODEP p1, p2; { if (p1 == NULL) return p2 == NULL; if (p2 == NULL) return 0; if (l_cmp(p1, p2, sizeof(*p1)/sizeof(long)) != 0) return 0; return same_list(p1->n_left, p2->n_left); } l_cmp(p1, p2, n) NODE *p1, *p2; { if (xstrcmp(p1,p2) != 0) return 1; if (p1->e_token != p2->e_token || p1->e_ival != p2->e_ival) return 1; return 0; } define(def, val, args) NODEP def, val, args; { NODEP oldp; if (args != NULL) { argsmod(val, args); freenode(args); } def->n_right = val; if ((oldp = hlook(deflist, def)) != NULL) { if (!samedef(oldp, def)) warnn("redefined", def); } #ifdef DEBUG if (debugd) { printf("define (%d args)", (int)def->e_ival); printnode(def); } #endif puthlist(deflist, def); } argsmod(toks, args) NODEP toks, args; { register NODE *np, *vp; for (np=toks; np != NULL; np = np->n_next) if (np->e_token == ID) { vp = llook(args,np); if (vp != NULL) { np->e_token = DPARAM; np->e_ival = vp->e_ival; sprintf(np->n_name, "\\%d", (int)np->e_ival); } } } NODE * def_rgs() { NODE *rv; NODE *tail; NODE *np; rv = NULL; tail = NULL; nxttok(); if (curtok.tnum == ')') { goto out; } more: if (curtok.tnum != ID) { error("expect ID"); goto bad; } np = tok_to_node(); np->e_ival = defnargs; /* hold sequence number */ defnargs++; if (tail == NULL) { /* first one */ rv = np; tail = np; } else { /* more */ tail->n_next = np; tail = np; } nxttok(); if (curtok.tnum == ',') { nxttok(); goto more; } if (curtok.tnum == ')') goto out; error("define arg syntax"); bad: freenode(rv); rv = NULL; defnargs = 0; out: return rv; } NODE * def_val() { NODE *rv; NODE *tail; NODE *np; rv = NULL; tail = NULL; more: nxttok(); if (curtok.tnum == NL) { goto out; /* } else if (curtok.tnum == '\\') { nxttok(); if (curtok.tnum != NL) goto bad; goto more; */ } np = tok_to_node(); if (tail == NULL) { /* first one */ rv = np; tail = np; } else { /* more */ tail->n_next = np; tail = np; } goto more; bad: freenode(rv); rv = NULL; out: return rv; } NODE * gath1(sep) int *sep; { NODE *np, *rv, *tail; int inparen; inparen = 0; rv = NULL; tail = NULL; more: np = hi_node(); if (np == NULL) { goto bad; } switch (np->e_token) { case ')': case ',': if (inparen) { /* dont end, part of subexpr */ if (np->e_token == ')') inparen--; break; } *sep = np->e_token; freenode(np); goto out; case '(': inparen++; break; } if (tail == NULL) { /* first one */ rv = np; tail = np; } else { /* more */ tail->n_next = np; tail = np; } goto more; bad: freenode(rv); rv = NULL; *sep = 0; out: return rv; } NODE * gath_args(n) { NODE *rv; NODE *tail; NODE *np; int sep; int getn; getn = 0; rv = NULL; tail = NULL; np = hi_node(); if (np->e_token != '(') { error("expect ("); goto bad; } freenode(np); if (n == 0) { np = hi_node(); if (np->e_token != ')') { error("expect )"); goto bad; } freenode(np); return NULL; } more: np = gath1(&sep); if (np == NULL) { error("expect arg"); goto bad; } getn++; if (tail == NULL) { /* first one */ rv = np; tail = np; } else { /* more */ tail->n_right = np; tail = np; } if (sep) switch (sep) { case ',': goto more; case ')': if (getn != n) { error("arg num mismatch"); goto bad; } goto out; } error("expand arg syntax"); bad: freenode(rv); rv = NULL; out: return rv; } NODE * argfix(val, args, rt) NODE *val, *args; NODE **rt; { register NODE *scan, *sub; NODE *head; NODE *tail, *back; NODE *rthnode(); NODE *copylist(); head = val; back = NULL; for (scan = val; scan != NULL; back=scan, scan=scan->n_next) if (scan->e_token == DPARAM) { sub = rthnode(args, (int)scan->e_ival); sub = copylist(sub,&tail); if (back) { back->n_next = sub; tail->n_next = scan->n_next; } else { head = sub; tail->n_next = scan->n_next; } scan->n_next = NULL; freenode(scan); scan = tail; } *rt = back; return head; } expand(dp) NODEP dp; { int nargs; NODEP args; register NODEP val; NODEP tail; val = dp->n_right; if (val) val = copylist(val, &tail); nargs = dp->e_ival; if (nargs >= 0) { args = gath_args(nargs); if (args) { if (val) val = argfix(val,args,&tail); freenode(args); } } if (val == NULL) return; #ifdef DEBUG if (debugd > 1) { printf("Expand"); printnode(val); } #endif tail->n_next = holdtok; holdtok = val; } p_undef() { NODEP np, tp; nxttok(); if (curtok.tnum != ID) { error("bad #undef"); goto out; } tp = tok_to_node(); if ((np = hlook(deflist, tp)) != NULL) /* quick and dirty */ np->n_name[0] = '#'; freenode(tp); out: ; } p_inc() { int chkhere; FILE *newf, *srch_open(); char *scopy(), *newnm; tk_flags |= TK_NOESC|TK_LTSTR; nxttok(); switch (curtok.tnum) { case SCON: chkhere = 1; break; case SCON2: chkhere = 0; break; case NL: case EOF: error("bad #include"); return; } newf = srch_open(curstr, chkhere); if (newf == NULL) { fatals("Cant open ", curstr); return; } newnm = scopy(curstr); do nxttok(); while (curtok.tnum != NL); newfile(newf,newnm); } int inclvl; struct svinc { int lineno; FILE *fd; char *filenm; } svincs[MAXINCL]; #if NEEDBUF char p_buf[MAXINCL][BUFSIZ]; #endif static char obuf[MAXSTR]; newfile(fd,s) FILE *fd; char *s; { register struct svinc *p; inclvl++; if (inclvl > MAXINCL) { inclvl--; fclose(fd); error("too many includes"); return; } p = &svincs[inclvl-1]; p->lineno = lineno; p->fd = input; p->filenm = inname; input = fd; lineno = 1; inname = s; #if NEEDBUF setbuf(input, p_buf[inclvl-1]); #endif } endfile() { register struct svinc *p; if (inclvl == 0) return 0; fclose(input); inclvl--; p = &svincs[inclvl]; sfree(inname); input = p->fd; lineno = p->lineno; inname = p->filenm; return 1; } #define MAXIDIR 10 char *srchlist[MAXIDIR] = { "", "\\include\\", "\\sozobon\\include\\", "", 0 }; static int idir_n = 4; /* number of entries in above table */ static int idir_put = 1; /* where to put -I dirs */ optincl(s) char *s; { register char **pp; if (idir_n >= MAXIDIR-1) { warn("too many -I dirs"); return; } for (pp = &srchlist[idir_n]; pp > &srchlist[idir_put]; ) { pp--; pp[1] = pp[0]; } *pp = s; idir_put++; idir_n++; } FILE * srch_open(s, chkhere) char *s; { char **dir; FILE *fd; dir = srchlist; if (chkhere == 0) dir++; while (*dir) { strcpy(obuf, *dir); strcat(obuf, s); fd = fopen(obuf, ROPEN); if (fd != NULL) { return fd; } dir++; } return NULL; } p_if(kind,skipping) { int truth; NODEP tp; if (skipping) { ifnest++; return; } switch (kind) { case 0: truth = if_expr(); break; case 1: case 2: nxttok(); if (curtok.tnum != ID) { error("bad #if(n)def"); goto flush; } tp = tok_to_node(); truth = (hlook(deflist, tp) != NULL); freenode(tp); if (kind == 2) truth = !truth; } iflevel++; iftruth = truth; flush: ; } extern NODE *cur; if_expr() { NODE *tp, *questx(); int rv; advnode(); tp = questx(); if (tp) { rv = conxval(tp); } else rv = 0; if (cur->e_token != NL) { error("bad #if"); } else freenode(cur); return rv; } p_swit(kind,skipping) { if (skipping && ifnest) { if (kind == 1) ifnest--; return; } if (iflevel == 0) { error("not in #if"); goto out; } switch (kind) { case 0: /* else */ iftruth = !iftruth; break; case 1: /* endif */ iflevel--; iftruth = 1; break; } out: ; } p_line() { char *scopy(); nxttok(); if (curtok.tnum != ICON) { error("bad #line"); goto flush; } tk_flags |= TK_NOESC; nxttok(); if (curtok.tnum == SCON) { sfree(inname); inname = scopy(curtok.name); } lineno = curtok.ival; flush: ; } struct cmds { char *name; int (*fun)(); int arg; int skip; } pcmds[] = { {"define", p_def, 0, 1}, {"undef", p_undef, 0, 1}, {"include", p_inc, 0, 1}, {"if", p_if, 0, 0}, {"ifdef", p_if, 1, 0}, {"ifndef", p_if, 2, 0}, {"else", p_swit, 0, 0}, {"endif", p_swit, 1, 0}, {"line", p_line, 0, 1}, {0} }; dopound(skipping) { register struct cmds *p; register char *cname; tk_flags |= TK_SEENL; sawnl = 0; nxttok(); if (curtok.tnum != ID) { error("expect name"); return; } cname = curtok.name; for (p=pcmds; p->name; p++) if (strcmp(p->name, cname) == 0) { if (!skipping || !p->skip) (*p->fun)(p->arg, skipping); tk_flags = 0; if (sawnl == 0) tk_flags |= TK_ONLY1; return; } error("bad # command"); } NODEP tok_to_node() { register struct tok *tp; register NODEP np; tp = &curtok; np = allocnode(); np->e_token = tp->tnum; np->e_flags = tp->flags; if (tp->prec) /* binary op */ np->e_prec = tp->prec; else switch (np->e_token) { case ICON: np->e_ival = tp->ival; break; case FCON: np->e_fval = tp->fval; break; } nscpy(np, tp->name); return np; } NODEP id_tok(s) char *s; { NODEP np; np = allocnode(); np->e_token = ID; nscpy(np, s); return np; } SHAR_EOF cat << \SHAR_EOF > subs.c /* * Replace non-portable assembly assist routines lclr() * and lcpy() with portable, albeit possibly slightly slower * versions. */ void lclr (ptr, lcount) long *ptr; int lcount; { while (lcount-- > 0) { *ptr++ = 0; } } void lcpy (out, in, lcount) long *out; long *in; int lcount; { while (lcount-- > 0) { *out++ = *in++; } } SHAR_EOF cat << \SHAR_EOF > tok.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * tok.c * * Basic level token routines * * At this level, we return the following things: * id's - strings of alpha-alnum * integer constants * float constants * string constants * multi-char tokens * * We DONT know about: * keywords * #defined id's * any other meaning of a name * * Interface: * call nxttok() to get next token * look at 'curtok' for current token * note that curtok.name points to a static area * for ID or SCON * * if EOF is seen, we call endfile() before * giving up * * Special flags: (tk_flags) * These special flags are needed for the pre-processor. * All but TK_SEENL are 1-shot. * * TK_SEENL - want to see \n * TK_WS - want to see white space (for #define) * TK_NOESC - dont do '\' escapes in strings * TK_LTSTR - '<' is a string starter * TK_ONLY1 - skip to token after \n (for #if--) */ #include <stdio.h> #include "param.h" #include "tok.h" #ifdef dLibs #include <ctype.h> #endif struct tok curtok; char curstr[MAXSTR+1]; #define TK_SEENL 1 /* want to see NL token */ #define TK_SEEWS 2 /* want to see WS token */ #define TK_ONLY1 4 /* only want 1st token on line */ #define TK_LTSTR 8 /* '<' starts a string */ #define TK_NOESC 16 /* dont do '\' escapes in string */ int tk_flags, sawnl; extern FILE *input; extern int lineno; #define NOCHAR 0x100 #ifdef DEBUG extern int oflags[]; #define debug oflags['b'-'a'] #endif nxttok() { register struct tok *t; char *getname(); long getnumber(); register int c; double getfrac(); t = &curtok; t->name = curstr; t->name[0] = 0; t->prec = 0; t->flags = 0; more: c = mygetchar(); if (c == EOF) { tk_flags = 0; return 0; } if (c == '\n') { tk_flags &= ~TK_ONLY1; if ((tk_flags & TK_SEENL) == 0) goto more; t->tnum = NL; t->name = "\n"; goto out; } if (tk_flags & TK_ONLY1) goto more; if (c <= ' ') { if ((tk_flags & TK_SEEWS) == 0) goto more; t->tnum = WS; t->name = " "; goto out; } if (c >= '0' && c <= '9') { t->tnum = ICON; t->ival = getnumber(c); if (lookfrac(t->ival) || lookexp(t->ival,0.0)) goto out; moresuf: c = mygetchar(); if (tolower(c) == 'l') { t->flags |= SEE_L; goto moresuf; } else if (tolower(c) == 'u') { t->flags |= SEE_U; goto moresuf; } else { myungetc(c); } sprintf(curstr, "%ld", t->ival); goto out; } if (isalpha(c) || c == '_') { t->tnum = ID; t->name = getname(c); goto out; } if (c == '.') { c = mygetchar(); if (c >= '0' && c <= '9') { gotfrac(0L, getfrac(c)); goto out; } else { myungetc(c); matchop('.'); goto out; } } if(matchop(c) == 0) goto more; out: if (debug) printf("<%s>", t->name); tk_flags &= TK_SEENL; /* all but SEENL are 1-shot */ return 1; } long getnumber(c) register int c; { register long val = 0; int base, i; if (c == '0') { base = 8; } else { base = 10; val = c - '0'; } more: c = mygetchar(); if (c == EOF) return val; if (tolower(c) == 'x' && val == 0) { base = 16; goto more; } if (c >= '0' && c <= '9') { val = base*val + (c - '0'); goto more; } if (base == 16 && (i = ishexa(c))) { val = 16*val + i; goto more; } myungetc(c); return val; } double getfrac(c) register c; { register double val; register double dig = 0.1; val = dig * (c - '0'); more: c = mygetchar(); if (c >= '0' && c <= '9') { dig = .1 * dig; val += dig * (c - '0'); goto more; } myungetc(c); return val; } lookfrac(intpart) long intpart; { int c; double frac; c = mygetchar(); if (c != '.') { myungetc(c); return 0; } c = mygetchar(); if (c >= '0' && c <= '9') { frac = getfrac(c); } else { myungetc(c); frac = 0.0; } gotfrac(intpart, frac); return 1; } gotfrac(intpart, frac) long intpart; double frac; { if (lookexp(intpart, frac) == 0) makeflt(intpart, frac, 0); } lookexp(intpart, frac) long intpart; double frac; { int c; int minus; int exp; minus = 0; c = mygetchar(); if (tolower(c) != 'e') { myungetc(c); return 0; } c = mygetchar(); if (c == '-') { minus = 1; c = mygetchar(); } else if (c == '+') c = mygetchar(); if (c >= '0' && c <= '9') { exp = getnumber(c); } else { exp = 0; myungetc(c); } if (minus) exp = -exp; makeflt(intpart, frac, exp); return 1; } makeflt(intpart, frac, exp) long intpart; double frac; { register double val; double mod, mod10, mod100; register struct tok *t; val = intpart + frac; if (exp > 0) { mod = 1e1; mod10 = 1e10; #if IEEE_FP mod100 = 1e100; #endif } else if (exp < 0) { mod = 1e-1; mod10 = 1e-10; #if IEEE_FP mod100 = 1e-100; #endif exp = -exp; } #if IEEE_FP while (exp >= 100) { val *= mod100; exp -= 100; } #endif while (exp >= 10) { val *= mod10; exp -= 10; } while (exp--) val *= mod; /* slow and dirty */ t = &curtok; t->tnum = FCON; t->fval = val; sprintf(t->name, FLTFORM, val); } char * getname(c) register int c; { register int nhave; nhave = 0; do { if (nhave < MAXSTR) curstr[nhave++] = c; c = mygetchar(); } while (isalnum(c) || c == '_'); myungetc(c); curstr[nhave] = 0; return curstr; } static char *holdstr; chr_push(s) char *s; { holdstr = s; } static int holdchar, xholdchar; mygetchar() { register int c; int c2; if (holdchar) { c = holdchar; holdchar = 0; goto out; } if (holdstr) { /* used for -D args */ c = *holdstr++; if (c == 0) { holdstr = NULL; return '\n'; } return c; } retry: c = xgetc(); if (c == EOF) { if (endfile()) goto retry; } else if (c == '\\') { /* ansi handling of backslash nl */ c2 = xgetc(); if (c2 == '\n') { lineno++; goto retry; } else xholdchar = c2; } out: if (c == '\n') { sawnl++; /* for pre.c */ lineno++; } return c; } xgetc() { register int c; if (xholdchar) { c = xholdchar; xholdchar = 0; return c; } #if CC68|dLibs if (input == stdin) /* bypass stupid input */ c = hackgetc(); else #endif c = getc(input); if (c != EOF) c &= 0x7f; return c; } myungetc(c) char c; { if (c != EOF) holdchar = c; if (c == '\n') lineno--; } struct op { char *name; char *asname; int flags; char prec; char value; } ops[] = { {"{"}, {"}"}, {"["}, {"]"}, {"("}, {")"}, {"#"}, {"\\"}, {";"}, {","}, {":"}, {"."}, {"\"", 0, SPECIAL}, {"'", 0, SPECIAL}, {"==", 0, C_NOT_A, 5}, {"=", 0, 0}, {"++", 0, CAN_U}, {"+", "+=", CAN_AS|C_AND_A, 2}, {"--", 0, CAN_U}, {"->", 0, 0, 0, ARROW}, {"-", "-=", CAN_U|CAN_AS, 2}, {"*", "*=", CAN_U|CAN_AS|C_AND_A, 1}, {"%", "%=", CAN_AS, 1}, {"/*", 0, SPECIAL}, {"/", "/=", CAN_AS, 1}, {"&&", 0, 0, 9}, {"&", "&=", CAN_U|CAN_AS|C_AND_A, 6}, {"||", 0, 0, 10}, {"|", "|=", CAN_AS|C_AND_A, 8}, {"!=", 0, C_NOT_A, 5, NOTEQ}, {"!", 0, CAN_U}, {"~", 0, CAN_U}, {"^", "^=", CAN_AS|C_AND_A, 7}, {"<<", "<<=", CAN_AS, 3}, {"<=", 0, C_NOT_A, 4, LTEQ}, {"<", 0, SPECIAL|C_NOT_A, 4}, {">>", ">>=", CAN_AS, 3}, {">=", 0, C_NOT_A, 4, GTEQ}, {">", 0, C_NOT_A, 4}, {"?", 0, 0}, {0, 0, 0} }; #define FIRST_C '!' #define LAST_C 0177 struct op *opstart[LAST_C-FIRST_C+1]; mo_init() { register struct op *p; register c; for (p=ops; p->name; p++) { c = p->name[0]; if (opstart[c-FIRST_C] == 0) opstart[c-FIRST_C] = p; } } matchop(c) { register struct tok *t; register struct op *p; int nxt; int value; static first = 0; t = &curtok; nxt = mygetchar(); value = c; if (first == 0) { mo_init(); first = 1; } p = opstart[c-FIRST_C]; if (p) for (; p->name; p++) if (p->name[0] == c) if (p->name[1] == 0 || p->name[1] == nxt) { if (p->name[1] == 0) myungetc(nxt); else { value = p->value ? p->value : DOUBLE value; } if (p->flags & SPECIAL) if (c != '<' || tk_flags & TK_LTSTR) return dospec(p); t->flags = p->flags; if (p->flags & CAN_AS) { nxt = mygetchar(); if (nxt != '=') { myungetc(nxt); } else { value = ASSIGN value; t->flags = 0; } } t->name = isassign(value)?p->asname:p->name; t->tnum = value; t->prec = isassign(value)? 0 : p->prec; return 1; } myungetc(nxt); t->name = "???"; t->tnum = BADTOK; return 0; } dospec(p) struct op *p; { register struct tok *t; register int c; int nhave; int endc; t = &curtok; switch (p->name[0]) { case '/': /* slash-star */ look: do { c = mygetchar(); } while (c != '*'); c = mygetchar(); if (c == '/') return 0; myungetc(c); goto look; case '\'': t->tnum = ICON; t->ival = getschar('\''); /* allow only 1 for now*/ while (getschar('\'') != NOCHAR) ; sprintf(curstr, "%d", (int)t->ival); return 1; case '<': endc = '>'; t->tnum = SCON2; goto strs; case '"': endc = '"'; t->tnum = SCON; strs: t->name = curstr; nhave = 0; c = getschar(endc); while (c != NOCHAR) { if (c >= 0 && c <= 1 && nhave < MAXSTR) { /* allow null */ curstr[nhave++] = 1; c++; } if (nhave < MAXSTR) curstr[nhave++] = c; c = getschar(endc); } curstr[nhave] = 0; return 1; } } getoct(c) { char n, i; n = c - '0'; for (i=1; i < 3; i++) { c = mygetchar(); if (c < '0' || c > '7') { myungetc(c); return (int)n; } n = 8*n + (c - '0'); } return (int)n; } getschar(del) char del; { register int c; more: c = mygetchar(); if (c == del) return NOCHAR; if (c == '\n') { error("nl in string"); myungetc(c); return NOCHAR; } if (c == '\\' && (tk_flags & TK_NOESC) == 0) { c = mygetchar(); if (c == del) return c; if (c >= '0' && c <= '7') return getoct(c); switch (c) { /* case '\n': goto more; */ case 'b': c = '\b'; break; case 'n': c = '\n'; break; case 't': c = '\t'; break; case 'r': c = '\r'; break; case 'f': c = '\f'; break; } } return c; } #ifndef dLibs isalpha(c) register char c; { if ((c>='a' && c<='z') || (c>='A' && c<='Z')) return 1; return 0; } isalnum(c) register char c; { return (isalpha(c) || (c>='0' && c<='9')); } tolower(c) register char c; { if (c>='A' && c<='Z') c += 'a'-'A'; return c; } #endif ishexa(c) register char c; { if (c>='a' && c<='f') return (c-'a'+10); if (c>='A' && c<='F') return (c-'A'+10); return 0; } #if CC68 hackgetc() { register int c; c = bios(2,2); switch (c) { case 4: return EOF; case '\r': case '\n': bios(3,2,'\r'); bios(3,2,'\n'); return '\n'; } bios(3,2,c); return c; } #endif #if dLibs hackgetc() { register int c; c = getchar(); switch (c) { case 4: return EOF; case '\n': putchar('\n'); break; } return c; } #endif SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.