summaryrefslogtreecommitdiff
path: root/bcc/table.c
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-03-24 17:45:55 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:29:43 +0200
commitfe22c37817ce338fbbc90b239320248c270957fa (patch)
treed9550410c4a20bdd382fcc58d2d3d7c5e04e5245 /bcc/table.c
parenta7aba15e8efffb1c5d3097656f1a93955a64f01f (diff)
parent42192453ea219b80d0bf9f41e51e36d3d4d0740b (diff)
downloaddev86-fe22c37817ce338fbbc90b239320248c270957fa.tar.gz
Import Dev86-0.0.4.tar.gzv0.0.4
Diffstat (limited to 'bcc/table.c')
-rw-r--r--bcc/table.c668
1 files changed, 668 insertions, 0 deletions
diff --git a/bcc/table.c b/bcc/table.c
new file mode 100644
index 0000000..5a5c34e
--- /dev/null
+++ b/bcc/table.c
@@ -0,0 +1,668 @@
+/* table.c - table handler for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* Can I now get rid of EXPRLEVEL? Yes, except expression symbols must
+ * usually be set to some level different from OFFKLUDGELEVEL.
+ */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "gencode.h"
+#include "os.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "table.h"
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+#define MARKER ((unsigned) 0x18C396A5L) /* lint everywhere it is used */
+#define MAXEXPR 500
+#define MAXLOCAL 100
+#define NKEYWORDS 34
+#define NSCALTYPES 12
+#define STACKSPACE 256 /* punt for normal recursions - switch extra */
+
+struct keywordstruct
+{
+ char *kwname;
+ sym_t kwcode;
+};
+
+#ifdef HOLDSTRINGS
+struct string
+{
+ struct string *snext;
+ char *sptr;
+ char *stop;
+ label_t slabel;
+};
+#endif
+
+struct typedatastruct
+{
+ char *tdname;
+ bool_t tdkeyscalar;
+ scalar_t tdscalar;
+ smalin_t tdsize;
+ struct typestruct **tdtypeptr;
+};
+
+PRIVATE struct symstruct exprsyms[MAXEXPR];
+PRIVATE struct symstruct *hashtab[HASHTABSIZE];
+ /* depends on zero init */
+#ifdef HOLDSTRINGS
+PRIVATE struct string *laststring; /* last in list of strings */
+ /* depends on NULL init */
+#endif
+PUBLIC struct symstruct locsyms[MAXLOCAL];
+
+PRIVATE struct symstruct constemplate =
+{
+ CONSTANT, /* storage */
+ 0, /* indcount */
+ 0, /* flags */
+ EXPRLEVEL, /* level */
+ NULL, /* next */
+ NULL, /* prev */
+ NULL, /* type, init later to itype */
+ /* offset is a union, set every time constemplate is used */
+ /* name is a union, namea member is constant "\0" */
+};
+
+PRIVATE struct keywordstruct keywords[NKEYWORDS] =
+{
+ { "enum", ENUMDECL, },
+ { "struct", STRUCTDECL, },
+ { "union", UNIONDECL, },
+ { "unsigned", UNSIGNDECL, },
+
+ { "auto", AUTODECL, },
+ { "extern", EXTERNDECL, },
+ { "register", REGDECL, },
+ { "static", STATICDECL, },
+
+ { "typedef", TYPEDEFDECL, },
+
+ { "break", BREAKSYM, },
+ { "case", CASESYM, },
+ { "continue", CONTSYM, },
+ { "default", DEFAULTSYM, },
+ { "do", DOSYM, },
+ { "else", ELSESYM, },
+ { "for", FORSYM, },
+ { "goto", GOTOSYM, },
+ { "if", IFSYM, },
+ { "return", RETURNSYM, },
+ { "sizeof", SIZEOFSYM, },
+ { "switch", SWITCHSYM, },
+ { "while", WHILESYM, },
+
+ { "#asm", ASMCNTL, },
+ { "#define", DEFINECNTL, },
+ { "#else", ELSECNTL, },
+ { "#endasm", ENDASMCNTL, },
+ { "#endif", ENDIFCNTL, },
+ { "#if", IFCNTL, },
+ { "#ifdef", IFDEFCNTL, },
+ { "#include", INCLUDECNTL, },
+ { "#ifndef", IFNDEFCNTL, },
+ { "#line", LINECNTL, },
+ { "#undef", UNDEFCNTL, },
+
+ { "defined", DEFINEDSYM, }, /* should be deactivated except in #if's */
+};
+
+PRIVATE struct typedatastruct scaltypes[NSCALTYPES] =
+{
+ { "void", TRUE, 0, 0, &vtype, }, /* first - addkeyword uses vtype */
+ { "char", TRUE, CHAR, 1, &ctype, },
+ { "char", FALSE, UNSIGNED | CHAR, 1, &uctype, },
+ { "char", FALSE, CHAR, 1, &sctype, },
+ { "short", TRUE, SHORT, 2, &stype, },
+ { "short", FALSE, UNSIGNED | SHORT, 2, &ustype, },
+ { "int", TRUE, INT, 2, &itype, },
+ { "int", FALSE, UNSIGNED | INT, 2, &uitype, },
+ { "long", TRUE, LONG | DLONG, 4, &ltype, },
+ { "long", FALSE, UNSIGNED | LONG | DLONG, 4, &ultype, },
+ { "float", TRUE, FLOAT, 4, &fltype, },
+ { "double", TRUE, DOUBLE, 8, &dtype, },
+};
+
+FORWARD struct symstruct *addkeyword P((char *name, sym_pt code));
+FORWARD void heapcorrupterror P((void));
+
+PUBLIC struct symstruct *addglb(name, type)
+char *name;
+struct typestruct *type;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr = NULL; /* for -Wall */
+ register struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ symptr = qmalloc(sizeof (struct symstruct) + strlen(name));
+#ifdef TS
+++ts_n_global;
+ts_size_global += sizeof (struct symstruct) + strlen(name);
+#endif
+ addsym(name, type, symptr);
+ symptr->storage = GLOBAL;
+ symptr->level = GLBLEVEL;
+ if (*hashptr == NULL)
+ {
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+ }
+ else
+ {
+ oldsymptr->next = symptr;
+ symptr->prev = &oldsymptr->next;
+ }
+ return symptr;
+}
+
+PRIVATE struct symstruct *addkeyword(name, code)
+char *name;
+sym_pt code;
+{
+ struct symstruct *symptr;
+
+ (symptr = addglb(name, vtype))->flags = KEYWORD;
+ symptr->offset.offsym = code;
+ return symptr;
+}
+
+PUBLIC struct symstruct *addloc(name, type)
+char *name;
+struct typestruct *type;
+{
+ struct symstruct **hashptr;
+ register struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ symptr = symptr->next;
+ symptr = locptr;
+ locptr = (struct symstruct *) align(&symptr->name.namea[strlen(name) + 1]);
+ if (locptr >= &locsyms[MAXLOCAL])
+ limiterror("too many local symbols (101)");
+ addsym(name, type, symptr);
+ if (type->constructor == FUNCTION)
+ symptr->storage = GLOBAL;
+ else
+ symptr->storage = LOCAL;
+ symptr->level = level;
+ if (*hashptr != NULL)
+ {
+ symptr->next = *hashptr;
+ symptr->next->prev = &symptr->next;
+ }
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+ return symptr;
+}
+
+PUBLIC struct symstruct *addlorg(name, type)
+char *name;
+struct typestruct *type;
+{
+ if (level != GLBLEVEL)
+ return addloc(name, type);
+ return addglb(name, type);
+}
+
+PUBLIC void addsym(name, type, symptr)
+char *name;
+struct typestruct *type;
+register struct symstruct *symptr;
+{
+ if (type->constructor & (ARRAY | FUNCTION))
+ symptr->indcount = 0;
+ else
+ symptr->indcount = 1;
+ symptr->flags = 0;
+ symptr->next = NULL;
+ symptr->type = type;
+ symptr->offset.offi = 0;
+ strcpy(symptr->name.namea, name);
+}
+
+PUBLIC struct symstruct *constsym(longconst)
+value_t longconst;
+{
+ register struct symstruct *symptr;
+
+ symptr = exprsym(&constemplate);
+ symptr->offset.offv = longconst;
+ return symptr;
+}
+
+PUBLIC void delsym(symptr)
+register struct symstruct *symptr;
+{
+ if ((*(symptr->prev) = symptr->next) != NULL)
+ symptr->next->prev = symptr->prev;
+}
+
+/* dumpglbs() - define locations of globals and reserve space for them */
+
+PUBLIC void dumpglbs()
+{
+ int i;
+ register struct symstruct *symptr;
+ register struct typestruct *type;
+
+#ifdef TS
+extern char *brksize;
+struct ts
+{
+ char *what;
+ uvalue_t *where;
+};
+static struct ts ts[] =
+{
+ "ts_n_newtypelist ", &ts_n_newtypelist,
+ "ts_s_newtypelist ", &ts_s_newtypelist,
+ "ts_n_filename_term ", &ts_n_filename_term,
+ "ts_s_filename_term ", &ts_s_filename_term,
+ "ts_n_filename ", &ts_n_filename,
+ "ts_s_filename ", &ts_s_filename,
+ "ts_s_filename_tot ", &ts_s_filename_tot,
+ "ts_n_pathname ", &ts_n_pathname,
+ "ts_s_pathname ", &ts_s_pathname,
+ "ts_s_pathname_tot ", &ts_s_pathname_tot,
+ "ts_n_inputbuf ", &ts_n_inputbuf,
+ "ts_s_inputbuf ", &ts_s_inputbuf,
+ "ts_s_inputbuf_tot ", &ts_s_inputbuf_tot,
+ "ts_n_includelist ", &ts_n_includelist,
+ "ts_s_includelist ", &ts_s_includelist,
+ "ts_s_outputbuf ", &ts_s_outputbuf,
+ "ts_n_macstring_ident ", &ts_n_macstring_ident,
+ "ts_n_macstring_ordinary ", &ts_n_macstring_ordinary,
+ "ts_n_macstring_param ", &ts_n_macstring_param,
+ "ts_n_macstring_quoted ", &ts_n_macstring_quoted,
+ "ts_n_macstring_term ", &ts_n_macstring_term,
+ "ts_s_macstring ", &ts_s_macstring,
+ "ts_n_defines ", &ts_n_defines,
+ "ts_s_defines ", &ts_s_defines,
+ "ts_n_macparam ", &ts_n_macparam,
+ "ts_s_macparam ", &ts_s_macparam,
+ "ts_s_macparam_tot ", &ts_s_macparam_tot,
+ "ts_n_macparam_string_ordinary ", &ts_n_macparam_string_ordinary,
+ "ts_n_macparam_string_quoted ", &ts_n_macparam_string_quoted,
+ "ts_n_macparam_string_term ", &ts_n_macparam_string_term,
+ "ts_s_macparam_string ", &ts_s_macparam_string,
+ "ts_s_macparam_string_tot ", &ts_s_macparam_string_tot,
+ "ts_s_macparam_string_alloced ", &ts_s_macparam_string_alloced,
+ "ts_s_macparam_string_alloced_tot ", &ts_s_macparam_string_alloced_tot,
+ "ts_s_fakeline ", &ts_s_fakeline,
+ "ts_s_fakeline_tot ", &ts_s_fakeline_tot,
+ "ts_n_string ", &ts_n_string,
+ "ts_n_case ", &ts_n_case,
+ "ts_n_case_realloc ", &ts_n_case_realloc,
+ "ts_s_case ", &ts_s_case,
+ "ts_s_case_tot ", &ts_s_case_tot,
+ "ts_n_structname ", &ts_n_structname,
+ "ts_s_structname ", &ts_s_structname,
+ "ts_n_type ", &ts_n_type,
+ "ts_s_type ", &ts_s_type,
+ "ts_n_global ", &ts_n_global,
+ "ts_size_global ", &ts_size_global,
+ "ts_n_holdstr ", &ts_n_holdstr,
+ "ts_size_holdstr ", &ts_size_holdstr,
+ "ts_n_growobj ", &ts_n_growobj,
+ "ts_size_growobj_wasted ", &ts_size_growobj_wasted,
+ "ts_n_growheap ", &ts_n_growheap,
+ "ts_s_growheap ", &ts_s_growheap,
+};
+struct ts *tp;
+
+for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp)
+{
+ comment();
+ outstr(tp->what);
+ outstr("");
+ outuvalue(*tp->where);
+ outnl();
+}
+comment();
+outstr("brksize ");
+outhex((uvalue_t) brksize);
+outnl();
+#endif
+
+#ifndef DIRECTPAGE
+ bssseg();
+#endif
+ for (i = 0; i < HASHTABSIZE; ++i)
+ for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next)
+ if (symptr->storage == GLOBAL && !(symptr->flags & EXTERNAL)
+ && *symptr->name.namea >= 'A' && symptr->flags <= MAXDUMPFLAG
+ /* Don't access type unless flags <= MAXDUMPFLAG, because
+ * type is punned to a symbol pointer for the label chain
+ * and might be null.
+ */
+ && symptr->type->constructor != FUNCTION)
+ {
+#ifdef DIRECTPAGE
+ if (symptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ type = symptr->type;
+ if (symptr->flags & STATIC)
+ lcommon(symptr->name.namea);
+ else
+ common(symptr->name.namea);
+ outnhex(type->typesize);
+ }
+ if (printf_fp)
+ globl("__xfpcvt");
+ if (scanf_fp)
+ globl("__xfptvc");
+}
+
+/* dumplocs() - define offsets of current locals */
+
+PUBLIC void dumplocs()
+{
+ register struct symstruct *symptr;
+ int i;
+
+ for (i = 0; i < HASHTABSIZE; ++i)
+ for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next)
+ if (symptr->storage == LOCAL)
+ set(symptr->name.namea, symptr->offset.offi - sp);
+}
+
+#ifdef HOLDSTRINGS
+
+/* dumpstrings() - dump held-up strings */
+
+PUBLIC void dumpstrings()
+{
+ struct string *stringp;
+
+ dseg();
+ for (stringp = laststring; stringp != NULL; stringp = stringp->snext)
+ {
+ outnlabel(stringp->slabel);
+ defstr(stringp->sptr, stringp->stop, TRUE);
+ dataoffset += stringp->stop - stringp->sptr + 1;
+ }
+}
+
+#endif
+
+PUBLIC struct symstruct *exprsym(symptr)
+struct symstruct *symptr;
+{
+ register struct symstruct *newsymptr;
+
+ newsymptr = exprptr++;
+ if (exprptr >= &exprsyms[MAXEXPR])
+ limiterror("expression too complex (501 symbols)");
+ *newsymptr = *symptr;
+ newsymptr->level = EXPRLEVEL;
+ newsymptr->name.namep = symptr->name.namea;
+ return newsymptr;
+}
+
+PUBLIC struct symstruct *findlorg(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (strcmp(symptr->name.namea, name) != 0 ||
+ symptr->flags == STRUCTNAME))
+ symptr = symptr->next;
+ return symptr;
+}
+
+PUBLIC struct symstruct *findstruct(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (symptr->flags != STRUCTNAME ||
+ strcmp(symptr->name.namea, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PUBLIC struct symstruct **gethashptr(sname)
+char *sname;
+{
+ register int hashval;
+ register char *rsname;
+
+ hashval = 0;
+ rsname = sname;
+#if 1
+ while (*rsname)
+ hashval = hashval * 2 + *rsname++;
+#else
+ hashval = rsname[0];
+ if (rsname[1] != 0)
+ hashval = (rsname[2] << 2) ^ rsname[1] ^ (rsname[0] << 1);
+ else
+ hashval = rsname[0];
+#endif
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+}
+
+PRIVATE void heapcorrupterror()
+{
+ outofmemoryerror(" (heap corrupt - stack overflow?)");
+}
+
+#ifdef HOLDSTRINGS
+
+/* hold string for dumping at end, to avoid mixing it with other data */
+
+PUBLIC label_t holdstr(sptr, stop)
+char *sptr;
+char *stop;
+{
+ register struct string *stringp;
+
+ stringp = qmalloc(sizeof *stringp);
+#ifdef TS
+++ts_n_holdstr;
+ts_size_holdstr += sizeof *stringp;
+#endif
+ stringp->snext = laststring;
+ stringp->sptr = sptr;
+ stringp->stop = stop;
+ laststring = stringp;
+ return stringp->slabel = getlabel();
+}
+
+#endif /* HOLDSTRINGS */
+
+PUBLIC void newlevel()
+{
+ if (*(unsigned *) chartop != MARKER)
+ heapcorrupterror();
+ if (level >= MAXLEVEL)
+ limiterror("compound statements nested too deeply (126 levels)");
+ else
+ ++level;
+}
+
+PUBLIC void oldlevel()
+{
+ register struct symstruct *symptr;
+
+ if (*(unsigned *) chartop != MARKER)
+ heapcorrupterror();
+ if (level == 0)
+ bugerror("not in a compound statement");
+ else
+ --level;
+ for (symptr = &locsyms[0]; symptr < locptr;
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ if (symptr->level > level)
+ delsym(symptr);
+}
+
+PUBLIC void ourfree(ptr)
+void *ptr;
+{
+ free(ptr);
+}
+
+PUBLIC void *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ void *ptr;
+
+ if ((ptr = malloc(nbytes)) == NULL)
+ outofmemoryerror("");
+ return ptr;
+}
+
+PUBLIC void outofmemoryerror(message)
+char *message;
+{
+ error2error("compiler out of memory", message);
+
+#if defined(DEBUG) && 0
+ {
+ unsigned size;
+ char *ptr;
+
+ for (size = 0x1000; size != 0; --size)
+ if ((ptr = malloc(size)) != NULL)
+ {
+ outstr("found free memory at ");
+ outuvalue((uvalue_t) ptr);
+ outstr(" size ");
+ outuvalue((uvalue_t) size);
+ outnl();
+ }
+ }
+#endif
+
+ finishup();
+}
+
+PUBLIC void *growobject(object, extra)
+void *object;
+unsigned extra;
+{
+ /* size_t */ unsigned oblength;
+
+ /* It would be nice to realloc the previous memory if it can be left in
+ * the same place. Since a realloc that moves the memory can almost be
+ * relied on to mess up pointers before *obptr, and since malloc(extra)
+ * would be unlikely to produce memory adjoining chartop, it is not
+ * clear how to do this.
+ */
+#ifdef TS
+ts_size_growobj_wasted += chartop - (char *) object;
+#endif
+ oblength = (/* size_t */ unsigned) (charptr - (char *) object);
+ growheap(oblength + extra);
+#ifdef TS
+++ts_n_growobj;
+#endif
+ memcpy(charptr, object, oblength);
+ object = charptr;
+ charptr += oblength;
+ return object;
+}
+
+#define ALLOC_UNIT ((unsigned) 0x400)
+#ifdef S_ALIGNMENT
+#define ALLOC_OVERHEAD (S_ALIGNMENT - 1 + sizeof (unsigned))
+#else
+#define ALLOC_OVERHEAD (sizeof (unsigned))
+#endif
+
+PUBLIC void growheap(size)
+unsigned size;
+{
+ register char *newptr;
+
+ if ((newptr = malloc(size += ALLOC_UNIT + ALLOC_OVERHEAD)) == NULL
+ && (newptr = malloc(size -= ALLOC_UNIT)) == NULL)
+ outofmemoryerror("");
+#ifdef TS
+++ts_n_growheap;
+ts_s_growheap += size;
+#endif
+ charptr = newptr;
+ newptr = (char *) align(newptr + size - ALLOC_OVERHEAD);
+ chartop = newptr;
+ char1top = newptr - 1;
+ char3top = newptr - 3;
+ *(unsigned *) newptr = MARKER;
+}
+
+PUBLIC void *qmalloc(size)
+unsigned size;
+{
+ register char *ptr;
+
+ if ((charptr = (char *) align(charptr)) + size > chartop)
+ growheap(size);
+ ptr = charptr;
+ charptr += size;
+ return ptr;
+}
+
+PUBLIC void swapsym(sym1, sym2)
+struct symstruct *sym1;
+struct symstruct *sym2;
+{
+ struct symstruct swaptemp;
+
+ swaptemp = *sym1;
+ *sym1 = *sym2;
+ *sym2 = swaptemp;
+}
+
+PUBLIC void syminit()
+{
+ struct keywordstruct *kwptr;
+ struct typedatastruct *tdptr;
+ struct typestruct *type;
+
+ exprptr = exprsyms;
+ locptr = locsyms;
+ for (tdptr = scaltypes; tdptr < scaltypes + NSCALTYPES; ++tdptr)
+ {
+ (*tdptr->tdtypeptr = type = newtype())->scalar = tdptr->tdscalar;
+ type->alignmask = ~((type->typesize = tdptr->tdsize) - 1) |
+ alignmask;
+ type->tname = tdptr->tdname;
+ if (tdptr->tdkeyscalar)
+ addkeyword(tdptr->tdname, TYPEDECL)->type = type;
+ }
+ for (kwptr = keywords; kwptr < keywords + NKEYWORDS; ++kwptr)
+ addkeyword(kwptr->kwname, kwptr->kwcode);
+ constemplate.type = itype;
+}