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".
5 /* $Id: lpass2.c,v 1.10 1994/06/24 12:25:48 ceriel Exp $ */
15 extern char *strcpy();
17 #define streq(s1,s2) (strcmp(s1, s2) == 0)
19 PRIVATE char cur_name[NAMESIZE];
20 PRIVATE struct inpdef *dot, *lib, *proto, *ext, *sta;
31 PRIVATE one_ext_decl();
32 PRIVATE one_func_call();
33 PRIVATE one_var_usage();
38 #define same_name() (dot && streq(cur_name, dot->id_name))
39 #define same_obj(stnr) (same_name() && dot->id_statnr == stnr)
41 #define def_or_dec(id) (is_class(id, CL_DEF) ? "defined" : "declared")
42 #define fun_or_var(id) (is_class(id, CL_FUNC) ? "function" : "variable")
45 /******** M A I N ********/
72 static char *table[] = {0};
74 PRIVATE init(argc, argv)
78 * Get command line options
79 * Prepare standard input for reading using the input-package
85 while (argc > 1 && argv[1][0] == '-') {
86 register char *arg = &argv[1][1];
92 /* don't report situations like
95 case 'X': /* ??? prints incoming inpdefs */
96 default: /* and any other */
104 if (!InsertFile((char *)0, table, &result)) {
105 panic("InsertFile() fails");
117 print_id("get_dot", dot);
123 strcpy(cur_name, dot->id_name);
138 /* there are lines for this name that have not been absorbed */
139 panic("sequence error in intermediate file");
143 /******** L I B R A R Y ********/
147 if (same_obj(0) && is_class(dot, CL_LIB)) {
151 while (same_obj(0) && is_class(dot, CL_LIB)) {
152 report(">%L: multiple definition of %s in library",
160 /******** P R O T O T Y P E S ********/
163 if (same_obj(0) && dot->id_class == PFDF) {
165 report("%L: function %s also defined in %L",
166 dot, dot->id_name, lib);
171 while (same_obj(0) && dot->id_class == PFDF) {
178 PRIVATE chk_proto(def)
181 if (proto->id_args) {
182 chk_args(def, proto);
184 if (!type_equal(def->id_type, proto->id_type)) {
185 report("%L: return type of function %s declared differently at %L",
186 def, def->id_name, proto);
191 /******** E X T E R N ********/
195 if (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) {
197 report("%L: %s %s also defined in %L",
198 dot, fun_or_var(dot), dot->id_name, lib);
206 while (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) {
207 report("%L: %s %s also defined at %L",
208 dot, fun_or_var(dot), dot->id_name, ext);
216 while (same_obj(0) && dot->id_class == EFDC) {
217 one_ext_decl("function", "variable", CL_VAR);
220 while (same_obj(0) && dot->id_class == EVDC) {
221 one_ext_decl("variable", "function", CL_FUNC);
224 while (same_obj(0) && dot->id_class == IFDC) {
225 one_ext_decl("function", "variable", CL_VAR);
229 PRIVATE one_ext_decl(kind, other_kind, other_class)
234 struct inpdef *def = (proto ? proto : ext ? ext : lib ? lib : 0);
237 /* the declaration will have to serve */
244 if (is_class(def, other_class)) {
245 /* e.g.: function FFF declared as variable at ... */
246 report("%L: %s %s %s as %s at %L",
247 dot, kind, dot->id_name,
248 def_or_dec(def), other_kind, def
250 /* no further testing possible */
255 if (!type_equal(dot->id_type, def->id_type)) {
256 /* e.g.: type of variable VVV defined differently at ... */
257 report("%L: type of %s %s %s differently at %L",
258 dot, kind, dot->id_name, def_or_dec(def), def);
260 /* no further testing needed */
269 /******** U S A G E ********/
274 register struct inpdef *def =
275 (stnr ? sta : proto ? proto : ext ? ext : lib ? lib : 0);
276 register int VU_count = 0;
277 register int VU_samefile = 0;
279 while (same_obj(stnr) && dot->id_class == FC) {
283 while (same_obj(stnr) && dot->id_class == VU) {
285 if (def && streq(def->id_file, dot->id_file)) {
291 if (def && loptions['h']) {
292 register char *fn = def->id_file;
298 || (def == ext && !is_class(ext, CL_IMPL))
300 && streq(&fn[strlen(fn)-2], ".c")
302 report("%L: extern %s could be declared static",
308 PRIVATE one_func_call(def)
312 if (!loptions['u']) {
313 report("%L: function %s used but not defined",
324 if ( dot->id_valused == USED
325 && def->id_valreturned == NOVALRETURNED
327 report("%L: value of %s is used, but none is returned at %L",
328 dot, dot->id_name, def);
332 switch (dot->id_valused) {
343 panic("invalid dot->id_valused in one_func_call()");
350 PRIVATE one_var_usage(def)
354 if (!loptions['u']) {
355 report("%L: variable %s used but not defined",
368 /******** S T A T I C ********/
372 while (same_name()) {
373 int stnr = dot->id_statnr;
376 panic("sequence error in intermediate file: externals after statics");
391 if (same_obj(stnr)) {
392 panic("sequence error in intermediate file: statics out of order");
397 PRIVATE stat_def(stnr)
400 if (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) {
402 report("%L: %s %s also defined in %L",
403 dot, fun_or_var(dot), dot->id_name, lib);
406 struct inpdef *def = (proto ? proto : ext);
408 if (!streq(dot->id_file, def->id_file)) {
409 report("%L: %s %s also %s at %L",
410 dot, fun_or_var(dot), dot->id_name,
418 while (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) {
419 report("%L: %s %s also defined at %L",
420 dot, fun_or_var(dot), dot->id_name, sta);
432 if (!def->id_called) {
433 if (streq(def->id_name, "main")) {
436 else if (ext && is_class(ext, CL_LIB)) {
440 if (!loptions['u']) {
441 report("%L: %s %s not used anywhere",
442 def, fun_or_var(def), def->id_name);
447 if (is_class(def, CL_DEF|CL_FUNC)) {
448 if ( def->id_valreturned == VALRETURNED
452 report("%L: %s returns value which is %s ignored",
454 (def->id_used || def->id_voided) ?
455 "sometimes" : "always");
461 /******** D E B U G G I N G ********/
468 print("%s: <NO_INPDEF>\n", name);
472 print("%s: %s, %s, %04d, \"%s\", %d, %s", name,
473 id->id_class == LFDF ? "LFDF" :
474 id->id_class == LVDF ? "LVDF" :
475 id->id_class == PFDF ? "PFDF" :
476 id->id_class == EFDF ? "EFDF" :
477 id->id_class == EVDF ? "EVDF" :
478 id->id_class == EFDC ? "EFDC" :
479 id->id_class == EVDC ? "EVDC" :
480 id->id_class == IFDC ? "IFDC" :
481 id->id_class == SFDF ? "SFDF" :
482 id->id_class == SVDF ? "SVDF" :
483 id->id_class == FC ? "FC" :
484 id->id_class == VU ? "VU" : "<BADCLASS>",
491 if (is_class(id, CL_FUNC|CL_DEF) || is_class(id, CL_FUNC|CL_USAGE)) {
492 print(", %d, %s, %s",
494 (id->id_nrargs == 0 ? "" : id->id_argtps),
496 ? ( id->id_valused == USED ? "USED" :
497 id->id_valused == IGNORED ? "IGNORED" :
498 id->id_valused == VOIDED ? "VOIDED" :
501 : ( id->id_valreturned == NOVALRETURNED
503 : id->id_valreturned == VALRETURNED
505 : id->id_valreturned == NORETURN
507 : "<BAD VALRETURNED>"