diff options
author | Aurelien Jarno <aurel32@debian.org> | 2005-12-18 04:02:56 +0000 |
---|---|---|
committer | Guillem Jover <guillem@hadrons.org> | 2008-05-06 08:45:48 +0300 |
commit | 91473e2748a0081962a2ecae8ab7787858722efd (patch) | |
tree | 87e26d91684846349717413ebfd4ab4a6e1d1eca | |
parent | 657f1b59ceec215ae13f57d03a5ce39c03d30b21 (diff) | |
download | libbsd-91473e2748a0081962a2ecae8ab7787858722efd.tar.gz |
fmtcheck: New function
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Versions | 1 | ||||
-rw-r--r-- | fmtcheck.c | 267 | ||||
-rw-r--r-- | include/bsd/string.h | 1 |
5 files changed, 276 insertions, 1 deletions
@@ -1,3 +1,9 @@ +2005-12-18 Aurelien Jarno <aurel32@debian.org> + + * fmtcheck.c: new + * include/string.h: added fmtcheck + * Versions: added fmtcheck + 2005-11-01 Guillem Jover <guillem@debian.org> * ip_icmp.h: Move to ... @@ -4,7 +4,7 @@ # $Id$ # -LIB_SRCS = arc4random.c fgetln.c inet_net_pton.c strlcat.c strlcpy.c md5c.c +LIB_SRCS = arc4random.c fgetln.c inet_net_pton.c strlcat.c strlcpy.c md5c.c fmtcheck.c LIB_INCLUDES = bsd.h md5.h @@ -2,6 +2,7 @@ LIBBSD_0.0 { global: arc4random; fgetln; + fmtcheck; inet_net_pton; strlcpy; strlcat; diff --git a/fmtcheck.c b/fmtcheck.c new file mode 100644 index 0000000..5d54b7c --- /dev/null +++ b/fmtcheck.c @@ -0,0 +1,267 @@ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code was contributed to The NetBSD Foundation by Allen Briggs. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $NetBSD: fmtcheck.c,v 1.2 2000/11/01 01:17:20 briggs Exp $ */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/fmtcheck.c,v 1.8 2005/03/21 08:00:55 das Exp $"); + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +__weak_reference(__fmtcheck, fmtcheck); + +enum __e_fmtcheck_types { + FMTCHECK_START, + FMTCHECK_SHORT, + FMTCHECK_INT, + FMTCHECK_LONG, + FMTCHECK_QUAD, + FMTCHECK_PTRDIFFT, + FMTCHECK_SIZET, + FMTCHECK_SHORTPOINTER, + FMTCHECK_INTPOINTER, + FMTCHECK_LONGPOINTER, + FMTCHECK_QUADPOINTER, + FMTCHECK_PTRDIFFTPOINTER, + FMTCHECK_SIZETPOINTER, +#ifndef NO_FLOATING_POINT + FMTCHECK_DOUBLE, + FMTCHECK_LONGDOUBLE, +#endif + FMTCHECK_STRING, + FMTCHECK_WIDTH, + FMTCHECK_PRECISION, + FMTCHECK_DONE, + FMTCHECK_UNKNOWN +}; +typedef enum __e_fmtcheck_types EFT; + +#define RETURN(pf,f,r) do { \ + *(pf) = (f); \ + return r; \ + } /*NOTREACHED*/ /*CONSTCOND*/ while (0) + +static EFT +get_next_format_from_precision(const char **pf) +{ + int sh, lg, quad, longdouble, ptrdifft, sizet; + const char *f; + + sh = lg = quad = longdouble = ptrdifft = sizet = 0; + + f = *pf; + switch (*f) { + case 'h': + f++; + sh = 1; + break; + case 'l': + f++; + if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); + if (*f == 'l') { + f++; + quad = 1; + } else { + lg = 1; + } + break; + case 'q': + f++; + quad = 1; + break; + case 't': + f++; + ptrdifft = 1; + break; + case 'z': + f++; + sizet = 1; + break; + case 'L': + f++; + longdouble = 1; + break; + default: + break; + } + if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); + if (strchr("diouxX", *f)) { + if (longdouble) + RETURN(pf,f,FMTCHECK_UNKNOWN); + if (lg) + RETURN(pf,f,FMTCHECK_LONG); + if (quad) + RETURN(pf,f,FMTCHECK_QUAD); + if (ptrdifft) + RETURN(pf,f,FMTCHECK_PTRDIFFT); + if (sizet) + RETURN(pf,f,FMTCHECK_SIZET); + RETURN(pf,f,FMTCHECK_INT); + } + if (*f == 'n') { + if (longdouble) + RETURN(pf,f,FMTCHECK_UNKNOWN); + if (sh) + RETURN(pf,f,FMTCHECK_SHORTPOINTER); + if (lg) + RETURN(pf,f,FMTCHECK_LONGPOINTER); + if (quad) + RETURN(pf,f,FMTCHECK_QUADPOINTER); + if (ptrdifft) + RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER); + if (sizet) + RETURN(pf,f,FMTCHECK_SIZETPOINTER); + RETURN(pf,f,FMTCHECK_INTPOINTER); + } + if (strchr("DOU", *f)) { + if (sh + lg + quad + longdouble + ptrdifft + sizet) + RETURN(pf,f,FMTCHECK_UNKNOWN); + RETURN(pf,f,FMTCHECK_LONG); + } +#ifndef NO_FLOATING_POINT + if (strchr("aAeEfFgG", *f)) { + if (longdouble) + RETURN(pf,f,FMTCHECK_LONGDOUBLE); + if (sh + lg + quad + ptrdifft + sizet) + RETURN(pf,f,FMTCHECK_UNKNOWN); + RETURN(pf,f,FMTCHECK_DOUBLE); + } +#endif + if (*f == 'c') { + if (sh + lg + quad + longdouble + ptrdifft + sizet) + RETURN(pf,f,FMTCHECK_UNKNOWN); + RETURN(pf,f,FMTCHECK_INT); + } + if (*f == 's') { + if (sh + lg + quad + longdouble + ptrdifft + sizet) + RETURN(pf,f,FMTCHECK_UNKNOWN); + RETURN(pf,f,FMTCHECK_STRING); + } + if (*f == 'p') { + if (sh + lg + quad + longdouble + ptrdifft + sizet) + RETURN(pf,f,FMTCHECK_UNKNOWN); + RETURN(pf,f,FMTCHECK_LONG); + } + RETURN(pf,f,FMTCHECK_UNKNOWN); + /*NOTREACHED*/ +} + +static EFT +get_next_format_from_width(const char **pf) +{ + const char *f; + + f = *pf; + if (*f == '.') { + f++; + if (*f == '*') { + RETURN(pf,f,FMTCHECK_PRECISION); + } + /* eat any precision (empty is allowed) */ + while (isdigit(*f)) f++; + if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN); + } + RETURN(pf,f,get_next_format_from_precision(pf)); + /*NOTREACHED*/ +} + +static EFT +get_next_format(const char **pf, EFT eft) +{ + int infmt; + const char *f; + + if (eft == FMTCHECK_WIDTH) { + (*pf)++; + return get_next_format_from_width(pf); + } else if (eft == FMTCHECK_PRECISION) { + (*pf)++; + return get_next_format_from_precision(pf); + } + + f = *pf; + infmt = 0; + while (!infmt) { + f = strchr(f, '%'); + if (f == NULL) + RETURN(pf,f,FMTCHECK_DONE); + f++; + if (!*f) + RETURN(pf,f,FMTCHECK_UNKNOWN); + if (*f != '%') + infmt = 1; + else + f++; + } + + /* Eat any of the flags */ + while (*f && (strchr("#'0- +", *f))) + f++; + + if (*f == '*') { + RETURN(pf,f,FMTCHECK_WIDTH); + } + /* eat any width */ + while (isdigit(*f)) f++; + if (!*f) { + RETURN(pf,f,FMTCHECK_UNKNOWN); + } + + RETURN(pf,f,get_next_format_from_width(pf)); + /*NOTREACHED*/ +} + +__const char * +__fmtcheck(const char *f1, const char *f2) +{ + const char *f1p, *f2p; + EFT f1t, f2t; + + if (!f1) return f2; + + f1p = f1; + f1t = FMTCHECK_START; + f2p = f2; + f2t = FMTCHECK_START; + while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) { + if (f1t == FMTCHECK_UNKNOWN) + return f2; + f2t = get_next_format(&f2p, f2t); + if (f1t != f2t) + return f2; + } + return f1; +} diff --git a/include/bsd/string.h b/include/bsd/string.h index ed31933..70a9b38 100644 --- a/include/bsd/string.h +++ b/include/bsd/string.h @@ -7,5 +7,6 @@ size_t strlcpy(char *dst, const char *src, size_t siz); size_t strlcat(char *dst, const char *src, size_t siz); char *fgetln(FILE *fp, size_t *lenp); +const char *fmtcheck(const char *, const char *); #endif |