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