#include #include "c.h" #include "expr.h" #include "gen.h" #include "cglbdec.h" /* * 68000 C compiler * * Copyright 1984, 1985, 1986 Matthew Brandt. * all commercial rights reserved. * * This compiler is intended as an instructive tool for personal use. Any * use for profit without the written consent of the author is prohibited. * * This compiler may be distributed freely for non-commercial use as long * as this notice stays intact. Please forward any enhancements or questions * to: * * Matthew Brandt * Box 920337 * Norcross, Ga 30092 */ TYP *head = 0; TYP *tail = 0; char *declid = 0; TABLE tagtable = {0,0}; TYP stdconst = { bt_long, 1, 4, {0, 0}, 0, "stdconst"}; int imax(i,j) int i,j; { return (i > j) ? i : j; } char *litlate(s) char *s; { char *p; p = xalloc(strlen(s) + 1); strcpy(p,s); return p; } TYP *maketype(bt,siz) enum e_bt bt; int siz; { TYP *tp; tp = xalloc(sizeof(TYP)); tp->val_flag = 0; tp->size = siz; tp->type = bt; tp->sname = 0; tp->lst.head = 0; return tp; } int decl(table) TABLE *table; { switch (lastst) { case kw_char: head = tail = maketype(bt_char,1); getsym(); break; case kw_short: head = tail = maketype(bt_short,2); getsym(); break; case kw_int: case kw_long: head = tail = maketype(bt_long,4); getsym(); break; case kw_unsigned: head = tail = maketype(bt_unsigned,4); getsym(); if( lastst == kw_int ) getsym(); break; case id: /* no type declarator */ head = tail = maketype(bt_long,4); break; case kw_float: head = tail = maketype(bt_float,4); getsym(); break; case kw_double: head = tail = maketype(bt_double,8); getsym(); break; case kw_enum: getsym(); declenum(table); break; case kw_struct: getsym(); declstruct(bt_struct); break; case kw_union: getsym(); declstruct(bt_union); break; } } decl1() { TYP *temp1, *temp2, *temp3, *temp4; switch (lastst) { case id: declid = litlate(lastid); getsym(); decl2(); break; case star: temp1 = maketype(bt_pointer,4); temp1->btp = head; head = temp1; if(tail == NULL) tail = head; getsym(); decl1(); break; case openpa: getsym(); temp1 = head; temp2 = tail; head = tail = NULL; decl1(); needpunc(closepa); temp3 = head; temp4 = tail; head = temp1; tail = temp2; decl2(); temp4->btp = head; if(temp4->type == bt_pointer && temp4->val_flag != 0 && head != NULL) temp4->size *= head->size; head = temp3; break; default: decl2(); break; } } decl2() { TYP *temp1; switch (lastst) { case openbr: getsym(); temp1 = maketype(bt_pointer,0); temp1->val_flag = 1; temp1->btp = head; if(lastst == closebr) { temp1->size = 0; getsym(); } else if(head != NULL) { temp1->size = intexpr() * head->size; needpunc(closebr); } else { temp1->size = intexpr(); needpunc(closebr); } head = temp1; if( tail == NULL) tail = head; decl2(); break; case openpa: getsym(); temp1 = maketype(bt_func,0); temp1->val_flag = 1; temp1->btp = head; head = temp1; if( lastst == closepa) { getsym(); if(lastst == begin) temp1->type = bt_ifunc; } else temp1->type = bt_ifunc; break; } } int alignment(tp) TYP *tp; { switch(tp->type) { case bt_char: return AL_CHAR; case bt_short: return AL_SHORT; case bt_long: return AL_LONG; case bt_enum: return AL_SHORT; case bt_pointer: if(tp->val_flag) return alignment(tp->btp); else return AL_POINTER; case bt_float: return AL_FLOAT; case bt_double: return AL_DOUBLE; case bt_struct: case bt_union: return AL_STRUCT; default: return AL_CHAR; } } int declare(table,al,ilc,ztype) /* * process declarations of the form: * * , ...; * * leaves the declarations in the symbol table pointed to by * table and returns the number of bytes declared. al is the * allocation type to assign, ilc is the initial location * counter. if al is sc_member then no initialization will * be processed. ztype should be bt_struct for normal and in * structure declarations and sc_union for in union declarations. */ TABLE *table; enum e_sc al; int ilc; enum e_bt ztype; { SYM *sp, *sp1; TYP *dhead; int nbytes; nbytes = 0; decl(table); dhead = head; for(;;) { declid = 0; decl1(); if( declid != 0) { /* otherwise just struct tag... */ sp = xalloc(sizeof(SYM)); sp->name = declid; sp->storage_class = al; while( (ilc + nbytes) % alignment(head)) { if( al != sc_member && al != sc_external && al != sc_auto) { dseg(); genbyte(0); } ++nbytes; } if( al == sc_static) sp->value.i = nextlabel++; else if( ztype == bt_union) sp->value.i = ilc; else if( al != sc_auto ) sp->value.i = ilc + nbytes; else sp->value.i = -(ilc + nbytes + head->size); sp->tp = head; if( sp->tp->type == bt_func && sp->storage_class == sc_global ) sp->storage_class = sc_external; if(ztype == bt_union) nbytes = imax(nbytes,sp->tp->size); else if(al != sc_external) nbytes += sp->tp->size; if( sp->tp->type == bt_ifunc && (sp1 = search(sp->name,table->head)) != 0 && sp1->tp->type == bt_func ) { sp1->tp = sp->tp; sp1->storage_class = sp->storage_class; sp1->value.i = sp->value.i; sp = sp1; } else insert(sp,table); if( sp->tp->type == bt_ifunc) { /* function body follows */ funcbody(sp); return nbytes; } if( (al == sc_global || al == sc_static) && sp->tp->type != bt_func) doinit(sp); } if(lastst == semicolon) break; needpunc(comma); if(declbegin(lastst) == 0) break; head = dhead; } getsym(); return nbytes; } int declbegin(st) enum e_sym st; { return (st == star || st == id || st == openpa || st == openbr); } declenum(table) TABLE *table; { SYM *sp; TYP *tp; int evalue; if( lastst == id) { if((sp = search(lastid,tagtable.head)) == 0) { sp = xalloc(sizeof(SYM)); sp->tp = xalloc(sizeof(TYP)); sp->tp->type = bt_enum; sp->tp->size = 2; sp->tp->lst.head = sp->tp->btp = 0; sp->storage_class = sc_type; sp->name = litlate(lastid); sp->tp->sname = sp->name; getsym(); if( lastst != begin) error(ERR_INCOMPLETE); else { insert(sp,&tagtable); getsym(); enumbody(table); } } else getsym(); head = sp->tp; } else { tp = xalloc(sizeof(tp)); tp->type = bt_short; if( lastst != begin) error(ERR_INCOMPLETE); else { getsym(); enumbody(table); } head = tp; } } enumbody(table) TABLE *table; { int evalue; SYM *sp; evalue = 0; while(lastst == id) { sp = xalloc(sizeof(SYM)); sp->value.i = evalue++; sp->name = litlate(lastid); sp->storage_class = sc_const; sp->tp = &stdconst; insert(sp,table); getsym(); if( lastst == comma) getsym(); else if(lastst != end) break; } needpunc(end); } declstruct(ztype) /* * declare a structure or union type. ztype should be either * bt_struct or bt_union. */ enum e_bt ztype; { SYM *sp; TYP *tp; int slc; if(lastst == id) { if((sp = search(lastid,tagtable.head)) == 0) { sp = xalloc(sizeof(SYM)); sp->name = litlate(lastid); sp->tp = xalloc(sizeof(TYP)); sp->tp->type = ztype; sp->tp->lst.head = 0; sp->storage_class = sc_type; sp->tp->sname = sp->name; getsym(); if(lastst != begin) error(ERR_INCOMPLETE); else { insert(sp,&tagtable); getsym(); structbody(sp->tp,ztype); } } else getsym(); head = sp->tp; } else { tp = xalloc(sizeof(TYP)); tp->type = ztype; tp->sname = 0; tp->lst.head = 0; if( lastst != begin) error(ERR_INCOMPLETE); else { getsym(); structbody(tp,ztype); } head = tp; } } structbody(tp,ztype) TYP *tp; enum e_bt ztype; { int slc; slc = 0; tp->val_flag = 1; while( lastst != end) { if(ztype == bt_struct) slc += declare(&(tp->lst),sc_member,slc,ztype); else slc = imax(slc,declare(&tp->lst,sc_member,0,ztype)); } tp->size = slc; getsym(); } compile() /* * main compiler routine. this routine parses all of the * declarations using declare which will call funcbody as * functions are encountered. */ { while(lastst != eof) { dodecl(sc_global); if( lastst != eof) getsym(); } dumplits(); } dodecl(defclass) enum e_sc defclass; { int size; for(;;) { switch(lastst) { case kw_register: getsym(); if( defclass != sc_auto && defclass != sc_member ) error(ERR_ILLCLASS); goto do_decl; case id: if(defclass == sc_auto) return; /* else fall through to declare */ case kw_char: case kw_int: case kw_short: case kw_unsigned: case kw_long: case kw_struct: case kw_union: case kw_enum: case kw_void: case kw_float: case kw_double: do_decl: if( defclass == sc_global) lc_static += declare(&gsyms,sc_global,lc_static,bt_struct); else if( defclass == sc_auto) lc_auto += declare(&lsyms,sc_auto,lc_auto,bt_struct); else declare(&lsyms,sc_auto,0,bt_struct); break; case kw_static: getsym(); if( defclass == sc_member) error(ERR_ILLCLASS); if( defclass == sc_auto ) lc_static += declare(&lsyms,sc_static,lc_static,bt_struct); else lc_static += declare(&gsyms,sc_static,lc_static,bt_struct); break; case kw_extern: getsym(); if( defclass == sc_member) error(ERR_ILLCLASS); ++global_flag; declare(&gsyms,sc_external,0,bt_struct); --global_flag; break; default: return; } } }