1 /* $NetBSD: fmtcheck.c,v 1.1.1.1 2014/06/13 01:48:21 christos Exp $ */ 2 /* NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp */ 3 4 /*- 5 * Copyright (c) 2000 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code was contributed to The NetBSD Foundation by Allen Briggs. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "file.h" 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <ctype.h> 37 38 enum __e_fmtcheck_types { 39 FMTCHECK_START, 40 FMTCHECK_SHORT, 41 FMTCHECK_INT, 42 FMTCHECK_LONG, 43 FMTCHECK_QUAD, 44 FMTCHECK_SHORTPOINTER, 45 FMTCHECK_INTPOINTER, 46 FMTCHECK_LONGPOINTER, 47 FMTCHECK_QUADPOINTER, 48 FMTCHECK_DOUBLE, 49 FMTCHECK_LONGDOUBLE, 50 FMTCHECK_STRING, 51 FMTCHECK_WIDTH, 52 FMTCHECK_PRECISION, 53 FMTCHECK_DONE, 54 FMTCHECK_UNKNOWN 55 }; 56 typedef enum __e_fmtcheck_types EFT; 57 58 #define RETURN(pf,f,r) do { \ 59 *(pf) = (f); \ 60 return r; \ 61 } /*NOTREACHED*/ /*CONSTCOND*/ while (0) 62 63 static EFT 64 get_next_format_from_precision(const char **pf) 65 { 66 int sh, lg, quad, longdouble; 67 const char *f; 68 69 sh = lg = quad = longdouble = 0; 70 71 f = *pf; 72 switch (*f) { 73 case 'h': 74 f++; 75 sh = 1; 76 break; 77 case 'l': 78 f++; 79 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 80 if (*f == 'l') { 81 f++; 82 quad = 1; 83 } else { 84 lg = 1; 85 } 86 break; 87 case 'q': 88 f++; 89 quad = 1; 90 break; 91 case 'L': 92 f++; 93 longdouble = 1; 94 break; 95 default: 96 break; 97 } 98 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 99 if (strchr("diouxX", *f)) { 100 if (longdouble) 101 RETURN(pf,f,FMTCHECK_UNKNOWN); 102 if (lg) 103 RETURN(pf,f,FMTCHECK_LONG); 104 if (quad) 105 RETURN(pf,f,FMTCHECK_QUAD); 106 RETURN(pf,f,FMTCHECK_INT); 107 } 108 if (*f == 'n') { 109 if (longdouble) 110 RETURN(pf,f,FMTCHECK_UNKNOWN); 111 if (sh) 112 RETURN(pf,f,FMTCHECK_SHORTPOINTER); 113 if (lg) 114 RETURN(pf,f,FMTCHECK_LONGPOINTER); 115 if (quad) 116 RETURN(pf,f,FMTCHECK_QUADPOINTER); 117 RETURN(pf,f,FMTCHECK_INTPOINTER); 118 } 119 if (strchr("DOU", *f)) { 120 if (sh + lg + quad + longdouble) 121 RETURN(pf,f,FMTCHECK_UNKNOWN); 122 RETURN(pf,f,FMTCHECK_LONG); 123 } 124 if (strchr("eEfg", *f)) { 125 if (longdouble) 126 RETURN(pf,f,FMTCHECK_LONGDOUBLE); 127 if (sh + lg + quad) 128 RETURN(pf,f,FMTCHECK_UNKNOWN); 129 RETURN(pf,f,FMTCHECK_DOUBLE); 130 } 131 if (*f == 'c') { 132 if (sh + lg + quad + longdouble) 133 RETURN(pf,f,FMTCHECK_UNKNOWN); 134 RETURN(pf,f,FMTCHECK_INT); 135 } 136 if (*f == 's') { 137 if (sh + lg + quad + longdouble) 138 RETURN(pf,f,FMTCHECK_UNKNOWN); 139 RETURN(pf,f,FMTCHECK_STRING); 140 } 141 if (*f == 'p') { 142 if (sh + lg + quad + longdouble) 143 RETURN(pf,f,FMTCHECK_UNKNOWN); 144 RETURN(pf,f,FMTCHECK_LONG); 145 } 146 RETURN(pf,f,FMTCHECK_UNKNOWN); 147 /*NOTREACHED*/ 148 } 149 150 static EFT 151 get_next_format_from_width(const char **pf) 152 { 153 const char *f; 154 155 f = *pf; 156 if (*f == '.') { 157 f++; 158 if (*f == '*') { 159 RETURN(pf,f,FMTCHECK_PRECISION); 160 } 161 /* eat any precision (empty is allowed) */ 162 while (isdigit((unsigned char)*f)) f++; 163 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); 164 } 165 RETURN(pf,f,get_next_format_from_precision(pf)); 166 /*NOTREACHED*/ 167 } 168 169 static EFT 170 get_next_format(const char **pf, EFT eft) 171 { 172 int infmt; 173 const char *f; 174 175 if (eft == FMTCHECK_WIDTH) { 176 (*pf)++; 177 return get_next_format_from_width(pf); 178 } else if (eft == FMTCHECK_PRECISION) { 179 (*pf)++; 180 return get_next_format_from_precision(pf); 181 } 182 183 f = *pf; 184 infmt = 0; 185 while (!infmt) { 186 f = strchr(f, '%'); 187 if (f == NULL) 188 RETURN(pf,f,FMTCHECK_DONE); 189 f++; 190 if (!*f) 191 RETURN(pf,f,FMTCHECK_UNKNOWN); 192 if (*f != '%') 193 infmt = 1; 194 else 195 f++; 196 } 197 198 /* Eat any of the flags */ 199 while (*f && (strchr("#0- +", *f))) 200 f++; 201 202 if (*f == '*') { 203 RETURN(pf,f,FMTCHECK_WIDTH); 204 } 205 /* eat any width */ 206 while (isdigit((unsigned char)*f)) f++; 207 if (!*f) { 208 RETURN(pf,f,FMTCHECK_UNKNOWN); 209 } 210 211 RETURN(pf,f,get_next_format_from_width(pf)); 212 /*NOTREACHED*/ 213 } 214 215 const char * 216 fmtcheck(const char *f1, const char *f2) 217 { 218 const char *f1p, *f2p; 219 EFT f1t, f2t; 220 221 if (!f1) return f2; 222 223 f1p = f1; 224 f1t = FMTCHECK_START; 225 f2p = f2; 226 f2t = FMTCHECK_START; 227 while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) { 228 if (f1t == FMTCHECK_UNKNOWN) 229 return f2; 230 f2t = get_next_format(&f2p, f2t); 231 if (f1t != f2t) 232 return f2; 233 } 234 return f1; 235 } 236