root/src/noit_tokenizer.re

Revision 6210da7ee0e2ed143d71a8e00b709f16e71059f8, 4.1 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 5 years ago)

various changes to avoid dereferencing type-punned pointers and breaking strict-aliasing rules, refs #34

  • Property mode set to 100644
Line 
1 #include "noit_defines.h"
2 #include <stdlib.h>
3 #include <string.h>
4
5 struct token {
6   char *token;
7   const char *start;
8   const char *end;
9   const char *next;
10   enum { NT_IDENT, NT_DQSTRING, NT_SPACE, NT_UNKNOWN, NT_EOF } type;
11 };
12 #define SET_TOKEN(t,a) (t)->next = (a)
13
14 static void c_unescape(char *p, char *only) {
15   char *bt = p;
16 #define ASSIGN(a) *(bt++) = (a)
17   while(p[0] != '\0') {
18     if(p[0] == '\\' && p[1] != '\0' && (!only || p[1] == *only)) {
19       switch(p[1]) {
20         case ' ': ASSIGN(' '); p+=2; break;
21         case '"': ASSIGN('"'); p+=2; break;
22         case 'n': ASSIGN('\n'); p+=2; break;
23         case 'r': ASSIGN('\r'); p+=2; break;
24         case 't': ASSIGN('\t'); p+=2; break;
25         case 'a': ASSIGN('\a'); p+=2; break;
26         case 'b': ASSIGN('\b'); p+=2; break;
27         case 'v': ASSIGN('\v'); p+=2; break;
28         case 'f': ASSIGN('\f'); p+=2; break;
29         case '0': ASSIGN('\0'); p+=2; break;
30         case '\\': ASSIGN('\\'); p+=2; break;
31         default: ASSIGN(*p); p++; ASSIGN(*p); p++; break;
32       }
33     }
34     else {
35       ASSIGN(*p); p++;
36     }
37   }
38   *bt = '\0';
39 }
40
41 #define BAIL_UNKNOWN do { t->type = NT_UNKNOWN; return -1; } while(0)
42 static int token_scan(struct token *t)
43 {
44   t->start = t->end = t->next;
45
46  mainpattern:
47 /*!re2c
48     re2c:define:YYCTYPE  = "unsigned char";
49     re2c:define:YYCURSOR = t->next;
50     re2c:yyfill:enable   = 0;
51     re2c:yych:conversion = 1;
52     re2c:indent:top      = 1;
53
54     [ \t\r\n]+      { t->token = NULL;
55                       t->end = t->next;
56                       t->type = NT_SPACE;
57                       return 1; }
58     ["]             { t->type = NT_DQSTRING;
59                       if(t->start != t->end) {
60                         t->start++;
61                         t->end = t->next - 1;
62                         t->token = malloc(t->end-t->start + 1);
63                         strlcpy(t->token, t->start, t->end-t->start + 1);
64                         c_unescape(t->token, NULL);
65                         return 1;
66                       }
67                       else
68                         goto dqstring;
69                     }
70     "'"             { t->type = NT_IDENT;
71                       if(t->start != t->end) {
72                         t->start++;
73                         t->end = t->next - 1;
74                         t->token = malloc(t->end-t->start + 1);
75                         strlcpy(t->token, t->start, t->end-t->start + 1);
76                         return 1;
77                       }
78                       else
79                         goto sqstring;
80                     }
81     [^\000'" \t\r\n] ([^\000 \t\r\n]|[\\][ ])*
82                     { char only = ' ';
83                       t->end = t->next;
84                       t->type = NT_IDENT;
85                       t->token = malloc(t->end-t->start + 1);
86                       strlcpy(t->token, t->start, t->end-t->start + 1);
87                       c_unescape(t->token, &only);
88                       return 1;
89                     }
90     [\000]          { t->token = NULL;
91                       t->type = NT_EOF;
92                       return 0;
93                     }
94     [\000-\377]     { BAIL_UNKNOWN; }
95 */
96
97  sqstring:
98 /*!re2c
99     [^'\000]*       { t->end = t->next;
100                       goto mainpattern; }
101     [\000]          { BAIL_UNKNOWN; }
102 */
103
104  dqstring:
105 /*!re2c
106     [\\][nrtabvf0"\\]
107                     { goto dqstring; }
108     "\\" ( [^\000] \ [nrtabvf0"\\] )
109                     { goto dqstring; }
110     ["]             { t->end = t->next--;
111                       goto mainpattern;
112                     }
113     [^"\000]\[\\"]  { goto dqstring; }
114     [\000]          { BAIL_UNKNOWN; }
115 */
116 }
117
118 int noit_tokenize(const char *input, char **vector, int *cnt) {
119   struct token t;
120   int i = 0;
121
122   SET_TOKEN(&t, input);
123   while(token_scan(&t) != -1) {
124     switch(t.type) {
125       case NT_IDENT:
126       case NT_DQSTRING:
127         if(i<*cnt) vector[i] = t.token;
128         i++;
129         break;
130       case NT_SPACE:
131         break;
132       case NT_EOF:
133         if(i<*cnt) *cnt = i;
134         return i;
135       case NT_UNKNOWN:
136         /* UNREACHED */
137         goto failure;
138     }
139   }
140  failure:
141   if(i<*cnt) *cnt = i;
142   return input - t.next;
143 }
Note: See TracBrowser for help on using the browser.