Annotation of embedaddon/libpdel/util/string_quote.c, revision 1.1.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>