/********************************************
str.c
libmawk changes (C) 2009-2010, Tibor 'Igor2' Palinkas;
based on mawk code coming with the below copyright:
copyright 1991, Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
#include "mawk.h"
#include "scan.h"
static const char hex_val['f' - 'A' + 1] = /* read-only */
{
10, 11, 12, 13, 14, 15, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
10, 11, 12, 13, 14, 15
};
#define isoctal(x) ((x)>='0'&&(x)<='7')
#define hex_value(x) hex_val[(x)-'A']
#define ishex(x) (MAWK->scan_code[x] == SC_DIGIT ||\
('A' <= (x) && (x) <= 'f' && hex_value(x)))
static int octal(char **);
static int hex(mawk_state_t *, char **);
/* process one , two or three octal digits
moving a pointer forward by reference */
static int octal(char **start_p)
{
register char *p = *start_p;
register unsigned x;
x = *p++ - '0';
if (isoctal(*p)) {
x = (x << 3) + *p++ - '0';
if (isoctal(*p))
x = (x << 3) + *p++ - '0';
}
*start_p = p;
return x & 0xff;
}
/* process one or two hex digits
moving a pointer forward by reference */
static int hex(mawk_state_t *MAWK, char **start_p)
{
register unsigned char *p = (unsigned char *) *start_p;
register unsigned x;
unsigned t;
if (MAWK->scan_code[*p] == SC_DIGIT)
x = *p++ - '0';
else
x = hex_value(*p++);
if (MAWK->scan_code[*p] == SC_DIGIT)
x = (x << 4) + *p++ - '0';
else if ('A' <= *p && *p <= 'f' && (t = hex_value(*p))) {
x = (x << 4) + t;
p++;
}
*start_p = (char *) p;
return x;
}
/* process the escape characters in a string, in place . */
char *mawk_rm_escape(mawk_state_t *MAWK, char *s)
{
register char *p, *q;
char *t;
int i;
q = p = s;
while (*p) {
if (*p == '\\') {
MAWK->escape_test[ET_END].in = *++p; /* sentinal */
i = 0;
while (MAWK->escape_test[i].in != *p)
i++;
if (i != ET_END) { /* in table */
p++;
*q++ = MAWK->escape_test[i].out;
}
else if (isoctal(*p)) {
t = p;
*q++ = octal(&t);
p = t;
}
else if ((*p == 'x') && (ishex(*(unsigned char *) (p + 1)))) {
t = p + 1;
*q++ = hex(MAWK, &t);
p = t;
}
else if (*p == 0) /* can only happen with command line assign */
*q++ = '\\';
else { /* not an escape sequence */
*q++ = '\\';
*q++ = *p++;
}
}
else
*q++ = *p++;
}
*q = 0;
return s;
}