blob: 138e751f568705b65e014d284de2cf5ea7cdd600 [file] [log] [blame]
Eric Andersenaad1a882001-03-16 22:47:14 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
Manuel Novoa III cad53642003-03-19 09:13:01 +00005 * Copyright (C) Manuel Novoa III <mjn3@codepoet.org>
Glenn L McGrathb4a1baa2003-01-13 22:09:50 +00006 * and Vladimir Oleynik <dzo@simtreas.ru>
Eric Andersenaad1a882001-03-16 22:47:14 +00007 *
Bernhard Reutner-Fischerb1629b12006-05-19 19:29:19 +00008 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Eric Andersenaad1a882001-03-16 22:47:14 +00009 */
10
11#include <stdio.h>
12#include <limits.h>
Eric Andersenb2a30052004-07-26 12:11:32 +000013#include <ctype.h>
Eric Andersenaad1a882001-03-16 22:47:14 +000014#include "libbb.h"
15
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000016#define WANT_HEX_ESCAPES 1
17
18/* Usual "this only works for ascii compatible encodings" disclaimer. */
19#undef _tolower
20#define _tolower(X) ((X)|((char) 0x20))
21
Manuel Novoa III cad53642003-03-19 09:13:01 +000022char bb_process_escape_sequence(const char **ptr)
Eric Andersenaad1a882001-03-16 22:47:14 +000023{
Eric Andersene5dfced2001-04-09 22:48:12 +000024 static const char charmap[] = {
25 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0,
26 '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
Eric Andersenaad1a882001-03-16 22:47:14 +000027
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000028 const char *p;
29 const char *q;
30 unsigned int num_digits;
31 unsigned int r;
32 unsigned int n;
33 unsigned int d;
34 unsigned int base;
35
36 num_digits = n = 0;
37 base = 8;
Eric Andersene5dfced2001-04-09 22:48:12 +000038 q = *ptr;
Eric Andersenaad1a882001-03-16 22:47:14 +000039
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000040#ifdef WANT_HEX_ESCAPES
Eric Andersenb2a30052004-07-26 12:11:32 +000041 if (*q == 'x') {
Eric Andersenb2a30052004-07-26 12:11:32 +000042 ++q;
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000043 base = 16;
44 ++num_digits;
Eric Andersenb2a30052004-07-26 12:11:32 +000045 }
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000046#endif
Eric Andersenb2a30052004-07-26 12:11:32 +000047
Manuel Novoa III cad53642003-03-19 09:13:01 +000048 do {
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000049 d = (unsigned int)(*q - '0');
50#ifdef WANT_HEX_ESCAPES
51 if (d >= 10) {
52 d = ((unsigned int)(_tolower(*q) - 'a')) + 10;
53 }
54#endif
55
56 if (d >= base) {
57#ifdef WANT_HEX_ESCAPES
58 if ((base == 16) && (!--num_digits)) {
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000059/* return '\\'; */
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000060 --q;
61 }
62#endif
Eric Andersenccfc4482004-07-27 16:45:46 +000063 break;
Eric Andersenb2a30052004-07-26 12:11:32 +000064 }
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000065
66 r = n * base + d;
67 if (r > UCHAR_MAX) {
68 break;
Eric Andersene5dfced2001-04-09 22:48:12 +000069 }
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000070
71 n = r;
72 ++q;
73 } while (++num_digits < 3);
Eric Andersenaad1a882001-03-16 22:47:14 +000074
Eric Andersene5dfced2001-04-09 22:48:12 +000075 if (num_digits == 0) { /* mnemonic escape sequence? */
Manuel Novoa III cad53642003-03-19 09:13:01 +000076 p = charmap;
77 do {
Eric Andersene5dfced2001-04-09 22:48:12 +000078 if (*p == *q) {
79 q++;
80 break;
81 }
Manuel Novoa III cad53642003-03-19 09:13:01 +000082 } while (*++p);
Eric Andersene5dfced2001-04-09 22:48:12 +000083 n = *(p+(sizeof(charmap)/2));
84 }
Eric Andersenaad1a882001-03-16 22:47:14 +000085
Eric Andersene5dfced2001-04-09 22:48:12 +000086 *ptr = q;
Manuel Novoa III 413db4d2004-07-29 23:15:16 +000087
Eric Andersene5dfced2001-04-09 22:48:12 +000088 return (char) n;
Eric Andersenaad1a882001-03-16 22:47:14 +000089}