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