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