home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d110
/
pdc.lha
/
Pdc
/
src
/
Decl.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-10-28
|
17KB
|
488 lines
#include <stdio.h>
#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"};
SYM *search();
extern long intexpr();
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:
*
* <type> <decl>, <decl>...;
*
* 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;
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;
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;
{
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;
}
}
}