fmtcheck.c revision 90039
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 90039 2002-02-01 00:57:29Z obrien $");
3975578Skris
4075578Skris#include "namespace.h"
4175578Skris
4275578Skris#include <stdio.h>
4375578Skris#include <string.h>
4475578Skris#include <ctype.h>
4575578Skris
4675578Skris#ifdef __weak_alias
4775578Skris__weak_alias(fmtcheck,__fmtcheck)
4875578Skris#endif
4975578Skris
5075578Skrisenum __e_fmtcheck_types {
5175578Skris	FMTCHECK_START,
5275578Skris	FMTCHECK_SHORT,
5375578Skris	FMTCHECK_INT,
5475578Skris	FMTCHECK_LONG,
5575578Skris	FMTCHECK_QUAD,
5675578Skris	FMTCHECK_SHORTPOINTER,
5775578Skris	FMTCHECK_INTPOINTER,
5875578Skris	FMTCHECK_LONGPOINTER,
5975578Skris	FMTCHECK_QUADPOINTER,
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{
7875578Skris	int		sh, lg, quad, longdouble;
7975578Skris	const char	*f;
8075578Skris
8175578Skris	sh = lg = quad = longdouble = 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;
10375578Skris	case 'L':
10475578Skris		f++;
10575578Skris		longdouble = 1;
10675578Skris		break;
10775578Skris	default:
10875578Skris		break;
10975578Skris	}
11075578Skris	if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
11175578Skris	if (strchr("diouxX", *f)) {
11275578Skris		if (longdouble)
11375578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
11475578Skris		if (lg)
11575578Skris			RETURN(pf,f,FMTCHECK_LONG);
11675578Skris		if (quad)
11775578Skris			RETURN(pf,f,FMTCHECK_QUAD);
11875578Skris		RETURN(pf,f,FMTCHECK_INT);
11975578Skris	}
12075578Skris	if (*f == 'n') {
12175578Skris		if (longdouble)
12275578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
12375578Skris		if (sh)
12475578Skris			RETURN(pf,f,FMTCHECK_SHORTPOINTER);
12575578Skris		if (lg)
12675578Skris			RETURN(pf,f,FMTCHECK_LONGPOINTER);
12775578Skris		if (quad)
12875578Skris			RETURN(pf,f,FMTCHECK_QUADPOINTER);
12975578Skris		RETURN(pf,f,FMTCHECK_INTPOINTER);
13075578Skris	}
13175578Skris	if (strchr("DOU", *f)) {
13275578Skris		if (sh + lg + quad + longdouble)
13375578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
13475578Skris		RETURN(pf,f,FMTCHECK_LONG);
13575578Skris	}
13675578Skris	if (strchr("eEfg", *f)) {
13775578Skris		if (longdouble)
13875578Skris			RETURN(pf,f,FMTCHECK_LONGDOUBLE);
13975578Skris		if (sh + lg + quad)
14075578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
14175578Skris		RETURN(pf,f,FMTCHECK_DOUBLE);
14275578Skris	}
14375578Skris	if (*f == 'c') {
14475578Skris		if (sh + lg + quad + longdouble)
14575578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
14675578Skris		RETURN(pf,f,FMTCHECK_INT);
14775578Skris	}
14875578Skris	if (*f == 's') {
14975578Skris		if (sh + lg + quad + longdouble)
15075578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
15175578Skris		RETURN(pf,f,FMTCHECK_STRING);
15275578Skris	}
15375578Skris	if (*f == 'p') {
15475578Skris		if (sh + lg + quad + longdouble)
15575578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
15675578Skris		RETURN(pf,f,FMTCHECK_LONG);
15775578Skris	}
15875578Skris	RETURN(pf,f,FMTCHECK_UNKNOWN);
15975578Skris	/*NOTREACHED*/
16075578Skris}
16175578Skris
16275578Skrisstatic EFT
16375578Skrisget_next_format_from_width(const char **pf)
16475578Skris{
16575578Skris	const char	*f;
16675578Skris
16775578Skris	f = *pf;
16875578Skris	if (*f == '.') {
16975578Skris		f++;
17075578Skris		if (*f == '*') {
17175578Skris			RETURN(pf,f,FMTCHECK_PRECISION);
17275578Skris		}
17375578Skris		/* eat any precision (empty is allowed) */
17475578Skris		while (isdigit(*f)) f++;
17575578Skris		if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
17675578Skris	}
17775578Skris	RETURN(pf,f,get_next_format_from_precision(pf));
17875578Skris	/*NOTREACHED*/
17975578Skris}
18075578Skris
18175578Skrisstatic EFT
18275578Skrisget_next_format(const char **pf, EFT eft)
18375578Skris{
18475578Skris	int		infmt;
18575578Skris	const char	*f;
18675578Skris
18775578Skris	if (eft == FMTCHECK_WIDTH) {
18875578Skris		(*pf)++;
18975578Skris		return get_next_format_from_width(pf);
19075578Skris	} else if (eft == FMTCHECK_PRECISION) {
19175578Skris		(*pf)++;
19275578Skris		return get_next_format_from_precision(pf);
19375578Skris	}
19475578Skris
19575578Skris	f = *pf;
19675578Skris	infmt = 0;
19775578Skris	while (!infmt) {
19875578Skris		f = strchr(f, '%');
19975578Skris		if (f == NULL)
20075578Skris			RETURN(pf,f,FMTCHECK_DONE);
20175578Skris		f++;
20275578Skris		if (!*f)
20375578Skris			RETURN(pf,f,FMTCHECK_UNKNOWN);
20475578Skris		if (*f != '%')
20575578Skris			infmt = 1;
20675578Skris		else
20775578Skris			f++;
20875578Skris	}
20975578Skris
21075578Skris	/* Eat any of the flags */
21175578Skris	while (*f && (strchr("#0- +", *f)))
21275578Skris		f++;
21375578Skris
21475578Skris	if (*f == '*') {
21575578Skris		RETURN(pf,f,FMTCHECK_WIDTH);
21675578Skris	}
21775578Skris	/* eat any width */
21875578Skris	while (isdigit(*f)) f++;
21975578Skris	if (!*f) {
22075578Skris		RETURN(pf,f,FMTCHECK_UNKNOWN);
22175578Skris	}
22275578Skris
22375578Skris	RETURN(pf,f,get_next_format_from_width(pf));
22475578Skris	/*NOTREACHED*/
22575578Skris}
22675578Skris
22775578Skris__const char *
22875578Skrisfmtcheck(const char *f1, const char *f2)
22975578Skris{
23075578Skris	const char	*f1p, *f2p;
23175578Skris	EFT		f1t, f2t;
23275578Skris
23375578Skris	if (!f1) return f2;
23475578Skris
23575578Skris	f1p = f1;
23675578Skris	f1t = FMTCHECK_START;
23775578Skris	f2p = f2;
23875578Skris	f2t = FMTCHECK_START;
23975578Skris	while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
24075578Skris		if (f1t == FMTCHECK_UNKNOWN)
24175578Skris			return f2;
24275578Skris		f2t = get_next_format(&f2p, f2t);
24375578Skris		if (f1t != f2t)
24475578Skris			return f2;
24575578Skris	}
24675578Skris	return f1;
24775578Skris}
248