/*-
* Copyright (c)1997-2005 by Hartmut Brandt
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
* 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 <string.h>
# include <ctype.h>
# 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 <stdio.h>
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
syntax highlighted by Code2HTML, v. 0.9.1