3
0

process_escape_sequence.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. /* bash builtin "echo -e '\ec'" interprets \e as ESC,
  18. * but coreutils "/bin/echo -e '\ec'" does not.
  19. * manpages tend to support coreutils way.
  20. * Update: coreutils added support for \e on 28 Oct 2009. */
  21. static const char charmap[] ALIGN1 = {
  22. 'a', 'b', 'e', 'f', 'n', 'r', 't', 'v', '\\', 0,
  23. '\a', '\b', 27, '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
  24. const char *p;
  25. const char *q;
  26. unsigned num_digits;
  27. unsigned r;
  28. unsigned n;
  29. unsigned d;
  30. unsigned base;
  31. num_digits = n = 0;
  32. base = 8;
  33. q = *ptr;
  34. #ifdef WANT_HEX_ESCAPES
  35. if (*q == 'x') {
  36. ++q;
  37. base = 16;
  38. ++num_digits;
  39. }
  40. #endif
  41. /* bash requires leading 0 in octal escapes:
  42. * \02 works, \2 does not (prints \ and 2).
  43. * We treat \2 as a valid octal escape sequence. */
  44. do {
  45. d = (unsigned char)(*q) - '0';
  46. #ifdef WANT_HEX_ESCAPES
  47. if (d >= 10) {
  48. d = (unsigned char)(_tolower(*q)) - 'a' + 10;
  49. }
  50. #endif
  51. if (d >= base) {
  52. #ifdef WANT_HEX_ESCAPES
  53. if ((base == 16) && (!--num_digits)) {
  54. /* return '\\'; */
  55. --q;
  56. }
  57. #endif
  58. break;
  59. }
  60. r = n * base + d;
  61. if (r > UCHAR_MAX) {
  62. break;
  63. }
  64. n = r;
  65. ++q;
  66. } while (++num_digits < 3);
  67. if (num_digits == 0) { /* mnemonic escape sequence? */
  68. p = charmap;
  69. do {
  70. if (*p == *q) {
  71. q++;
  72. break;
  73. }
  74. } while (*++p);
  75. /* p points to found escape char or NUL,
  76. * advance it and find what it translates to */
  77. p += sizeof(charmap) / 2;
  78. n = *p;
  79. }
  80. *ptr = q;
  81. return (char) n;
  82. }