diff options
Diffstat (limited to 'src/sp_config_scanner.re')
| -rw-r--r-- | src/sp_config_scanner.re | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/src/sp_config_scanner.re b/src/sp_config_scanner.re index 75e0424..063d332 100644 --- a/src/sp_config_scanner.re +++ b/src/sp_config_scanner.re | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | /*!types:re2c*/ | 3 | /*!types:re2c*/ |
| 4 | 4 | ||
| 5 | #define cs_error_log(fmt, ...) sp_log_err("config", fmt, ##__VA_ARGS__) | 5 | #define cs_log_error(fmt, ...) sp_log_err("config", fmt, ##__VA_ARGS__) |
| 6 | #define cs_log_info(fmt, ...) sp_log_msg("config", SP_LOG_INFO, fmt, ##__VA_ARGS__) | ||
| 6 | 7 | ||
| 7 | zend_string *sp_get_arg_string(sp_parsed_keyword *kw) { | 8 | zend_string *sp_get_arg_string(sp_parsed_keyword *kw) { |
| 8 | if (!kw || !kw->arg) { | 9 | if (!kw || !kw->arg) { |
| @@ -73,11 +74,11 @@ static void str_dtor(zval *zv) { | |||
| 73 | 74 | ||
| 74 | // sy_ functions and macros are helpers for the shunting yard algorithm | 75 | // sy_ functions and macros are helpers for the shunting yard algorithm |
| 75 | #define sy_res_push(val) \ | 76 | #define sy_res_push(val) \ |
| 76 | if (cond_res_i >= 100) { cs_error_log("condition too complex on line %d", lineno); goto out; } \ | 77 | if (cond_res_i >= 100) { cs_log_error("condition too complex on line %d", lineno); goto out; } \ |
| 77 | cond_res[cond_res_i++] = val; | 78 | cond_res[cond_res_i++] = val; |
| 78 | #define sy_res_pop() cond_res[--cond_res_i] | 79 | #define sy_res_pop() cond_res[--cond_res_i] |
| 79 | #define sy_op_push(op) \ | 80 | #define sy_op_push(op) \ |
| 80 | if (cond_op_i >= 100) { cs_error_log("condition too complex on line %d", lineno); goto out; } \ | 81 | if (cond_op_i >= 100) { cs_log_error("condition too complex on line %d", lineno); goto out; } \ |
| 81 | cond_op[cond_op_i++] = op; | 82 | cond_op[cond_op_i++] = op; |
| 82 | #define sy_op_pop() cond_op[--cond_op_i] | 83 | #define sy_op_pop() cond_op[--cond_op_i] |
| 83 | #define sy_op_peek() cond_op[cond_op_i-1] | 84 | #define sy_op_peek() cond_op[cond_op_i-1] |
| @@ -119,7 +120,7 @@ static int sy_apply_op(char op, int a, int b) { | |||
| 119 | #define SY_APPLY_OP_FROM_STACK() \ | 120 | #define SY_APPLY_OP_FROM_STACK() \ |
| 120 | char op = sy_op_pop(); \ | 121 | char op = sy_op_pop(); \ |
| 121 | int unary = (op == '!'); \ | 122 | int unary = (op == '!'); \ |
| 122 | if (cond_res_i < (2 - unary)) { cs_error_log("not enough input on line %d", lineno); goto out; } \ | 123 | if (cond_res_i < (2 - unary)) { cs_log_error("not enough input on line %d", lineno); goto out; } \ |
| 123 | int a = sy_res_pop(); \ | 124 | int a = sy_res_pop(); \ |
| 124 | int b = unary ? 0 : sy_res_pop(); \ | 125 | int b = unary ? 0 : sy_res_pop(); \ |
| 125 | int res = sy_apply_op(op, a, b); \ | 126 | int res = sy_apply_op(op, a, b); \ |
| @@ -166,7 +167,7 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key | |||
| 166 | keyword = [a-zA-Z_][a-zA-Z0-9_]*; | 167 | keyword = [a-zA-Z_][a-zA-Z0-9_]*; |
| 167 | string = "\"" ("\\\"" | [^"\r\n])* "\""; | 168 | string = "\"" ("\\\"" | [^"\r\n])* "\""; |
| 168 | 169 | ||
| 169 | <init> * { cs_error_log("Parser error on line %d", lineno); goto out; } | 170 | <init> * { cs_log_error("Parser error on line %d", lineno); goto out; } |
| 170 | <init> ws+ { goto yyc_init; } | 171 | <init> ws+ { goto yyc_init; } |
| 171 | <init> [;#] .* { goto yyc_init; } | 172 | <init> [;#] .* { goto yyc_init; } |
| 172 | <init> nl { lineno++; goto yyc_init; } | 173 | <init> nl { lineno++; goto yyc_init; } |
| @@ -185,6 +186,14 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key | |||
| 185 | } | 186 | } |
| 186 | <init> "@condition" ws+ { goto yyc_cond; } | 187 | <init> "@condition" ws+ { goto yyc_cond; } |
| 187 | <init> "@end_condition" ws* ";" { cond_res[0] = 1; goto yyc_init; } | 188 | <init> "@end_condition" ws* ";" { cond_res[0] = 1; goto yyc_init; } |
| 189 | <init> "@log" ws+ @t1 string? @t2 { | ||
| 190 | char tmpstr[1024]; | ||
| 191 | size_t tmplen = MIN(t2-t1-2, 1023); | ||
| 192 | strncpy(tmpstr, t1+1, tmplen); | ||
| 193 | tmpstr[tmplen] = 0; | ||
| 194 | cs_log_info("[line %d]: %s", lineno, tmpstr); | ||
| 195 | goto yyc_init; | ||
| 196 | } | ||
| 188 | 197 | ||
| 189 | <cond> ws+ { goto yyc_cond; } | 198 | <cond> ws+ { goto yyc_cond; } |
| 190 | <cond> nl { lineno++; goto yyc_cond; } | 199 | <cond> nl { lineno++; goto yyc_cond; } |
| @@ -193,7 +202,7 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key | |||
| 193 | int is_loaded = (zend_hash_str_find_ptr(&module_registry, t3+1, t4-t3-2) != NULL); | 202 | int is_loaded = (zend_hash_str_find_ptr(&module_registry, t3+1, t4-t3-2) != NULL); |
| 194 | sy_res_push(is_loaded); | 203 | sy_res_push(is_loaded); |
| 195 | } else { | 204 | } else { |
| 196 | cs_error_log("unknown function in condition on line %d", lineno); | 205 | cs_log_error("unknown function in condition on line %d", lineno); |
| 197 | goto out; | 206 | goto out; |
| 198 | } | 207 | } |
| 199 | goto yyc_cond_op; | 208 | goto yyc_cond_op; |
| @@ -201,7 +210,7 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key | |||
| 201 | <cond> @t1 keyword @t2 { | 210 | <cond> @t1 keyword @t2 { |
| 202 | zend_string *tmp = zend_hash_str_find_ptr(&vars, t1, t2-t1); | 211 | zend_string *tmp = zend_hash_str_find_ptr(&vars, t1, t2-t1); |
| 203 | if (!tmp) { | 212 | if (!tmp) { |
| 204 | cs_error_log("unknown variable in condition on line %d", lineno); | 213 | cs_log_error("unknown variable in condition on line %d", lineno); |
| 205 | goto out; | 214 | goto out; |
| 206 | } | 215 | } |
| 207 | sy_res_push(atoi(ZSTR_VAL(tmp))); | 216 | sy_res_push(atoi(ZSTR_VAL(tmp))); |
| @@ -231,27 +240,27 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key | |||
| 231 | SY_APPLY_OP_FROM_STACK(); | 240 | SY_APPLY_OP_FROM_STACK(); |
| 232 | } | 241 | } |
| 233 | if (cond_op_i == 0 || sy_op_peek() != '(') { | 242 | if (cond_op_i == 0 || sy_op_peek() != '(') { |
| 234 | cs_error_log("unbalanced parathesis on line %d", lineno); goto out; | 243 | cs_log_error("unbalanced parathesis on line %d", lineno); goto out; |
| 235 | } | 244 | } |
| 236 | cond_op_i--; | 245 | cond_op_i--; |
| 237 | goto yyc_cond_op; | 246 | goto yyc_cond_op; |
| 238 | } | 247 | } |
| 239 | <cond_op> ";" { | 248 | <cond_op> ";" { |
| 240 | while (cond_op_i) { | 249 | while (cond_op_i) { |
| 241 | if (sy_op_peek() == '(') { cs_error_log("unbalanced parathesis on line %d", lineno); goto out; } | 250 | if (sy_op_peek() == '(') { cs_log_error("unbalanced parathesis on line %d", lineno); goto out; } |
| 242 | SY_APPLY_OP_FROM_STACK(); | 251 | SY_APPLY_OP_FROM_STACK(); |
| 243 | } | 252 | } |
| 244 | if (cond_res_i > 1) { cs_error_log("invalid condition on line %d", lineno); goto out; } | 253 | if (cond_res_i > 1) { cs_log_error("invalid condition on line %d", lineno); goto out; } |
| 245 | goto yyc_init; | 254 | goto yyc_init; |
| 246 | } | 255 | } |
| 247 | <cond, cond_op> * { cs_error_log("Syntax error in condition on line %d", lineno); goto out; } | 256 | <cond, cond_op> * { cs_log_error("Syntax error in condition on line %d", lineno); goto out; } |
| 248 | 257 | ||
| 249 | <rule> ws+ { goto yyc_rule; } | 258 | <rule> ws+ { goto yyc_rule; } |
| 250 | <rule> nl / ( nl | ws )* "." { lineno++; goto yyc_rule; } | 259 | <rule> nl / ( nl | ws )* "." { lineno++; goto yyc_rule; } |
| 251 | <rule> "." @t1 keyword @t2 ( "(" @t3 ( string? | keyword ) @t4 ")" )? { | 260 | <rule> "." @t1 keyword @t2 ( "(" @t3 ( string? | keyword ) @t4 ")" )? { |
| 252 | if (!cond_res[0]) { goto yyc_rule; } | 261 | if (!cond_res[0]) { goto yyc_rule; } |
| 253 | if (kw_i == max_keywords) { | 262 | if (kw_i == max_keywords) { |
| 254 | cs_error_log("Too many keywords in rule (more than %d) on line %d", max_keywords, lineno); | 263 | cs_log_error("Too many keywords in rule (more than %d) on line %d", max_keywords, lineno); |
| 255 | goto out; | 264 | goto out; |
| 256 | } | 265 | } |
| 257 | sp_parsed_keyword kw = {.kw = (char*)t1, .kwlen = t2-t1, .arg = (char*)t3, .arglen = t4-t3, .argtype = SP_ARGTYPE_UNKNOWN, .lineno = lineno}; | 266 | sp_parsed_keyword kw = {.kw = (char*)t1, .kwlen = t2-t1, .arg = (char*)t3, .arglen = t4-t3, .argtype = SP_ARGTYPE_UNKNOWN, .lineno = lineno}; |
| @@ -265,7 +274,7 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key | |||
| 265 | } else { | 274 | } else { |
| 266 | zend_string *tmp = zend_hash_str_find_ptr(&vars, t3, t4-t3); | 275 | zend_string *tmp = zend_hash_str_find_ptr(&vars, t3, t4-t3); |
| 267 | if (!tmp) { | 276 | if (!tmp) { |
| 268 | cs_error_log("unknown variable on line %d", lineno); | 277 | cs_log_error("unknown variable on line %d", lineno); |
| 269 | goto out; | 278 | goto out; |
| 270 | } | 279 | } |
| 271 | kw.arg = ZSTR_VAL(tmp); | 280 | kw.arg = ZSTR_VAL(tmp); |
