Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / l_outdef.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: l_outdef.c,v 1.7 1994/06/27 08:01:04 ceriel Exp $ */
6 /*      Lint outdef construction        */
7
8 #include        "lint.h"
9
10 #ifdef  LINT
11
12 #include        <alloc.h>
13 #include        "interface.h"
14 #ifdef ANSI
15 #include        <flt_arith.h>
16 #endif /* ANSI */
17 #include        "arith.h"
18 #include        "assert.h"
19 #include        "type.h"
20 #include        "proto.h"
21 #include        "declar.h"
22 #include        "decspecs.h"
23 #include        "LLlex.h"
24 #include        "Lpars.h"
25 #include        "stack.h"
26 #include        "def.h"
27 #include        "struct.h"
28 #include        "field.h"
29 #include        "idf.h"
30 #include        "level.h"
31 #include        "label.h"
32 #include        "code.h"
33 #include        "expr.h"
34 #include        "l_lint.h"
35 #include        "l_comment.h"
36 #include        "l_outdef.h"
37 #include        "l_class.h"
38
39 extern char *bts2str();
40 extern char *symbol2str();
41 extern char *strindex();
42
43 int stat_number = 9999;                 /* static scope number */
44 struct outdef OutDef;
45
46 PRIVATE struct outdef OutCall;
47
48 PRIVATE local_EFDC();
49 PRIVATE output_def();
50 PRIVATE outargs();
51 PRIVATE outarg();
52 PRIVATE outargstring();
53 PRIVATE outargtype();
54 PRIVATE add_expr_arg();
55 PRIVATE def2decl();
56
57 lint_declare_idf(idf, sc)
58         struct idf *idf;
59         int sc;
60 {
61         register struct def *def = idf->id_def;
62         register int is_function = def->df_type->tp_fund == FUNCTION;
63
64         if (level == L_GLOBAL) {
65                 lint_ext_def(idf, sc);
66                 if (is_function)
67                         def2decl(sc);
68                 if (sc != TYPEDEF)
69                         outdef();
70         }
71         else
72         if (level >= L_LOCAL && sc != STATIC && is_function) {
73                 local_EFDC(idf);
74         }
75 }
76
77 lint_non_function_decl(ds, dc)
78         struct decspecs *ds;
79         struct declarator *dc;
80 {
81         register struct def *def = dc->dc_idf->id_def;
82         register int is_function = def->df_type->tp_fund == FUNCTION;
83
84         if (is_function)
85                 def2decl(ds->ds_sc);
86         if (def->df_sc != TYPEDEF)
87                 outdef();
88 }
89
90 lint_ext_def(idf, sc)
91         struct idf *idf;
92 {
93 /* At this place the following fields of the output definition can be
94  * filled:
95  *              od_name, od_statnr, od_class, od_file, od_line, od_type.
96  * For variable definitions and declarations this will be all.
97  * For functions the fields od_nrargs and od_arg are filled after parsing
98  * the arguments.
99  * The od_valreturned field is known at the end of the function definition.
100  * sc indicates the storage class defined by the declaration specifier.
101  */
102         register struct def *def = idf->id_def;
103         register struct type *type = def->df_type;
104
105         OutDef.od_name = idf->id_text;
106         OutDef.od_statnr = (sc == STATIC ? stat_number : 0);
107
108         switch (type->tp_fund) {
109         case ERRONEOUS:
110                 OutDef.od_class = XXDF;
111                 break;
112         case FUNCTION:
113                 /* For the moment assume it will be a definition.
114                  * If no compound_statement follows, it is a declaration,
115                  * in which case the class will be adjusted by def2decl().
116                  */
117                 OutDef.od_class = (sc == STATIC ? SFDF : EFDF);
118                 break;
119         default:        /* a variable */
120                 OutDef.od_class =
121                         sc == EXTERN ? EVDC :
122                         sc == STATIC ? SVDF : EVDF;
123                 break;
124         }
125         OutDef.od_file = def->df_file;
126         OutDef.od_line = def->df_line;
127         OutDef.od_type = (type->tp_fund == FUNCTION ? type->tp_up : type);
128         OutDef.od_valreturned = NORETURN;
129 }
130
131 PRIVATE
132 def2decl(sc)
133         int sc;
134 {
135 /* It was assumed we were parsing a function definition.
136  * There was no compound statement following, so actually it was a
137  * declaration. This function updates the class.
138  */
139         OutDef.od_class = (sc == STATIC ? XXDF : EFDC);
140 }
141
142 set_od_valreturned(n)
143 {
144         OutDef.od_valreturned = n;
145 }
146
147 PRIVATE
148 local_EFDC(idf)
149         struct idf *idf;
150 {
151         struct outdef od;
152
153         od.od_class = EFDC;
154         od.od_statnr = 0;
155         od.od_name = idf->id_text;
156         od.od_file = idf->id_def->df_file;
157         od.od_line = idf->id_def->df_line;
158         od.od_type = idf->id_def->df_type->tp_up;
159         output_def(&od);
160         /* The other fields are not used for this class. */
161 }
162
163 lint_formals()
164 {
165 /* Make a list of 'struct argument's containing the types of the formal
166  * parameters of the function definition just parsed.
167  */
168         register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
169         register struct argument **hook = &OutDef.od_arg;
170         register int nrargs = 0;
171
172         while (se) {
173                 register struct type *type = se->se_idf->id_def->df_type;
174                 register struct argument *arg = new_argument();
175
176                 if (f_FORMAT && nrargs == f_FORMATn) {
177                         if (    !f_FORMATvar
178                         &&      (       type->tp_fund != POINTER
179                                 ||      type->tp_up->tp_fund != CHAR
180                                 )
181                         ) {
182                                 warning("format parameter %d is not pointer to char",
183                                         nrargs);
184                         }
185                         arg->ar_type = string_type;
186                         arg->ar_class = ArgString;
187                         arg->CAS_VALUE = f_FORMAT;
188                         arg->CAS_LEN = strlen(f_FORMAT);
189                         f_FORMAT = 0;
190                 }
191                 else {
192                         arg->ar_type = type;
193                         arg->ar_class = ArgFormal;
194                 }
195                 *hook = arg;
196                 hook = &arg->next;
197
198                 nrargs++;
199                 se = se->next;
200         }
201
202         if (f_FORMAT) {
203                 /*      f_FORMAT has not been consumed, perhaps due to
204                         a varargs-like construction; add erroneous ArgFormals
205                         until f_FORMATn, then an ArgString, if necessary.
206                 */
207                 if (!f_FORMATvar) {
208                         warning("FORMAT%d function has only %d argument%s",
209                                 f_FORMATn, nrargs, nrargs == 1 ? "" : "s"
210                         );
211                 }
212
213                 while (nrargs < f_FORMATn) {
214                         register struct argument *arg = new_argument();
215                         
216                         arg->ar_type = error_type;
217                         arg->ar_class = ArgFormal;
218                         *hook = arg;
219                         hook = &arg->next;
220                         nrargs++;
221                 }
222                 if (nrargs == f_FORMATn) {
223                         register struct argument *arg = new_argument();
224                         
225                         arg->ar_type = string_type;
226                         arg->ar_class = ArgString;
227                         arg->CAS_VALUE = f_FORMAT;
228                         arg->CAS_LEN = strlen(f_FORMAT);
229                         f_FORMAT = 0;
230                         *hook = arg;
231                         hook = &arg->next;
232                         nrargs++;
233                 }
234                 /* life is full of duplicated code; this is no good */
235         }
236
237         if (f_VARARGSn > nrargs) {
238                 warning("VARARGS%d function has only %d argument%s",
239                         f_VARARGSn, nrargs, nrargs == 1 ? "" : "s"
240                 );
241                 f_VARARGSn = nrargs;
242         }
243         OutDef.od_nrargs = nrargs;
244 }
245
246 output_proto(idf, def)
247         struct idf *idf;
248         struct def *def;
249 {
250         /* fund == FUNCTION && sc != STATIC */
251         register struct proto *pl = def->df_type->tp_proto;
252         register int nrargs = 0;
253
254         if (!pl) return;
255
256         OutDef.od_name = idf->id_text;
257         OutDef.od_statnr = 0;
258         OutDef.od_class = PFDF;
259         OutDef.od_file = def->df_file;
260         OutDef.od_line = def->df_line;
261         OutDef.od_type = def->df_type->tp_up;
262         OutDef.od_valreturned = NORETURN;/*???*/
263
264         while (pl) {
265                 register struct type *type = pl->pl_type;
266                 register struct argument *arg = new_argument();
267
268                 if (type) {
269                         arg->ar_type = type;
270                         arg->ar_class = ArgFormal;
271                 }
272                 else {
273                         arg->ar_class = ArgEllipsis;
274                 }
275                 arg->next = OutDef.od_arg;
276                 OutDef.od_arg = arg;
277
278                 nrargs++;
279                 pl = pl->next;
280         }
281
282         OutDef.od_nrargs = nrargs;
283         outdef();
284 }
285
286 output_use(idf)
287         struct idf *idf;
288 {
289 /* Output the usage-definition of the variable described by idf.
290  */
291         OutDef.od_name = idf->id_text;
292         OutDef.od_statnr = (idf->id_def->df_sc == STATIC ? stat_number : 0);
293         OutDef.od_class = VU;
294         OutDef.od_file = FileName;
295         OutDef.od_line = LineNumber;
296         OutDef.od_type = idf->id_def->df_type;
297         outdef();
298 }
299
300 outdef()
301 {
302         output_def(&OutDef);
303 }
304
305 outcall()
306 {
307         output_def(&OutCall);
308 }
309
310 PRIVATE
311 output_def(od)
312         struct outdef *od;
313 {
314 /* As the types are output the 'struct argument's are freed, because they
315  * are then not needed anymore.
316  */
317         if (od->od_class == XXDF || !od->od_name || od->od_name[0] == '#')
318                 return;
319
320         if (LINTLIB) {
321                 switch (od->od_class) {
322                 case EFDF:
323                         od->od_class = LFDF;
324                         break;
325                 case EVDF:
326                         od->od_class = LVDF;
327                         break;
328                 case SFDF:
329                         /* free the 'struct argument's */
330                         while (od->od_arg) {
331                                 register struct argument *tmp = od->od_arg;
332                                 od->od_arg = od->od_arg->next;
333                                 free_argument(tmp);
334                         }
335                         return;
336                 default:
337                         return;
338                 }
339         }
340         printf("%s:%d:%c", od->od_name, od->od_statnr, od->od_class);
341         switch (od->od_class) {
342         case LFDF:
343         case PFDF:
344         case EFDF:
345         case SFDF:
346                 if (f_VARARGSn != -1) {
347                         printf(":%d", -1 - f_VARARGSn);
348                         outargs(od->od_arg, f_VARARGSn);
349                 }
350                 else {
351                         printf(":%d", od->od_nrargs);
352                         outargs(od->od_arg, od->od_nrargs);
353                 }
354                 od->od_arg = 0;
355                 printf(":%d", od->od_valreturned);
356                 break;
357         case FC:
358                 printf(":%d", od->od_nrargs);
359                 outargs(od->od_arg, od->od_nrargs);
360                 od->od_arg = 0;
361                 printf(":%d", od->od_valused);
362                 break;
363         case EVDF:
364         case SVDF:
365         case LVDF:
366         case EFDC:
367         case EVDC:
368         case IFDC:
369         case VU:
370                 break;
371         default:
372                 NOTREACHED();
373                 /*NOTREACHED*/
374         }
375         printf(":");
376         outargtype(od->od_type);
377         printf(":%u:%s\n", od->od_line, od->od_file);
378 }
379
380 PRIVATE
381 outargs(arg, n)
382         struct argument *arg;
383 {
384 /* Output the n arguments in the argument list and remove them */
385
386         register struct argument *tmp;
387
388         while (n--) {
389                 ASSERT(arg);
390                 outarg(arg);
391                 tmp = arg;
392                 arg = arg->next;
393                 free_argument(tmp);
394         }
395         /* remove the remaining entries */
396         while (arg) {
397                 tmp = arg;
398                 arg = arg->next;
399                 free_argument(tmp);
400         }
401 }
402
403 PRIVATE
404 outarg(arg)
405         struct argument *arg;
406 {
407         printf(":");
408         switch (arg->ar_class) {
409         case ArgConst:
410                 if (arg->CAA_VALUE >= 0) {
411                         /* constant non-negative actual parameter */
412                         printf("+");
413                 }
414                 outargtype(arg->ar_type);
415                 break;
416
417         case ArgString:
418                 outargstring(arg);
419                 break;
420
421         case ArgFormal:
422         case ArgExpr:
423                 outargtype(arg->ar_type);
424                 if (arg->ar_type->tp_fund == FUNCTION) {
425                         /* UGLY PATCH !!! ??? */
426                         /*      function names as operands are sometimes
427                                 FUNCTION and sometimes POINTER to FUNCTION,
428                                 depending on opaque circumstances.  E.g., in
429                                         f(main, main);
430                                 the first main is PtF and the second is F.
431                         */
432                         printf("*");
433                 }
434                 break;
435
436         case ArgEllipsis:
437                 printf(".");    /* one is enough for computers */
438                 break;
439
440         default:
441                 NOTREACHED();
442                 /*NOTREACHED*/
443         }
444 }
445
446 PRIVATE
447 outargstring(arg)
448         struct argument *arg;
449 {
450         char buff[1000];
451         register char *p;
452
453         bts2str(arg->CAS_VALUE, arg->CAS_LEN, buff);
454         for (p = &buff[0]; *p; p++) {
455                 if (*p == '"' || *p == ':')
456                         *p = ' ';
457         }
458         printf("\"%s\"", buff);
459 }
460
461 PRIVATE
462 outargtype(tp)
463         struct type *tp;
464 {
465         switch (tp->tp_fund) {
466         case POINTER:
467                 outargtype(tp->tp_up);
468                 printf("*");
469                 break;
470
471         case ARRAY:
472                 outargtype(tp->tp_up);
473                 printf("*");    /* compatible with [] */
474                 break;
475
476         case FUNCTION:
477                 outargtype(tp->tp_up);
478                 printf("()");
479                 break;
480
481         case STRUCT:
482         case UNION:
483         case ENUM:
484                 /* watch out for anonymous identifiers; the count field does
485                    not have to be the same for all compilation units.
486                    Remove it, so that pass 2 does not see it. The only
487                    problem with this is that pass2 will not see a difference
488                    between two non-tagged types declared on the same line.
489                 */
490                 printf("%s ", symbol2str(tp->tp_fund));
491                 if (is_anon_idf(tp->tp_idf)) {
492                         /* skip the #<num>, replace it by '#anonymous id' */
493                         printf("#anonymous id%s",
494                                 strindex(tp->tp_idf->id_text, ' ')
495                         );
496                 }
497                 else {
498                         printf(tp->tp_idf->id_text);
499                 }
500                 break;
501
502         case CHAR:
503         case INT:
504         case SHORT:
505         case LONG:
506         case ULONG:
507         case FLOAT:
508         case DOUBLE:
509         case LNGDBL:
510         case VOID:
511         case ERRONEOUS:
512                 if (tp->tp_unsigned) {
513                         printf("unsigned ");
514                 }
515                 printf("%s", symbol2str(tp->tp_fund));
516                 break;
517         default:
518                 NOTREACHED();
519                 /*NOTREACHED*/
520         }
521 }
522
523 #ifdef  IMPLICIT
524 PRIVATE
525 implicit_func_decl(idf, file, line)
526         struct idf *idf;
527         char *file;
528         unsigned int line;
529 {
530         struct outdef od;
531
532         od.od_class = IFDC;
533         od.od_statnr = 0;
534         od.od_name = idf->id_text;
535         od.od_file = file;
536         od.od_line = line;
537         od.od_type = idf->id_def->df_type->tp_up;
538         output_def(&od);
539         /* The other fields are not used for this class. */
540 }
541 #endif  /* IMPLICIT */
542
543 fill_outcall(ex, used)
544         struct expr *ex;
545         int used;
546 {
547         register struct idf *idf = ex->OP_LEFT->VL_IDF;
548         register struct def *def = idf->id_def;
549
550 #ifdef  IMPLICIT
551         if (def->df_sc == IMPLICIT && !idf->id_def->df_used) {
552                 /* IFDC, first time */
553                 implicit_func_decl(idf, ex->ex_file, ex->ex_line);
554         }
555 #endif  /* IMPLICIT */
556
557         OutCall.od_type = def->df_type->tp_up;
558         OutCall.od_statnr = (def->df_sc == STATIC ? stat_number : 0);
559         OutCall.od_class = FC;
560         OutCall.od_name = idf->id_text;
561         OutCall.od_file = ex->ex_file;
562         OutCall.od_line = ex->ex_line;
563         OutCall.od_arg = (struct argument *)0;
564         OutCall.od_nrargs = 0;
565
566         if ((ex = ex->OP_RIGHT) != 0) {
567                 /* function call with arguments: */
568                 /* store types of argument expressions in 'struct argument's */
569                 while (ex->ex_class == Oper && ex->OP_OPER == PARCOMMA) {
570                         add_expr_arg(ex->OP_RIGHT);
571                         ex = ex->OP_LEFT;
572                 }
573                 add_expr_arg(ex);
574         }
575         OutCall.od_valused = used;      /* USED, IGNORED or VOIDED */
576 }
577
578 PRIVATE
579 add_expr_arg(e)
580         struct expr *e;
581 {
582         register struct argument *arg;
583
584         arg = new_argument();
585         arg->ar_type = e->ex_type;
586         if (is_cp_cst(e)) {
587                 arg->ar_class = ArgConst;
588                 arg->CAA_VALUE = e->VL_VALUE;
589         }
590         else if (       e->ex_type == string_type
591                 &&      e->ex_class == Value
592                 &&      e->VL_CLASS == Label
593                 ) {
594                 /* it may be a string; let's look it up */
595                 register struct string_cst *sc = str_list;
596
597                 while (sc) {
598                         if (sc->sc_dlb == e->VL_LBL)
599                                 break;
600                         sc = sc->next;
601                 }
602                 if (sc) {
603                         /* it was a string */
604                         arg->ar_class = ArgString;
605                         arg->CAS_VALUE = sc->sc_value;
606                         arg->CAS_LEN = sc->sc_len - 1;  /* included the \0 */
607                 }
608                 else {
609                         arg->ar_class = ArgExpr;
610                 }
611         }
612         else {
613                 arg->ar_class = ArgExpr;
614         }
615         arg->next = OutCall.od_arg;
616         OutCall.od_arg = arg;
617         OutCall.od_nrargs++;
618 }
619
620 #endif  /* LINT */