* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / lcc / src / .svn / text-base / decl.c.svn-base
blob132241edf63887a22827013977926aeb1b819361
1 #include "c.h"
4 #define add(x,n) (x > inttype->u.sym->u.limits.max.i-(n) ? (overflow=1,x) : x+(n))
5 #define chkoverflow(x,n) ((void)add(x,n))
6 #define bits2bytes(n) (((n) + 7)/8)
7 static int regcount;
9 static List autos, registers;
10 Symbol cfunc;           /* current function */
11 Symbol retv;            /* return value location for structs */
13 static void checkref(Symbol, void *);
14 static Symbol dclglobal(int, char *, Type, Coordinate *);
15 static Symbol dcllocal(int, char *, Type, Coordinate *);
16 static Symbol dclparam(int, char *, Type, Coordinate *);
17 static Type dclr(Type, char **, Symbol **, int);
18 static Type dclr1(char **, Symbol **, int);
19 static void decl(Symbol (*)(int, char *, Type, Coordinate *));
20 extern void doconst(Symbol, void *);
21 static void doglobal(Symbol, void *);
22 static void doextern(Symbol, void *);
23 static void exitparams(Symbol []);
24 static void fields(Type);
25 static void funcdefn(int, char *, Type, Symbol [], Coordinate);
26 static void initglobal(Symbol, int);
27 static void oldparam(Symbol, void *);
28 static Symbol *parameters(Type);
29 static Type specifier(int *);
30 static Type structdcl(int);
31 static Type tnode(int, Type);
32 void program(void) {
33         int n;
34         
35         level = GLOBAL;
36         for (n = 0; t != EOI; n++)
37                 if (kind[t] == CHAR || kind[t] == STATIC
38                 || t == ID || t == '*' || t == '(') {
39                         decl(dclglobal);
40                         deallocate(STMT);
41                         if (!(glevel >= 3 || xref))
42                         deallocate(FUNC);
43                 } else if (t == ';') {
44                         warning("empty declaration\n");
45                         t = gettok();
46                 } else {
47                         error("unrecognized declaration\n");
48                         t = gettok();
49                 }
50         if (n == 0)
51                 warning("empty input file\n");
53 static Type specifier(int *sclass) {
54         int cls, cons, sign, size, type, vol;
55         Type ty = NULL;
57         cls = vol = cons = sign = size = type = 0;
58         if (sclass == NULL)
59                 cls = AUTO;
60         for (;;) {
61                 int *p, tt = t;
62                 switch (t) {
63                 case AUTO:
64                 case REGISTER: if (level <= GLOBAL && cls == 0)
65                                 error("invalid use of `%k'\n", t);
66                                p = &cls;  t = gettok();      break;
67                 case STATIC: case EXTERN:
68                 case TYPEDEF:  p = &cls;  t = gettok();      break;
69                 case CONST:    p = &cons; t = gettok();      break;
70                 case VOLATILE: p = &vol;  t = gettok();      break;
71                 case SIGNED:
72                 case UNSIGNED: p = &sign; t = gettok();      break;
73                 case LONG:     if (size == LONG) {
74                                        size = 0;
75                                        tt = LONG+LONG;
76                                }
77                                p = &size; t = gettok();      break;
78                 case SHORT:    p = &size; t = gettok();      break;
79                 case VOID: case CHAR: case INT: case FLOAT:
80                 case DOUBLE:   p = &type; ty = tsym->type;
81                                           t = gettok();      break;
82                 case ENUM:     p = &type; ty = enumdcl();    break;
83                 case STRUCT:
84                 case UNION:    p = &type; ty = structdcl(t); break;
85                 case ID:
86                         if (istypename(t, tsym) && type == 0
87                         && sign == 0 && size == 0) {
88                                 use(tsym, src);
89                                 ty = tsym->type;
90                                 if (isqual(ty)
91                                 && ty->size != ty->type->size) {
92                                         ty = unqual(ty);
93                                         if (isconst(tsym->type))
94                                                 ty = qual(CONST, ty);
95                                         if (isvolatile(tsym->type))
96                                                 ty = qual(VOLATILE, ty);
97                                         tsym->type = ty;
98                                 }
99                                 p = &type;
100                                 t = gettok();
101                         } else
102                                 p = NULL;
103                         break;
104                 default: p = NULL;
105                 }
106                 if (p == NULL)
107                         break;
108                 if (*p)
109                         error("invalid use of `%k'\n", tt);
110                 *p = tt;
111         }
112         if (sclass)
113                 *sclass = cls;
114         if (type == 0) {
115                 type = INT;
116                 ty = inttype;
117         }
118         if ((size == SHORT     && type != INT)
119         ||  (size == LONG+LONG && type != INT)
120         ||  (size == LONG      && type != INT && type != DOUBLE)
121         ||  (sign && type != INT && type != CHAR))
122                 error("invalid type specification\n");
123         if (type == CHAR && sign)
124                 ty = sign == UNSIGNED ? unsignedchar : signedchar;
125         else if (size == SHORT)
126                 ty = sign == UNSIGNED ? unsignedshort : shorttype;
127         else if (size == LONG && type == DOUBLE)
128                 ty = longdouble;
129         else if (size == LONG+LONG) {
130                 ty = sign == UNSIGNED ? unsignedlonglong : longlong;
131                 if (Aflag >= 1)
132                         warning("`%t' is a non-ANSI type\n", ty);
133         } else if (size == LONG)
134                 ty = sign == UNSIGNED ? unsignedlong : longtype;
135         else if (sign == UNSIGNED && type == INT)
136                 ty = unsignedtype;
137         if (cons == CONST)
138                 ty = qual(CONST, ty);
139         if (vol  == VOLATILE)
140                 ty = qual(VOLATILE, ty);
141         return ty;
143 static void decl(Symbol (*dcl)(int, char *, Type, Coordinate *)) {
144         int sclass;
145         Type ty, ty1;
146         static char stop[] = { CHAR, STATIC, ID, 0 };
148         ty = specifier(&sclass);
149         if (t == ID || t == '*' || t == '(' || t == '[') {
150                 char *id;
151                 Coordinate pos;
152                 id = NULL;
153                 pos = src;
154                 if (level == GLOBAL) {
155                         Symbol *params = NULL;
156                         ty1 = dclr(ty, &id, &params, 0);
157                         if (params && id && isfunc(ty1)
158                             && (t == '{' || istypename(t, tsym)
159                             || (kind[t] == STATIC && t != TYPEDEF))) {
160                                 if (sclass == TYPEDEF) {
161                                         error("invalid use of `typedef'\n");
162                                         sclass = EXTERN;
163                                 }
164                                 if (ty1->u.f.oldstyle)
165                                         exitscope();
166                                 funcdefn(sclass, id, ty1, params, pos);
167                                 return;
168                         } else if (params)
169                                 exitparams(params);
170                 } else
171                         ty1 = dclr(ty, &id, NULL, 0);
172                 for (;;) {
173                         if (Aflag >= 1 && !hasproto(ty1))
174                                 warning("missing prototype\n");
175                         if (id == NULL)
176                                 error("missing identifier\n");
177                         else if (sclass == TYPEDEF)
178                                 {
179                                         Symbol p = lookup(id, identifiers);
180                                         if (p && p->scope == level)
181                                                 error("redeclaration of `%s'\n", id);
182                                         p = install(id, &identifiers, level,
183                                                 level < LOCAL ? PERM : FUNC);
184                                         p->type = ty1;
185                                         p->sclass = TYPEDEF;
186                                         p->src = pos;
187                                 }
188                         else
189                                 (void)(*dcl)(sclass, id, ty1, &pos);
190                         if (t != ',')
191                                 break;
192                         t = gettok();
193                         id = NULL;
194                         pos = src;
195                         ty1 = dclr(ty, &id, NULL, 0);
196                 }
197         } else if (ty == NULL
198         || !(isenum(ty) ||
199              (isstruct(ty) && (*unqual(ty)->u.sym->name < '1' || *unqual(ty)->u.sym->name > '9'))))
200                 error("empty declaration\n");
201         test(';', stop);
203 static Symbol dclglobal(int sclass, char *id, Type ty, Coordinate *pos) {
204         Symbol p;
206         if (sclass == 0)
207                 sclass = AUTO;
208         else if (sclass != EXTERN && sclass != STATIC) {
209                 error("invalid storage class `%k' for `%t %s'\n",
210                         sclass, ty, id);
211                 sclass = AUTO;
212         }
213         p = lookup(id, identifiers);
214         if (p && p->scope == GLOBAL) {
215                 if (p->sclass != TYPEDEF && eqtype(ty, p->type, 1))
216                         ty = compose(ty, p->type);
217                 else
218                         error("redeclaration of `%s' previously declared at %w\n", p->name, &p->src);
220                 if (!isfunc(ty) && p->defined && t == '=')
221                         error("redefinition of `%s' previously defined at %w\n", p->name, &p->src);
223                 if ((p->sclass == EXTERN && sclass == STATIC)
224                 ||  (p->sclass == STATIC && sclass == AUTO)
225                 ||  (p->sclass == AUTO   && sclass == STATIC))
226                         warning("inconsistent linkage for `%s' previously declared at %w\n", p->name, &p->src);
228         }
229         if (p == NULL || p->scope != GLOBAL) {
230                 Symbol q = lookup(id, externals);
231                 if (q) {
232                         if (sclass == STATIC || !eqtype(ty, q->type, 1))
233                                 warning("declaration of `%s' does not match previous declaration at %w\n", id, &q->src);
235                         p = relocate(id, externals, globals);
236                         p->sclass = sclass;
237                 } else {
238                         p = install(id, &globals, GLOBAL, PERM);
239                         p->sclass = sclass;
240                         (*IR->defsymbol)(p);
241                 }
242                 if (p->sclass != STATIC) {
243                         static int nglobals;
244                         nglobals++;
245                         if (Aflag >= 2 && nglobals == 512)
246                                 warning("more than 511 external identifiers\n");
247                 }
248         } else if (p->sclass == EXTERN)
249                 p->sclass = sclass;
250         p->type = ty;
251         p->src = *pos;
252         if (t == '=' && isfunc(p->type)) {
253                 error("illegal initialization for `%s'\n", p->name);
254                 t = gettok();
255                 initializer(p->type, 0);
256         } else if (t == '=') {
257                 initglobal(p, 0);
258                 if (glevel > 0 && IR->stabsym) {
259                         (*IR->stabsym)(p); swtoseg(p->u.seg); }
260         } else if (p->sclass == STATIC && !isfunc(p->type)
261         && p->type->size == 0)
262                 error("undefined size for `%t %s'\n", p->type, p->name);
263         return p;
265 static void initglobal(Symbol p, int flag) {
266         Type ty;
268         if (t == '=' || flag) {
269                 if (p->sclass == STATIC) {
270                         for (ty = p->type; isarray(ty); ty = ty->type)
271                                 ;
272                         defglobal(p, isconst(ty) ? LIT : DATA);
273                 } else
274                         defglobal(p, DATA);
275                 if (t == '=')
276                         t = gettok();
277                 ty = initializer(p->type, 0);
278                 if (isarray(p->type) && p->type->size == 0)
279                         p->type = ty;
280                 if (p->sclass == EXTERN)
281                         p->sclass = AUTO;
282         }
284 void defglobal(Symbol p, int seg) {
285         p->u.seg = seg;
286         swtoseg(p->u.seg);
287         if (p->sclass != STATIC)
288                 (*IR->export)(p);
289         (*IR->global)(p);
290         p->defined = 1;
293 static Type dclr(Type basety, char **id, Symbol **params, int abstract) {
294         Type ty = dclr1(id, params, abstract);
296         for ( ; ty; ty = ty->type)
297                 switch (ty->op) {
298                 case POINTER:
299                         basety = ptr(basety);
300                         break;
301                 case FUNCTION:
302                         basety = func(basety, ty->u.f.proto,
303                                 ty->u.f.oldstyle);
304                         break;
305                 case ARRAY:
306                         basety = array(basety, ty->size, 0);
307                         break;
308                 case CONST: case VOLATILE:
309                         basety = qual(ty->op, basety);
310                         break;
311                 default: assert(0);
312                 }
313         if (Aflag >= 2 && basety->size > 32767)
314                 warning("more than 32767 bytes in `%t'\n", basety);
315         return basety;
317 static Type tnode(int op, Type type) {
318         Type ty;
320         NEW0(ty, STMT);
321         ty->op = op;
322         ty->type = type;
323         return ty;
325 static Type dclr1(char **id, Symbol **params, int abstract) {
326         Type ty = NULL;
328         switch (t) {
329         case ID:                if (id)
330                                         *id = token;
331                                 else
332                                         error("extraneous identifier `%s'\n", token);
333                                 t = gettok(); break;
334         case '*': t = gettok(); if (t == CONST || t == VOLATILE) {
335                                         Type ty1;
336                                         ty1 = ty = tnode(t, NULL);
337                                         while ((t = gettok()) == CONST || t == VOLATILE)
338                                                 ty1 = tnode(t, ty1);
339                                         ty->type = dclr1(id, params, abstract);
340                                         ty = ty1;
341                                 } else
342                                         ty = dclr1(id, params, abstract);
343                                 ty = tnode(POINTER, ty); break;
344         case '(': t = gettok(); if (abstract
345                                 && (t == REGISTER || istypename(t, tsym) || t == ')')) {
346                                         Symbol *args;
347                                         ty = tnode(FUNCTION, ty);
348                                         enterscope();
349                                         if (level > PARAM)
350                                                 enterscope();
351                                         args = parameters(ty);
352                                         exitparams(args);
353                                 } else {
354                                         ty = dclr1(id, params, abstract);
355                                         expect(')');
356                                         if (abstract && ty == NULL
357                                         && (id == NULL || *id == NULL))
358                                                 return tnode(FUNCTION, NULL);
359                                 } break;
360         case '[': break;
361         default:  return ty;
362         }
363         while (t == '(' || t == '[')
364                 switch (t) {
365                 case '(': t = gettok(); { Symbol *args;
366                                           ty = tnode(FUNCTION, ty);
367                                           enterscope();
368                                           if (level > PARAM)
369                                                 enterscope();
370                                           args = parameters(ty);
371                                           if (params && *params == NULL)
372                                                 *params = args;
373                                           else
374                                                 exitparams(args);
376                           break;
377                 case '[': t = gettok(); { int n = 0;
378                                           if (kind[t] == ID) {
379                                                 n = intexpr(']', 1);
380                                                 if (n <= 0) {
381                                                         error("`%d' is an illegal array size\n", n);
382                                                         n = 1;
383                                                 }
384                                           } else
385                                                 expect(']');
386                                           ty = tnode(ARRAY, ty);
387                                           ty->size = n; } break;
388                 default: assert(0);
389                 }
390         return ty;
392 static Symbol *parameters(Type fty) {
393         List list = NULL;
394         Symbol *params;
396         if (kind[t] == STATIC || istypename(t, tsym)) {
397                 int n = 0;
398                 Type ty1 = NULL;
399                 for (;;) {
400                         Type ty;
401                         int sclass = 0;
402                         char *id = NULL;
403                         if (ty1 && t == ELLIPSIS) {
404                                 static struct symbol sentinel;
405                                 if (sentinel.type == NULL) {
406                                         sentinel.type = voidtype;
407                                         sentinel.defined = 1;
408                                 }
409                                 if (ty1 == voidtype)
410                                         error("illegal formal parameter types\n");
411                                 list = append(&sentinel, list);
412                                 t = gettok();
413                                 break;
414                         }
415                         if (!istypename(t, tsym) && t != REGISTER)
416                                 error("missing parameter type\n");
417                         n++;
418                         ty = dclr(specifier(&sclass), &id, NULL, 1);
419                         if ( (ty == voidtype && (ty1 || id))
420                         ||  ty1 == voidtype)
421                                 error("illegal formal parameter types\n");
422                         if (id == NULL)
423                                 id = stringd(n);
424                         if (ty != voidtype)
425                                 list = append(dclparam(sclass, id, ty, &src), list);
426                         if (Aflag >= 1 && !hasproto(ty))
427                                 warning("missing prototype\n");
428                         if (ty1 == NULL)
429                                 ty1 = ty;
430                         if (t != ',')
431                                 break;
432                         t = gettok();
433                 }
434                 fty->u.f.proto = newarray(length(list) + 1,
435                         sizeof (Type *), PERM);
436                 params = ltov(&list, FUNC);
437                 for (n = 0; params[n]; n++)
438                         fty->u.f.proto[n] = params[n]->type;
439                 fty->u.f.proto[n] = NULL;
440                 fty->u.f.oldstyle = 0;
441         } else {
442                 if (t == ID)
443                         for (;;) {
444                                 Symbol p;
445                                 if (t != ID) {
446                                         error("expecting an identifier\n");
447                                         break;
448                                 }
449                                 p = dclparam(0, token, inttype, &src);
450                                 p->defined = 0;
451                                 list = append(p, list);
452                                 t = gettok();
453                                 if (t != ',')
454                                         break;
455                                 t = gettok();
456                         }
457                 params = ltov(&list, FUNC);
458                 fty->u.f.proto = NULL;
459                 fty->u.f.oldstyle = 1;
460         }
461         if (t != ')') {
462                 static char stop[] = { CHAR, STATIC, IF, ')', 0 };
463                 expect(')');
464                 skipto('{', stop);
465         }
466         if (t == ')')
467                 t = gettok();
468         return params;
470 static void exitparams(Symbol params[]) {
471         assert(params);
472         if (params[0] && !params[0]->defined)
473                 error("extraneous old-style parameter list\n");
474         if (level > PARAM)
475                 exitscope();
476         exitscope();
479 static Symbol dclparam(int sclass, char *id, Type ty, Coordinate *pos) {
480         Symbol p;
482         if (isfunc(ty))
483                 ty = ptr(ty);
484         else if (isarray(ty))
485                 ty = atop(ty);
486         if (sclass == 0)
487                 sclass = AUTO;
488         else if (sclass != REGISTER) {
489                 error("invalid storage class `%k' for `%t%s\n",
490                         sclass, ty, stringf(id ? " %s'" : "' parameter", id));
491                 sclass = AUTO;
492         } else if (isvolatile(ty) || isstruct(ty)) {
493                 warning("register declaration ignored for `%t%s\n",
494                         ty, stringf(id ? " %s'" : "' parameter", id));
495                 sclass = AUTO;
496         }
498         p = lookup(id, identifiers);
499         if (p && p->scope == level)
500                 error("duplicate declaration for `%s' previously declared at %w\n", id, &p->src);
502         else
503                 p = install(id, &identifiers, level, FUNC);
504         p->sclass = sclass;
505         p->src = *pos;
506         p->type = ty;
507         p->defined = 1;
508         if (t == '=') {
509                 error("illegal initialization for parameter `%s'\n", id);
510                 t = gettok();
511                 (void)expr1(0);
512         }
513         return p;
515 static Type structdcl(int op) {
516         char *tag;
517         Type ty;
518         Symbol p;
519         Coordinate pos;
521         t = gettok();
522         pos = src;
523         if (t == ID) {
524                 tag = token;
525                 t = gettok();
526         } else
527                 tag = "";
528         if (t == '{') {
529                 static char stop[] = { IF, ',', 0 };
530                 ty = newstruct(op, tag);
531                 ty->u.sym->src = pos;
532                 ty->u.sym->defined = 1;
533                 t = gettok();
534                 if (istypename(t, tsym))
535                         fields(ty);
536                 else
537                         error("invalid %k field declarations\n", op);
538                 test('}', stop);
539         }
540         else if (*tag && (p = lookup(tag, types)) != NULL
541         && p->type->op == op) {
542                 ty = p->type;
543                 if (t == ';' && p->scope < level)
544                         ty = newstruct(op, tag);
545         }
546         else {
547                 if (*tag == 0)
548                         error("missing %k tag\n", op);
549                 ty = newstruct(op, tag);
550         }
551         if (*tag && xref)
552                 use(ty->u.sym, pos);
553         return ty;
555 static void fields(Type ty) {
556         { int n = 0;
557           while (istypename(t, tsym)) {
558                 static char stop[] = { IF, CHAR, '}', 0 };
559                 Type ty1 = specifier(NULL);
560                 for (;;) {
561                         Field p;
562                         char *id = NULL;
563                         Type fty = dclr(ty1, &id, NULL, 0);
564                         p = newfield(id, ty, fty);
565                         if (Aflag >= 1 && !hasproto(p->type))
566                                 warning("missing prototype\n");
567                         if (t == ':') {
568                                 if (unqual(p->type) != inttype
569                                 &&  unqual(p->type) != unsignedtype) {
570                                         error("`%t' is an illegal bit-field type\n",
571                                                 p->type);
572                                         p->type = inttype;
573                                 }
574                                 t = gettok();
575                                 p->bitsize = intexpr(0, 0);
576                                 if (p->bitsize > 8*inttype->size || p->bitsize < 0) {
577                                         error("`%d' is an illegal bit-field size\n",
578                                                 p->bitsize);
579                                         p->bitsize = 8*inttype->size;
580                                 } else if (p->bitsize == 0 && id) {
581                                         warning("extraneous 0-width bit field `%t %s' ignored\n", p->type, id);
583                                         p->name = stringd(genlabel(1));
584                                 }
585                                 p->lsb = 1;
586                         }
587                         else {
588                                 if (id == NULL)
589                                         error("field name missing\n");
590                                 else if (isfunc(p->type))
591                                         error("`%t' is an illegal field type\n", p->type);
592                                 else if (p->type->size == 0)
593                                         error("undefined size for field `%t %s'\n",
594                                                 p->type, id);
595                         }
596                         if (isconst(p->type))
597                                 ty->u.sym->u.s.cfields = 1;
598                         if (isvolatile(p->type))
599                                 ty->u.sym->u.s.vfields = 1;
600                         n++;
601                         if (Aflag >= 2 && n == 128)
602                                 warning("more than 127 fields in `%t'\n", ty);
603                         if (t != ',')
604                                 break;
605                         t = gettok();
606                 }
607                 test(';', stop);
608           } }
609         { int bits = 0, off = 0, overflow = 0;
610           Field p, *q = &ty->u.sym->u.s.flist;
611           ty->align = IR->structmetric.align;
612           for (p = *q; p; p = p->link) {
613                 int a = p->type->align ? p->type->align : 1;
614                 if (p->lsb)
615                         a = unsignedtype->align;
616                 if (ty->op == UNION)
617                         off = bits = 0;
618                 else if (p->bitsize == 0 || bits == 0
619                 || bits - 1 + p->bitsize > 8*unsignedtype->size) {
620                         off = add(off, bits2bytes(bits-1));
621                         bits = 0;
622                         chkoverflow(off, a - 1);
623                         off = roundup(off, a);
624                 }
625                 if (a > ty->align)
626                         ty->align = a;
627                 p->offset = off;
629                 if (p->lsb) {
630                         if (bits == 0)
631                                 bits = 1;
632                         if (IR->little_endian)
633                                 p->lsb = bits;
634                         else
635                                 p->lsb = 8*unsignedtype->size - bits + 1
636                                         - p->bitsize + 1;
637                         bits += p->bitsize;
638                 } else
639                         off = add(off, p->type->size);
640                 if (off + bits2bytes(bits-1) > ty->size)
641                         ty->size = off + bits2bytes(bits-1);
642                 if (p->name == NULL
643                 || !('1' <= *p->name && *p->name <= '9')) {
644                         *q = p;
645                         q = &p->link;
646                 }
647           }
648           *q = NULL;
649           chkoverflow(ty->size, ty->align - 1);
650           ty->size = roundup(ty->size, ty->align);
651           if (overflow) {
652                 error("size of `%t' exceeds %d bytes\n", ty, inttype->u.sym->u.limits.max.i);
653                 ty->size = inttype->u.sym->u.limits.max.i&(~(ty->align - 1));
654           } }
656 static void funcdefn(int sclass, char *id, Type ty, Symbol params[], Coordinate pt) {
657         int i, n;
658         Symbol *callee, *caller, p;
659         Type rty = freturn(ty);
661         if (isstruct(rty) && rty->size == 0)
662                 error("illegal use of incomplete type `%t'\n", rty);
663         for (n = 0; params[n]; n++)
664                 ;
665         if (n > 0 && params[n-1]->name == NULL)
666                 params[--n] = NULL;
667         if (Aflag >= 2 && n > 31)
668                 warning("more than 31 parameters in function `%s'\n", id);
669         if (ty->u.f.oldstyle) {
670                 if (Aflag >= 1)
671                         warning("old-style function definition for `%s'\n", id);
672                 caller = params;
673                 callee = newarray(n + 1, sizeof *callee, FUNC);
674                 memcpy(callee, caller, (n+1)*sizeof *callee);
675                 enterscope();
676                 assert(level == PARAM);
677                 while (kind[t] == STATIC || istypename(t, tsym))
678                         decl(dclparam);
679                 foreach(identifiers, PARAM, oldparam, callee);
681                 for (i = 0; (p = callee[i]) != NULL; i++) {
682                         if (!p->defined)
683                                 callee[i] = dclparam(0, p->name, inttype, &p->src);
684                         *caller[i] = *p;
685                         caller[i]->sclass = AUTO;
686                         caller[i]->type = promote(p->type);
687                 }
688                 p = lookup(id, identifiers);
689                 if (p && p->scope == GLOBAL && isfunc(p->type)
690                 && p->type->u.f.proto) {
691                         Type *proto = p->type->u.f.proto;
692                         for (i = 0; caller[i] && proto[i]; i++) {
693                                 Type ty = unqual(proto[i]);
694                                 if (eqtype(isenum(ty) ? ty->type : ty,
695                                         unqual(caller[i]->type), 1) == 0)
696                                         break;
697                                 else if (isenum(ty) && !isenum(unqual(caller[i]->type)))
698                                         warning("compatibility of `%t' and `%t' is compiler dependent\n",
699                                                 proto[i], caller[i]->type);
700                         }
701                         if (proto[i] || caller[i])
702                                 error("conflicting argument declarations for function `%s'\n", id);
704                 }
705                 else {
706                         Type *proto = newarray(n + 1, sizeof *proto, PERM);
707                         if (Aflag >= 1)
708                                 warning("missing prototype for `%s'\n", id);
709                         for (i = 0; i < n; i++)
710                                 proto[i] = caller[i]->type;
711                         proto[i] = NULL;
712                         ty = func(rty, proto, 1);
713                 }
714         } else {
715                 callee = params;
716                 caller = newarray(n + 1, sizeof *caller, FUNC);
717                 for (i = 0; (p = callee[i]) != NULL && p->name; i++) {
718                         NEW(caller[i], FUNC);
719                         *caller[i] = *p;
720                         if (isint(p->type))
721                                 caller[i]->type = promote(p->type);
722                         caller[i]->sclass = AUTO;
723                         if ('1' <= *p->name && *p->name <= '9')
724                                 error("missing name for parameter %d to function `%s'\n", i + 1, id);
726                 }
727                 caller[i] = NULL;
728         }
729         for (i = 0; (p = callee[i]) != NULL; i++)
730                 if (p->type->size == 0) {
731                         error("undefined size for parameter `%t %s'\n",
732                                 p->type, p->name);
733                         caller[i]->type = p->type = inttype;
734                 }
735         if (Aflag >= 2 && sclass != STATIC && strcmp(id, "main") == 0) {
736                 if (ty->u.f.oldstyle)
737                         warning("`%t %s()' is a non-ANSI definition\n", rty, id);
738                 else if (!(rty == inttype
739                         && ((n == 0 && callee[0] == NULL)
740                         ||  (n == 2 && callee[0]->type == inttype
741                         && isptr(callee[1]->type) && callee[1]->type->type == charptype
742                         && !variadic(ty)))))
743                         warning("`%s' is a non-ANSI definition\n", typestring(ty, id));
744         }
745         p = lookup(id, identifiers);
746         if (p && isfunc(p->type) && p->defined)
747                 error("redefinition of `%s' previously defined at %w\n",
748                         p->name, &p->src);
749         cfunc = dclglobal(sclass, id, ty, &pt);
750         cfunc->u.f.label = genlabel(1);
751         cfunc->u.f.callee = callee;
752         cfunc->u.f.pt = src;
753         cfunc->defined = 1;
754         if (xref)
755                 use(cfunc, cfunc->src);
756         if (Pflag)
757                 printproto(cfunc, cfunc->u.f.callee);
758         if (ncalled >= 0)
759                 ncalled = findfunc(cfunc->name, pt.file);
760         labels   = table(NULL, LABELS);
761         stmtlabs = table(NULL, LABELS);
762         refinc = 1.0;
763         regcount = 0;
764         codelist = &codehead;
765         codelist->next = NULL;
766         if (!IR->wants_callb && isstruct(rty))
767                 retv = genident(AUTO, ptr(rty), PARAM);
768         compound(0, NULL, 0);
770         {
771                 Code cp;
772                 for (cp = codelist; cp->kind < Label; cp = cp->prev)
773                         ;
774                 if (cp->kind != Jump) {
775                         if (rty != voidtype) {
776                                 warning("missing return value\n");
777                                 retcode(cnsttree(inttype, 0L));
778                         } else
779                                 retcode(NULL);
780                 }
781         }
782         definelab(cfunc->u.f.label);
783         if (events.exit)
784                 apply(events.exit, cfunc, NULL);
785         walk(NULL, 0, 0);
786         exitscope();
787         assert(level == PARAM);
788         foreach(identifiers, level, checkref, NULL);
789         if (!IR->wants_callb && isstruct(rty)) {
790                 Symbol *a;
791                 a = newarray(n + 2, sizeof *a, FUNC);
792                 a[0] = retv;
793                 memcpy(&a[1], callee, (n+1)*sizeof *callee);
794                 callee = a;
795                 a = newarray(n + 2, sizeof *a, FUNC);
796                 NEW(a[0], FUNC);
797                 *a[0] = *retv;
798                 memcpy(&a[1], caller, (n+1)*sizeof *callee);
799                 caller = a;
800         }
801         if (!IR->wants_argb)
802                 for (i = 0; caller[i]; i++)
803                         if (isstruct(caller[i]->type)) {
804                                 caller[i]->type = ptr(caller[i]->type);
805                                 callee[i]->type = ptr(callee[i]->type);
806                                 caller[i]->structarg = callee[i]->structarg = 1;
807                         }
808         if (glevel > 1) for (i = 0; callee[i]; i++) callee[i]->sclass = AUTO;
809         if (cfunc->sclass != STATIC)
810                 (*IR->export)(cfunc);
811         if (glevel && IR->stabsym) {
812                 swtoseg(CODE); (*IR->stabsym)(cfunc); }
813         swtoseg(CODE);
814         (*IR->function)(cfunc, caller, callee, cfunc->u.f.ncalls);
815         if (glevel && IR->stabfend)
816                 (*IR->stabfend)(cfunc, lineno);
817         foreach(stmtlabs, LABELS, checklab, NULL);
818         exitscope();
819         expect('}');
820         labels = stmtlabs = NULL;
821         retv  = NULL;
822         cfunc = NULL;
824 static void oldparam(Symbol p, void *cl) {
825         int i;
826         Symbol *callee = cl;
828         for (i = 0; callee[i]; i++)
829                 if (p->name == callee[i]->name) {
830                         callee[i] = p;
831                         return;
832                 }
833         error("declared parameter `%s' is missing\n", p->name);
835 void compound(int loop, struct swtch *swp, int lev) {
836         Code cp;
837         int nregs;
839         walk(NULL, 0, 0);
840         cp = code(Blockbeg);
841         enterscope();
842         assert(level >= LOCAL);
843         if (level == LOCAL && events.entry)
844                 apply(events.entry, cfunc, NULL);
845         definept(NULL);
846         expect('{');
847         autos = registers = NULL;
848         if (level == LOCAL && IR->wants_callb
849         && isstruct(freturn(cfunc->type))) {
850                 retv = genident(AUTO, ptr(freturn(cfunc->type)), level);
851                 retv->defined = 1;
852                 retv->ref = 1;
853                 registers = append(retv, registers);
854         }
855         while (kind[t] == CHAR || kind[t] == STATIC
856         || (istypename(t, tsym) && getchr() != ':'))
857                 decl(dcllocal);
858         {
859                 int i;
860                 Symbol *a = ltov(&autos, STMT);
861                 nregs = length(registers);
862                 for (i = 0; a[i]; i++)
863                         registers = append(a[i], registers);
864                 cp->u.block.locals = ltov(&registers, FUNC);
865         }
866         if (events.blockentry)
867                 apply(events.blockentry, cp->u.block.locals, NULL);
868         while (kind[t] == IF || kind[t] == ID)
869                 statement(loop, swp, lev);
870         walk(NULL, 0, 0);
871         foreach(identifiers, level, checkref, NULL);
872         {
873                 int i = nregs, j;
874                 Symbol p;
875                 for ( ; (p = cp->u.block.locals[i]) != NULL; i++) {
876                         for (j = i; j > nregs
877                                 && cp->u.block.locals[j-1]->ref < p->ref; j--)
878                                 cp->u.block.locals[j] = cp->u.block.locals[j-1];
879                         cp->u.block.locals[j] = p;
880                 }
881         }
882         if (events.blockexit)
883                 apply(events.blockexit, cp->u.block.locals, NULL);
884         cp->u.block.level = level;
885         cp->u.block.identifiers = identifiers;
886         cp->u.block.types = types;
887         code(Blockend)->u.begin = cp;
888         if (reachable(Gen))
889                 definept(NULL);
890         if (level > LOCAL) {
891                 exitscope();
892                 expect('}');
893         }
895 static void checkref(Symbol p, void *cl) {
896         if (p->scope >= PARAM
897         && (isvolatile(p->type) || isfunc(p->type)))
898                 p->addressed = 1;
899         if (Aflag >= 2 && p->defined && p->ref == 0) {
900                 if (p->sclass == STATIC)
901                         warning("static `%t %s' is not referenced\n",
902                                 p->type, p->name);
903                 else if (p->scope == PARAM)
904                         warning("parameter `%t %s' is not referenced\n",
905                                 p->type, p->name);
906                 else if (p->scope >= LOCAL && p->sclass != EXTERN)
907                         warning("local `%t %s' is not referenced\n",
908                                 p->type, p->name);
909         }
910         if (p->sclass == AUTO
911         && ((p->scope  == PARAM && regcount == 0)
912          || p->scope  >= LOCAL)
913         && !p->addressed && isscalar(p->type) && p->ref >= 3.0)
914                 p->sclass = REGISTER;
915         if (level == GLOBAL && p->sclass == STATIC && !p->defined
916         && isfunc(p->type) && p->ref)
917                 error("undefined static `%t %s'\n", p->type, p->name);
918         assert(!(level == GLOBAL && p->sclass == STATIC && !p->defined && !isfunc(p->type)));
920 static Symbol dcllocal(int sclass, char *id, Type ty, Coordinate *pos) {
921         Symbol p, q;
923         if (sclass == 0)
924                 sclass = isfunc(ty) ? EXTERN : AUTO;
925         else if (isfunc(ty) && sclass != EXTERN) {
926                 error("invalid storage class `%k' for `%t %s'\n",
927                         sclass, ty, id);
928                 sclass = EXTERN;
929         } else if (sclass == REGISTER
930         && (isvolatile(ty) || isstruct(ty) || isarray(ty))) {
931                 warning("register declaration ignored for `%t %s'\n",
932                         ty, id);
933                 sclass = AUTO;
934         }
935         q = lookup(id, identifiers);
936         if ((q && q->scope >= level)
937         ||  (q && q->scope == PARAM && level == LOCAL)) {
938                 if (sclass == EXTERN && q->sclass == EXTERN
939                 && eqtype(q->type, ty, 1))
940                         ty = compose(ty, q->type);
941                 else
942                         error("redeclaration of `%s' previously declared at %w\n", q->name, &q->src);
943         }
945         assert(level >= LOCAL);
946         p = install(id, &identifiers, level, sclass == STATIC || sclass == EXTERN ? PERM : FUNC);
947         p->type = ty;
948         p->sclass = sclass;
949         p->src = *pos;
950         switch (sclass) {
951         case EXTERN:   q = lookup(id, globals);
952                        if (q == NULL || q->sclass == TYPEDEF || q->sclass == ENUM) {
953                         q = lookup(id, externals);
954                         if (q == NULL) {
955                                 q = install(p->name, &externals, GLOBAL, PERM);
956                                 q->type = p->type;
957                                 q->sclass = EXTERN;
958                                 q->src = src;
959                                 (*IR->defsymbol)(q);
960                         }
961                        }
962                        if (!eqtype(p->type, q->type, 1))
963                         warning("declaration of `%s' does not match previous declaration at %w\n", q->name, &q->src);
965                        p->u.alias = q; break;
966         case STATIC:   (*IR->defsymbol)(p);
967                        initglobal(p, 0);
968                        if (!p->defined) {
969                         if (p->type->size > 0) {
970                                 defglobal(p, BSS);
971                                 (*IR->space)(p->type->size);
972                         } else
973                                 error("undefined size for `%t %s'\n",
974                                         p->type, p->name);
975                        }
976                        p->defined = 1; break;
977         case REGISTER: registers = append(p, registers);
978                        regcount++;
979                        p->defined = 1;
980  break;
981         case AUTO:     autos = append(p, autos);
982                        p->defined = 1; break;
983         default: assert(0);
984         }
985         if (t == '=') {
986                 Tree e;
987                 if (sclass == EXTERN)
988                         error("illegal initialization of `extern %s'\n", id);
989                 t = gettok();
990                 definept(NULL);
991                 if (isscalar(p->type)
992                 ||  (isstruct(p->type) && t != '{')) {
993                         if (t == '{') {
994                                 t = gettok();
995                                 e = expr1(0);
996                                 expect('}');
997                         } else
998                                 e = expr1(0);
999                 } else {
1000                         Symbol t1;
1001                         Type ty = p->type, ty1 = ty;
1002                         while (isarray(ty1))
1003                                 ty1 = ty1->type;
1004                         if (!isconst(ty) && (!isarray(ty) || !isconst(ty1)))
1005                                 ty = qual(CONST, ty);
1006                         t1 = genident(STATIC, ty, GLOBAL);
1007                         initglobal(t1, 1);
1008                         if (isarray(p->type) && p->type->size == 0
1009                         && t1->type->size > 0)
1010                                 p->type = array(p->type->type,
1011                                         t1->type->size/t1->type->type->size, 0);
1012                         e = idtree(t1);
1013                 }
1014                 walk(root(asgn(p, e)), 0, 0);
1015                 p->ref = 1;
1016         }
1017         if (!isfunc(p->type) && p->defined && p->type->size <= 0)
1018                 error("undefined size for `%t %s'\n", p->type, id);
1019         return p;
1021 void finalize(void) {
1022         foreach(externals,   GLOBAL,    doextern, NULL);
1023         foreach(identifiers, GLOBAL,    doglobal, NULL);
1024         foreach(identifiers, GLOBAL,    checkref, NULL);
1025         foreach(constants,   CONSTANTS, doconst,  NULL);
1027 static void doextern(Symbol p, void *cl) {
1028         (*IR->import)(p);
1030 static void doglobal(Symbol p, void *cl) {
1031         if (!p->defined && (p->sclass == EXTERN
1032         || (isfunc(p->type) && p->sclass == AUTO)))
1033                 (*IR->import)(p);
1034         else if (!p->defined && !isfunc(p->type)
1035         && (p->sclass == AUTO || p->sclass == STATIC)) {
1036                 if (isarray(p->type)
1037                 && p->type->size == 0 && p->type->type->size > 0)
1038                         p->type = array(p->type->type, 1, 0);
1039                 if (p->type->size > 0) {
1040                         defglobal(p, BSS);
1041                         (*IR->space)(p->type->size);
1042                         if (glevel > 0 && IR->stabsym)
1043                                 (*IR->stabsym)(p);
1044                 } else
1045                         error("undefined size for `%t %s'\n",
1046                                 p->type, p->name);
1047                 p->defined = 1;
1048         }
1049         if (Pflag
1050         && !isfunc(p->type)
1051         && !p->generated && p->sclass != EXTERN)
1052                 printdecl(p, p->type);
1054 void doconst(Symbol p, void *cl) {
1055         if (p->u.c.loc) {
1056                 assert(p->u.c.loc->u.seg == 0); 
1057                 defglobal(p->u.c.loc, LIT);
1058                 if (isarray(p->type) && p->type->type == widechar) {
1059                         unsigned int *s = p->u.c.v.p;
1060                         int n = p->type->size/widechar->size;
1061                         while (n-- > 0) {
1062                                 Value v;
1063                                 v.u = *s++;
1064                                 (*IR->defconst)(widechar->op, widechar->size, v);
1065                         }
1066                 } else if (isarray(p->type))
1067                         (*IR->defstring)(p->type->size, p->u.c.v.p);
1068                 else
1069                         (*IR->defconst)(p->type->op, p->type->size, p->u.c.v);
1070                 p->u.c.loc = NULL;
1071         }
1073 void checklab(Symbol p, void *cl) {
1074         if (!p->defined)
1075                 error("undefined label `%s'\n", p->name);
1076         p->defined = 1;
1079 Type enumdcl(void) {
1080         char *tag;
1081         Type ty;
1082         Symbol p = {0};
1083         Coordinate pos;
1085         t = gettok();
1086         pos = src;
1087         if (t == ID) {
1088                 tag = token;
1089                 t = gettok();
1090         } else
1091                 tag = "";
1092         if (t == '{') {
1093                 static char follow[] = { IF, 0 };
1094                 int n = 0;
1095                 long k = -1;
1096                 List idlist = 0;
1097                 ty = newstruct(ENUM, tag);
1098                 t = gettok();
1099                 if (t != ID)
1100                         error("expecting an enumerator identifier\n");
1101                 while (t == ID) {
1102                         char *id = token;
1103                         Coordinate s;
1104                         if (tsym && tsym->scope == level)
1105                                 error("redeclaration of `%s' previously declared at %w\n",
1106                                         token, &tsym->src);
1107                         s = src;
1108                         t = gettok();
1109                         if (t == '=') {
1110                                 t = gettok();
1111                                 k = intexpr(0, 0);
1112                         } else {
1113                                 if (k == inttype->u.sym->u.limits.max.i)
1114                                         error("overflow in value for enumeration constant `%s'\n", id);
1115                                 k++;
1116                         }
1117                         p = install(id, &identifiers, level,  level < LOCAL ? PERM : FUNC);
1118                         p->src = s;
1119                         p->type = ty;
1120                         p->sclass = ENUM;
1121                         p->u.value = k;
1122                         idlist = append(p, idlist);
1123                         n++;
1124                         if (Aflag >= 2 && n == 128)
1125                                 warning("more than 127 enumeration constants in `%t'\n", ty);
1126                         if (t != ',')
1127                                 break;
1128                         t = gettok();
1129                         if (Aflag >= 2 && t == '}')
1130                                 warning("non-ANSI trailing comma in enumerator list\n");
1131                 }
1132                 test('}', follow);
1133                 ty->type = inttype;
1134                 ty->size = ty->type->size;
1135                 ty->align = ty->type->align;
1136                 ty->u.sym->u.idlist = ltov(&idlist, PERM);
1137                 ty->u.sym->defined = 1;
1138         } else if ((p = lookup(tag, types)) != NULL && p->type->op == ENUM) {
1139                 ty = p->type;
1140                 if (t == ';')
1141                         error("empty declaration\n");
1142         } else {
1143                 error("unknown enumeration `%s'\n",  tag);
1144                 ty = newstruct(ENUM, tag);
1145                 ty->type = inttype;
1146         }
1147         if (*tag && xref)
1148                 use(p, pos);
1149         return ty;
1152 Type typename(void) {
1153         Type ty = specifier(NULL);
1155         if (t == '*' || t == '(' || t == '[') {
1156                 ty = dclr(ty, NULL, NULL, 1);
1157                 if (Aflag >= 1 && !hasproto(ty))
1158                         warning("missing prototype\n");
1159         }
1160         return ty;