Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.bin / xlint / lint2 / chk.c
1 /*      $NetBSD: chk.c,v 1.2 1995/07/03 21:24:42 cgd Exp $      */
2
3 /*
4  * Copyright (c) 1994, 1995 Jochen Pohl
5  * All Rights Reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Jochen Pohl for
18  *      The NetBSD Project.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 static char rcsid[] = "$NetBSD: chk.c,v 1.2 1995/07/03 21:24:42 cgd Exp $";
36 #endif
37
38 #include <stdlib.h>
39 #include <ctype.h>
40 #include <limits.h>
41 #include <err.h>
42
43 #include "lint2.h"
44
45 /* various type information */
46 ttab_t  ttab[NTSPEC];
47
48
49 static  void    chkund __P((hte_t *));
50 static  void    chkdnu __P((hte_t *));
51 static  void    chkdnud __P((hte_t *));
52 static  void    chkmd __P((hte_t *));
53 static  void    chkvtui __P((hte_t *, sym_t *, sym_t *));
54 static  void    chkvtdi __P((hte_t *, sym_t *, sym_t *));
55 static  void    chkfaui __P((hte_t *, sym_t *, sym_t *));
56 static  void    chkau __P((hte_t *, int, sym_t *, sym_t *, pos_t *,
57                            fcall_t *, fcall_t *, type_t *, type_t *));
58 static  void    chkrvu __P((hte_t *, sym_t *));
59 static  void    chkadecl __P((hte_t *, sym_t *, sym_t *));
60 static  void    printflike __P((hte_t *,fcall_t *, int,
61                                 const char *, type_t **));
62 static  void    scanflike __P((hte_t *, fcall_t *, int,
63                                const char *, type_t **));
64 static  void    badfmt __P((hte_t *, fcall_t *));
65 static  void    inconarg __P((hte_t *, fcall_t *, int));
66 static  void    tofewarg __P((hte_t *, fcall_t *));
67 static  void    tomanyarg __P((hte_t *, fcall_t *));
68 static  int     eqtype __P((type_t *, type_t *, int, int, int, int *));
69 static  int     eqargs __P((type_t *, type_t *, int *));
70 static  int     mnoarg __P((type_t *, int *));
71
72
73 void
74 inittyp()
75 {
76         int     i;
77         static  struct {
78                 tspec_t it_tspec;
79                 ttab_t  it_ttab;
80         } ittab[] = {
81                 { SIGNED,   { 0, 0,
82                                       SIGNED, UNSIGN,
83                                       0, 0, 0, 0, 0, "signed" } },
84                 { UNSIGN,   { 0, 0,
85                                       SIGNED, UNSIGN,
86                                       0, 0, 0, 0, 0, "unsigned" } },
87                 { CHAR,     { CHAR_BIT, CHAR_BIT,
88                                       SCHAR, UCHAR,
89                                       1, 0, 0, 1, 1, "char" } },
90                 { SCHAR,    { CHAR_BIT, CHAR_BIT,
91                                       SCHAR, UCHAR,
92                                       1, 0, 0, 1, 1, "signed char" } },
93                 { UCHAR,    { CHAR_BIT, CHAR_BIT,
94                                       SCHAR, UCHAR,
95                                       1, 1, 0, 1, 1, "unsigned char" } },
96                 { SHORT,    { sizeof (short) * CHAR_BIT, 2 * CHAR_BIT,
97                                       SHORT, USHORT,
98                                       1, 0, 0, 1, 1, "short" } },
99                 { USHORT,   { sizeof (u_short) * CHAR_BIT, 2 * CHAR_BIT,
100                                       SHORT, USHORT,
101                                       1, 1, 0, 1, 1, "unsigned short" } },
102                 { INT,      { sizeof (int) * CHAR_BIT, 3 * CHAR_BIT,
103                                       INT, UINT,
104                                       1, 0, 0, 1, 1, "int" } },
105                 { UINT,     { sizeof (u_int) * CHAR_BIT, 3 * CHAR_BIT,
106                                       INT, UINT,
107                                       1, 1, 0, 1, 1, "unsigned int" } },
108                 { LONG,     { sizeof (long) * CHAR_BIT, 4 * CHAR_BIT,
109                                       LONG, ULONG,
110                                       1, 0, 0, 1, 1, "long" } },
111                 { ULONG,    { sizeof (u_long) * CHAR_BIT, 4 * CHAR_BIT,
112                                       LONG, ULONG,
113                                       1, 1, 0, 1, 1, "unsigned long" } },
114                 { QUAD,     { sizeof (quad_t) * CHAR_BIT, 8 * CHAR_BIT,
115                                       QUAD, UQUAD,
116                                       1, 0, 0, 1, 1, "long long" } },
117                 { UQUAD,    { sizeof (u_quad_t) * CHAR_BIT, 8 * CHAR_BIT,
118                                       QUAD, UQUAD,
119                                       1, 1, 0, 1, 1, "unsigned long long" } },
120                 { FLOAT,    { sizeof (float) * CHAR_BIT, 4 * CHAR_BIT,
121                                       FLOAT, FLOAT,
122                                       0, 0, 1, 1, 1, "float" } },
123                 { DOUBLE,   { sizeof (double) * CHAR_BIT, 8 * CHAR_BIT,
124                                       DOUBLE, DOUBLE,
125                                       0, 0, 1, 1, 1, "double" } },
126                 { LDOUBLE,  { sizeof (ldbl_t) * CHAR_BIT, 10 * CHAR_BIT,
127                                       LDOUBLE, LDOUBLE,
128                                       0, 0, 1, 1, 1, "long double" } },
129                 { VOID,     { -1, -1,
130                                       VOID, VOID,
131                                       0, 0, 0, 0, 0, "void" } },
132                 { STRUCT,   { -1, -1,
133                                       STRUCT, STRUCT,
134                                       0, 0, 0, 0, 0, "struct" } },
135                 { UNION,    { -1, -1,
136                                       UNION, UNION,
137                                       0, 0, 0, 0, 0, "union" } },
138                 { ENUM,     { sizeof (int) * CHAR_BIT, 3 * CHAR_BIT,
139                                       ENUM, ENUM,
140                                       1, 0, 0, 1, 1, "enum" } },
141                 { PTR,      { sizeof (void *) * CHAR_BIT, 4 * CHAR_BIT,
142                                       PTR, PTR,
143                                       0, 1, 0, 0, 1, "pointer" } },
144                 { ARRAY,    { -1, -1,
145                                       ARRAY, ARRAY,
146                                       0, 0, 0, 0, 0, "array" } },
147                 { FUNC,     { -1, -1,
148                                       FUNC, FUNC,
149                                       0, 0, 0, 0, 0, "function" } },
150         };
151
152         for (i = 0; i < sizeof (ittab) / sizeof (ittab[0]); i++)
153                 STRUCT_ASSIGN(ttab[ittab[i].it_tspec], ittab[i].it_ttab);
154         if (!pflag) {
155                 for (i = 0; i < NTSPEC; i++)
156                         ttab[i].tt_psz = ttab[i].tt_sz;
157         }
158 }
159
160
161 /*
162  * If there is a symbol named "main", mark it as used.
163  */
164 void
165 mainused()
166 {
167         hte_t   *hte;
168
169         if ((hte = hsearch("main", 0)) != NULL)
170                 hte->h_used = 1;
171 }
172
173 /*
174  * Performs all tests for a single name
175  */
176 void
177 chkname(hte)
178         hte_t   *hte;
179 {
180         sym_t   *sym, *def, *pdecl, *decl;
181
182         if (uflag) {
183                 chkund(hte);
184                 chkdnu(hte);
185                 if (xflag)
186                         chkdnud(hte);
187         }
188         chkmd(hte);
189
190         /* Get definition, prototype declaration and declaration */
191         def = pdecl = decl = NULL;
192         for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
193                 if (def == NULL && (sym->s_def == DEF || sym->s_def == TDEF))
194                         def = sym;
195                 if (pdecl == NULL && sym->s_def == DECL &&
196                     TP(sym->s_type)->t_tspec == FUNC &&
197                     TP(sym->s_type)->t_proto) {
198                         pdecl = sym;
199                 }
200                 if (decl == NULL && sym->s_def == DECL)
201                         decl = sym;
202         }
203
204         /* A prototype is better than an old style declaration. */
205         if (pdecl != NULL)
206                 decl = pdecl;
207
208         chkvtui(hte, def, decl);
209
210         chkvtdi(hte, def, decl);
211
212         chkfaui(hte, def, decl);
213
214         chkrvu(hte, def);
215
216         chkadecl(hte, def, decl);
217 }
218
219 /*
220  * Print a warning if the name has been used, but not defined.
221  */
222 static void
223 chkund(hte)
224         hte_t   *hte;
225 {
226         fcall_t *fcall;
227         usym_t  *usym;
228
229         if (!hte->h_used || hte->h_def)
230                 return;
231
232         if ((fcall = hte->h_calls) != NULL) {
233                 /* %s used( %s ), but not defined */
234                 msg(0, hte->h_name, mkpos(&fcall->f_pos));
235         } else if ((usym = hte->h_usyms) != NULL) {
236                 /* %s used( %s ), but not defined */
237                 msg(0, hte->h_name, mkpos(&usym->u_pos));
238         }
239 }
240
241 /*
242  * Print a warning if the name has been defined, but never used.
243  */
244 static void
245 chkdnu(hte)
246         hte_t   *hte;
247 {
248         sym_t   *sym;
249
250         if (!hte->h_def || hte->h_used)
251                 return;
252
253         for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
254                 if (sym->s_def == DEF || sym->s_def == TDEF) {
255                         /* %s defined( %s ), but never used */
256                         msg(1, hte->h_name, mkpos(&sym->s_pos));
257                         break;
258                 }
259         }
260 }
261
262 /*
263  * Print a warning if the name has been declared, but is not used
264  * or defined.
265  */
266 static void
267 chkdnud(hte)
268         hte_t   *hte;
269 {
270         sym_t   *sym;
271
272         if (hte->h_syms == NULL || hte->h_used || hte->h_def)
273                 return;
274         
275         if ((sym = hte->h_syms) != NULL) {
276                 if (sym->s_def != DECL)
277                         errx(1, "internal error: chkdnud() 1");
278                 /* %s declared( %s ), but never used or defined */
279                 msg(2, hte->h_name, mkpos(&sym->s_pos));
280         }
281 }
282
283 /*
284  * Print a warning if there is more then one definition for
285  * this name.
286  */
287 static void
288 chkmd(hte)
289         hte_t   *hte;
290 {
291         sym_t   *sym, *def1;
292         char    *pos1;
293
294         if (!hte->h_def)
295                 return;
296
297         def1 = NULL;
298         for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
299                 /*
300                  * ANSI C allows tentative definitions of the same name in
301                  * only one compilation unit.
302                  */
303                 if (sym->s_def != DEF && (!sflag || sym->s_def != TDEF))
304                         continue;
305                 if (def1 == NULL) {
306                         def1 = sym;
307                         continue;
308                 }
309                 pos1 = xstrdup(mkpos(&def1->s_pos));
310                 /* %s multiply defined\t%s  ::  %s */
311                 msg(3, hte->h_name, pos1, mkpos(&sym->s_pos));
312                 free(pos1);
313         }
314 }
315
316 /*
317  * Print a warning if the return value assumed for a function call
318  * differs from the return value of the function definition or
319  * function declaration.
320  *
321  * If no definition/declaration can be found, the assumed return values
322  * are always int. So there is no need to compare with another function
323  * call as it's done for function arguments.
324  */
325 static void
326 chkvtui(hte, def, decl)
327         hte_t   *hte;
328         sym_t   *def, *decl;
329 {
330         fcall_t *call;
331         char    *pos1;
332         type_t  *tp1, *tp2;
333         /* LINTED (automatic hides external declaration: warn) */
334         int     warn, eq;
335         tspec_t t1;
336
337         if (hte->h_calls == NULL)
338                 return;
339
340         if (def == NULL)
341                 def = decl;
342         if (def == NULL)
343                 return;
344
345         t1 = (tp1 = TP(def->s_type)->t_subt)->t_tspec;
346         for (call = hte->h_calls; call != NULL; call = call->f_nxt) {
347                 tp2 = TP(call->f_type)->t_subt;
348                 eq = eqtype(tp1, tp2, 1, 0, 0, (warn = 0, &warn));
349                 if (!call->f_rused) {
350                         /* no return value used */
351                         if ((t1 == STRUCT || t1 == UNION) && !eq) {
352                                 /*
353                                  * If a function returns a struct or union it
354                                  * must be declared to return a struct or
355                                  * union, also if the return value is ignored.
356                                  * This is necessary because the caller must
357                                  * allocate stack space for the return value.
358                                  * If it does not, the return value would over-
359                                  * write other data.
360                                  * XXX Following massage may be confusing
361                                  * because it appears also if the return value
362                                  * was declared inconsistently. But this
363                                  * behaviour matches pcc based lint, so it is
364                                  * accepted for now.
365                                  */
366                                 pos1 = xstrdup(mkpos(&def->s_pos));
367                                 /* %s value must be decl. before use %s :: %s */
368                                 msg(17, hte->h_name,
369                                     pos1, mkpos(&call->f_pos));
370                                 free(pos1);
371                         }
372                         continue;
373                 }
374                 if (!eq || (sflag && warn)) {
375                         pos1 = xstrdup(mkpos(&def->s_pos));
376                         /* %s value used inconsistenty\t%s  ::  %s */
377                         msg(4, hte->h_name, pos1, mkpos(&call->f_pos));
378                         free(pos1);
379                 }
380         }
381 }
382
383 /*
384  * Print a warning if a definition/declaration does not match another
385  * definition/declaration of the same name. For functions, only the
386  * types of return values are tested.
387  */
388 static void
389 chkvtdi(hte, def, decl)
390         hte_t   *hte;
391         sym_t   *def, *decl;
392 {
393         sym_t   *sym;
394         type_t  *tp1, *tp2;
395         /* LINTED (automatic hides external declaration: warn) */
396         int     eq, warn;
397         char    *pos1;
398
399         if (def == NULL)
400                 def = decl;
401         if (def == NULL)
402                 return;
403
404         tp1 = TP(def->s_type);
405         for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
406                 if (sym == def)
407                         continue;
408                 tp2 = TP(sym->s_type);
409                 warn = 0;
410                 if (tp1->t_tspec == FUNC && tp2->t_tspec == FUNC) {
411                         eq = eqtype(tp1->t_subt, tp2->t_subt, 1, 0, 0, &warn);
412                 } else {
413                         eq = eqtype(tp1, tp2, 0, 0, 0, &warn);
414                 }
415                 if (!eq || (sflag && warn)) {
416                         pos1 = xstrdup(mkpos(&def->s_pos));
417                         /* %s value declared inconsistently\t%s  ::  %s */
418                         msg(5, hte->h_name, pos1, mkpos(&sym->s_pos));
419                         free(pos1);
420                 }
421         }
422 }
423
424 /*
425  * Print a warning if a function is called with arguments which does
426  * not match the function definition, declaration or another call
427  * of the same function.
428  */
429 static void
430 chkfaui(hte, def, decl)
431         hte_t   *hte;
432         sym_t   *def, *decl;
433 {
434         type_t  *tp1, *tp2, **ap1, **ap2;
435         pos_t   *pos1p;
436         fcall_t *calls, *call, *call1;
437         int     n, as;
438         char    *pos1;
439         arginf_t *ai;
440
441         if ((calls = hte->h_calls) == NULL)
442                 return;
443
444         /*
445          * If we find a function definition, we use this for comparision,
446          * otherwise the first prototype we can find. If there is no
447          * definition or prototype declaration, the first function call
448          * is used.
449          */
450         tp1 = NULL;
451         call1 = NULL;
452         if (def != NULL) {
453                 if ((tp1 = TP(def->s_type))->t_tspec != FUNC)
454                         return;
455                 pos1p = &def->s_pos;
456         } else if (decl != NULL && TP(decl->s_type)->t_proto) {
457                 if ((tp1 = TP(decl->s_type))->t_tspec != FUNC)
458                         return;
459                 pos1p = &decl->s_pos;
460         }
461         if (tp1 == NULL) {
462                 call1 = calls;
463                 calls = calls->f_nxt;
464                 if ((tp1 = TP(call1->f_type))->t_tspec != FUNC)
465                         return;
466                 pos1p = &call1->f_pos;
467         }
468
469         n = 1;
470         for (call = calls; call != NULL; call = call->f_nxt) {
471                 if ((tp2 = TP(call->f_type))->t_tspec != FUNC)
472                         continue;
473                 ap1 = tp1->t_args;
474                 ap2 = tp2->t_args;
475                 n = 0;
476                 while (*ap1 != NULL && *ap2 != NULL) {
477                         if (def != NULL && def->s_va && n >= def->s_nva)
478                                 break;
479                         n++;
480                         chkau(hte, n, def, decl, pos1p, call1, call,
481                               *ap1, *ap2);
482                         ap1++;
483                         ap2++;
484                 }
485                 if (*ap1 == *ap2) {
486                         /* equal # of arguments */
487                 } else if (def != NULL && def->s_va && n >= def->s_nva) {
488                         /*
489                          * function definition with VARARGS; The # of
490                          * arguments of the call must be at least as large
491                          * as the parameter of VARARGS.
492                          */
493                 } else if (*ap2 != NULL && tp1->t_proto && tp1->t_vararg) {
494                         /*
495                          * prototype with ... and function call with
496                          * at least the same # of arguments as declared
497                          * in the prototype.
498                          */
499                 } else {
500                         pos1 = xstrdup(mkpos(pos1p));
501                         /* %s: variable # of args\t%s  ::  %s */
502                         msg(7, hte->h_name, pos1, mkpos(&call->f_pos));
503                         free(pos1);
504                         continue;
505                 }
506
507                 /* perform SCANFLIKE/PRINTFLIKE tests */
508                 if (def == NULL || (!def->s_prfl && !def->s_scfl))
509                         continue;
510                 as = def->s_prfl ? def->s_nprfl : def->s_nscfl;
511                 for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) {
512                         if (ai->a_num == as)
513                                 break;
514                 }
515                 if (ai == NULL || !ai->a_fmt)
516                         continue;
517                 if (def->s_prfl) {
518                         printflike(hte, call, n, ai->a_fstrg, ap2);
519                 } else {
520                         scanflike(hte, call, n, ai->a_fstrg, ap2);
521                 }
522         }
523 }
524
525 /*
526  * Check a single argument in a function call.
527  *
528  *  hte         a pointer to the hash table entry of the function
529  *  n           the number of the argument (1..)
530  *  def         the function definition or NULL
531  *  decl        prototype declaration, old style declaration or NULL
532  *  pos1p       position of definition, declaration of first call
533  *  call1       first call, if both def and decl are old style def/decl
534  *  call        checked call
535  *  arg1        currently checked argument of def/decl/call1
536  *  arg2        currently checked argument of call
537  *
538  */
539 static void
540 chkau(hte, n, def, decl, pos1p, call1, call, arg1, arg2)
541         hte_t   *hte;
542         int     n;
543         sym_t   *def, *decl;
544         pos_t   *pos1p;
545         fcall_t *call1, *call;
546         type_t  *arg1, *arg2;
547 {
548         /* LINTED (automatic hides external declaration: warn) */
549         int     promote, asgn, warn;
550         tspec_t t1, t2;
551         arginf_t *ai, *ai1;
552         char    *pos1;
553
554         /*
555          * If a function definition is available (def != NULL), we compair the
556          * function call (call) with the definition. Otherwise, if a function
557          * definition is available and it is not an old style definition
558          * (decl != NULL && TP(decl->s_type)->t_proto), we compair the call
559          * with this declaration. Otherwise we compair it with the first
560          * call we have found (call1).
561          */
562
563         /* arg1 must be promoted if it stems from an old style definition */
564         promote = def != NULL && def->s_osdef;
565
566         /*
567          * If we compair with a definition or declaration, we must perform
568          * the same checks for qualifiers in indirected types as in
569          * assignments.
570          */
571         asgn = def != NULL || (decl != NULL && TP(decl->s_type)->t_proto);
572
573         warn = 0;
574         if (eqtype(arg1, arg2, 1, promote, asgn, &warn) && (!sflag || !warn))
575                 return;
576
577         /*
578          * Other lint implementations print warnings as soon as the type
579          * of an argument does not match exactly the expected type. The
580          * result are lots of warnings which are really not neccessary.
581          * We print a warning only if
582          *   (0) at least one type is not an interger type and types differ
583          *   (1) hflag is set and types differ
584          *   (2) types differ, except in signedness
585          * If the argument is an integer constant whose msb is not set,
586          * signedness is ignored (e.g. 0 matches both signed and unsigned
587          * int). This is with and without hflag.
588          * If the argument is an integer constant with value 0 and the
589          * expected argument is of type pointer and the width of the
590          * interger constant is the same as the width of the pointer,
591          * no warning is printed.
592          */
593         t1 = arg1->t_tspec;
594         t2 = arg2->t_tspec;
595         if (isityp(t1) && isityp(t2) && !arg1->t_isenum && !arg2->t_isenum) {
596                 if (promote) {
597                         /*
598                          * XXX Here is a problem: Althrough it is possible to
599                          * pass an int where a char/short it expected, there
600                          * may be loss in significant digits. We should first
601                          * check for const arguments if they can be converted
602                          * into the original parameter type.
603                          */
604                         if (t1 == FLOAT) {
605                                 t1 = DOUBLE;
606                         } else if (t1 == CHAR || t1 == SCHAR) {
607                                 t1 = INT;
608                         } else if (t1 == UCHAR) {
609                                 t1 = tflag ? UINT : INT;
610                         } else if (t1 == SHORT) {
611                                 t1 = INT;
612                         } else if (t1 == USHORT) {
613                                 /* CONSTCOND */
614                                 t1 = INT_MAX < USHRT_MAX || tflag ? UINT : INT;
615                         }
616                 }
617
618                 if (styp(t1) == styp(t2)) {
619
620                         /*
621                          * types differ only in signedness; get information
622                          * about arguments
623                          */
624
625                         /*
626                          * treat a definition like a call with variable
627                          * arguments
628                          */
629                         ai1 = call1 != NULL ? call1->f_args : NULL;
630
631                         /*
632                          * if two calls are compared, ai1 is set to the
633                          * information for the n-th argument, if this was
634                          * a constant, otherwise to NULL
635                          */
636                         for ( ; ai1 != NULL; ai1 = ai1->a_nxt) {
637                                 if (ai1->a_num == n)
638                                         break;
639                         }
640                         /*
641                          * ai is set to the information of the n-th arg
642                          * of the (second) call, if this was a constant,
643                          * otherwise to NULL
644                          */
645                         for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) {
646                                 if (ai->a_num == n)
647                                         break;
648                         }
649
650                         if (ai1 == NULL && ai == NULL) {
651                                 /* no constant at all */
652                                 if (!hflag)
653                                         return;
654                         } else if (ai1 == NULL || ai == NULL) {
655                                 /* one constant */
656                                 if (ai == NULL)
657                                         ai = ai1;
658                                 if (ai->a_zero || ai->a_pcon)
659                                         /* same value in signed and unsigned */
660                                         return;
661                                 /* value (not representation) differently */
662                         } else {
663                                 /*
664                                  * two constants, one signed, one unsigned;
665                                  * if the msb of one of the constants is set,
666                                  * the argument is used inconsistently.
667                                  */
668                                 if (!ai1->a_ncon && !ai->a_ncon)
669                                         return;
670                         }
671                 }
672
673         } else if (t1 == PTR && isityp(t2) && psize(t1) == psize(t2)) {
674                 for (ai = call->f_args; ai != NULL; ai = ai->a_nxt) {
675                         if (ai->a_num == n)
676                                 break;
677                 }
678                 if (ai != NULL && ai->a_zero)
679                         return;
680         }
681
682         pos1 = xstrdup(mkpos(pos1p));
683         /* %s, arg %d used inconsistently\t%s  ::  %s */
684         msg(6, hte->h_name, n, pos1, mkpos(&call->f_pos));
685         free(pos1);
686 }
687
688 /*
689  * Compare the types in the NULL-terminated array ap with the format
690  * string fmt.
691  */
692 static void
693 printflike(hte, call, n, fmt, ap)
694         hte_t   *hte;
695         fcall_t *call;
696         int     n;
697         const   char *fmt;
698         type_t  **ap;
699 {
700         const   char *fp;
701         int     fc;
702         int     fwidth, prec, left, sign, space, alt, zero;
703         tspec_t sz, t1, t2;
704         type_t  *tp;
705
706         fp = fmt;
707         fc = *fp++;
708
709         for ( ; ; ) {
710                 if (fc == '\0') {
711                         if (*ap != NULL)
712                                 tomanyarg(hte, call);
713                         break;
714                 }
715                 if (fc != '%') {
716                         badfmt(hte, call);
717                         break;
718                 }
719                 fc = *fp++;
720                 fwidth = prec = left = sign = space = alt = zero = 0;
721                 sz = NOTSPEC;
722
723                 /* Flags */
724                 for ( ; ; ) {
725                         if (fc == '-') {
726                                 if (left)
727                                         break;
728                                 left = 1;
729                         } else if (fc == '+') {
730                                 if (sign)
731                                         break;
732                                 sign = 1;
733                         } else if (fc == ' ') {
734                                 if (space)
735                                         break;
736                                 space = 1;
737                         } else if (fc == '#') {
738                                 if (alt)
739                                         break;
740                                 alt = 1;
741                         } else if (fc == '0') {
742                                 if (zero)
743                                         break;
744                                 zero = 1;
745                         } else {
746                                 break;
747                         }
748                         fc = *fp++;
749                 }
750
751                 /* field width */
752                 if (isdigit(fc)) {
753                         fwidth = 1;
754                         do { fc = *fp++; } while (isdigit(fc)) ;
755                 } else if (fc == '*') {
756                         fwidth = 1;
757                         fc = *fp++;
758                         if ((tp = *ap++) == NULL) {
759                                 tofewarg(hte, call);
760                                 break;
761                         }
762                         n++;
763                         if ((t1 = tp->t_tspec) != INT && (hflag || t1 != UINT))
764                                 inconarg(hte, call, n);
765                 }
766
767                 /* precision */
768                 if (fc == '.') {
769                         fc = *fp++;
770                         prec = 1;
771                         if (isdigit(fc)) {
772                                 do { fc = *fp++; } while (isdigit(fc));
773                         } else if (fc == '*') {
774                                 fc = *fp++;
775                                 if ((tp = *ap++) == NULL) {
776                                         tofewarg(hte, call);
777                                         break;
778                                 }
779                                 n++;
780                                 if (tp->t_tspec != INT)
781                                         inconarg(hte, call, n);
782                         } else {
783                                 badfmt(hte, call);
784                                 break;
785                         }
786                 }
787
788                 if (fc == 'h') {
789                         sz = SHORT;
790                 } else if (fc == 'l') {
791                         sz = LONG;
792                 } else if (fc == 'q') {
793                         sz = QUAD;
794                 } else if (fc == 'L') {
795                         sz = LDOUBLE;
796                 }
797                 if (sz != NOTSPEC)
798                         fc = *fp++;
799
800                 if (fc == '%') {
801                         if (sz != NOTSPEC || left || sign || space ||
802                             alt || zero || prec || fwidth) {
803                                 badfmt(hte, call);
804                         }
805                         fc = *fp++;
806                         continue;
807                 }
808
809                 if (fc == '\0') {
810                         badfmt(hte, call);
811                         break;
812                 }
813
814                 if ((tp = *ap++) == NULL) {
815                         tofewarg(hte, call);
816                         break;
817                 }
818                 n++;
819                 if ((t1 = tp->t_tspec) == PTR)
820                         t2 = tp->t_subt->t_tspec;
821
822                 if (fc == 'd' || fc == 'i') {
823                         if (alt || sz == LDOUBLE) {
824                                 badfmt(hte, call);
825                                 break;
826                         }
827                 int_conv:
828                         if (sz == LONG) {
829                                 if (t1 != LONG && (hflag || t1 != ULONG))
830                                         inconarg(hte, call, n);
831                         } else if (sz == QUAD) {
832                                 if (t1 != QUAD && (hflag || t1 != UQUAD))
833                                         inconarg(hte, call, n);
834                         } else {
835                                 /*
836                                  * SHORT is always promoted to INT, USHORT
837                                  * to INT or UINT.
838                                  */
839                                 if (t1 != INT && (hflag || t1 != UINT))
840                                         inconarg(hte, call, n);
841                         }
842                 } else if (fc == 'o' || fc == 'u' || fc == 'x' || fc == 'X') {
843                         if ((alt && fc == 'u') || sz == LDOUBLE)
844                                 badfmt(hte, call);
845                 uint_conv:
846                         if (sz == LONG) {
847                                 if (t1 != ULONG && (hflag || t1 != LONG))
848                                         inconarg(hte, call, n);
849                         } else if (sz == QUAD) {
850                                 if (t1 != UQUAD && (hflag || t1 != QUAD))
851                                         inconarg(hte, call, n);
852                         } else if (sz == SHORT) {
853                                 /* USHORT was promoted to INT or UINT */
854                                 if (t1 != UINT && t1 != INT)
855                                         inconarg(hte, call, n);
856                         } else {
857                                 if (t1 != UINT && (hflag || t1 != INT))
858                                         inconarg(hte, call, n);
859                         }
860                 } else if (fc == 'D' || fc == 'O' || fc == 'U') {
861                         if ((alt && fc != 'O') || sz != NOTSPEC || !tflag)
862                                 badfmt(hte, call);
863                         sz = LONG;
864                         if (fc == 'D') {
865                                 goto int_conv;
866                         } else {
867                                 goto uint_conv;
868                         }
869                 } else if (fc == 'f' || fc == 'e' || fc == 'E' ||
870                            fc == 'g' || fc == 'G') {
871                         if (sz == NOTSPEC)
872                                 sz = DOUBLE;
873                         if (sz != DOUBLE && sz != LDOUBLE)
874                                 badfmt(hte, call);
875                         if (t1 != sz)
876                                 inconarg(hte, call, n);
877                 } else if (fc == 'c') {
878                         if (sz != NOTSPEC || alt || zero)
879                                 badfmt(hte, call);
880                         if (t1 != INT)
881                                 inconarg(hte, call, n);
882                 } else if (fc == 's') {
883                         if (sz != NOTSPEC || alt || zero)
884                                 badfmt(hte, call);
885                         if (t1 != PTR ||
886                             (t2 != CHAR && t2 != UCHAR && t2 != SCHAR)) {
887                                 inconarg(hte, call, n);
888                         }
889                 } else if (fc == 'p') {
890                         if (fwidth || prec || sz != NOTSPEC || alt || zero)
891                                 badfmt(hte, call);
892                         if (t1 != PTR || (hflag && t2 != VOID))
893                                 inconarg(hte, call, n);
894                 } else if (fc == 'n') {
895                         if (fwidth || prec || alt || zero || sz == LDOUBLE)
896                                 badfmt(hte, call);
897                         if (t1 != PTR) {
898                                 inconarg(hte, call, n);
899                         } else if (sz == LONG) {
900                                 if (t2 != LONG && t2 != ULONG)
901                                         inconarg(hte, call, n);
902                         } else if (sz == SHORT) {
903                                 if (t2 != SHORT && t2 != USHORT)
904                                         inconarg(hte, call, n);
905                         } else {
906                                 if (t2 != INT && t2 != UINT)
907                                         inconarg(hte, call, n);
908                         }
909                 } else {
910                         badfmt(hte, call);
911                         break;
912                 }
913
914                 fc = *fp++;
915         }
916 }
917
918 /*
919  * Compare the types in the NULL-terminated array ap with the format
920  * string fmt.
921  */
922 static void
923 scanflike(hte, call, n, fmt, ap)
924         hte_t   *hte;
925         fcall_t *call;
926         int     n;
927         const   char *fmt;
928         type_t  **ap;
929 {
930         const   char *fp;
931         int     fc;
932         int     noasgn, fwidth;
933         tspec_t sz, t1, t2;
934         type_t  *tp;
935
936         fp = fmt;
937         fc = *fp++;
938
939         for ( ; ; ) {
940                 if (fc == '\0') {
941                         if (*ap != NULL)
942                                 tomanyarg(hte, call);
943                         break;
944                 }
945                 if (fc != '%') {
946                         badfmt(hte, call);
947                         break;
948                 }
949                 fc = *fp++;
950
951                 noasgn = fwidth = 0;
952                 sz = NOTSPEC;
953
954                 if (fc == '*') {
955                         noasgn = 1;
956                         fc = *fp++;
957                 }
958                 
959                 if (isdigit(fc)) {
960                         fwidth = 1;
961                         do { fc = *fp++; } while (isdigit(fc));
962                 }
963
964                 if (fc == 'h') {
965                         sz = SHORT;
966                 } else if (fc == 'l') {
967                         sz = LONG;
968                 } else if (fc == 'q') {
969                         sz = QUAD;
970                 } else if (fc == 'L') {
971                         sz = LDOUBLE;
972                 }
973                 if (sz != NOTSPEC)
974                         fc = *fp++;
975
976                 if (fc == '%') {
977                         if (sz != NOTSPEC || noasgn || fwidth)
978                                 badfmt(hte, call);
979                         fc = *fp++;
980                         continue;
981                 }
982
983                 if (!noasgn) {
984                         if ((tp = *ap++) == NULL) {
985                                 tofewarg(hte, call);
986                                 break;
987                         }
988                         n++;
989                         if ((t1 = tp->t_tspec) == PTR)
990                                 t2 = tp->t_subt->t_tspec;
991                 }
992
993                 if (fc == 'd' || fc == 'i' || fc == 'n') {
994                         if (sz == LDOUBLE)
995                                 badfmt(hte, call);
996                         if (sz != SHORT && sz != LONG && sz != QUAD)
997                                 sz = INT;
998                 conv:
999                         if (!noasgn) {
1000                                 if (t1 != PTR) {
1001                                         inconarg(hte, call, n);
1002                                 } else if (t2 != styp(sz)) {
1003                                         inconarg(hte, call, n);
1004                                 } else if (hflag && t2 != sz) {
1005                                         inconarg(hte, call, n);
1006                                 } else if (tp->t_subt->t_const) {
1007                                         inconarg(hte, call, n);
1008                                 }
1009                         }
1010                 } else if (fc == 'o' || fc == 'u' || fc == 'x') {
1011                         if (sz == LDOUBLE)
1012                                 badfmt(hte, call);
1013                         if (sz == SHORT) {
1014                                 sz = USHORT;
1015                         } else if (sz == LONG) {
1016                                 sz = ULONG;
1017                         } else if (sz == QUAD) {
1018                                 sz = UQUAD;
1019                         } else {
1020                                 sz = UINT;
1021                         }
1022                         goto conv;
1023                 } else if (fc == 'D') {
1024                         if (sz != NOTSPEC || !tflag)
1025                                 badfmt(hte, call);
1026                         sz = LONG;
1027                         goto conv;
1028                 } else if (fc == 'O') {
1029                         if (sz != NOTSPEC || !tflag)
1030                                 badfmt(hte, call);
1031                         sz = ULONG;
1032                         goto conv;
1033                 } else if (fc == 'X') {
1034                         /*
1035                          * XXX valid in ANSI C, but in NetBSD's libc imple-
1036                          * mented as "lx". Thats why it should be avoided.
1037                          */
1038                         if (sz != NOTSPEC || !tflag)
1039                                 badfmt(hte, call);
1040                         sz = ULONG;
1041                         goto conv;
1042                 } else if (fc == 'E') {
1043                         /*
1044                          * XXX valid in ANSI C, but in NetBSD's libc imple-
1045                          * mented as "lf". Thats why it should be avoided.
1046                          */
1047                         if (sz != NOTSPEC || !tflag)
1048                                 badfmt(hte, call);
1049                         sz = DOUBLE;
1050                         goto conv;
1051                 } else if (fc == 'F') {
1052                         /* XXX only for backward compatibility */
1053                         if (sz != NOTSPEC || !tflag)
1054                                 badfmt(hte, call);
1055                         sz = DOUBLE;
1056                         goto conv;
1057                 } else if (fc == 'G') {
1058                         /*
1059                          * XXX valid in ANSI C, but in NetBSD's libc not
1060                          * implemented
1061                          */
1062                         if (sz != NOTSPEC && sz != LONG && sz != LDOUBLE)
1063                                 badfmt(hte, call);
1064                         goto fconv;
1065                 } else if (fc == 'e' || fc == 'f' || fc == 'g') {
1066                 fconv:
1067                         if (sz == NOTSPEC) {
1068                                 sz = FLOAT;
1069                         } else if (sz == LONG) {
1070                                 sz = DOUBLE;
1071                         } else if (sz != LDOUBLE) {
1072                                 badfmt(hte, call);
1073                                 sz = FLOAT;
1074                         }
1075                         goto conv;
1076                 } else if (fc == 's' || fc == '[' || fc == 'c') {
1077                         if (sz != NOTSPEC)
1078                                 badfmt(hte, call);
1079                         if (fc == '[') {
1080                                 if ((fc = *fp++) == '-') {
1081                                         badfmt(hte, call);
1082                                         fc = *fp++;
1083                                 }
1084                                 if (fc != ']') {
1085                                         badfmt(hte, call);
1086                                         if (fc == '\0')
1087                                                 break;
1088                                 }
1089                         }
1090                         if (!noasgn) {
1091                                 if (t1 != PTR) {
1092                                         inconarg(hte, call, n);
1093                                 } else if (t2 != CHAR && t2 != UCHAR &&
1094                                            t2 != SCHAR) {
1095                                         inconarg(hte, call, n);
1096                                 }
1097                         }
1098                 } else if (fc == 'p') {
1099                         if (sz != NOTSPEC)
1100                                 badfmt(hte, call);
1101                         if (!noasgn) {
1102                                 if (t1 != PTR || t2 != PTR) {
1103                                         inconarg(hte, call, n);
1104                                 } else if (tp->t_subt->t_subt->t_tspec!=VOID) {
1105                                         if (hflag)
1106                                                 inconarg(hte, call, n);
1107                                 }
1108                         }
1109                 } else {
1110                         badfmt(hte, call);
1111                         break;
1112                 }
1113
1114                 fc = *fp++;
1115         }
1116 }
1117
1118 static void
1119 badfmt(hte, call)
1120         hte_t   *hte;
1121         fcall_t *call;
1122 {
1123         /* %s: malformed format string\t%s */
1124         msg(13, hte->h_name, mkpos(&call->f_pos));
1125 }
1126
1127 static void
1128 inconarg(hte, call, n)
1129         hte_t   *hte;
1130         fcall_t *call;
1131         int     n;
1132 {
1133         /* %s, arg %d inconsistent with format\t%s(%d) */
1134         msg(14, hte->h_name, n, mkpos(&call->f_pos));
1135 }
1136
1137 static void
1138 tofewarg(hte, call)
1139         hte_t   *hte;
1140         fcall_t *call;
1141 {
1142         /* %s: too few args for format  \t%s */
1143         msg(15, hte->h_name, mkpos(&call->f_pos));
1144 }
1145
1146 static void
1147 tomanyarg(hte, call)
1148         hte_t   *hte;
1149         fcall_t *call;
1150 {
1151         /* %s: too many args for format  \t%s */
1152         msg(16, hte->h_name, mkpos(&call->f_pos));
1153 }
1154
1155
1156 /*
1157  * Print warnings for return values which are used, but not returned,
1158  * or return values which are always or sometimes ignored.
1159  */
1160 static void
1161 chkrvu(hte, def)
1162         hte_t   *hte;
1163         sym_t   *def;
1164 {
1165         fcall_t *call;
1166         int     used, ignored;
1167
1168         if (def == NULL)
1169                 /* don't know wheter or not the functions returns a value */
1170                 return;
1171
1172         if (hte->h_calls == NULL)
1173                 return;
1174
1175         if (def->s_rval) {
1176                 /* function has return value */
1177                 used = ignored = 0;
1178                 for (call = hte->h_calls; call != NULL; call = call->f_nxt) {
1179                         used |= call->f_rused;
1180                         ignored |= !call->f_rused && !call->f_rdisc;
1181                 }
1182                 /*
1183                  * XXX as soon as we are able to disable single warnings
1184                  * the following dependencies from hflag should be removed.
1185                  * but for now I do'nt want to be botherd by this warnings
1186                  * which are almost always useless.
1187                  */
1188                 if (!used && ignored) {
1189                         if (hflag)
1190                                 /* %s returns value which is always ignored */
1191                                 msg(8, hte->h_name);
1192                 } else if (used && ignored) {
1193                         if (hflag)
1194                                 /* %s returns value which is sometimes ign. */
1195                                 msg(9, hte->h_name);
1196                 }
1197         } else {
1198                 /* function has no return value */
1199                 for (call = hte->h_calls; call != NULL; call = call->f_nxt) {
1200                         if (call->f_rused)
1201                                 /* %s value is used( %s ), but none ret. */
1202                                 msg(10, hte->h_name, mkpos(&call->f_pos));
1203                 }
1204         }
1205 }
1206
1207 /*
1208  * Print warnings for inconsistent argument declarations.
1209  */
1210 static void
1211 chkadecl(hte, def, decl)
1212         hte_t   *hte;
1213         sym_t   *def, *decl;
1214 {
1215         /* LINTED (automatic hides external declaration: warn) */
1216         int     osdef, eq, warn, n;
1217         sym_t   *sym1, *sym;
1218         type_t  **ap1, **ap2, *tp1, *tp2;
1219         char    *pos1;
1220         const   char *pos2;
1221
1222         osdef = 0;
1223         if (def != NULL) {
1224                 osdef = def->s_osdef;
1225                 sym1 = def;
1226         } else if (decl != NULL && TP(decl->s_type)->t_proto) {
1227                 sym1 = decl;
1228         } else {
1229                 return;
1230         }
1231         if (TP(sym1->s_type)->t_tspec != FUNC)
1232                 return;
1233
1234         /*
1235          * XXX Prototypes should also be compared with old style function
1236          * declarations.
1237          */
1238
1239         for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
1240                 if (sym == sym1 || !TP(sym->s_type)->t_proto)
1241                         continue;
1242                 ap1 = TP(sym1->s_type)->t_args;
1243                 ap2 = TP(sym->s_type)->t_args;
1244                 n = 0;
1245                 while (*ap1 != NULL && *ap2 != NULL) {
1246                         warn = 0;
1247                         eq = eqtype(*ap1, *ap2, 1, osdef, 0, &warn);
1248                         if (!eq || warn) {
1249                                 pos1 = xstrdup(mkpos(&sym1->s_pos));
1250                                 pos2 = mkpos(&sym->s_pos);
1251                                 /* %s, arg %d declared inconsistently ... */
1252                                 msg(11, hte->h_name, n + 1, pos1, pos2);
1253                                 free(pos1);
1254                         }
1255                         n++;
1256                         ap1++;
1257                         ap2++;
1258                 }
1259                 if (*ap1 == *ap2) {
1260                         tp1 = TP(sym1->s_type);
1261                         tp2 = TP(sym->s_type);
1262                         if (tp1->t_vararg == tp2->t_vararg)
1263                                 continue;
1264                         if (tp2->t_vararg &&
1265                             sym1->s_va && sym1->s_nva == n && !sflag) {
1266                                 continue;
1267                         }
1268                 }
1269                 /* %s: variable # of args declared\t%s  ::  %s */
1270                 pos1 = xstrdup(mkpos(&sym1->s_pos));
1271                 msg(12, hte->h_name, pos1, mkpos(&sym->s_pos));
1272                 free(pos1);
1273         }
1274 }
1275
1276
1277 /*
1278  * Check compatibility of two types. Returns 1 if types are compatible,
1279  * otherwise 0.
1280  *
1281  * ignqual      if set, ignore qualifiers of outhermost type; used for
1282  *              function arguments
1283  * promote      if set, promote left type before comparision; used for
1284  *              comparisions of arguments with parameters of old style
1285  *              definitions
1286  * asgn         left indirected type must have at least the same qualifiers
1287  *              like right indirected type (for assignments and function
1288  *              arguments)
1289  * *warn        set to 1 if an old style declaration was compared with
1290  *              an incompatible prototype declaration
1291  */
1292 static int
1293 eqtype(tp1, tp2, ignqual, promot, asgn, warn)
1294         type_t  *tp1, *tp2;
1295         int     ignqual, promot, asgn, *warn;
1296 {
1297         tspec_t t, to;
1298         int     indir;
1299
1300         to = NOTSPEC;
1301         indir = 0;
1302
1303         while (tp1 != NULL && tp2 != NULL) {
1304
1305                 t = tp1->t_tspec;
1306                 if (promot) {
1307                         if (t == FLOAT) {
1308                                 t = DOUBLE;
1309                         } else if (t == CHAR || t == SCHAR) {
1310                                 t = INT;
1311                         } else if (t == UCHAR) {
1312                                 t = tflag ? UINT : INT;
1313                         } else if (t == SHORT) {
1314                                 t = INT;
1315                         } else if (t == USHORT) {
1316                                 /* CONSTCOND */
1317                                 t = INT_MAX < USHRT_MAX || tflag ? UINT : INT;
1318                         }
1319                 }
1320
1321                 if (asgn && to == PTR) {
1322                         if (indir == 1 && (t == VOID || tp2->t_tspec == VOID))
1323                                 return (1);
1324                 }
1325                 
1326                 if (t != tp2->t_tspec) {
1327                         /*
1328                          * Give pointer to types which differ only in
1329                          * signedness a chance if not sflag and not hflag.
1330                          */
1331                         if (sflag || hflag || to != PTR)
1332                                 return (0);
1333                         if (styp(t) != styp(tp2->t_tspec))
1334                                 return (0);
1335                 }
1336
1337                 if (tp1->t_isenum && tp2->t_isenum) {
1338                         if (tp1->t_istag && tp2->t_istag) {
1339                                 return (tp1->t_tag == tp2->t_tag);
1340                         } else if (tp1->t_istynam && tp2->t_istynam) {
1341                                 return (tp1->t_tynam == tp2->t_tynam);
1342                         } else {
1343                                 return (0);
1344                         }
1345                 }
1346
1347                 /*
1348                  * XXX Handle combinations of enum and int if eflag is set.
1349                  * But note: enum and 0 should be allowed.
1350                  */
1351
1352                 if (asgn && indir == 1) {
1353                         if (!tp1->t_const && tp2->t_const)
1354                                 return (0);
1355                         if (!tp1->t_volatile && tp2->t_volatile)
1356                                 return (0);
1357                 } else if (!ignqual && !tflag) {
1358                         if (tp1->t_const != tp2->t_const)
1359                                 return (0);
1360                         if (tp1->t_const != tp2->t_const)
1361                                 return (0);
1362                 }
1363
1364                 if (t == STRUCT || t == UNION) {
1365                         if (tp1->t_istag && tp2->t_istag) {
1366                                 return (tp1->t_tag == tp2->t_tag);
1367                         } else if (tp1->t_istynam && tp2->t_istynam) {
1368                                 return (tp1->t_tynam == tp2->t_tynam);
1369                         } else {
1370                                 return (0);
1371                         }
1372                 }
1373
1374                 if (t == ARRAY && tp1->t_dim != tp2->t_dim) {
1375                         if (tp1->t_dim != 0 && tp2->t_dim != 0)
1376                                 return (0);
1377                 }
1378
1379                 if (t == FUNC) {
1380                         if (tp1->t_proto && tp2->t_proto) {
1381                                 if (!eqargs(tp1, tp2, warn))
1382                                         return (0);
1383                         } else if (tp1->t_proto) {
1384                                 if (!mnoarg(tp1, warn))
1385                                         return (0);
1386                         } else if (tp2->t_proto) {
1387                                 if (!mnoarg(tp2, warn))
1388                                         return (0);
1389                         }
1390                 }
1391
1392                 tp1 = tp1->t_subt;
1393                 tp2 = tp2->t_subt;
1394                 ignqual = promot = 0;
1395                 to = t;
1396                 indir++;
1397
1398         }
1399
1400         return (tp1 == tp2);
1401 }
1402
1403 /*
1404  * Compares arguments of two prototypes
1405  */
1406 static int
1407 eqargs(tp1, tp2, warn)
1408         type_t  *tp1, *tp2;
1409         int     *warn;
1410 {
1411         type_t  **a1, **a2;
1412
1413         if (tp1->t_vararg != tp2->t_vararg)
1414                 return (0);
1415
1416         a1 = tp1->t_args;
1417         a2 = tp2->t_args;
1418
1419         while (*a1 != NULL && *a2 != NULL) {
1420
1421                 if (eqtype(*a1, *a2, 1, 0, 0, warn) == 0)
1422                         return (0);
1423
1424                 a1++;
1425                 a2++;
1426
1427         }
1428
1429         return (*a1 == *a2);
1430 }
1431
1432 /*
1433  * mnoarg() (matches functions with no argument type information)
1434  * returns 1 if all parameters of a prototype are compatible with
1435  * and old style function declaration.
1436  * This is the case if following conditions are met:
1437  *      1. the prototype must have a fixed number of parameters
1438  *      2. no parameter is of type float
1439  *      3. no parameter is converted to another type if integer promotion
1440  *         is applied on it
1441  */
1442 static int
1443 mnoarg(tp, warn)
1444         type_t  *tp;
1445         int     *warn;
1446 {
1447         type_t  **arg;
1448         tspec_t t;
1449
1450         if (tp->t_vararg && warn != NULL)
1451                 *warn = 1;
1452         for (arg = tp->t_args; *arg != NULL; arg++) {
1453                 if ((t = (*arg)->t_tspec) == FLOAT)
1454                         return (0);
1455                 if (t == CHAR || t == SCHAR || t == UCHAR)
1456                         return (0);
1457                 if (t == SHORT || t == USHORT)
1458                         return (0);
1459         }
1460         return (1);
1461 }
1462