1 /*
2  * phpdbg_lexer.l
3  */
4 
5 #include "phpdbg.h"
6 #include "phpdbg_cmd.h"
7 
8 #include "phpdbg_parser.h"
9 
10 #define LEX(v) (PHPDBG_G(lexer).v)
11 
12 #define YYCTYPE unsigned char
13 #define YYSETCONDITION(x) LEX(state) = x;
14 #define YYGETCONDITION() LEX(state)
15 #define YYCURSOR LEX(cursor)
16 #define YYMARKER LEX(marker)
17 #define YYCTXMARKER LEX(ctxmarker)
18 #define yyleng LEX(len)
19 #define yytext ((char*) LEX(text))
20 #undef YYDEBUG
21 #define YYDEBUG(a, b)
22 #define YYFILL(n)
23 
24 #define NORMAL 0
25 #define PRE_RAW 1
26 #define RAW 2
27 #define INITIAL 3
28 
ZEND_EXTERN_MODULE_GLOBALS(phpdbg)29 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
30 
31 void phpdbg_init_lexer (phpdbg_param_t *stack, char *input) {
32 	PHPDBG_G(parser_stack) = stack;
33 
34 	YYSETCONDITION(INITIAL);
35 
36 	LEX(text) = YYCURSOR = (unsigned char *) input;
37 	LEX(len) = strlen(input);
38 }
39 
unescape_string(char * s)40 static int unescape_string(char *s) {
41 	switch (*s) {
42 		case '\'':
43 		case '\"': {
44 			char start = *s;
45 			size_t off = 1;
46 			do {
47 				if (s[off] == '\\') {
48 					off++;
49 				}
50 				*s = s[off];
51 			} while ((++s)[off] != start);
52 			return off + 1;
53 		}
54 	}
55 
56 	return 0;
57 }
58 
phpdbg_lex(phpdbg_param_t * yylval)59 int phpdbg_lex (phpdbg_param_t* yylval) {
60 
61 restart:
62 	LEX(text) = YYCURSOR;
63 
64 /*!re2c
65 re2c:yyfill:check = 0;
66 T_TRUE      'true'
67 T_YES       'yes'
68 T_ON        'on'
69 T_ENABLED   'enabled'
70 T_FALSE     'false'
71 T_NO        'no'
72 T_OFF       'off'
73 T_DISABLED  'disabled'
74 T_EVAL      'ev'
75 T_SHELL     'sh'
76 T_IF        'if'
77 T_RUN       'run'
78 T_RUN_SHORT "r"
79 WS          [ \r\t]+
80 DIGITS      [-]?[0-9\.]+
81 ID          [^ \r\n\t:#\000]+
82 GENERIC_ID  ([^ \r\n\t:#\000"']|":\\")+|["]([^\n\000"\\]|"\\\\"|"\\"["])+["]|[']([^\n\000'\\]|"\\\\"|"\\"['])+[']
83 ADDR        [0][x][a-fA-F0-9]+
84 OPCODE      (ZEND_|zend_)([A-Za-z])+
85 INPUT       ("\\"[#"']|["]("\\\\"|"\\"["]|[^\n\000"])+["]|[']("\\"[']|"\\\\"|[^\n\000'])+[']|[^\n\000#"'])+
86 
87 <!*> := yyleng = (size_t) YYCURSOR - (size_t) yytext;
88 
89 <*>[\n\000] {
90 	return 0;
91 }
92 
93 <PRE_RAW, NORMAL>"-r"{WS}?{DIGITS} {
94 	char *text = yytext + 2;
95 	while (*++text < '0');
96 	yylval->num = atoi(text);
97 	return T_REQ_ID;
98 }
99 
100 <NORMAL>{T_IF}{WS} {
101 	YYSETCONDITION(RAW);
102 	phpdbg_init_param(yylval, EMPTY_PARAM);
103 	return T_IF;
104 }
105 
106 <NORMAL>"#"/{DIGITS} {
107 	return T_POUND;
108 }
109 
110 <*>"#" {
111 	YYSETCONDITION(INITIAL);
112 	return T_SEPARATOR;
113 }
114 
115 <NORMAL>"::" {
116 	return T_DCOLON;
117 }
118 
119 <NORMAL>":"/[^\\] {
120 	return T_COLON;
121 }
122 
123 <NORMAL>{ID}"://" {
124 	phpdbg_init_param(yylval, STR_PARAM);
125 	yylval->str = estrndup(yytext, yyleng);
126 	yylval->len = yyleng;
127 	return T_PROTO;
128 }
129 
130 <NORMAL>({T_YES}|{T_ON}|{T_ENABLED}|{T_TRUE})/[ \r\t\n\000] {
131 	phpdbg_init_param(yylval, NUMERIC_PARAM);
132 	yylval->num = 1;
133 	return T_TRUTHY;
134 }
135 
136 <NORMAL>({T_NO}|{T_OFF}|{T_DISABLED}|{T_FALSE})/[ \r\t\n\000] {
137 	phpdbg_init_param(yylval, NUMERIC_PARAM);
138 	yylval->num = 0;
139 	return T_FALSY;
140 }
141 
142 <NORMAL>{DIGITS} {
143 	phpdbg_init_param(yylval, NUMERIC_PARAM);
144 	yylval->num = atoi(yytext);
145 	return T_DIGITS;
146 }
147 
148 <NORMAL>{ADDR} {
149 	phpdbg_init_param(yylval, ADDR_PARAM);
150 	yylval->addr = strtoul(yytext, 0, 16);
151 	return T_ADDR;
152 }
153 
154 <NORMAL>{OPCODE} {
155 	phpdbg_init_param(yylval, OP_PARAM);
156 	yylval->str = estrndup(yytext, yyleng);
157 	yylval->len = yyleng;
158 	return T_OPCODE;
159 }
160 
161 <NORMAL>{GENERIC_ID} {
162 	phpdbg_init_param(yylval, STR_PARAM);
163 	yylval->str = estrndup(yytext, yyleng - unescape_string(yytext));
164 	yylval->len = yyleng;
165 	return T_ID;
166 }
167 
168 <RAW>{INPUT} {
169 	phpdbg_init_param(yylval, STR_PARAM);
170 	yylval->str = estrdup(yytext);
171 	yylval->len = yyleng;
172 	return T_INPUT;
173 }
174 
175 <*>{WS} {
176 	/* ignore whitespace */
177 
178 	goto restart;
179 }
180 
181 <INITIAL>{T_EVAL}{WS} {
182 	YYSETCONDITION(PRE_RAW);
183 	phpdbg_init_param(yylval, EMPTY_PARAM);
184 	return T_EVAL;
185 }
186 
187 <INITIAL>{T_SHELL}{WS} {
188 	YYSETCONDITION(PRE_RAW);
189 	phpdbg_init_param(yylval, EMPTY_PARAM);
190 	return T_SHELL;
191 }
192 
193 <INITIAL>({T_RUN}|{T_RUN_SHORT}){WS} {
194 	YYSETCONDITION(PRE_RAW);
195 	phpdbg_init_param(yylval, EMPTY_PARAM);
196 	return T_RUN;
197 }
198 
199 <PRE_RAW>[^ ] {
200 	YYSETCONDITION(RAW);
201 
202 	YYCURSOR = LEX(text);
203 	goto restart;
204 }
205 
206 <INITIAL>[^ ] {
207 	YYSETCONDITION(NORMAL);
208 
209 	YYCURSOR = LEX(text);
210 	goto restart;
211 }
212 
213 */
214 }
215