ref: 0af5513b097a22fa8cb181e4d11f671f2f02ab26
dir: /types.c/
#include <assert.h> #include <stdlib.h> #include "sizes.h" #include "cc.h" #include "tokens.h" #include "types.h" /* TODO: create wrapper file */ #define xcalloc calloc struct type tschar = {.btype = CHAR}; struct type tshort = {.btype = SHORT}; struct type tint = {.btype = INT}; struct type tfloat = {.btype = FLOAT}; struct type tdouble = {.btype = DOUBLE}; struct type tldouble = {.btype = LDOUBLE}; struct type tlong = {.btype = LONG}; struct type tllong = {.btype = LLONG}; struct type tvoid = {.btype = VOID}; struct type tbool = {.btype = BOOL}; static unsigned char stack[NR_DECLARATORS]; static unsigned char *stackp = stack; struct type *btype(struct type *tp, unsigned char tok) { switch (tok) { case VOID: if (tp == NULL) return T_VOID; break; case BOOL: if (tp == NULL) return T_BOOL; break; case CHAR: if (tp == NULL) return T_CHAR; break; case SHORT: if (tp == NULL || tp == T_INT) return T_SHORT; break; case INT: if (tp == NULL) return T_INT; if (tp == T_SHORT) return T_SHORT; if (tp == T_LONG) return T_LONG; break; case LONG: if (tp == NULL || tp == T_INT) return T_LONG; if (tp == T_LONG) return T_LLONG; if (tp == T_DOUBLE) return T_LDOUBLE; if (tp == T_LLONG) error("'long long long' is too long"); if (tp == T_LDOUBLE) error("'long long double' is too long"); break; case FLOAT: if (tp == NULL) return T_FLOAT; break; case DOUBLE: if (tp == NULL) return T_DOUBLE; if (tp == T_LONG) return T_LDOUBLE; break; default: abort(); } error("two or more basic types"); } void pushtype(unsigned char mod) { if (stackp == stack + NR_DECLARATORS) error("Too much type declarators"); *stackp++ = mod; } struct type *decl_type(struct type *t) { while (stackp != stack) t = mktype(t, *--stackp); ptype(t); return t; } struct type *mktype(register struct type *base, unsigned char op) { register struct type **ptr, *nt; assert(op == PTR || op == ARY || op == FTN || op == VOLATILE || op == RESTRICT || op == CONST); switch (op) { case PTR: ptr = &base->ptr; break; case ARY: ptr = &base->ary; break; case FTN: ptr = &base->ftn; break; case VOLATILE: ptr = &base->vltl; break; case RESTRICT: ptr = &base->rstr; break; case CONST: ptr = &base->cnst; break; } if (*ptr) return *ptr; nt = xcalloc(sizeof(*base), 1); *ptr = nt; nt->op = op; nt->base = base; return nt; } #ifndef NDEBUG #include <stdio.h> void ptype(register struct type *t) { assert(t); for (; t; t = t->base) { switch (t->op) { case ARY: fputs("array of ", stdout); break; case PTR: fputs("pointer to ", stdout); break; case FTN: fputs("function that returns ", stdout); break; case VOLATILE: fputs("volatile ", stdout); break; break; case RESTRICT: fputs("restrict ", stdout); break; case CONST: fputs("const ", stdout); break; default: { static char *type, *sign; /* sign = (t->sign) ? "signed" : "unsigned"; */ switch (t->btype) { case INT: type = "int"; break; case CHAR: type = "char"; break; case FLOAT: type = "float"; break; case LONG: type = "long"; break; case LLONG: type = "long long"; break; case SHORT: type = "short"; break; case VOID: type = "void"; break; case DOUBLE: type = "double"; break; case LDOUBLE: type = "long double"; break; default: abort(); } /* printf("%s %s", sign, type); */ } } } putchar('\n'); } #endif unsigned char isfunction(struct type *t) { return t->op == FTN; }