Annotation of embedaddon/libpdel/util/string_quote.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (c) 2001-2002 Packet Design, LLC.
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Subject to the following obligations and disclaimer of warranty,
        !             7:  * use and redistribution of this software, in source or object code
        !             8:  * forms, with or without modifications are expressly permitted by
        !             9:  * Packet Design; provided, however, that:
        !            10:  * 
        !            11:  *    (i)  Any and all reproductions of the source or object code
        !            12:  *         must include the copyright notice above and the following
        !            13:  *         disclaimer of warranties; and
        !            14:  *    (ii) No rights are granted, in any manner or form, to use
        !            15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
        !            16:  *         on advertising, endorsements, or otherwise except as such
        !            17:  *         appears in the above copyright notice or in the software.
        !            18:  * 
        !            19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
        !            20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
        !            21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
        !            22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
        !            23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
        !            24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
        !            25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
        !            26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
        !            27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
        !            28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
        !            29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
        !            30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
        !            31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
        !            32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
        !            33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
        !            35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
        !            36:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            37:  *
        !            38:  * Author: Archie Cobbs <archie@freebsd.org>
        !            39:  */
        !            40: 
        !            41: #include <sys/types.h>
        !            42: 
        !            43: #include <stdio.h>
        !            44: #include <stdarg.h>
        !            45: #include <string.h>
        !            46: #include <ctype.h>
        !            47: #include <errno.h>
        !            48: #include <pthread.h>
        !            49: 
        !            50: #include "structs/structs.h"
        !            51: #include "structs/type/array.h"
        !            52: 
        !            53: #include "util/string_quote.h"
        !            54: #include "util/typed_mem.h"
        !            55: 
        !            56: struct string_dequote_info {
        !            57:        const char      *mtype;
        !            58:        char            **bufp;
        !            59: };
        !            60: 
        !            61: /*
        !            62:  * Internal variables
        !            63:  */
        !            64: static const   char *escapes[2] = { "tnrvf\"\\", "\t\n\r\v\f\"\\" };
        !            65: static const   char hexdigit[16] = "0123456789abcdef";
        !            66: 
        !            67: /*
        !            68:  * Internal functions
        !            69:  */
        !            70: static void    string_dequote_cleanup(void *arg);
        !            71: 
        !            72: /*
        !            73:  * Parse a doubly-quoted string token.
        !            74:  */
        !            75: char *
        !            76: string_dequote(FILE *fp, const char *mtype)
        !            77: {
        !            78:        struct string_dequote_info info;
        !            79:        char *buf = NULL;
        !            80:        int alloc = 0;
        !            81:        int len = 0;
        !            82:        void *mem;
        !            83:        int ch;
        !            84: 
        !            85:        /* Cleanup properly if thread is canceled */
        !            86:        info.bufp = &buf;
        !            87:        info.mtype = mtype;
        !            88:        pthread_cleanup_push(string_dequote_cleanup, &info);
        !            89: 
        !            90:        /* Parse string */
        !            91:        while ((ch = getc(fp)) != EOF) {
        !            92: 
        !            93:                /* Increase buffer length if necessary */
        !            94:                if (len + 8 >= alloc) {
        !            95:                        alloc += 64;
        !            96:                        if ((mem = REALLOC(mtype, buf, alloc)) == NULL)
        !            97:                                goto fail;
        !            98:                        buf = mem;
        !            99:                }
        !           100: 
        !           101:                /* Check special characters */
        !           102:                switch (ch) {
        !           103:                case '"':
        !           104:                        buf[len] = '\0';
        !           105:                        goto done;
        !           106:                case '\\':
        !           107:                        switch ((ch = getc(fp))) {
        !           108:                        case '0': case '1': case '2': case '3':
        !           109:                        case '4': case '5': case '6': case '7':
        !           110:                            {
        !           111:                                char chsave[3];
        !           112:                                int x, k;
        !           113: 
        !           114:                                for (x = k = 0; k < 3; k++) {
        !           115:                                        if (k > 0 && (ch = getc(fp)) == EOF) {
        !           116:                                                k--;    /* char not saved */
        !           117:                                                break;
        !           118:                                        }
        !           119:                                        chsave[k] = ch;
        !           120:                                        if (ch < '0' || ch > '7')
        !           121:                                                break;
        !           122:                                        x = (x << 3) + (ch - '0');
        !           123:                                }
        !           124:                                if (k == 3)             /* got a whole byte */
        !           125:                                        buf[len++] = (char)x;
        !           126:                                else {                  /* copy chars as-is */
        !           127:                                        buf[len++] = '\\';
        !           128:                                        for (x = 0; x <= k; x++)
        !           129:                                                buf[len++] = chsave[x];
        !           130:                                }
        !           131:                                break;
        !           132:                            }
        !           133:                        case 'x':
        !           134:                            {
        !           135:                                char chsave[2];
        !           136:                                int x, k;
        !           137: 
        !           138:                                for (x = k = 0; k < 2; k++) {
        !           139:                                        if ((ch = getc(fp)) == EOF) {
        !           140:                                                k--;    /* char not saved */
        !           141:                                                break;
        !           142:                                        }
        !           143:                                        chsave[k] = ch;
        !           144:                                        if (!isxdigit(ch))
        !           145:                                                break;
        !           146:                                        x = (x << 4) + (isdigit(ch) ?
        !           147:                                              (ch - '0') :
        !           148:                                              (tolower(ch) - 'a' + 10));
        !           149:                                }
        !           150:                                if (k == 2)             /* got a whole byte */
        !           151:                                        buf[len++] = (char)x;
        !           152:                                else {                  /* copy chars as-is */
        !           153:                                        buf[len++] = '\\';
        !           154:                                        buf[len++] = 'x';
        !           155:                                        for (x = 0; x <= k; x++)
        !           156:                                                buf[len++] = chsave[x];
        !           157:                                }
        !           158:                                break;
        !           159:                            }
        !           160: 
        !           161:                        case EOF:
        !           162:                                goto got_eof;
        !           163: 
        !           164:                        default:
        !           165:                            {
        !           166:                                char *x;
        !           167: 
        !           168:                                if ((x = strchr(escapes[0], ch)) != NULL)
        !           169:                                        buf[len++] = escapes[1][x - escapes[0]];
        !           170:                                else
        !           171:                                        buf[len++] = ch;
        !           172:                            }
        !           173:                        }
        !           174:                        break;
        !           175:                default:
        !           176:                        buf[len++] = (char)ch;
        !           177:                        break;
        !           178:                }
        !           179:        }
        !           180: 
        !           181: got_eof:
        !           182:        /* EOF was read: check for error or actual end of file */
        !           183:        if (!ferror(fp))
        !           184:                errno = EINVAL;
        !           185: 
        !           186: fail:
        !           187:        /* Error */
        !           188:        FREE(mtype, buf);
        !           189:        buf = NULL;
        !           190: 
        !           191: done:;
        !           192:        /* Done */
        !           193:        pthread_cleanup_pop(0);
        !           194:        return (buf);
        !           195: }
        !           196: 
        !           197: /*
        !           198:  * Cleanup for string_dequote()
        !           199:  */
        !           200: static void
        !           201: string_dequote_cleanup(void *arg)
        !           202: {
        !           203:        struct string_dequote_info *const info = arg;
        !           204: 
        !           205:        FREE(info->mtype, *info->bufp);
        !           206: }
        !           207: 
        !           208: /*
        !           209:  * Enquote a string.
        !           210:  */
        !           211: char *
        !           212: string_enquote(const char *s, const char *mtype)
        !           213: {
        !           214:        char *buf = NULL;
        !           215:        int pass2 = 0;
        !           216:        int len;
        !           217:        char *t;
        !           218:        int i;
        !           219: 
        !           220: pass2:
        !           221:        /* Encode characters */
        !           222:        len = 0;
        !           223:        if (pass2)
        !           224:                buf[len] = '"';
        !           225:        len++;
        !           226:        for (i = 0; s[i] != '\0'; i++) {
        !           227:                if ((t = strchr(escapes[1], s[i])) != NULL) {
        !           228:                        if (pass2) {
        !           229:                                buf[len] = '\\';
        !           230:                                buf[len + 1] = escapes[0][t - escapes[1]];
        !           231:                        }
        !           232:                        len += 2;
        !           233:                } else if (isprint(s[i])) {
        !           234:                        if (pass2)
        !           235:                                buf[len] = s[i];
        !           236:                        len++;
        !           237:                } else {
        !           238:                        if (pass2) {
        !           239:                                buf[len] = '\\';
        !           240:                                buf[len + 1] = 'x';
        !           241:                                buf[len + 2] = hexdigit[((s[i]) >> 4) & 0x0f];
        !           242:                                buf[len + 3] = hexdigit[(s[i]) & 0x0f];
        !           243:                        }
        !           244:                        len += 4;
        !           245:                }
        !           246:        }
        !           247:        if (pass2)
        !           248:                buf[len] = '"';
        !           249:        len++;
        !           250: 
        !           251:        /* Finish up */
        !           252:        if (pass2) {
        !           253:                buf[len] = '\0';
        !           254:                return (buf);
        !           255:        }
        !           256: 
        !           257:        /* Initialize buffer */
        !           258:        if ((buf = MALLOC(mtype, len + 1)) == NULL)
        !           259:                return (NULL);
        !           260:        pass2 = 1;
        !           261:        goto pass2;
        !           262: }
        !           263: 
        !           264: #ifdef STRING_QUOTE_TEST
        !           265: 
        !           266: #include <unistd.h>
        !           267: #include <err.h>
        !           268: 
        !           269: int
        !           270: main(int ac, char **av)
        !           271: {
        !           272:        int decode = -1;
        !           273:        FILE *fp;
        !           274:        char *s;
        !           275:        int ch;
        !           276: 
        !           277:        while ((ch = getopt(ac, av, "de")) != -1) {
        !           278:                switch (ch) {
        !           279:                case 'd':
        !           280:                        decode = 1;
        !           281:                        break;
        !           282:                case 'e':
        !           283:                        decode = 0;
        !           284:                        break;
        !           285:                default:
        !           286:                usage:
        !           287:                        errx(1, "usage: string_quote -d dquotefile\n"
        !           288:                                "\tstring_quote -e [rawtext]");
        !           289:                }
        !           290:        }
        !           291:        ac -= optind;
        !           292:        av += optind;
        !           293:        if (decode == -1)
        !           294:                goto usage;
        !           295:        if (decode && ac != 1)
        !           296:                goto usage;
        !           297:        if (!decode && ac != 0 && ac != 1)
        !           298:                goto usage;
        !           299: 
        !           300:        /* Encode or decode */
        !           301:        if (ac == 0)
        !           302:                fp = stdin;
        !           303:        else if ((fp = fopen(av[0], "r")) == NULL)
        !           304:                err(1, "%s", av[0]);
        !           305:        if (decode) {
        !           306:                if ((ch = getc(fp)) != '"')
        !           307:                        errx(1, "input does not start with a double quote");
        !           308:                if ((s = string_dequote(fp, TYPED_MEM_TEMP)) == NULL)
        !           309:                        err(1, "error dequoting %s", av[0]);
        !           310:                fputs(s, stdout);
        !           311:                FREE(TYPED_MEM_TEMP, s);
        !           312:        } else {
        !           313:                char buf[1024];
        !           314:                int len;
        !           315: 
        !           316:                len = fread(buf, 1, sizeof(buf) - 1, fp);
        !           317:                if (ferror(fp))
        !           318:                        err(1, "reading rawtext input");
        !           319:                if (len == sizeof(buf) - 1)
        !           320:                        warnx("warning: only %u characters dealt with", len);
        !           321:                buf[len] = '\0';
        !           322:                if ((s = string_enquote(buf, TYPED_MEM_TEMP)) == NULL)
        !           323:                        err(1, "error dequoting %s", av[0]);
        !           324:                fputs(s, stdout);
        !           325:                putchar('\n');
        !           326:                FREE(TYPED_MEM_TEMP, s);
        !           327:        }
        !           328:        return (0);
        !           329: }
        !           330: 
        !           331: #endif /* STRING_QUOTE_TEST */
        !           332: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>