fmtcheck.c revision 128818
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 128818 2004-05-02 10:55:05Z 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,
60128818Sdas#ifndef NO_FLOATING_POINT
6175578Skris	FMTCHECK_DOUBLE,
6275578Skris	FMTCHECK_LONGDOUBLE,
63128818Sdas#endif
6475578Skris	FMTCHECK_STRING,
6575578Skris	FMTCHECK_WIDTH,
6675578Skris	FMTCHECK_PRECISION,
6775578Skris	FMTCHECK_DONE,
6875578Skris	FMTCHECK_UNKNOWN
6975578Skris};
7075578Skristypedef enum __e_fmtcheck_types EFT;
7175578Skris
7275578Skris#define RETURN(pf,f,r) do { \
7375578Skris			*(pf) = (f); \
7475578Skris			return r; \
7575578Skris		       } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
7675578Skris
7775578Skrisstatic EFT
7875578Skrisget_next_format_from_precision(const char **pf)
7975578Skris{
80117014Sdas	int		sh, lg, quad, longdouble, ptrdifft, sizet;
8175578Skris	const char	*f;
8275578Skris
83117014Sdas	sh = lg = quad = longdouble = ptrdifft = sizet = 0;
8475578Skris
8575578Skris	f = *pf;
8675578Skris	switch (*f) {
8775578Skris	case 'h':
8875578Skris		f++;
8975578Skris		sh = 1;
9075578Skris		break;
9175578Skris	case 'l':
9275578Skris		f++;
9375578Skris		if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
9475578Skris		if (*f == 'l') {
9575578Skris			f++;
9675578Skris			quad = 1;
9775578Skris		} else {
9875578Skris			lg = 1;
9975578Skris		}
10075578Skris		break;
10175578Skris	case 'q':
10275578Skris		f++;
10375578Skris		quad = 1;
10475578Skris		break;
105117014Sdas	case 't':
106117014Sdas		f++;
107117014Sdas		ptrdifft = 1;
108117014Sdas		break;
109117014Sdas	case 'z':
110117014Sdas		f++;
111117014Sdas		sizet = 1;
112117014Sdas		break;
11375578Skris	case 'L':
11475578Skris		f++;
11575578Skris		longdouble = 1;
11675578Skris		break;
11775578Skris	default:
11875578Skris		break;
11975578Skris	}
12075578Skris	if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
12175578Skris	if (strchr("diouxX", *f)) {
12275578Skris		if (longdouble)
12375578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
12475578Skris		if (lg)
12575578Skris			RETURN(pf,f,FMTCHECK_LONG);
12675578Skris		if (quad)
12775578Skris			RETURN(pf,f,FMTCHECK_QUAD);
128117014Sdas		if (ptrdifft)
129117014Sdas			RETURN(pf,f,FMTCHECK_PTRDIFFT);
130117014Sdas		if (sizet)
131117014Sdas			RETURN(pf,f,FMTCHECK_SIZET);
13275578Skris		RETURN(pf,f,FMTCHECK_INT);
13375578Skris	}
13475578Skris	if (*f == 'n') {
13575578Skris		if (longdouble)
13675578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
13775578Skris		if (sh)
13875578Skris			RETURN(pf,f,FMTCHECK_SHORTPOINTER);
13975578Skris		if (lg)
14075578Skris			RETURN(pf,f,FMTCHECK_LONGPOINTER);
14175578Skris		if (quad)
14275578Skris			RETURN(pf,f,FMTCHECK_QUADPOINTER);
143117014Sdas		if (ptrdifft)
144117014Sdas			RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
145117014Sdas		if (sizet)
146117014Sdas			RETURN(pf,f,FMTCHECK_SIZETPOINTER);
14775578Skris		RETURN(pf,f,FMTCHECK_INTPOINTER);
14875578Skris	}
14975578Skris	if (strchr("DOU", *f)) {
150117014Sdas		if (sh + lg + quad + longdouble + ptrdifft + sizet)
15175578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
15275578Skris		RETURN(pf,f,FMTCHECK_LONG);
15375578Skris	}
154128818Sdas#ifndef NO_FLOATING_POINT
155117014Sdas	if (strchr("aAeEfFgG", *f)) {
15675578Skris		if (longdouble)
15775578Skris			RETURN(pf,f,FMTCHECK_LONGDOUBLE);
158117014Sdas		if (sh + lg + quad + ptrdifft + sizet)
15975578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
16075578Skris		RETURN(pf,f,FMTCHECK_DOUBLE);
16175578Skris	}
162128818Sdas#endif
16375578Skris	if (*f == 'c') {
164117014Sdas		if (sh + lg + quad + longdouble + ptrdifft + sizet)
16575578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
16675578Skris		RETURN(pf,f,FMTCHECK_INT);
16775578Skris	}
16875578Skris	if (*f == 's') {
169117014Sdas		if (sh + lg + quad + longdouble + ptrdifft + sizet)
17075578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
17175578Skris		RETURN(pf,f,FMTCHECK_STRING);
17275578Skris	}
17375578Skris	if (*f == 'p') {
174117014Sdas		if (sh + lg + quad + longdouble + ptrdifft + sizet)
17575578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
17675578Skris		RETURN(pf,f,FMTCHECK_LONG);
17775578Skris	}
17875578Skris	RETURN(pf,f,FMTCHECK_UNKNOWN);
17975578Skris	/*NOTREACHED*/
18075578Skris}
18175578Skris
18275578Skrisstatic EFT
18375578Skrisget_next_format_from_width(const char **pf)
18475578Skris{
18575578Skris	const char	*f;
18675578Skris
18775578Skris	f = *pf;
18875578Skris	if (*f == '.') {
18975578Skris		f++;
19075578Skris		if (*f == '*') {
19175578Skris			RETURN(pf,f,FMTCHECK_PRECISION);
19275578Skris		}
19375578Skris		/* eat any precision (empty is allowed) */
19475578Skris		while (isdigit(*f)) f++;
19575578Skris		if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
19675578Skris	}
19775578Skris	RETURN(pf,f,get_next_format_from_precision(pf));
19875578Skris	/*NOTREACHED*/
19975578Skris}
20075578Skris
20175578Skrisstatic EFT
20275578Skrisget_next_format(const char **pf, EFT eft)
20375578Skris{
20475578Skris	int		infmt;
20575578Skris	const char	*f;
20675578Skris
20775578Skris	if (eft == FMTCHECK_WIDTH) {
20875578Skris		(*pf)++;
20975578Skris		return get_next_format_from_width(pf);
21075578Skris	} else if (eft == FMTCHECK_PRECISION) {
21175578Skris		(*pf)++;
21275578Skris		return get_next_format_from_precision(pf);
21375578Skris	}
21475578Skris
21575578Skris	f = *pf;
21675578Skris	infmt = 0;
21775578Skris	while (!infmt) {
21875578Skris		f = strchr(f, '%');
21975578Skris		if (f == NULL)
22075578Skris			RETURN(pf,f,FMTCHECK_DONE);
22175578Skris		f++;
22275578Skris		if (!*f)
22375578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
22475578Skris		if (*f != '%')
22575578Skris			infmt = 1;
22675578Skris		else
22775578Skris			f++;
22875578Skris	}
22975578Skris
23075578Skris	/* Eat any of the flags */
23175578Skris	while (*f && (strchr("#0- +", *f)))
23275578Skris		f++;
23375578Skris
23475578Skris	if (*f == '*') {
23575578Skris		RETURN(pf,f,FMTCHECK_WIDTH);
23675578Skris	}
23775578Skris	/* eat any width */
23875578Skris	while (isdigit(*f)) f++;
23975578Skris	if (!*f) {
24075578Skris		RETURN(pf,f,FMTCHECK_UNKNOWN);
24175578Skris	}
24275578Skris
24375578Skris	RETURN(pf,f,get_next_format_from_width(pf));
24475578Skris	/*NOTREACHED*/
24575578Skris}
24675578Skris
24775578Skris__const char *
24898908Sdeischen__fmtcheck(const char *f1, const char *f2)
24975578Skris{
25075578Skris	const char	*f1p, *f2p;
25175578Skris	EFT		f1t, f2t;
25275578Skris
25375578Skris	if (!f1) return f2;
25475578Skris
25575578Skris	f1p = f1;
25675578Skris	f1t = FMTCHECK_START;
25775578Skris	f2p = f2;
25875578Skris	f2t = FMTCHECK_START;
25975578Skris	while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
26075578Skris		if (f1t == FMTCHECK_UNKNOWN)
26175578Skris			return f2;
26275578Skris		f2t = get_next_format(&f2p, f2t);
26375578Skris		if (f1t != f2t)
26475578Skris			return f2;
26575578Skris	}
26675578Skris	return f1;
26775578Skris}
268