/*- * Copyright (c)1997-2005 by Hartmut Brandt * All rights reserved. * * Author: Harti Brandt * * 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. * * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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. * * $Begemot: libbegemot/cstrc.c,v 1.5 2005/06/01 07:50:35 brandt_h Exp $ */ # include # include # include "begemot.h" # define GROW 100 int cstrwarn; static unsigned char getx(char **); static unsigned char geto(char **); char * cstrc(char **pp, char delim, size_t *plen) { size_t alloc; char *str; unsigned char c; alloc = GROW; *plen = 0; str = xalloc(alloc); while((c = **pp) != (unsigned char)delim && c != '\0') { (*pp)++; if(c == '\\') { switch(c = *(*pp)++) { case '\0': (*pp)--; c = '\\'; break; case '\\': case '\'': case '"': break; default: if(cstrwarn) warn("unknown escape sequence '%c'", c); break; case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; case 'x': if(!isascii((u_int)**pp) || !isxdigit((u_int)**pp)) { if(cstrwarn) warn("\\x used with no following hex digits"); break; } c = getx(pp); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': (*pp)--; c = geto(pp); break; } } if(alloc == *plen) { alloc += GROW; str = xrealloc(str, alloc); } str[(*plen)++] = c; } if(alloc == *plen) { alloc += 1; str = xrealloc(str, alloc); } str[*plen] = '\0'; return str; } static unsigned char getx(char **pp) { unsigned char c, ci; int len = 2; c = 0; while(len--) { ci = **pp; if(!isxdigit(ci)) break; if(isupper(ci)) c = (c << 4) + ci - 'A' + 10; else if(islower(ci)) c = (c << 4) + ci - 'a' + 10; else c = (c << 4) + ci - '0'; (*pp)++; } return c; } static unsigned char geto(char **pp) { unsigned char ci; unsigned c; int len = 3; c = 0; while(len--) { ci = **pp; if(!isdigit(ci) || ci == '8' || ci == '9') break; c = (c << 3) + ci - '0'; (*pp)++; } if(c > 0377 && cstrwarn) warn("escape sequence out of range"); return c; } # ifdef TEST # include int main(int argc, char *argv[]) { char *ret, *str; size_t len; cstrwarn = 1; str = argv[1]; ret = cstrc(&str, '"', &len); fprintf(stderr, "'%s'\n", str); fwrite(ret, 1, len, stdout); return 0; } # endif