1/* vi: set sw=4 ts=4: */ 2/* 3 * Utility routines. 4 * 5 * Copyright (C) Manuel Novoa III <mjn3@codepoet.org> 6 * and Vladimir Oleynik <dzo@simtreas.ru> 7 * 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 9 */ 10 11#include "libbb.h" 12 13#define WANT_HEX_ESCAPES 1 14 15/* Usual "this only works for ascii compatible encodings" disclaimer. */ 16#undef _tolower 17#define _tolower(X) ((X)|((char) 0x20)) 18 19char bb_process_escape_sequence(const char **ptr) 20{ 21 static const char charmap[] ALIGN1 = { 22 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0, 23 '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' }; 24 25 const char *p; 26 const char *q; 27 unsigned int num_digits; 28 unsigned int r; 29 unsigned int n; 30 unsigned int d; 31 unsigned int base; 32 33 num_digits = n = 0; 34 base = 8; 35 q = *ptr; 36 37#ifdef WANT_HEX_ESCAPES 38 if (*q == 'x') { 39 ++q; 40 base = 16; 41 ++num_digits; 42 } 43#endif 44 45 do { 46 d = (unsigned char)(*q) - '0'; 47#ifdef WANT_HEX_ESCAPES 48 if (d >= 10) { 49 d = (unsigned char)(_tolower(*q)) - 'a' + 10; 50 } 51#endif 52 53 if (d >= base) { 54#ifdef WANT_HEX_ESCAPES 55 if ((base == 16) && (!--num_digits)) { 56/* return '\\'; */ 57 --q; 58 } 59#endif 60 break; 61 } 62 63 r = n * base + d; 64 if (r > UCHAR_MAX) { 65 break; 66 } 67 68 n = r; 69 ++q; 70 } while (++num_digits < 3); 71 72 if (num_digits == 0) { /* mnemonic escape sequence? */ 73 p = charmap; 74 do { 75 if (*p == *q) { 76 q++; 77 break; 78 } 79 } while (*++p); 80 n = *(p + (sizeof(charmap)/2)); 81 } 82 83 *ptr = q; 84 85 return (char) n; 86} 87