home *** CD-ROM | disk | FTP | other *** search
- /*
- * 68K/386 32-bit C compiler.
- *
- * copyright (c) 1996, David Lindauer
- *
- * This compiler is intended for educational use. It may not be used
- * for profit without the express written consent of the author.
- *
- * It may be freely redistributed, as long as this notice remains intact
- * and sources are distributed along with any executables derived from them.
- *
- * The author is not responsible for damages, either direct or consequential,
- * that may arise from use of this software.
- *
- * v1.5 August 1996
- * David Lindauer, gclind01@starbase.spd.louisville.edu
- *
- * Credits to Mathew Brandt for original K&R C compiler
- *
- */
- #include <stdio.h>
- #include "expr.h"
- #include "c.h"
- #include "gen.h"
- #include "cglbdec.h"
-
- extern int skm_declend[];
- extern long bittab[];
- extern int nextlabel;
- extern TYP stdmatch;
- extern int skm_closebr[];
- extern int prm_cplusplus;
- extern SYM *currentfunc;
- extern long lc_maxauto,lc_auto;
-
- static SYM *locsp;
- static short cursize;
- static short startbit,bits;
- static long totbits;
- static int allocated;
- static ENODE *cpprefhead;
- static ENODE **cppreftail;
- static int baseoffs = 0;
- void initini(void)
- {
- cpprefhead = 0;
- }
- void initrundown(void)
- {
- if (cpprefhead) {
- int lbl = nextlabel++;
- SNODE stmt;
- currentfunc = xalloc(sizeof(SYM));
- currentfunc->tp = maketype(bt_func,0);
- currentfunc->tp->btp = maketype(bt_void,0);
- currentfunc->tp->lst.head = 0;
- currentfunc->intflag = 0;
- stmt.stype = st_expr;
- stmt.next = 0;
- stmt.exp = cpprefhead;
- lc_maxauto = lc_auto = 0;
- cseg();
- gen_label(lbl);
- genfunc(&stmt);
- flush_peep();
- cppseg();
- gen_labref(lbl);
- currentfunc = 0;
- cpprefhead = 0;
- }
- }
- void cppinitinsert(ENODE *node)
- {
- if (!cpprefhead) {
- cpprefhead = node;
- cppreftail = &cpprefhead;
- }
- else {
- *cppreftail = makenode(en_void,*cppreftail,node);
- cppreftail = & (*cppreftail)->v.p[1];
- }
- }
- void doinit(SYM *sp)
- /*
- * Handle static variable initialize
- */
- {
- sp->tp->uflags |= UF_DEFINED;
- allocated = FALSE;
- baseoffs = 0;
- totbits = 0;
- cursize = -1;
- bits = -1;
- locsp = sp;
- if (!sp->absflag) {
- char buf[100];
- strcpy(buf,sp->name);
- gen_strlab(buf);
- }
- if( lastst != assign) {
- genstorage(sp->tp->size);
- }
- else {
- if (sp->absflag) {
- generror(ERR_NOINIT,0,skm_declend);
- return;
- }
- getsym();
- inittype(sp->tp);
- }
- if (sp->tp->size == 0 && !allocated)
- gensymerror(ERR_ZEROSTORAGE,sp->name);
- endinit();
- }
-
- int inittype(TYP *tp)
- /*
- * Init for basic types
- */
- { int nbytes;
- switch(tp->type) {
-
- case bt_float:
- nbytes = initfloat();
- break;
- case bt_longdouble:
- nbytes = initlongdouble();
- break;
- case bt_double:
- nbytes = initdouble();
- break;
- case bt_char:
- case bt_unsignedchar:
- nbytes = initchar();
- break;
- case bt_short:
- case bt_unsignedshort:
- case bt_enum:
- nbytes = initshort();
- break;
- case bt_ptrfunc:
- nbytes = initpointerfunc();
- break;
- case bt_pointer:
- if( tp->val_flag)
- nbytes = initarray(tp);
- else
- nbytes = initpointer();
- break;
- case bt_ref:
- nbytes = initref(tp->btp);
- break;
- case bt_long:
- case bt_matchall:
- case bt_unsigned:
- nbytes = initlong();
- break;
- case bt_struct:
- nbytes = initstruct(tp);
- break;
- default:
- gensymerror(ERR_NOINIT,locsp->name);
- nbytes = 0;
- }
- baseoffs+=nbytes;
- return nbytes;
- }
-
- int initarray(TYP *tp)
- /*
- * Init for arrays
- */
- { int nbytes;
- char *p;
- int needend = FALSE;
- nbytes = 0;
- if( lastst == begin) {
- getsym(); /* skip past the brace */
- needend = TRUE;
- if (tp->btp->type == bt_char && lastst == sconst)
- goto grabchar;
- while(lastst != end) {
- nbytes += inittype(tp->btp);
- if( lastst == comma)
- getsym();
- else if( lastst != end) {
- expecttoken(end,0);
- break;
- }
- }
- getsym(); /* skip closing brace */
- }
- else {
- grabchar:
- allocated = TRUE;
- if( lastst == sconst && tp->btp->type == bt_char) {
- nbytes = strlen(laststr) + 1;
- p = laststr;
- while( *p )
- genbyte(*p++);
- genbyte(0);
- if (nbytes & 1) {
- nbytes++;
- genbyte(0);
- }
- getsym();
- if (needend)
- needpunc(end,skm_declend);
- }
- else generror(ERR_PUNCT,semicolon,0);
- }
- if( nbytes < tp->size) {
- nl();
- genstorage( tp->size - nbytes);
- nbytes = tp->size;
- }
- else if( tp->size != 0 && nbytes > tp->size)
- generror(ERR_INITSIZE,0,0); /* too many initializers */
- return nbytes;
- }
-
- int initstruct(TYP *tp)
- /*
- * Init for structures
- */
- { SYM *sp;
- int nbytes;
- needpunc(begin,0);
- nbytes = 0;
- sp = tp->lst.head; /* start at top of symbol table */
- while(sp != 0) {
- startbit = sp->tp->startbit;
- bits = sp->tp->bits;
- while(nbytes < sp->value.i) { /* align properly */
- nbytes++;
- genbyte(0);
- }
- nbytes += inittype(sp->tp);
- if( lastst == comma)
- getsym();
- else if(lastst == end)
- break;
- else
- expecttoken(end,0);
- sp = sp->next;
- }
- nbytes += agbits(-1,0);
- if( nbytes < tp->size) {
- genstorage(tp->size - nbytes);
- }
- needpunc(end,skm_declend);
- return tp->size;
- }
-
- int agflush(int size, long val)
- {
- switch (size) {
- case 1:
- genbyte(val);
- return 1;
- case 2:
- genword(val);
- return 2;
- case 4:
- genlong(val);
- return 4;
- default:
- return 0;
- }
- }
- /* Aggregate bits */
- int agbits(int size, long value)
- {
- long rv = 0;
- if (cursize != -1 && (size != cursize || bits == -1 || (bits != -1 &&startbit==0)))
- rv = agflush(cursize,totbits);
- if (bits != -1) {
- totbits |= (value & bittab[bits-1]) << startbit;
- cursize = size;
- }
- else {
- rv+= agflush(size,value);
- cursize = -1;
- totbits = 0;
- }
- startbit = -1;
- return(rv);
- }
- /* Basic type subroutines */
- int initfloat(void)
- {
- allocated = TRUE;
- genfloat(floatexpr());
- return(4);
- }
- int initlongdouble(void)
- {
- allocated = TRUE;
- genlongdouble(floatexpr());
- return(8);
- }
- int initdouble(void)
- {
- allocated = TRUE;
- gendouble(floatexpr());
- return(8);
- }
- int initchar(void)
- {
- allocated = TRUE;
- return agbits(1,intexpr(0));
- }
- int initshort(void)
- {
- allocated = TRUE;
- return agbits(2,intexpr(0));
- }
- int initlong(void)
- {
- allocated = TRUE;
- return agbits(4,intexpr(0));
- }
- void getreflvalue(ENODE **node, TYP **tp,int pointer)
- {
- SYM *sp;
- ENODE *pnode=0;
- sp = 0;
- while (lastst == star) {
- getsym();
- getreflvalue(&pnode,tp,pointer);
- if ((*tp)->type == bt_pointer) {
- *tp = (*tp)->btp;
- pnode = makenode(en_l_ref,pnode,0);
- }
- else {
- generror(ERR_DEREF,0,0);
- }
- *node = pnode;
- return;
- }
- if (lastst == and && pointer) {
- getsym();
- getreflvalue(&pnode,tp,pointer);
- if (!((*tp)->type == bt_ifunc) && !((*tp)->type == bt_func)) {
- TYP *tp1 = maketype(bt_pointer,4);
- tp1->btp = *tp;
- *tp = tp1;
- pnode = pnode->v.p[0];
- }
- *node = pnode;
- return;
- }
- if (lastst != id) {
- long temp;
- getsym();
- temp = intexpr(tp);
- (*node) = makenode(en_icon,(char *)temp,0);
- return;
- }
- if ((sp = search(lastid,&gsyms)) == 0) {
- gensymerror(ERR_UNDEFINED,lastid);
- return;
- }
- pnode = makenode(en_nacon,(char *)sp->name,0);
- if (pointer)
- pnode = makenode(en_l_ref,pnode,0);
- *tp = sp->tp;
- getsym();
- while (TRUE) {
- long temp;
- switch(lastst) {
- case openbr: /* build a subscript reference */
- getsym();
- temp = intexpr(0);
- if( (*tp)->type != bt_pointer )
- generrorexp(ERR_NOPOINTER,0,skm_closebr);
- else {
- (*tp) = (*tp)->btp;
- pnode = makenode(en_add,pnode,makenode(en_icon,(char *)(temp*(*tp)->size),0));
- }
- needpuncexp(closebr,skm_closebr);
- break;
- case pointsto:
- if( (*tp)->type != bt_pointer ) {
- generror(ERR_NOPOINTER,0,0);
- while (lastst == pointsto || lastst == dot) {
- getsym();
- getsym();
- }
- break;
- }
- else {
- (*tp) = (*tp)->btp;
- pnode = makenode(en_l_ref,pnode,0);
- }
- /*
- * fall through to dot operation
- */
- case dot:
- getsym(); /* past -> or . */
- if( lastst != id )
- generror(ERR_IDEXPECT,0,0);
- else {
- sp = search(lastid,&(*tp)->lst);
- if( sp == 0 ) {
- (*tp) = &stdmatch;
- gensymerror(ERR_UNDEFINED,lastid);
- getsym();
- while (lastst == pointsto || lastst == dot) {
- getsym();
- getsym();
- }
- }
- else {
- pnode = makenode(en_add,pnode,makenode(en_icon,(char *)sp->value.i,0));
- (*tp) = sp->tp;
- getsym(); /* past id */
- }
- break;
-
- }
- case plus:
- getsym();
- pnode = makenode(en_add,pnode,makenode(en_icon,(char *)intexpr(0),0));
- break;
- case minus:
- getsym();
- pnode = makenode(en_add,pnode,makenode(en_icon,(char *)(-intexpr(0)),0));
- break;
- default:
- *node =pnode;
- return;
- }
- }
- }
- int checkrefeval(ENODE *node)
- {
- switch(node->nodetype) {
- case en_add:
- return(checkrefeval(node->v.p[0]) || checkrefeval(node->v.p[1]));
- case en_l_ref:
- return 1;
- case en_nacon:
- case en_icon:
- return 0;
- default:
- return 1;
- }
- }
- int refeval(ENODE *one, ENODE **two)
- {
- while (1) {
- switch (one->nodetype) {
- case en_add:
- return(refeval(one->v.p[0],two) + refeval(one->v.p[1],two));
- case en_icon:
- return(one->v.i);
- case en_nacon:
- *two = one;
- return 0;
- default:
- return 0;
- }
- }
- }
- int initref(TYP *tp)
- {
- SYM *sp;
- TYP *tp1;
- ENODE *node=0,*node1;
- int ofs;
- allocated = TRUE;
- getreflvalue(&node,&tp1,0);
- if (!node || !checktype(tp,tp1)) {
- genlong(0);
- generror(ERR_REFLVALUE,0,0);
- }
- else {
- if (!checkrefeval(node)) {
- ofs = refeval(node,&node1);
- sp = search(node1->v.sp,&gsyms);
- genref(sp,ofs);
- sp->tp->uflags |= UF_USED;
- }
- else {
- node1 = makenode(en_l_ref,makenode(en_nacon,locsp->name,0),0);
- node1 = makenode(en_assign,node1,node);
- cppinitinsert(node1);
- genlong(0);
- }
- }
- endinit();
- return 4;
- }
- int initpointer(void)
- { SYM *sp;
- ENODE *node=0,*node1;
- TYP *tp1;
- allocated = TRUE;
- if(lastst == sconst) {
- gen_labref(stringlit(laststr));
- getsym();
- }
- else if (lastst == iconst) {
- int temp;
- TYP *tp;
- genlong(temp = intexpr(&tp));
- if (temp && (tp->type != bt_pointer && tp->type != bt_ptrfunc))
- generror(ERR_NONPORT,0,0);
- }
- else {
- getreflvalue(&node,&tp1,1);
- if (!node || (tp1->type != bt_pointer && tp1->type != bt_func && tp1->type != bt_ifunc))
- gensymerror(ERR_NOINIT,locsp->name);
- else {
- if (!checkrefeval(node)) {
- int ofs = refeval(node,&node1);
- sp = search(node1->v.sp,&gsyms);
- if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc)
- genpcref(sp,ofs);
- else
- genref(sp,ofs);
- sp->tp->uflags |= UF_USED;
- }
- else {
- if (!prm_cplusplus)
- gensymerror(ERR_NOINIT,locsp->name);
- else {
- node1 = makenode(en_l_ref,makenode(en_nacon,locsp->name,0),0);
- node1 = makenode(en_assign,node1,node);
- cppinitinsert(node1);
- }
- genlong(0);
- }
- }
- }
- endinit();
- return 4; /* pointers are 4 bytes long */
- }
- int initpointerfunc(void)
- { SYM *sp;
- char *nm;
- allocated = TRUE;
- if(lastst == and) /* address of a variable */
- getsym();
- if(lastst != id) {
- int temp;
- TYP *tp;
- genlong(temp = intexpr(&tp));
- if (temp && (tp->type != bt_pointer && tp->type != bt_ptrfunc))
- generror(ERR_NONPORT,0,0);
- endinit();
- return(4);
- }
- else {
- if (prm_cplusplus)
- nm = cppmangle(lastid,locsp->tp);
- else
- nm = lastid;
- if( (sp = gsearch(nm)) == 0)
- gensymerror(ERR_UNDEFINED,nm);
- else
- getsym();
- }
- genpcref(sp,0);
- if (sp)
- sp->tp->uflags |= UF_USED;
- endinit();
- return 4; /* pointers are 4 bytes long */
- }
- /* Finish init */
- void endinit(void)
- { if( lastst != comma && lastst != semicolon && lastst != end) {
- expecttoken(end,0);
- while( lastst != comma && lastst != semicolon && lastst != end)
- getsym();
- }
- }