fmtcheck.c revision 75578
175578Skris/* $FreeBSD: head/lib/libc/gen/fmtcheck.c 75578 2001-04-17 07:59:52Z kris $ */ 275578Skris/* $NetBSD: fmtcheck.c,v 1.2 2000/11/01 01:17:20 briggs Exp $ */ 375578Skris 475578Skris/*- 575578Skris * Copyright (c) 2000 The NetBSD Foundation, Inc. 675578Skris * All rights reserved. 775578Skris * 875578Skris * This code was contributed to The NetBSD Foundation by Allen Briggs. 975578Skris * 1075578Skris * Redistribution and use in source and binary forms, with or without 1175578Skris * modification, are permitted provided that the following conditions 1275578Skris * are met: 1375578Skris * 1. Redistributions of source code must retain the above copyright 1475578Skris * notice, this list of conditions and the following disclaimer. 1575578Skris * 2. Redistributions in binary form must reproduce the above copyright 1675578Skris * notice, this list of conditions and the following disclaimer in the 1775578Skris * documentation and/or other materials provided with the distribution. 1875578Skris * 3. All advertising materials mentioning features or use of this software 1975578Skris * must display the following acknowledgement: 2075578Skris * This product includes software developed by the NetBSD 2175578Skris * Foundation, Inc. and its contributors. 2275578Skris * 4. Neither the name of The NetBSD Foundation nor the names of its 2375578Skris * contributors may be used to endorse or promote products derived 2475578Skris * from this software without specific prior written permission. 2575578Skris * 2675578Skris * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2775578Skris * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2875578Skris * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2975578Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 3075578Skris * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3175578Skris * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3275578Skris * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3375578Skris * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3475578Skris * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3575578Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3675578Skris * POSSIBILITY OF SUCH DAMAGE. 3775578Skris */ 3875578Skris 3975578Skris#include <sys/cdefs.h> 4075578Skris#ifndef lint 4175578Skrisstatic const char rcsid[] = 4275578Skris "$FreeBSD: head/lib/libc/gen/fmtcheck.c 75578 2001-04-17 07:59:52Z kris $"; 4375578Skris#endif /* not lint */ 4475578Skris 4575578Skris#include "namespace.h" 4675578Skris 4775578Skris#include <stdlib.h> 4875578Skris#include <stdio.h> 4975578Skris#include <string.h> 5075578Skris#include <ctype.h> 5175578Skris 5275578Skris#ifdef __weak_alias 5375578Skris__weak_alias(fmtcheck,__fmtcheck) 5475578Skris#endif 5575578Skris 5675578Skrisenum __e_fmtcheck_types { 5775578Skris FMTCHECK_START, 5875578Skris FMTCHECK_SHORT, 5975578Skris FMTCHECK_INT, 6075578Skris FMTCHECK_LONG, 6175578Skris FMTCHECK_QUAD, 6275578Skris FMTCHECK_SHORTPOINTER, 6375578Skris FMTCHECK_INTPOINTER, 6475578Skris FMTCHECK_LONGPOINTER, 6575578Skris FMTCHECK_QUADPOINTER, 6675578Skris FMTCHECK_DOUBLE, 6775578Skris FMTCHECK_LONGDOUBLE, 6875578Skris FMTCHECK_STRING, 6975578Skris FMTCHECK_WIDTH, 7075578Skris FMTCHECK_PRECISION, 7175578Skris FMTCHECK_DONE, 7275578Skris FMTCHECK_UNKNOWN 7375578Skris}; 7475578Skristypedef enum __e_fmtcheck_types EFT; 7575578Skris 7675578Skris#define RETURN(pf,f,r) do { \ 7775578Skris *(pf) = (f); \ 7875578Skris return r; \ 7975578Skris } /*NOTREACHED*/ /*CONSTCOND*/ while (0) 8075578Skris 8175578Skrisstatic EFT 8275578Skrisget_next_format_from_precision(const char **pf) 8375578Skris{ 8475578Skris int sh, lg, quad, longdouble; 8575578Skris const char *f; 8675578Skris 8775578Skris sh = lg = quad = longdouble = 0; 8875578Skris 8975578Skris f = *pf; 9075578Skris switch (*f) { 9175578Skris case 'h': 9275578Skris f++; 9375578Skris sh = 1; 9475578Skris break; 9575578Skris case 'l': 9675578Skris f++; 9775578Skris if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 9875578Skris if (*f == 'l') { 9975578Skris f++; 10075578Skris quad = 1; 10175578Skris } else { 10275578Skris lg = 1; 10375578Skris } 10475578Skris break; 10575578Skris case 'q': 10675578Skris f++; 10775578Skris quad = 1; 10875578Skris break; 10975578Skris case 'L': 11075578Skris f++; 11175578Skris longdouble = 1; 11275578Skris break; 11375578Skris default: 11475578Skris break; 11575578Skris } 11675578Skris if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 11775578Skris if (strchr("diouxX", *f)) { 11875578Skris if (longdouble) 11975578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 12075578Skris if (lg) 12175578Skris RETURN(pf,f,FMTCHECK_LONG); 12275578Skris if (quad) 12375578Skris RETURN(pf,f,FMTCHECK_QUAD); 12475578Skris RETURN(pf,f,FMTCHECK_INT); 12575578Skris } 12675578Skris if (*f == 'n') { 12775578Skris if (longdouble) 12875578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 12975578Skris if (sh) 13075578Skris RETURN(pf,f,FMTCHECK_SHORTPOINTER); 13175578Skris if (lg) 13275578Skris RETURN(pf,f,FMTCHECK_LONGPOINTER); 13375578Skris if (quad) 13475578Skris RETURN(pf,f,FMTCHECK_QUADPOINTER); 13575578Skris RETURN(pf,f,FMTCHECK_INTPOINTER); 13675578Skris } 13775578Skris if (strchr("DOU", *f)) { 13875578Skris if (sh + lg + quad + longdouble) 13975578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 14075578Skris RETURN(pf,f,FMTCHECK_LONG); 14175578Skris } 14275578Skris if (strchr("eEfg", *f)) { 14375578Skris if (longdouble) 14475578Skris RETURN(pf,f,FMTCHECK_LONGDOUBLE); 14575578Skris if (sh + lg + quad) 14675578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 14775578Skris RETURN(pf,f,FMTCHECK_DOUBLE); 14875578Skris } 14975578Skris if (*f == 'c') { 15075578Skris if (sh + lg + quad + longdouble) 15175578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 15275578Skris RETURN(pf,f,FMTCHECK_INT); 15375578Skris } 15475578Skris if (*f == 's') { 15575578Skris if (sh + lg + quad + longdouble) 15675578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 15775578Skris RETURN(pf,f,FMTCHECK_STRING); 15875578Skris } 15975578Skris if (*f == 'p') { 16075578Skris if (sh + lg + quad + longdouble) 16175578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 16275578Skris RETURN(pf,f,FMTCHECK_LONG); 16375578Skris } 16475578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 16575578Skris /*NOTREACHED*/ 16675578Skris} 16775578Skris 16875578Skrisstatic EFT 16975578Skrisget_next_format_from_width(const char **pf) 17075578Skris{ 17175578Skris const char *f; 17275578Skris 17375578Skris f = *pf; 17475578Skris if (*f == '.') { 17575578Skris f++; 17675578Skris if (*f == '*') { 17775578Skris RETURN(pf,f,FMTCHECK_PRECISION); 17875578Skris } 17975578Skris /* eat any precision (empty is allowed) */ 18075578Skris while (isdigit(*f)) f++; 18175578Skris if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 18275578Skris } 18375578Skris RETURN(pf,f,get_next_format_from_precision(pf)); 18475578Skris /*NOTREACHED*/ 18575578Skris} 18675578Skris 18775578Skrisstatic EFT 18875578Skrisget_next_format(const char **pf, EFT eft) 18975578Skris{ 19075578Skris int infmt; 19175578Skris const char *f; 19275578Skris 19375578Skris if (eft == FMTCHECK_WIDTH) { 19475578Skris (*pf)++; 19575578Skris return get_next_format_from_width(pf); 19675578Skris } else if (eft == FMTCHECK_PRECISION) { 19775578Skris (*pf)++; 19875578Skris return get_next_format_from_precision(pf); 19975578Skris } 20075578Skris 20175578Skris f = *pf; 20275578Skris infmt = 0; 20375578Skris while (!infmt) { 20475578Skris f = strchr(f, '%'); 20575578Skris if (f == NULL) 20675578Skris RETURN(pf,f,FMTCHECK_DONE); 20775578Skris f++; 20875578Skris if (!*f) 20975578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 21075578Skris if (*f != '%') 21175578Skris infmt = 1; 21275578Skris else 21375578Skris f++; 21475578Skris } 21575578Skris 21675578Skris /* Eat any of the flags */ 21775578Skris while (*f && (strchr("#0- +", *f))) 21875578Skris f++; 21975578Skris 22075578Skris if (*f == '*') { 22175578Skris RETURN(pf,f,FMTCHECK_WIDTH); 22275578Skris } 22375578Skris /* eat any width */ 22475578Skris while (isdigit(*f)) f++; 22575578Skris if (!*f) { 22675578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 22775578Skris } 22875578Skris 22975578Skris RETURN(pf,f,get_next_format_from_width(pf)); 23075578Skris /*NOTREACHED*/ 23175578Skris} 23275578Skris 23375578Skris__const char * 23475578Skrisfmtcheck(const char *f1, const char *f2) 23575578Skris{ 23675578Skris const char *f1p, *f2p; 23775578Skris EFT f1t, f2t; 23875578Skris 23975578Skris if (!f1) return f2; 24075578Skris 24175578Skris f1p = f1; 24275578Skris f1t = FMTCHECK_START; 24375578Skris f2p = f2; 24475578Skris f2t = FMTCHECK_START; 24575578Skris while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) { 24675578Skris if (f1t == FMTCHECK_UNKNOWN) 24775578Skris return f2; 24875578Skris f2t = get_next_format(&f2p, f2t); 24975578Skris if (f1t != f2t) 25075578Skris return f2; 25175578Skris } 25275578Skris return f1; 25375578Skris} 254