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>