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