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