[BACK]Return to fmtcheck.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / gen

Annotation of src/lib/libc/gen/fmtcheck.c, Revision 1.4

1.4     ! briggs      1: /*     $NetBSD: fmtcheck.c,v 1.3 2000/11/16 02:10:18 matt Exp $        */
1.1       briggs      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:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *        This product includes software developed by the NetBSD
                     20:  *        Foundation, Inc. and its contributors.
                     21:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     22:  *    contributors may be used to endorse or promote products derived
                     23:  *    from this software without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     26:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     35:  * POSSIBILITY OF SUCH DAMAGE.
                     36:  */
                     37:
                     38: #include <sys/cdefs.h>
                     39: #if defined(LIBC_SCCS) && !defined(lint)
1.4     ! briggs     40: __RCSID("$NetBSD: fmtcheck.c,v 1.3 2000/11/16 02:10:18 matt Exp $");
1.1       briggs     41: #endif
                     42:
                     43: #include "namespace.h"
                     44:
1.3       matt       45: #include <stdio.h>
1.1       briggs     46: #include <string.h>
                     47: #include <ctype.h>
                     48:
                     49: #ifdef __weak_alias
                     50: __weak_alias(fmtcheck,__fmtcheck)
                     51: #endif
                     52:
                     53: enum __e_fmtcheck_types {
                     54:        FMTCHECK_START,
                     55:        FMTCHECK_SHORT,
                     56:        FMTCHECK_INT,
                     57:        FMTCHECK_LONG,
                     58:        FMTCHECK_QUAD,
                     59:        FMTCHECK_SHORTPOINTER,
                     60:        FMTCHECK_INTPOINTER,
                     61:        FMTCHECK_LONGPOINTER,
                     62:        FMTCHECK_QUADPOINTER,
                     63:        FMTCHECK_DOUBLE,
                     64:        FMTCHECK_LONGDOUBLE,
                     65:        FMTCHECK_STRING,
                     66:        FMTCHECK_WIDTH,
                     67:        FMTCHECK_PRECISION,
                     68:        FMTCHECK_DONE,
                     69:        FMTCHECK_UNKNOWN
                     70: };
                     71: typedef enum __e_fmtcheck_types EFT;
                     72:
                     73: #define RETURN(pf,f,r) do { \
                     74:                        *(pf) = (f); \
                     75:                        return r; \
                     76:                       } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
                     77:
                     78: static EFT
                     79: get_next_format_from_precision(const char **pf)
                     80: {
                     81:        int             sh, lg, quad, longdouble;
                     82:        const char      *f;
                     83:
                     84:        sh = lg = quad = longdouble = 0;
                     85:
                     86:        f = *pf;
                     87:        switch (*f) {
                     88:        case 'h':
                     89:                f++;
                     90:                sh = 1;
                     91:                break;
                     92:        case 'l':
                     93:                f++;
                     94:                if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
                     95:                if (*f == 'l') {
                     96:                        f++;
                     97:                        quad = 1;
                     98:                } else {
                     99:                        lg = 1;
                    100:                }
                    101:                break;
                    102:        case 'q':
                    103:                f++;
                    104:                quad = 1;
                    105:                break;
                    106:        case 'L':
                    107:                f++;
                    108:                longdouble = 1;
                    109:                break;
                    110:        default:
                    111:                break;
                    112:        }
                    113:        if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
                    114:        if (strchr("diouxX", *f)) {
                    115:                if (longdouble)
                    116:                        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    117:                if (lg)
                    118:                        RETURN(pf,f,FMTCHECK_LONG);
                    119:                if (quad)
                    120:                        RETURN(pf,f,FMTCHECK_QUAD);
                    121:                RETURN(pf,f,FMTCHECK_INT);
                    122:        }
                    123:        if (*f == 'n') {
                    124:                if (longdouble)
                    125:                        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    126:                if (sh)
                    127:                        RETURN(pf,f,FMTCHECK_SHORTPOINTER);
                    128:                if (lg)
                    129:                        RETURN(pf,f,FMTCHECK_LONGPOINTER);
                    130:                if (quad)
                    131:                        RETURN(pf,f,FMTCHECK_QUADPOINTER);
                    132:                RETURN(pf,f,FMTCHECK_INTPOINTER);
                    133:        }
                    134:        if (strchr("DOU", *f)) {
                    135:                if (sh + lg + quad + longdouble)
                    136:                        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    137:                RETURN(pf,f,FMTCHECK_LONG);
                    138:        }
                    139:        if (strchr("eEfg", *f)) {
                    140:                if (longdouble)
                    141:                        RETURN(pf,f,FMTCHECK_LONGDOUBLE);
                    142:                if (sh + lg + quad)
                    143:                        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    144:                RETURN(pf,f,FMTCHECK_DOUBLE);
                    145:        }
                    146:        if (*f == 'c') {
                    147:                if (sh + lg + quad + longdouble)
                    148:                        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    149:                RETURN(pf,f,FMTCHECK_INT);
                    150:        }
                    151:        if (*f == 's') {
                    152:                if (sh + lg + quad + longdouble)
                    153:                        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    154:                RETURN(pf,f,FMTCHECK_STRING);
                    155:        }
                    156:        if (*f == 'p') {
                    157:                if (sh + lg + quad + longdouble)
                    158:                        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    159:                RETURN(pf,f,FMTCHECK_LONG);
                    160:        }
                    161:        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    162:        /*NOTREACHED*/
                    163: }
                    164:
                    165: static EFT
                    166: get_next_format_from_width(const char **pf)
                    167: {
                    168:        const char      *f;
                    169:
                    170:        f = *pf;
                    171:        if (*f == '.') {
                    172:                f++;
                    173:                if (*f == '*') {
                    174:                        RETURN(pf,f,FMTCHECK_PRECISION);
                    175:                }
                    176:                /* eat any precision (empty is allowed) */
                    177:                while (isdigit(*f)) f++;
                    178:                if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
                    179:        }
                    180:        RETURN(pf,f,get_next_format_from_precision(pf));
                    181:        /*NOTREACHED*/
                    182: }
                    183:
                    184: static EFT
                    185: get_next_format(const char **pf, EFT eft)
                    186: {
                    187:        int             infmt;
                    188:        const char      *f;
                    189:
                    190:        if (eft == FMTCHECK_WIDTH) {
                    191:                (*pf)++;
                    192:                return get_next_format_from_width(pf);
                    193:        } else if (eft == FMTCHECK_PRECISION) {
                    194:                (*pf)++;
                    195:                return get_next_format_from_precision(pf);
                    196:        }
                    197:
                    198:        f = *pf;
                    199:        infmt = 0;
                    200:        while (!infmt) {
                    201:                f = strchr(f, '%');
                    202:                if (f == NULL)
                    203:                        RETURN(pf,f,FMTCHECK_DONE);
                    204:                f++;
                    205:                if (!*f)
                    206:                        RETURN(pf,f,FMTCHECK_UNKNOWN);
                    207:                if (*f != '%')
                    208:                        infmt = 1;
                    209:                else
                    210:                        f++;
                    211:        }
                    212:
                    213:        /* Eat any of the flags */
                    214:        while (*f && (strchr("#0- +", *f)))
                    215:                f++;
                    216:
                    217:        if (*f == '*') {
                    218:                RETURN(pf,f,FMTCHECK_WIDTH);
                    219:        }
                    220:        /* eat any width */
                    221:        while (isdigit(*f)) f++;
                    222:        if (!*f) {
                    223:                RETURN(pf,f,FMTCHECK_UNKNOWN);
                    224:        }
                    225:
                    226:        RETURN(pf,f,get_next_format_from_width(pf));
                    227:        /*NOTREACHED*/
                    228: }
                    229:
                    230: __const char *
1.2       briggs    231: fmtcheck(const char *f1, const char *f2)
1.1       briggs    232: {
                    233:        const char      *f1p, *f2p;
                    234:        EFT             f1t, f2t;
                    235:
                    236:        if (!f1) return f2;
                    237:
                    238:        f1p = f1;
                    239:        f1t = FMTCHECK_START;
                    240:        f2p = f2;
                    241:        f2t = FMTCHECK_START;
                    242:        while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
                    243:                if (f1t == FMTCHECK_UNKNOWN)
                    244:                        return f2;
                    245:                f2t = get_next_format(&f2p, f2t);
                    246:                if (f1t != f2t)
                    247:                        return f2;
                    248:        }
                    249:        return f1;
                    250: }

CVSweb <webmaster@jp.NetBSD.org>