[alt.sources] How can I de-escape my strings at run time?

rsalz@bbn.com (Rich Salz) (06/01/90)

In <6550.26639B0A@puddle.fidonet.org> cspw.quagga@p0.f4.n494.z5.fidonet.org (cspw quagga) writes:
>Is there an easy way to read a string into a buffer with automatic run-time
>translation of the escape sequences?  I want to do something like this:
> 
> { char fmt[100];
>   gets(fmt);
>      descape(fmt);   /*   ... This is the function I need   */
>   printf(fmt,123);
>   ...
> }

/*
**  Convert C escape sequences in a string.  Returns a pointer to
**  malloc'd space, or NULL if malloc failed.
*/
#include <stdio.h>
#include <ctype.h>

#define OCTDIG(c)	('0' <= (c) && (c) <= '7')
#define HEXDIG(c)	isxdigit(c)

char *
UnEscapify(text)
    register char	*text;
{
    extern char		*malloc();
    register char	*p;
    char		*save;
    int			i;

    if ((save = malloc(strlen(text) + 1)) == NULL)
	return NULL;

    for (p = save; *text; text++, p++) {
	if (*text != '\\')
	    *p = *text;
	else {
	    switch (*++text) {
	    default:				/* Undefined; ignore it	*/
	    case '\'': case '\\': case '"': case '?':
		*p = *text;
		break;

	    case '\0':
		*p = '\0';
		return save;

	    case '0': case '1': case '2': case '3':
	    case '4': case '5': case '6': case '7':
		for (*p = 0, i = 0; OCTDIG(*text) && i < 3; text++, i++)
		    *p = (*p << 3) + *text - '0';
		text--;
		break;

	    case 'x':
		for (*p = 0; *++text && isxdigit(*text); )
		    if (isdigit(*text))
			*p = (*p << 4) + *text - '0';
		    else if (isupper(*text))
			*p = (*p << 4) + *text - 'A';
		    else
			*p = (*p << 4) + *text - 'a';
		text--;
		break;

	    case 'a':	*p = '\007';	break;	/* Alert		*/
	    case 'b':	*p = '\b';	break;	/* Backspace		*/
	    case 'f':	*p = '\f';	break;	/* Form feed		*/
	    case 'n':	*p = '\n';	break;	/* New line		*/
	    case 'r':	*p = '\r';	break;	/* Carriage return	*/
	    case 't':	*p = '\t';	break;	/* Horizontal tab	*/
	    case 'v':	*p = '\n';	break;	/* Vertical tab		*/

	    }
	}
    }
    *p = '\0';
    return save;
}

#ifdef	TEST

main()
{
    char	buff[256];
    char	*p;

    printf("Enter strings, EOF to quit:\n");
    while (gets(buff)) {
	if ((p = UnEscapify(buff)) == NULL) {
	    perror("Malloc failed");
	    abort();
	}
	printf("|%s|\n", p);
	free(p);
    }
    exit(0);

}
#endif	/*TEST */
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.

rsalz@bbn.com (Rich Salz) (06/01/90)

Oops...

From: Kevin Braunsdorf <ksb@nostromo.cc.purdue.edu>
To: rsalz@BBN.COM

In article <2596@litchi.bbn.com> you write:
|	    case 'x':
|		for (*p = 0; *++text && isxdigit(*text); )
|		    if (isdigit(*text))
|			*p = (*p << 4) + *text - '0';
|		    else if (isupper(*text))
|			*p = (*p << 4) + *text - 'A';
|		    else
|			*p = (*p << 4) + *text - 'a';
|		text--;
|		break;
Nope.  You forgot to add 10 for the 'a' and 'A' case.
			*p = (*p << 4) + *text - 'A' + 10;
		    else
			*p = (*p << 4) + *text - 'a' + 10;

Sorry about that.
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.