scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 2fae9d998da0050e988c600e6581a076441382ef
parent 9adea1257259dd445efff48073917cc5a6b3f230
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 11 Jan 2016 10:10:40 +0100

Add support for k&r functions

I know that this was the most expected feature of scc. You guys
can begin to work with scc after this commit.

Diffstat:
cc1/cc1.h | 4+++-
cc1/code.c | 13++++---------
cc1/decl.c | 207+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
cc1/expr.c | 4++--
cc1/symbol.c | 4++++
cc1/types.c | 7++++++-
6 files changed, 149 insertions(+), 90 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -45,6 +45,7 @@ struct type { bool integer : 1; /* this type is INT or enum */ bool arith : 1; /* this type is INT, ENUM, FLOAT */ bool aggreg : 1; /* this type is struct or union */ + bool k_r : 1; /* This is a k&r function */ size_t size; /* sizeof the type */ size_t align; /* align of the type */ Type *type; /* base type */ @@ -134,7 +135,8 @@ enum { enum { FTN = 1, PTR, - ARY + ARY, + KRFTN }; /* namespaces */ diff --git a/cc1/code.c b/cc1/code.c @@ -355,20 +355,15 @@ static void emitfun(unsigned op, void *arg) { Symbol *sym = arg, **sp; - TINT n; emitdcl(op, arg); puts("\n{"); - n = sym->type->n.elem; - for (sp = sym->u.pars; n-- > 0; ++sp) { - if ((sym = *sp) == NULL) - continue; - /* enable non used warnings in parameters */ - sym->flags &= ~ISUSED; - emit(ODECL, sym); - } + for (sp = sym->u.pars; sp && *sp; ++sp) + emit(ODECL, *sp); puts("\\"); + free(sym->u.pars); + sym->u.pars = NULL; } static void diff --git a/cc1/decl.c b/cc1/decl.c @@ -52,6 +52,7 @@ push(struct declarators *dp, int op, ...) case ARY: p->nelem = va_arg(va, TINT); break; + case KRFTN: case FTN: p->nelem = va_arg(va, TINT); p->tpars = va_arg(va, Type **); @@ -87,7 +88,7 @@ pop(struct declarators *dp, struct decl *dcl) popctx(); dcl->pars = NULL; } - if (p->op == FTN) + if (p->op == FTN || p->op == KRFTN) dcl->pars = p->pars; dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars); return 1; @@ -159,7 +160,7 @@ parameter(struct decl *dcl) switch (tp->op) { case VOID: - if (n != 0) { + if (n != 0 || funtp->k_r) { errorp("incorrect void parameter"); return NULL; } @@ -175,13 +176,22 @@ parameter(struct decl *dcl) return NULL; } if (!empty(sym, tp)) { - if ((sym = install(NS_IDEN, sym)) == NULL) { + Symbol *p = install(NS_IDEN, sym); + if (!p && !funtp->k_r) { errorp("redefinition of parameter '%s'", name); return NULL; } + if (p && funtp->k_r) { + errorp("declaration for parameter ā€˜%sā€™ but no such parameter", + sym->name); + return NULL; + } + if (p) + sym = p; } sym->type = tp; + sym->flags &= ~(ISAUTO|ISREGISTER); sym->flags |= flags; return sym; } @@ -192,66 +202,114 @@ static Symbol *dodcl(int rep, Type *type); static void -fundcl(struct declarators *dp) +krfun(Type *tp, Type *types[], Symbol *syms[], int *ntypes, int *nsyms) { - Type type, *types[NR_FUNPARAM], *tp; - Symbol *syms[NR_FUNPARAM], *sym; - TINT size; - Symbol *pars; - int toomany = 0, toovoid = 0; - - pushctx(); - expect('('); - type.n.elem = 0; + int n = 0; + Symbol *sym; + int toomany = 0; - if (yytoken == ')') { - ++type.n.elem; - syms[0] = NULL; - types[0] = ellipsistype; - goto end_params; + if (yytoken != ')') { + do { + sym = yylval.sym; + expect(IDEN); + sym->type = inttype; + sym->flags |= ISAUTO; + if ((sym = install(NS_IDEN, sym)) == NULL) { + errorp("redefinition of parameter '%s'", + sym->name); + continue; + } + if (n < NR_FUNPARAM) { + ++n; + *syms++ = sym; + continue; + } + if (!toomany) + errorp("too much parameters in function definition"); + toomany = 1; + } while (accept(',')); } + + *nsyms = n; + *ntypes = 1; + types[0] = ellipsistype; +} + +static void +ansifun(Type *tp, Type *types[], Symbol *syms[], int *ntypes, int *nsyms) +{ + int n = 0; + Symbol *sym; + int toomany = 0, toovoid = 0; + do { - if (type.n.elem == -1) { + if (n == -1) { if (!toovoid) errorp("'void' must be the only parameter"); toovoid = 1; } - if (!accept(ELLIPSIS)) { - sym = dodcl(0, parameter, NS_IDEN, &type); - if (!sym) - continue; - tp = sym->type; - } else { - if (type.n.elem == 0) + if (accept(ELLIPSIS)) { + if (n == 0) errorp("a named argument is requiered before '...'"); - tp = ellipsistype; - sym = NULL; + ++n; + *syms = NULL; + *types++ = ellipsistype; + break; } - if (type.n.elem == NR_FUNPARAM) { - if (toomany) - continue; - errorp("too much parameters in function definition"); - toomany = 1; - } else if (type.n.elem >= 0) { - syms[type.n.elem] = sym; - types[type.n.elem] = tp; - ++type.n.elem; + if ((sym = dodcl(0, parameter, NS_IDEN, tp)) == NULL) + continue; + if (tp->n.elem == -1) { + n = -1; + continue; + } + if (n < NR_FUNPARAM) { + *syms++ = sym; + *types++ = sym->type; + ++n; + continue; } - } while (tp != ellipsistype && accept(',')); + if (!toomany) + errorp("too much parameters in function definition"); + toomany = 1; + } while (accept(',')); + + *nsyms = n; + *ntypes = n; +} + +static void +fundcl(struct declarators *dp) +{ + Type *types[NR_FUNPARAM], type; + Symbol *syms[NR_FUNPARAM+1], **pars; + int k_r, ntypes, nsyms; + size_t size; + void (*fp)(Type **, Symbol **, int *, int *); -end_params: + pushctx(); + expect('('); + type.n.elem = 0; + type.k_r = 0; + + k_r = (yytoken == ')' || yytoken == IDEN); + (*(k_r ? krfun : ansifun))(&type, types, syms, &ntypes, &nsyms); expect(')'); - if (type.n.elem > 0) { - size = type.n.elem * sizeof(Symbol *); - pars = memcpy(xmalloc(size), syms, size); - size = type.n.elem * sizeof(Type *); - type.p.pars = memcpy(xmalloc(size), types, size); + type.n.elem = ntypes; + if (ntypes <= 0) { + type.p.pars = NULL; } else { + size = ntypes * sizeof(Type *); + type.p.pars = memcpy(xmalloc(size), types, size); + } + if (nsyms <= 0) { pars = NULL; - type.p.pars = NULL; + } else { + size = (nsyms + 1) * sizeof(Symbol *); + pars = memcpy(xmalloc(size), syms, size); + pars[nsyms] = NULL; } - push(dp, FTN, type.n.elem, type.p.pars, pars); + push(dp, (k_r) ? KRFTN : FTN, type.n.elem, type.p.pars, pars); } static void declarator(struct declarators *dp, unsigned ns); @@ -757,51 +815,47 @@ dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent) return sym; } -static void -prototype(Symbol *sym) -{ - int n; - Symbol **p; - - emit(ODECL, sym); - /* - * avoid non used warnings in prototypes - */ - n = sym->type->n.elem; - for (p = sym->u.pars; n-- > 0; ++p) { - if (*p == NULL) - continue; - (*p)->flags |= ISUSED; - } - free(sym->u.pars); - sym->u.pars = NULL; - popctx(); -} - void decl(void) { - Symbol *sym; + Symbol **p, *par, *sym, *ocurfun; if (accept(';')) return; sym = dodcl(1, identifier, NS_IDEN, NULL); - /* - * Functions only can appear at global context, - * but due to parameter context, we have to check - * against GLOBALCTX+1 - */ if (sym->type->op != FTN) { expect(';'); return; } + ocurfun = curfun; + curfun = sym; + /* + * Functions only can appear at global context, + * but due to parameter context, we have to check + * against GLOBALCTX+1 + */ if (curctx != GLOBALCTX+1 || yytoken == ';') { - prototype(sym); + emit(ODECL, sym); + /* + * avoid non used warnings in prototypes + */ + for (p = sym->u.pars; p && *p; ++p) + (*p)->flags |= ISUSED; + popctx(); expect(';'); + free(sym->u.pars); + sym->u.pars = NULL; + curfun = ocurfun; return; } + if (sym->type->k_r) { + while (yytoken != '{') { + par = dodcl(1, parameter, NS_IDEN, sym->type); + expect(';'); + } + } if (sym->flags & ISTYPEDEF) errorp("function definition declared 'typedef'"); @@ -811,14 +865,13 @@ decl(void) sym->flags &= ~ISEXTERN; sym->flags |= ISGLOBAL; } + sym->flags |= ISDEFINED; sym->flags &= ~ISEMITTED; - curfun = sym; emit(OFUN, sym); - free(sym->u.pars); compound(NULL, NULL, NULL); emit(OEFUN, NULL); - curfun = NULL; + curfun = ocurfun; } static void diff --git a/cc1/expr.c b/cc1/expr.c @@ -339,9 +339,9 @@ arithmetic(char op, Node *lp, Node *rp) if (ltp->arith && rtp->arith) { arithconv(&lp, &rp); } else if ((ltp->op == PTR || rtp->op == PTR) && - op == OADD || op == OSUB) { + (op == OADD || op == OSUB)) { return parithmetic(op, rp, lp); - } else { + } else if (op != OINC && op != ODEC) { errorp("incorrect arithmetic operands"); } return simplify(op, lp->type, lp, rp); diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -111,6 +111,10 @@ popctx(void) killsym(sym); } labels = NULL; + if (curfun) { + free(curfun->u.pars); + curfun->u.pars = NULL; + } } for (sym = head; sym && sym->ctx > curctx; sym = next) { diff --git a/cc1/types.c b/cc1/types.c @@ -436,11 +436,15 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[]) Type **tbl, type; unsigned t; Type *bp; - int c; + int c, k_r = 0; if (op == PTR && tp == voidtype) return pvoidtype; + if (op == KRFTN) { + k_r = 1; + op = FTN; + } switch (op) { case PTR: c = L_POINTER; break; case ARY: c = L_ARRAY; break; @@ -458,6 +462,7 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[]) type.integer = 0; type.printed = 0; type.aggreg = 0; + type.k_r = k_r; type.letter = c; type.p.pars = pars; type.n.elem = nelem;