1267843Sdelphij/* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */ 2267843Sdelphij 3267843Sdelphij/*- 4267843Sdelphij * Copyright (c) 2000 The NetBSD Foundation, Inc. 5267843Sdelphij * All rights reserved. 6267843Sdelphij * 7267843Sdelphij * This code was contributed to The NetBSD Foundation by Allen Briggs. 8267843Sdelphij * 9267843Sdelphij * Redistribution and use in source and binary forms, with or without 10267843Sdelphij * modification, are permitted provided that the following conditions 11267843Sdelphij * are met: 12267843Sdelphij * 1. Redistributions of source code must retain the above copyright 13267843Sdelphij * notice, this list of conditions and the following disclaimer. 14267843Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 15267843Sdelphij * notice, this list of conditions and the following disclaimer in the 16267843Sdelphij * documentation and/or other materials provided with the distribution. 17267843Sdelphij * 18267843Sdelphij * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19267843Sdelphij * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20267843Sdelphij * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21267843Sdelphij * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22267843Sdelphij * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23267843Sdelphij * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24267843Sdelphij * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25267843Sdelphij * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26267843Sdelphij * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27267843Sdelphij * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28267843Sdelphij * POSSIBILITY OF SUCH DAMAGE. 29267843Sdelphij */ 30267843Sdelphij 31267843Sdelphij#include "file.h" 32267843Sdelphij 33267843Sdelphij#include <stdio.h> 34267843Sdelphij#include <string.h> 35267843Sdelphij#include <ctype.h> 36267843Sdelphij 37267843Sdelphijenum __e_fmtcheck_types { 38267843Sdelphij FMTCHECK_START, 39267843Sdelphij FMTCHECK_SHORT, 40267843Sdelphij FMTCHECK_INT, 41267843Sdelphij FMTCHECK_LONG, 42267843Sdelphij FMTCHECK_QUAD, 43267843Sdelphij FMTCHECK_SHORTPOINTER, 44267843Sdelphij FMTCHECK_INTPOINTER, 45267843Sdelphij FMTCHECK_LONGPOINTER, 46267843Sdelphij FMTCHECK_QUADPOINTER, 47267843Sdelphij FMTCHECK_DOUBLE, 48267843Sdelphij FMTCHECK_LONGDOUBLE, 49267843Sdelphij FMTCHECK_STRING, 50267843Sdelphij FMTCHECK_WIDTH, 51267843Sdelphij FMTCHECK_PRECISION, 52267843Sdelphij FMTCHECK_DONE, 53267843Sdelphij FMTCHECK_UNKNOWN 54267843Sdelphij}; 55267843Sdelphijtypedef enum __e_fmtcheck_types EFT; 56267843Sdelphij 57267843Sdelphij#define RETURN(pf,f,r) do { \ 58267843Sdelphij *(pf) = (f); \ 59267843Sdelphij return r; \ 60267843Sdelphij } /*NOTREACHED*/ /*CONSTCOND*/ while (0) 61267843Sdelphij 62267843Sdelphijstatic EFT 63267843Sdelphijget_next_format_from_precision(const char **pf) 64267843Sdelphij{ 65267843Sdelphij int sh, lg, quad, longdouble; 66267843Sdelphij const char *f; 67267843Sdelphij 68267843Sdelphij sh = lg = quad = longdouble = 0; 69267843Sdelphij 70267843Sdelphij f = *pf; 71267843Sdelphij switch (*f) { 72267843Sdelphij case 'h': 73267843Sdelphij f++; 74267843Sdelphij sh = 1; 75267843Sdelphij break; 76267843Sdelphij case 'l': 77267843Sdelphij f++; 78267843Sdelphij if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 79267843Sdelphij if (*f == 'l') { 80267843Sdelphij f++; 81267843Sdelphij quad = 1; 82267843Sdelphij } else { 83267843Sdelphij lg = 1; 84267843Sdelphij } 85267843Sdelphij break; 86267843Sdelphij case 'q': 87267843Sdelphij f++; 88267843Sdelphij quad = 1; 89267843Sdelphij break; 90267843Sdelphij case 'L': 91267843Sdelphij f++; 92267843Sdelphij longdouble = 1; 93267843Sdelphij break; 94298192Sdelphij#ifdef WIN32 95298192Sdelphij case 'I': 96298192Sdelphij f++; 97298192Sdelphij if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 98298192Sdelphij if (*f == '3' && f[1] == '2') { 99298192Sdelphij f += 2; 100298192Sdelphij } else if (*f == '6' && f[1] == '4') { 101298192Sdelphij f += 2; 102298192Sdelphij quad = 1; 103298192Sdelphij } 104298192Sdelphij#ifdef _WIN64 105298192Sdelphij else { 106298192Sdelphij quad = 1; 107298192Sdelphij } 108298192Sdelphij#endif 109298192Sdelphij break; 110298192Sdelphij#endif 111267843Sdelphij default: 112267843Sdelphij break; 113267843Sdelphij } 114267843Sdelphij if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 115267843Sdelphij if (strchr("diouxX", *f)) { 116267843Sdelphij if (longdouble) 117267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 118267843Sdelphij if (lg) 119267843Sdelphij RETURN(pf,f,FMTCHECK_LONG); 120267843Sdelphij if (quad) 121267843Sdelphij RETURN(pf,f,FMTCHECK_QUAD); 122267843Sdelphij RETURN(pf,f,FMTCHECK_INT); 123267843Sdelphij } 124267843Sdelphij if (*f == 'n') { 125267843Sdelphij if (longdouble) 126267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 127267843Sdelphij if (sh) 128267843Sdelphij RETURN(pf,f,FMTCHECK_SHORTPOINTER); 129267843Sdelphij if (lg) 130267843Sdelphij RETURN(pf,f,FMTCHECK_LONGPOINTER); 131267843Sdelphij if (quad) 132267843Sdelphij RETURN(pf,f,FMTCHECK_QUADPOINTER); 133267843Sdelphij RETURN(pf,f,FMTCHECK_INTPOINTER); 134267843Sdelphij } 135267843Sdelphij if (strchr("DOU", *f)) { 136267843Sdelphij if (sh + lg + quad + longdouble) 137267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 138267843Sdelphij RETURN(pf,f,FMTCHECK_LONG); 139267843Sdelphij } 140267843Sdelphij if (strchr("eEfg", *f)) { 141267843Sdelphij if (longdouble) 142267843Sdelphij RETURN(pf,f,FMTCHECK_LONGDOUBLE); 143267843Sdelphij if (sh + lg + quad) 144267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 145267843Sdelphij RETURN(pf,f,FMTCHECK_DOUBLE); 146267843Sdelphij } 147267843Sdelphij if (*f == 'c') { 148267843Sdelphij if (sh + lg + quad + longdouble) 149267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 150267843Sdelphij RETURN(pf,f,FMTCHECK_INT); 151267843Sdelphij } 152267843Sdelphij if (*f == 's') { 153267843Sdelphij if (sh + lg + quad + longdouble) 154267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 155267843Sdelphij RETURN(pf,f,FMTCHECK_STRING); 156267843Sdelphij } 157267843Sdelphij if (*f == 'p') { 158267843Sdelphij if (sh + lg + quad + longdouble) 159267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 160267843Sdelphij RETURN(pf,f,FMTCHECK_LONG); 161267843Sdelphij } 162267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 163267843Sdelphij /*NOTREACHED*/ 164267843Sdelphij} 165267843Sdelphij 166267843Sdelphijstatic EFT 167267843Sdelphijget_next_format_from_width(const char **pf) 168267843Sdelphij{ 169267843Sdelphij const char *f; 170267843Sdelphij 171267843Sdelphij f = *pf; 172267843Sdelphij if (*f == '.') { 173267843Sdelphij f++; 174267843Sdelphij if (*f == '*') { 175267843Sdelphij RETURN(pf,f,FMTCHECK_PRECISION); 176267843Sdelphij } 177267843Sdelphij /* eat any precision (empty is allowed) */ 178267843Sdelphij while (isdigit((unsigned char)*f)) f++; 179267843Sdelphij if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 180267843Sdelphij } 181267843Sdelphij RETURN(pf,f,get_next_format_from_precision(pf)); 182267843Sdelphij /*NOTREACHED*/ 183267843Sdelphij} 184267843Sdelphij 185267843Sdelphijstatic EFT 186267843Sdelphijget_next_format(const char **pf, EFT eft) 187267843Sdelphij{ 188267843Sdelphij int infmt; 189267843Sdelphij const char *f; 190267843Sdelphij 191267843Sdelphij if (eft == FMTCHECK_WIDTH) { 192267843Sdelphij (*pf)++; 193267843Sdelphij return get_next_format_from_width(pf); 194267843Sdelphij } else if (eft == FMTCHECK_PRECISION) { 195267843Sdelphij (*pf)++; 196267843Sdelphij return get_next_format_from_precision(pf); 197267843Sdelphij } 198267843Sdelphij 199267843Sdelphij f = *pf; 200267843Sdelphij infmt = 0; 201267843Sdelphij while (!infmt) { 202267843Sdelphij f = strchr(f, '%'); 203267843Sdelphij if (f == NULL) 204267843Sdelphij RETURN(pf,f,FMTCHECK_DONE); 205267843Sdelphij f++; 206267843Sdelphij if (!*f) 207267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 208267843Sdelphij if (*f != '%') 209267843Sdelphij infmt = 1; 210267843Sdelphij else 211267843Sdelphij f++; 212267843Sdelphij } 213267843Sdelphij 214267843Sdelphij /* Eat any of the flags */ 215267843Sdelphij while (*f && (strchr("#0- +", *f))) 216267843Sdelphij f++; 217267843Sdelphij 218267843Sdelphij if (*f == '*') { 219267843Sdelphij RETURN(pf,f,FMTCHECK_WIDTH); 220267843Sdelphij } 221267843Sdelphij /* eat any width */ 222267843Sdelphij while (isdigit((unsigned char)*f)) f++; 223267843Sdelphij if (!*f) { 224267843Sdelphij RETURN(pf,f,FMTCHECK_UNKNOWN); 225267843Sdelphij } 226267843Sdelphij 227267843Sdelphij RETURN(pf,f,get_next_format_from_width(pf)); 228267843Sdelphij /*NOTREACHED*/ 229267843Sdelphij} 230267843Sdelphij 231267843Sdelphijconst char * 232267843Sdelphijfmtcheck(const char *f1, const char *f2) 233267843Sdelphij{ 234267843Sdelphij const char *f1p, *f2p; 235267843Sdelphij EFT f1t, f2t; 236267843Sdelphij 237267843Sdelphij if (!f1) return f2; 238354939Sdelphij 239267843Sdelphij f1p = f1; 240267843Sdelphij f1t = FMTCHECK_START; 241267843Sdelphij f2p = f2; 242267843Sdelphij f2t = FMTCHECK_START; 243267843Sdelphij while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) { 244267843Sdelphij if (f1t == FMTCHECK_UNKNOWN) 245267843Sdelphij return f2; 246267843Sdelphij f2t = get_next_format(&f2p, f2t); 247267843Sdelphij if (f1t != f2t) 248267843Sdelphij return f2; 249267843Sdelphij } 250267843Sdelphij return f1; 251267843Sdelphij} 252