
/********************************************
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;
}
