process_escape_sequence.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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. #include "libbb.h"
  11. #define WANT_HEX_ESCAPES 1
  12. /* Usual "this only works for ascii compatible encodings" disclaimer. */
  13. #undef _tolower
  14. #define _tolower(X) ((X)|((char) 0x20))
  15. char FAST_FUNC bb_process_escape_sequence(const char **ptr)
  16. {
  17. static const char charmap[] ALIGN1 = {
  18. 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0,
  19. '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
  20. const char *p;
  21. const char *q;
  22. unsigned int num_digits;
  23. unsigned int r;
  24. unsigned int n;
  25. unsigned int d;
  26. unsigned int base;
  27. num_digits = n = 0;
  28. base = 8;
  29. q = *ptr;
  30. #ifdef WANT_HEX_ESCAPES
  31. if (*q == 'x') {
  32. ++q;
  33. base = 16;
  34. ++num_digits;
  35. }
  36. #endif
  37. do {
  38. d = (unsigned char)(*q) - '0';
  39. #ifdef WANT_HEX_ESCAPES
  40. if (d >= 10) {
  41. d = (unsigned char)(_tolower(*q)) - 'a' + 10;
  42. }
  43. #endif
  44. if (d >= base) {
  45. #ifdef WANT_HEX_ESCAPES
  46. if ((base == 16) && (!--num_digits)) {
  47. /* return '\\'; */
  48. --q;
  49. }
  50. #endif
  51. break;
  52. }
  53. r = n * base + d;
  54. if (r > UCHAR_MAX) {
  55. break;
  56. }
  57. n = r;
  58. ++q;
  59. } while (++num_digits < 3);
  60. if (num_digits == 0) { /* mnemonic escape sequence? */
  61. p = charmap;
  62. do {
  63. if (*p == *q) {
  64. q++;
  65. break;
  66. }
  67. } while (*++p);
  68. n = *(p + (sizeof(charmap)/2));
  69. }
  70. *ptr = q;
  71. return (char) n;
  72. }