[hackers] [scc] Add support for k&r functions || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Mon, 11 Jan 2016 10:17:13 +0100 (CET)

commit 2fae9d998da0050e988c600e6581a076441382ef
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Mon Jan 11 10:10:40 2016 +0100
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Mon Jan 11 10:10:40 2016 +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.

diff --git a/cc1/cc1.h b/cc1/cc1.h
index 391b995..73a76fb 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
_AT_@ -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 */
_AT_@ -134,7 +135,8 @@ enum {
 enum {
         FTN = 1,
         PTR,
- ARY
+ ARY,
+ KRFTN
 };
 
 /* namespaces */
diff --git a/cc1/code.c b/cc1/code.c
index 4d1441b..e62619f 100644
--- a/cc1/code.c
+++ b/cc1/code.c
_AT_@ -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
index f5a43f1..2858c9d 100644
--- a/cc1/decl.c
+++ b/cc1/decl.c
_AT_@ -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 **);
_AT_@ -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;
_AT_@ -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;
                 }
_AT_@ -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;
 }
_AT_@ -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);
_AT_@ -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'");
_AT_@ -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
index ed8eb63..9702950 100644
--- a/cc1/expr.c
+++ b/cc1/expr.c
_AT_@ -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
index 8ca6d92..47795c3 100644
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
_AT_@ -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
index 1607bd4..b213407 100644
--- a/cc1/types.c
+++ b/cc1/types.c
_AT_@ -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;
_AT_@ -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;
Received on Mon Jan 11 2016 - 10:17:13 CET

This archive was generated by hypermail 2.3.0 : Mon Jan 11 2016 - 10:24:25 CET