1194800Sdelphij/* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */ 2194800Sdelphij 375578Skris/*- 475578Skris * Copyright (c) 2000 The NetBSD Foundation, Inc. 575578Skris * All rights reserved. 675578Skris * 775578Skris * This code was contributed to The NetBSD Foundation by Allen Briggs. 875578Skris * 975578Skris * Redistribution and use in source and binary forms, with or without 1075578Skris * modification, are permitted provided that the following conditions 1175578Skris * are met: 1275578Skris * 1. Redistributions of source code must retain the above copyright 1375578Skris * notice, this list of conditions and the following disclaimer. 1475578Skris * 2. Redistributions in binary form must reproduce the above copyright 1575578Skris * notice, this list of conditions and the following disclaimer in the 1675578Skris * documentation and/or other materials provided with the distribution. 1775578Skris * 1875578Skris * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1975578Skris * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2075578Skris * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2175578Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2275578Skris * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2375578Skris * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2475578Skris * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2575578Skris * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2675578Skris * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2775578Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2875578Skris * POSSIBILITY OF SUCH DAMAGE. 2975578Skris */ 3075578Skris 3175578Skris#include <sys/cdefs.h> 3290039Sobrien__FBSDID("$FreeBSD$"); 3375578Skris 3475578Skris#include <stdio.h> 3575578Skris#include <string.h> 3675578Skris#include <ctype.h> 3775578Skris 3898908Sdeischen__weak_reference(__fmtcheck, fmtcheck); 3975578Skris 4075578Skrisenum __e_fmtcheck_types { 4175578Skris FMTCHECK_START, 4275578Skris FMTCHECK_SHORT, 4375578Skris FMTCHECK_INT, 44181154Sdas FMTCHECK_WINTT, 4575578Skris FMTCHECK_LONG, 4675578Skris FMTCHECK_QUAD, 47181154Sdas FMTCHECK_INTMAXT, 48117014Sdas FMTCHECK_PTRDIFFT, 49117014Sdas FMTCHECK_SIZET, 50181154Sdas FMTCHECK_CHARPOINTER, 5175578Skris FMTCHECK_SHORTPOINTER, 5275578Skris FMTCHECK_INTPOINTER, 5375578Skris FMTCHECK_LONGPOINTER, 5475578Skris FMTCHECK_QUADPOINTER, 55181154Sdas FMTCHECK_INTMAXTPOINTER, 56117014Sdas FMTCHECK_PTRDIFFTPOINTER, 57117014Sdas FMTCHECK_SIZETPOINTER, 58128818Sdas#ifndef NO_FLOATING_POINT 5975578Skris FMTCHECK_DOUBLE, 6075578Skris FMTCHECK_LONGDOUBLE, 61128818Sdas#endif 6275578Skris FMTCHECK_STRING, 63181154Sdas FMTCHECK_WSTRING, 6475578Skris FMTCHECK_WIDTH, 6575578Skris FMTCHECK_PRECISION, 6675578Skris FMTCHECK_DONE, 6775578Skris FMTCHECK_UNKNOWN 6875578Skris}; 6975578Skristypedef enum __e_fmtcheck_types EFT; 7075578Skris 71181154Sdasenum e_modifier { 72181154Sdas MOD_NONE, 73181154Sdas MOD_CHAR, 74181154Sdas MOD_SHORT, 75181154Sdas MOD_LONG, 76181154Sdas MOD_QUAD, 77181154Sdas MOD_INTMAXT, 78181154Sdas MOD_LONGDOUBLE, 79181154Sdas MOD_PTRDIFFT, 80181154Sdas MOD_SIZET, 81181154Sdas}; 82181154Sdas 8375578Skris#define RETURN(pf,f,r) do { \ 8475578Skris *(pf) = (f); \ 8575578Skris return r; \ 8675578Skris } /*NOTREACHED*/ /*CONSTCOND*/ while (0) 8775578Skris 8875578Skrisstatic EFT 8975578Skrisget_next_format_from_precision(const char **pf) 9075578Skris{ 91181154Sdas enum e_modifier modifier; 9275578Skris const char *f; 9375578Skris 9475578Skris f = *pf; 9575578Skris switch (*f) { 9675578Skris case 'h': 9775578Skris f++; 98181154Sdas if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 99181154Sdas if (*f == 'h') { 100181154Sdas f++; 101181154Sdas modifier = MOD_CHAR; 102181154Sdas } else { 103181154Sdas modifier = MOD_SHORT; 104181154Sdas } 10575578Skris break; 106181154Sdas case 'j': 107181154Sdas f++; 108181154Sdas modifier = MOD_INTMAXT; 109181154Sdas break; 11075578Skris case 'l': 11175578Skris f++; 11275578Skris if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 11375578Skris if (*f == 'l') { 11475578Skris f++; 115181154Sdas modifier = MOD_QUAD; 11675578Skris } else { 117181154Sdas modifier = MOD_LONG; 11875578Skris } 11975578Skris break; 12075578Skris case 'q': 12175578Skris f++; 122181154Sdas modifier = MOD_QUAD; 12375578Skris break; 124117014Sdas case 't': 125117014Sdas f++; 126181154Sdas modifier = MOD_PTRDIFFT; 127117014Sdas break; 128117014Sdas case 'z': 129117014Sdas f++; 130181154Sdas modifier = MOD_SIZET; 131117014Sdas break; 13275578Skris case 'L': 13375578Skris f++; 134181154Sdas modifier = MOD_LONGDOUBLE; 13575578Skris break; 13675578Skris default: 137181154Sdas modifier = MOD_NONE; 13875578Skris break; 13975578Skris } 14075578Skris if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 14175578Skris if (strchr("diouxX", *f)) { 142181154Sdas switch (modifier) { 143181154Sdas case MOD_LONG: 14475578Skris RETURN(pf,f,FMTCHECK_LONG); 145181154Sdas case MOD_QUAD: 14675578Skris RETURN(pf,f,FMTCHECK_QUAD); 147181154Sdas case MOD_INTMAXT: 148181154Sdas RETURN(pf,f,FMTCHECK_INTMAXT); 149181154Sdas case MOD_PTRDIFFT: 150117014Sdas RETURN(pf,f,FMTCHECK_PTRDIFFT); 151181154Sdas case MOD_SIZET: 152117014Sdas RETURN(pf,f,FMTCHECK_SIZET); 153181154Sdas case MOD_CHAR: 154181154Sdas case MOD_SHORT: 155181154Sdas case MOD_NONE: 156181154Sdas RETURN(pf,f,FMTCHECK_INT); 157181154Sdas default: 158181154Sdas RETURN(pf,f,FMTCHECK_UNKNOWN); 159181154Sdas } 16075578Skris } 16175578Skris if (*f == 'n') { 162181154Sdas switch (modifier) { 163181154Sdas case MOD_CHAR: 164181154Sdas RETURN(pf,f,FMTCHECK_CHARPOINTER); 165181154Sdas case MOD_SHORT: 16675578Skris RETURN(pf,f,FMTCHECK_SHORTPOINTER); 167181154Sdas case MOD_LONG: 16875578Skris RETURN(pf,f,FMTCHECK_LONGPOINTER); 169181154Sdas case MOD_QUAD: 17075578Skris RETURN(pf,f,FMTCHECK_QUADPOINTER); 171181154Sdas case MOD_INTMAXT: 172181154Sdas RETURN(pf,f,FMTCHECK_INTMAXTPOINTER); 173181154Sdas case MOD_PTRDIFFT: 174117014Sdas RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER); 175181154Sdas case MOD_SIZET: 176117014Sdas RETURN(pf,f,FMTCHECK_SIZETPOINTER); 177181154Sdas case MOD_NONE: 178181154Sdas RETURN(pf,f,FMTCHECK_INTPOINTER); 179181154Sdas default: 180181154Sdas RETURN(pf,f,FMTCHECK_UNKNOWN); 181181154Sdas } 18275578Skris } 18375578Skris if (strchr("DOU", *f)) { 184181154Sdas if (modifier != MOD_NONE) 18575578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 18675578Skris RETURN(pf,f,FMTCHECK_LONG); 18775578Skris } 188128818Sdas#ifndef NO_FLOATING_POINT 189117014Sdas if (strchr("aAeEfFgG", *f)) { 190181154Sdas switch (modifier) { 191181154Sdas case MOD_LONGDOUBLE: 19275578Skris RETURN(pf,f,FMTCHECK_LONGDOUBLE); 193181154Sdas case MOD_LONG: 194181154Sdas case MOD_NONE: 195181154Sdas RETURN(pf,f,FMTCHECK_DOUBLE); 196181154Sdas default: 19775578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 198181154Sdas } 19975578Skris } 200128818Sdas#endif 20175578Skris if (*f == 'c') { 202181154Sdas switch (modifier) { 203181154Sdas case MOD_LONG: 204181154Sdas RETURN(pf,f,FMTCHECK_WINTT); 205181154Sdas case MOD_NONE: 206181154Sdas RETURN(pf,f,FMTCHECK_INT); 207181154Sdas default: 20875578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 209181154Sdas } 21075578Skris } 211181154Sdas if (*f == 'C') { 212181154Sdas if (modifier != MOD_NONE) 213181154Sdas RETURN(pf,f,FMTCHECK_UNKNOWN); 214181154Sdas RETURN(pf,f,FMTCHECK_WINTT); 215181154Sdas } 21675578Skris if (*f == 's') { 217181154Sdas switch (modifier) { 218181154Sdas case MOD_LONG: 219181154Sdas RETURN(pf,f,FMTCHECK_WSTRING); 220181154Sdas case MOD_NONE: 221181154Sdas RETURN(pf,f,FMTCHECK_STRING); 222181154Sdas default: 22375578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 224181154Sdas } 22575578Skris } 226181154Sdas if (*f == 'S') { 227181154Sdas if (modifier != MOD_NONE) 228181154Sdas RETURN(pf,f,FMTCHECK_UNKNOWN); 229181154Sdas RETURN(pf,f,FMTCHECK_WSTRING); 230181154Sdas } 23175578Skris if (*f == 'p') { 232181154Sdas if (modifier != MOD_NONE) 23375578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 23475578Skris RETURN(pf,f,FMTCHECK_LONG); 23575578Skris } 23675578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 23775578Skris /*NOTREACHED*/ 23875578Skris} 23975578Skris 24075578Skrisstatic EFT 24175578Skrisget_next_format_from_width(const char **pf) 24275578Skris{ 24375578Skris const char *f; 24475578Skris 24575578Skris f = *pf; 24675578Skris if (*f == '.') { 24775578Skris f++; 24875578Skris if (*f == '*') { 24975578Skris RETURN(pf,f,FMTCHECK_PRECISION); 25075578Skris } 25175578Skris /* eat any precision (empty is allowed) */ 25275578Skris while (isdigit(*f)) f++; 25375578Skris if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 25475578Skris } 25575578Skris RETURN(pf,f,get_next_format_from_precision(pf)); 25675578Skris /*NOTREACHED*/ 25775578Skris} 25875578Skris 25975578Skrisstatic EFT 26075578Skrisget_next_format(const char **pf, EFT eft) 26175578Skris{ 26275578Skris int infmt; 26375578Skris const char *f; 26475578Skris 26575578Skris if (eft == FMTCHECK_WIDTH) { 26675578Skris (*pf)++; 26775578Skris return get_next_format_from_width(pf); 26875578Skris } else if (eft == FMTCHECK_PRECISION) { 26975578Skris (*pf)++; 27075578Skris return get_next_format_from_precision(pf); 27175578Skris } 27275578Skris 27375578Skris f = *pf; 27475578Skris infmt = 0; 27575578Skris while (!infmt) { 27675578Skris f = strchr(f, '%'); 27775578Skris if (f == NULL) 27875578Skris RETURN(pf,f,FMTCHECK_DONE); 27975578Skris f++; 28075578Skris if (!*f) 28175578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 28275578Skris if (*f != '%') 28375578Skris infmt = 1; 28475578Skris else 28575578Skris f++; 28675578Skris } 28775578Skris 28875578Skris /* Eat any of the flags */ 289143905Sdas while (*f && (strchr("#'0- +", *f))) 29075578Skris f++; 29175578Skris 29275578Skris if (*f == '*') { 29375578Skris RETURN(pf,f,FMTCHECK_WIDTH); 29475578Skris } 29575578Skris /* eat any width */ 29675578Skris while (isdigit(*f)) f++; 29775578Skris if (!*f) { 29875578Skris RETURN(pf,f,FMTCHECK_UNKNOWN); 29975578Skris } 30075578Skris 30175578Skris RETURN(pf,f,get_next_format_from_width(pf)); 30275578Skris /*NOTREACHED*/ 30375578Skris} 30475578Skris 305194800Sdelphijconst char * 30698908Sdeischen__fmtcheck(const char *f1, const char *f2) 30775578Skris{ 30875578Skris const char *f1p, *f2p; 30975578Skris EFT f1t, f2t; 31075578Skris 31175578Skris if (!f1) return f2; 31275578Skris 31375578Skris f1p = f1; 31475578Skris f1t = FMTCHECK_START; 31575578Skris f2p = f2; 31675578Skris f2t = FMTCHECK_START; 31775578Skris while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) { 31875578Skris if (f1t == FMTCHECK_UNKNOWN) 31975578Skris return f2; 32075578Skris f2t = get_next_format(&f2p, f2t); 32175578Skris if (f1t != f2t) 32275578Skris return f2; 32375578Skris } 32475578Skris return f1; 32575578Skris} 326