char.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include <string.h>
  2. #include "target.h"
  3. #include "lib.h"
  4. #include "allocate.h"
  5. #include "token.h"
  6. #include "expression.h"
  7. #include "char.h"
  8. static const char *parse_escape(const char *p, unsigned *val, const char *end, int bits, struct position pos)
  9. {
  10. unsigned c = *p++;
  11. unsigned d;
  12. if (c != '\\') {
  13. *val = c;
  14. return p;
  15. }
  16. c = *p++;
  17. switch (c) {
  18. case 'a': c = '\a'; break;
  19. case 'b': c = '\b'; break;
  20. case 't': c = '\t'; break;
  21. case 'n': c = '\n'; break;
  22. case 'v': c = '\v'; break;
  23. case 'f': c = '\f'; break;
  24. case 'r': c = '\r'; break;
  25. case 'e': c = '\e'; break;
  26. case 'x': {
  27. unsigned mask = -(1U << (bits - 4));
  28. for (c = 0; p < end; c = (c << 4) + d) {
  29. d = hexval(*p);
  30. if (d > 16)
  31. break;
  32. p++;
  33. if (c & mask) {
  34. warning(pos,
  35. "hex escape sequence out of range");
  36. mask = 0;
  37. }
  38. }
  39. break;
  40. }
  41. case '0'...'7': {
  42. if (p + 2 < end)
  43. end = p + 2;
  44. c -= '0';
  45. while (p < end && (d = *p - '0') < 8) {
  46. c = (c << 3) + d;
  47. p++;
  48. }
  49. if ((c & 0400) && bits < 9)
  50. warning(pos,
  51. "octal escape sequence out of range");
  52. break;
  53. }
  54. default: /* everything else is left as is */
  55. warning(pos, "unknown escape sequence: '\\%c'", c);
  56. break;
  57. case '\\':
  58. case '\'':
  59. case '"':
  60. case '?':
  61. break; /* those are legal, so no warnings */
  62. }
  63. *val = c & ~((~0U << (bits - 1)) << 1);
  64. return p;
  65. }
  66. void get_char_constant(struct token *token, unsigned long long *val)
  67. {
  68. const char *p = token->embedded, *end;
  69. unsigned v;
  70. int type = token_type(token);
  71. switch (type) {
  72. case TOKEN_CHAR:
  73. case TOKEN_WIDE_CHAR:
  74. p = token->string->data;
  75. end = p + token->string->length - 1;
  76. if (end == p) {
  77. sparse_error(token->pos, "empty character constant");
  78. *val = 0;
  79. return;
  80. }
  81. break;
  82. case TOKEN_CHAR_EMBEDDED_0 ... TOKEN_CHAR_EMBEDDED_3:
  83. end = p + type - TOKEN_CHAR;
  84. break;
  85. default:
  86. end = p + type - TOKEN_WIDE_CHAR;
  87. }
  88. p = parse_escape(p, &v, end,
  89. type < TOKEN_WIDE_CHAR ? bits_in_char : wchar_ctype->bit_size, token->pos);
  90. if (p != end)
  91. warning(token->pos,
  92. "multi-character character constant");
  93. *val = v;
  94. }
  95. struct token *get_string_constant(struct token *token, struct expression *expr)
  96. {
  97. struct string *string = token->string;
  98. struct token *next = token->next, *done = NULL;
  99. int stringtype = token_type(token);
  100. int is_wide = stringtype == TOKEN_WIDE_STRING;
  101. static char buffer[MAX_STRING];
  102. int len = 0;
  103. int bits;
  104. int esc_count = 0;
  105. while (!done) {
  106. switch (token_type(next)) {
  107. case TOKEN_WIDE_STRING:
  108. is_wide = 1;
  109. case TOKEN_STRING:
  110. next = next->next;
  111. break;
  112. default:
  113. done = next;
  114. }
  115. }
  116. bits = is_wide ? wchar_ctype->bit_size: bits_in_char;
  117. while (token != done) {
  118. unsigned v;
  119. const char *p = token->string->data;
  120. const char *end = p + token->string->length - 1;
  121. while (p < end) {
  122. if (*p == '\\')
  123. esc_count++;
  124. p = parse_escape(p, &v, end, bits, token->pos);
  125. if (len < MAX_STRING)
  126. buffer[len] = v;
  127. len++;
  128. }
  129. token = token->next;
  130. }
  131. if (len > MAX_STRING) {
  132. warning(token->pos, "trying to concatenate %d-character string (%d bytes max)", len, MAX_STRING);
  133. len = MAX_STRING;
  134. }
  135. if (esc_count || len >= string->length) {
  136. if (string->immutable || len >= string->length) /* can't cannibalize */
  137. string = __alloc_string(len+1);
  138. string->length = len+1;
  139. memcpy(string->data, buffer, len);
  140. string->data[len] = '\0';
  141. }
  142. expr->string = string;
  143. expr->wide = is_wide;
  144. return token;
  145. }