db: always split the return values if we're not using --info
[smatch.git] / char.c
blob6a46a11ec4d918a6e4941d7b61838a1a84925e40
1 #include <string.h>
2 #include "target.h"
3 #include "lib.h"
4 #include "allocate.h"
5 #include "token.h"
6 #include "expression.h"
8 static const char *parse_escape(const char *p, unsigned *val, const char *end, int bits, struct position pos)
10 unsigned c = *p++;
11 unsigned d;
12 if (c != '\\') {
13 *val = c;
14 return p;
17 c = *p++;
18 switch (c) {
19 case 'a': c = '\a'; break;
20 case 'b': c = '\b'; break;
21 case 't': c = '\t'; break;
22 case 'n': c = '\n'; break;
23 case 'v': c = '\v'; break;
24 case 'f': c = '\f'; break;
25 case 'r': c = '\r'; break;
26 case 'e': c = '\e'; break;
27 case 'x': {
28 unsigned mask = -(1U << (bits - 4));
29 for (c = 0; p < end; c = (c << 4) + d) {
30 d = hexval(*p++);
31 if (d > 16)
32 break;
33 if (c & mask) {
34 warning(pos,
35 "hex escape sequence out of range");
36 mask = 0;
39 break;
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 if ((c & 0400) && bits < 9)
48 warning(pos,
49 "octal escape sequence out of range");
50 break;
52 default: /* everything else is left as is */
53 break;
55 *val = c & ~((~0U << (bits - 1)) << 1);
56 return p;
59 void get_char_constant(struct token *token, unsigned long long *val)
61 const char *p = token->embedded, *end;
62 unsigned v;
63 int type = token_type(token);
64 switch (type) {
65 case TOKEN_CHAR:
66 case TOKEN_WIDE_CHAR:
67 p = token->string->data;
68 end = p + token->string->length;
69 break;
70 case TOKEN_CHAR_EMBEDDED_0 ... TOKEN_CHAR_EMBEDDED_3:
71 end = p + type - TOKEN_CHAR;
72 break;
73 default:
74 end = p + type - TOKEN_WIDE_CHAR;
76 p = parse_escape(p, &v, end,
77 type < TOKEN_WIDE_CHAR ? bits_in_char : 32, token->pos);
78 if (p != end)
79 warning(token->pos,
80 "multi-character character constant");
81 *val = v;
84 struct token *get_string_constant(struct token *token, struct expression *expr)
86 struct string *string = token->string;
87 struct token *next = token->next, *done = NULL;
88 int stringtype = token_type(token);
89 int is_wide = stringtype == TOKEN_WIDE_STRING;
90 static char buffer[MAX_STRING];
91 int len = 0;
92 int bits;
94 while (!done) {
95 switch (token_type(next)) {
96 case TOKEN_WIDE_STRING:
97 is_wide = 1;
98 case TOKEN_STRING:
99 next = next->next;
100 break;
101 default:
102 done = next;
105 bits = is_wide ? 32 : bits_in_char;
106 while (token != done) {
107 unsigned v;
108 const char *p = token->string->data;
109 const char *end = p + token->string->length - 1;
110 while (p < end) {
111 p = parse_escape(p, &v, end, bits, token->pos);
112 if (len < MAX_STRING)
113 buffer[len] = v;
114 len++;
116 token = token->next;
118 if (len > MAX_STRING) {
119 warning(token->pos, "trying to concatenate %d-character string (%d bytes max)", len, MAX_STRING);
120 len = MAX_STRING;
123 if (len >= string->length) /* can't cannibalize */
124 string = __alloc_string(len+1);
125 string->length = len+1;
126 memcpy(string->data, buffer, len);
127 string->data[len] = '\0';
128 expr->string = string;
129 expr->wide = is_wide;
130 return token;