fmtcheck.c revision 117014
175578Skris/*-
275578Skris * Copyright (c) 2000 The NetBSD Foundation, Inc.
375578Skris * All rights reserved.
475578Skris *
575578Skris * This code was contributed to The NetBSD Foundation by Allen Briggs.
675578Skris *
775578Skris * Redistribution and use in source and binary forms, with or without
875578Skris * modification, are permitted provided that the following conditions
975578Skris * are met:
1075578Skris * 1. Redistributions of source code must retain the above copyright
1175578Skris *    notice, this list of conditions and the following disclaimer.
1275578Skris * 2. Redistributions in binary form must reproduce the above copyright
1375578Skris *    notice, this list of conditions and the following disclaimer in the
1475578Skris *    documentation and/or other materials provided with the distribution.
1575578Skris * 3. All advertising materials mentioning features or use of this software
1675578Skris *    must display the following acknowledgement:
1775578Skris *        This product includes software developed by the NetBSD
1875578Skris *        Foundation, Inc. and its contributors.
1975578Skris * 4. Neither the name of The NetBSD Foundation nor the names of its
2075578Skris *    contributors may be used to endorse or promote products derived
2175578Skris *    from this software without specific prior written permission.
2275578Skris *
2375578Skris * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2475578Skris * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2575578Skris * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2675578Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2775578Skris * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2875578Skris * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2975578Skris * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3075578Skris * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3175578Skris * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3275578Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3375578Skris * POSSIBILITY OF SUCH DAMAGE.
3475578Skris */
3575578Skris
3690039Sobrien/*	$NetBSD: fmtcheck.c,v 1.2 2000/11/01 01:17:20 briggs Exp $	*/
3775578Skris#include <sys/cdefs.h>
3890039Sobrien__FBSDID("$FreeBSD: head/lib/libc/gen/fmtcheck.c 117014 2003-06-29 01:11:31Z das $");
3975578Skris
4075578Skris#include <stdio.h>
4175578Skris#include <string.h>
4275578Skris#include <ctype.h>
4375578Skris
4498908Sdeischen__weak_reference(__fmtcheck, fmtcheck);
4575578Skris
4675578Skrisenum __e_fmtcheck_types {
4775578Skris	FMTCHECK_START,
4875578Skris	FMTCHECK_SHORT,
4975578Skris	FMTCHECK_INT,
5075578Skris	FMTCHECK_LONG,
5175578Skris	FMTCHECK_QUAD,
52117014Sdas	FMTCHECK_PTRDIFFT,
53117014Sdas	FMTCHECK_SIZET,
5475578Skris	FMTCHECK_SHORTPOINTER,
5575578Skris	FMTCHECK_INTPOINTER,
5675578Skris	FMTCHECK_LONGPOINTER,
5775578Skris	FMTCHECK_QUADPOINTER,
58117014Sdas	FMTCHECK_PTRDIFFTPOINTER,
59117014Sdas	FMTCHECK_SIZETPOINTER,
6075578Skris	FMTCHECK_DOUBLE,
6175578Skris	FMTCHECK_LONGDOUBLE,
6275578Skris	FMTCHECK_STRING,
6375578Skris	FMTCHECK_WIDTH,
6475578Skris	FMTCHECK_PRECISION,
6575578Skris	FMTCHECK_DONE,
6675578Skris	FMTCHECK_UNKNOWN
6775578Skris};
6875578Skristypedef enum __e_fmtcheck_types EFT;
6975578Skris
7075578Skris#define RETURN(pf,f,r) do { \
7175578Skris			*(pf) = (f); \
7275578Skris			return r; \
7375578Skris		       } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
7475578Skris
7575578Skrisstatic EFT
7675578Skrisget_next_format_from_precision(const char **pf)
7775578Skris{
78117014Sdas	int		sh, lg, quad, longdouble, ptrdifft, sizet;
7975578Skris	const char	*f;
8075578Skris
81117014Sdas	sh = lg = quad = longdouble = ptrdifft = sizet = 0;
8275578Skris
8375578Skris	f = *pf;
8475578Skris	switch (*f) {
8575578Skris	case 'h':
8675578Skris		f++;
8775578Skris		sh = 1;
8875578Skris		break;
8975578Skris	case 'l':
9075578Skris		f++;
9175578Skris		if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
9275578Skris		if (*f == 'l') {
9375578Skris			f++;
9475578Skris			quad = 1;
9575578Skris		} else {
9675578Skris			lg = 1;
9775578Skris		}
9875578Skris		break;
9975578Skris	case 'q':
10075578Skris		f++;
10175578Skris		quad = 1;
10275578Skris		break;
103117014Sdas	case 't':
104117014Sdas		f++;
105117014Sdas		ptrdifft = 1;
106117014Sdas		break;
107117014Sdas	case 'z':
108117014Sdas		f++;
109117014Sdas		sizet = 1;
110117014Sdas		break;
11175578Skris	case 'L':
11275578Skris		f++;
11375578Skris		longdouble = 1;
11475578Skris		break;
11575578Skris	default:
11675578Skris		break;
11775578Skris	}
11875578Skris	if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
11975578Skris	if (strchr("diouxX", *f)) {
12075578Skris		if (longdouble)
12175578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
12275578Skris		if (lg)
12375578Skris			RETURN(pf,f,FMTCHECK_LONG);
12475578Skris		if (quad)
12575578Skris			RETURN(pf,f,FMTCHECK_QUAD);
126117014Sdas		if (ptrdifft)
127117014Sdas			RETURN(pf,f,FMTCHECK_PTRDIFFT);
128117014Sdas		if (sizet)
129117014Sdas			RETURN(pf,f,FMTCHECK_SIZET);
13075578Skris		RETURN(pf,f,FMTCHECK_INT);
13175578Skris	}
13275578Skris	if (*f == 'n') {
13375578Skris		if (longdouble)
13475578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
13575578Skris		if (sh)
13675578Skris			RETURN(pf,f,FMTCHECK_SHORTPOINTER);
13775578Skris		if (lg)
13875578Skris			RETURN(pf,f,FMTCHECK_LONGPOINTER);
13975578Skris		if (quad)
14075578Skris			RETURN(pf,f,FMTCHECK_QUADPOINTER);
141117014Sdas		if (ptrdifft)
142117014Sdas			RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
143117014Sdas		if (sizet)
144117014Sdas			RETURN(pf,f,FMTCHECK_SIZETPOINTER);
14575578Skris		RETURN(pf,f,FMTCHECK_INTPOINTER);
14675578Skris	}
14775578Skris	if (strchr("DOU", *f)) {
148117014Sdas		if (sh + lg + quad + longdouble + ptrdifft + sizet)
14975578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
15075578Skris		RETURN(pf,f,FMTCHECK_LONG);
15175578Skris	}
152117014Sdas	if (strchr("aAeEfFgG", *f)) {
15375578Skris		if (longdouble)
15475578Skris			RETURN(pf,f,FMTCHECK_LONGDOUBLE);
155117014Sdas		if (sh + lg + quad + ptrdifft + sizet)
15675578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
15775578Skris		RETURN(pf,f,FMTCHECK_DOUBLE);
15875578Skris	}
15975578Skris	if (*f == 'c') {
160117014Sdas		if (sh + lg + quad + longdouble + ptrdifft + sizet)
16175578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
16275578Skris		RETURN(pf,f,FMTCHECK_INT);
16375578Skris	}
16475578Skris	if (*f == 's') {
165117014Sdas		if (sh + lg + quad + longdouble + ptrdifft + sizet)
16675578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
16775578Skris		RETURN(pf,f,FMTCHECK_STRING);
16875578Skris	}
16975578Skris	if (*f == 'p') {
170117014Sdas		if (sh + lg + quad + longdouble + ptrdifft + sizet)
17175578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
17275578Skris		RETURN(pf,f,FMTCHECK_LONG);
17375578Skris	}
17475578Skris	RETURN(pf,f,FMTCHECK_UNKNOWN);
17575578Skris	/*NOTREACHED*/
17675578Skris}
17775578Skris
17875578Skrisstatic EFT
17975578Skrisget_next_format_from_width(const char **pf)
18075578Skris{
18175578Skris	const char	*f;
18275578Skris
18375578Skris	f = *pf;
18475578Skris	if (*f == '.') {
18575578Skris		f++;
18675578Skris		if (*f == '*') {
18775578Skris			RETURN(pf,f,FMTCHECK_PRECISION);
18875578Skris		}
18975578Skris		/* eat any precision (empty is allowed) */
19075578Skris		while (isdigit(*f)) f++;
19175578Skris		if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
19275578Skris	}
19375578Skris	RETURN(pf,f,get_next_format_from_precision(pf));
19475578Skris	/*NOTREACHED*/
19575578Skris}
19675578Skris
19775578Skrisstatic EFT
19875578Skrisget_next_format(const char **pf, EFT eft)
19975578Skris{
20075578Skris	int		infmt;
20175578Skris	const char	*f;
20275578Skris
20375578Skris	if (eft == FMTCHECK_WIDTH) {
20475578Skris		(*pf)++;
20575578Skris		return get_next_format_from_width(pf);
20675578Skris	} else if (eft == FMTCHECK_PRECISION) {
20775578Skris		(*pf)++;
20875578Skris		return get_next_format_from_precision(pf);
20975578Skris	}
21075578Skris
21175578Skris	f = *pf;
21275578Skris	infmt = 0;
21375578Skris	while (!infmt) {
21475578Skris		f = strchr(f, '%');
21575578Skris		if (f == NULL)
21675578Skris			RETURN(pf,f,FMTCHECK_DONE);
21775578Skris		f++;
21875578Skris		if (!*f)
21975578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
22075578Skris		if (*f != '%')
22175578Skris			infmt = 1;
22275578Skris		else
22375578Skris			f++;
22475578Skris	}
22575578Skris
22675578Skris	/* Eat any of the flags */
22775578Skris	while (*f && (strchr("#0- +", *f)))
22875578Skris		f++;
22975578Skris
23075578Skris	if (*f == '*') {
23175578Skris		RETURN(pf,f,FMTCHECK_WIDTH);
23275578Skris	}
23375578Skris	/* eat any width */
23475578Skris	while (isdigit(*f)) f++;
23575578Skris	if (!*f) {
23675578Skris		RETURN(pf,f,FMTCHECK_UNKNOWN);
23775578Skris	}
23875578Skris
23975578Skris	RETURN(pf,f,get_next_format_from_width(pf));
24075578Skris	/*NOTREACHED*/
24175578Skris}
24275578Skris
24375578Skris__const char *
24498908Sdeischen__fmtcheck(const char *f1, const char *f2)
24575578Skris{
24675578Skris	const char	*f1p, *f2p;
24775578Skris	EFT		f1t, f2t;
24875578Skris
24975578Skris	if (!f1) return f2;
25075578Skris
25175578Skris	f1p = f1;
25275578Skris	f1t = FMTCHECK_START;
25375578Skris	f2p = f2;
25475578Skris	f2t = FMTCHECK_START;
25575578Skris	while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
25675578Skris		if (f1t == FMTCHECK_UNKNOWN)
25775578Skris			return f2;
25875578Skris		f2t = get_next_format(&f2p, f2t);
25975578Skris		if (f1t != f2t)
26075578Skris			return f2;
26175578Skris	}
26275578Skris	return f1;
26375578Skris}
264