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