Mercurial > njs
changeset 140:23598cfcfd15
nxt_trace interface. nxt_regex, RegExp, and parser use it now.
| author | Igor Sysoev <igor@sysoev.ru> |
|---|---|
| date | Thu, 04 Aug 2016 16:05:38 +0300 |
| parents | 016339472304 |
| children | b33ba39a1108 |
| files | Makefile njs/njs_generator.c njs/njs_parser.c njs/njs_parser.h njs/njs_parser_expression.c njs/njs_regexp.c njs/njs_regexp.h njs/njs_string.c njs/njs_variable.c njs/njs_vm.c njs/njs_vm.h njs/njscript.c njs/test/njs_unit_test.c nxt/Makefile nxt/nxt_clang.h nxt/nxt_pcre.c nxt/nxt_regex.h |
| diffstat | 17 files changed, 263 insertions(+), 271 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Thu Aug 04 14:45:27 2016 +0300 +++ b/Makefile Thu Aug 04 16:05:38 2016 +0300 @@ -169,6 +169,7 @@ njs/njs_object_hash.h \ njs/njs_array.h \ njs/njs_function.h \ + njs/njs_regexp.h \ njs/njs_parser.h \ njs/njs_string.c \ @@ -404,6 +405,7 @@ -I$(NXT_LIB) -Injs \ njs/test/njs_unit_test.c \ $(NXT_BUILDDIR)/libnjs.a \ + $(NXT_BUILDDIR)/libnxt.a \ -lm $(NXT_PCRE_LIB) include $(NXT_LIB)/Makefile
--- a/njs/njs_generator.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_generator.c Thu Aug 04 16:05:38 2016 +0300 @@ -21,13 +21,6 @@ #include <njs_variable.h> #include <njs_parser.h> #include <string.h> -#include <stdio.h> - - -typedef enum { - NJS_GENERATOR_ERROR_ILLEGAL_CONTINUE = 0, - NJS_GENERATOR_ERROR_ILLEGAL_BREAK, -} njs_generator_error_t; static nxt_int_t njs_generator(njs_vm_t *vm, njs_parser_t *parser, @@ -125,8 +118,6 @@ static nxt_noinline nxt_int_t njs_generator_index_release(njs_vm_t *vm, njs_parser_t *parser, njs_index_t index); nxt_inline nxt_bool_t njs_generator_is_constant(njs_parser_node_t *node); -static nxt_int_t njs_generator_error(njs_vm_t *vm, njs_parser_node_t *node, - njs_generator_error_t err); static const nxt_str_t no_label = { 0, NULL }; @@ -1085,7 +1076,10 @@ } } - return njs_generator_error(vm, node, NJS_GENERATOR_ERROR_ILLEGAL_CONTINUE); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Illegal continue statement"); + + return NXT_ERROR; found: @@ -1126,7 +1120,10 @@ } } - return njs_generator_error(vm, node, NJS_GENERATOR_ERROR_ILLEGAL_BREAK); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Illegal break statement"); + + return NXT_ERROR; found: @@ -2476,25 +2473,3 @@ return (node->token >= NJS_TOKEN_FIRST_CONST && node->token <= NJS_TOKEN_LAST_CONST); } - - -static nxt_int_t -njs_generator_error(njs_vm_t *vm, njs_parser_node_t *node, - njs_generator_error_t err) -{ - uint32_t size; - const char *msg; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; - - static const char *errors[] = { - "SyntaxError: Illegal continue statement in %u", - "SyntaxError: Illegal break statement in %u", - }; - - msg = errors[err]; - - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - msg, node->token_line); - - return njs_vm_throw_exception(vm, buf, size); -}
--- a/njs/njs_parser.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_parser.c Thu Aug 04 16:05:38 2016 +0300 @@ -54,8 +54,6 @@ static njs_token_t njs_parser_if_statement(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_switch_statement(njs_vm_t *vm, njs_parser_t *parser); -static njs_token_t njs_parser_duplicate_default_branch(njs_vm_t *vm, - njs_parser_t *parser); static njs_token_t njs_parser_while_statement(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_do_while_statement(njs_vm_t *vm, @@ -68,8 +66,6 @@ static njs_token_t njs_parser_break_statement(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_try_statement(njs_vm_t *vm, njs_parser_t *parser); -static njs_token_t njs_parser_missing_catch_or_finally(njs_vm_t *vm, - njs_parser_t *parser); static njs_token_t njs_parser_try_block(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_throw_statement(njs_vm_t *vm, njs_parser_t *parser); @@ -844,7 +840,11 @@ } else { if (dflt != NULL) { - return njs_parser_duplicate_default_branch(vm, parser); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: More than one default clause " + "in switch statement"); + + return NJS_TOKEN_ILLEGAL; } branch = node; @@ -890,22 +890,6 @@ static njs_token_t -njs_parser_duplicate_default_branch(njs_vm_t *vm, njs_parser_t *parser) -{ - uint32_t size; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; - - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - "SyntaxError: More than one default clause " - "in switch statement in %u", parser->lexer->line); - - (void) njs_vm_throw_exception(vm, buf, size); - - return NJS_TOKEN_ILLEGAL; -} - - -static njs_token_t njs_parser_while_statement(njs_vm_t *vm, njs_parser_t *parser) { njs_token_t token; @@ -1099,19 +1083,14 @@ njs_parser_for_in_statement(njs_vm_t *vm, njs_parser_t *parser, nxt_str_t *name, njs_token_t token) { - uint32_t size; njs_parser_node_t *node; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; node = parser->node->left; if (node->token != NJS_TOKEN_NAME) { - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - "ReferenceError: Invalid left-hand side \"%.*s\" " - "in for-in statement in %u", - (int) name->length, name->start, parser->lexer->line); - - (void) njs_vm_throw_exception(vm, buf, size); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, "ReferenceError: Invalid " + "left-hand side \"%.*s\" in for-in statement", + (int) name->length, name->start); return NJS_TOKEN_ILLEGAL; } @@ -1326,29 +1305,15 @@ } if (try->right == NULL) { - return njs_parser_missing_catch_or_finally(vm, parser); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Missing catch or finally after try"); + + return NJS_TOKEN_ILLEGAL; } parser->node = try; return token; - -} - - -static njs_token_t -njs_parser_missing_catch_or_finally(njs_vm_t *vm, njs_parser_t *parser) -{ - uint32_t size; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; - - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - "SyntaxError: Missing catch or finally after try in %u", - parser->lexer->line); - - (void) njs_vm_throw_exception(vm, buf, size); - - return NJS_TOKEN_ILLEGAL; } @@ -1612,8 +1577,11 @@ break; case NJS_TOKEN_UNTERMINATED_STRING: - return njs_parser_error(vm, parser, - NJS_PARSER_ERROR_UNTERMINATED_STRING); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Unterminated string \"%.*s\"", + (int) parser->lexer->text.length, parser->lexer->text.start); + + return NJS_TOKEN_ILLEGAL; case NJS_TOKEN_NUMBER: nxt_thread_log_debug("JS: %f", parser->lexer->number); @@ -2042,8 +2010,7 @@ } if (hex_length == 0 || hex_length > 6) { - return njs_parser_error(vm, parser, - NJS_PARSER_ERROR_UNICODE); + goto invalid; } skip = 1; @@ -2118,12 +2085,12 @@ hex_end = src + hex_length; if (hex_end > end) { - return njs_parser_error(vm, parser, NJS_PARSER_ERROR_UNICODE); + goto invalid; } u = njs_number_radix_parse(src, hex_end, 16, 1); if (nxt_slow_path(u < 0)) { - return njs_parser_error(vm, parser, NJS_PARSER_ERROR_UNICODE); + goto invalid; } src = hex_end + skip; @@ -2150,6 +2117,14 @@ dst = start; } + +invalid: + + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Invalid Unicode code point \"%.*s\"", + (int) parser->lexer->text.length, parser->lexer->text.start); + + return NJS_TOKEN_ILLEGAL; } @@ -2208,48 +2183,53 @@ njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { - uint32_t size; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; - if (token != NJS_TOKEN_END) { - return njs_parser_error(vm, parser, NJS_PARSER_ERROR_UNEXPECTED_TOKEN); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Unexpected token \"%.*s\"", + (int) parser->lexer->text.length, parser->lexer->text.start); + + } else { + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Unexpected end of input"); } - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - "SyntaxError: Unexpected end of input in %u", - parser->lexer->line); - - (void) njs_vm_throw_exception(vm, buf, size); - return NJS_TOKEN_ILLEGAL; } -njs_token_t -njs_parser_error(njs_vm_t *vm, njs_parser_t *parser, njs_parser_error_t err) +u_char * +njs_parser_trace_handler(nxt_trace_t *trace, nxt_trace_data_t *td, + u_char *start) { - uint32_t size; - njs_lexer_t *lexer; - const char *msg; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; - - static const char *errors[] = { - "SyntaxError: Unexpected token \"%.*s\" in %u", - "SyntaxError: Unterminated string \"%.*s\" in %u", - "SyntaxError: Invalid Unicode code point \"%.*s\" in %u", - "SyntaxError: Unterminated RegExp \"%.*s\" in %u", - "SyntaxError: Invalid RegExp flags \"%.*s\" in %u", - "SyntaxError: Duplicate declaration \"%.*s\" in %u", - }; - - msg = errors[err]; - lexer = parser->lexer; - - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - msg, (int) lexer->text.length, lexer->text.start, - lexer->line); - - (void) njs_vm_throw_exception(vm, buf, size); - - return NJS_TOKEN_ILLEGAL; + int n; + u_char *p; + ssize_t size; + njs_vm_t *vm; + + p = start; + + if (td->level == NXT_LEVEL_CRIT) { + size = sizeof("InternalError: ") - 1; + memcpy(p, "InternalError: ", size); + p = start + size; + } + + vm = trace->data; + + trace = trace->next; + p = trace->handler(trace, td, p); + + if (vm->parser != NULL) { + size = td->end - start; + + n = snprintf((char *) p, size, " in %u", vm->parser->lexer->line); + + if (n < size) { + p += n; + } + } + + njs_vm_throw_exception(vm, start, p - start); + + return p; }
--- a/njs/njs_parser.h Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_parser.h Thu Aug 04 16:05:38 2016 +0300 @@ -314,16 +314,6 @@ }; -typedef enum { - NJS_PARSER_ERROR_UNEXPECTED_TOKEN = 0, - NJS_PARSER_ERROR_UNTERMINATED_STRING, - NJS_PARSER_ERROR_UNICODE, - NJS_PARSER_ERROR_UNTERMINATED_REGEXP, - NJS_PARSER_ERROR_REGEXP_FLAGS, - NJS_PARSER_ERROR_DUPLICATE_DECLARATION, -} njs_parser_error_t; - - njs_token_t njs_lexer_token(njs_lexer_t *lexer); nxt_int_t njs_lexer_keywords_init(nxt_mem_cache_pool_t *mcp, nxt_lvlhsh_t *hash); @@ -350,8 +340,8 @@ nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value); njs_index_t njs_parser_index(njs_parser_t *parser, uint32_t scope); nxt_bool_t njs_parser_has_side_effect(njs_parser_node_t *node); -njs_token_t njs_parser_error(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_error_t err); +u_char *njs_parser_trace_handler(nxt_trace_t *trace, nxt_trace_data_t *td, + u_char *start); nxt_int_t njs_generate_scope(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node);
--- a/njs/njs_parser_expression.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_parser_expression.c Thu Aug 04 16:05:38 2016 +0300 @@ -24,7 +24,6 @@ #include <njs_variable.h> #include <njs_parser.h> #include <string.h> -#include <stdio.h> typedef struct { @@ -75,8 +74,6 @@ njs_parser_t *parser, njs_token_t token); static njs_token_t njs_parser_property_brackets(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token); -static njs_token_t njs_parser_invalid_lvalue(njs_vm_t *vm, - njs_parser_t *parser, const char* operation); static const njs_parser_expression_t @@ -294,7 +291,9 @@ node = parser->node; if (parser->node->token != NJS_TOKEN_NAME) { - return njs_parser_invalid_lvalue(vm, parser, "assignment"); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "ReferenceError: Invalid left-hand side in assignment"); + return NJS_TOKEN_ILLEGAL; } pending = NULL; @@ -439,7 +438,9 @@ node = parser->node; if (!njs_parser_is_lvalue(parser->node)) { - return njs_parser_invalid_lvalue(vm, parser, "assignment"); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "ReferenceError: Invalid left-hand side in assignment"); + return NJS_TOKEN_ILLEGAL; } pending = NULL; @@ -811,7 +812,9 @@ } if (!njs_parser_is_lvalue(parser->node)) { - return njs_parser_invalid_lvalue(vm, parser, "prefix operation"); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "ReferenceError: Invalid left-hand side in prefix operation"); + return NJS_TOKEN_ILLEGAL; } node = njs_parser_node_alloc(vm); @@ -863,7 +866,9 @@ } if (!njs_parser_is_lvalue(parser->node)) { - return njs_parser_invalid_lvalue(vm, parser, "postfix operation"); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "ReferenceError: Invalid left-hand side in postfix operation"); + return NJS_TOKEN_ILLEGAL; } node = njs_parser_node_alloc(vm); @@ -1143,21 +1148,3 @@ return token; } - - -static njs_token_t -njs_parser_invalid_lvalue(njs_vm_t *vm, njs_parser_t *parser, - const char *operation) -{ - uint32_t size; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; - - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - "ReferenceError: Invalid left-hand side in %s in %u", - operation, parser->lexer->line); - - (void) njs_vm_throw_exception(vm, buf, size); - - return NJS_TOKEN_ILLEGAL; - -}
--- a/njs/njs_regexp.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_regexp.c Thu Aug 04 16:05:38 2016 +0300 @@ -39,6 +39,10 @@ nxt_bool_t bound); static int njs_regexp_pattern_compile(njs_vm_t *vm, nxt_regex_t *regex, u_char *source, int options); +static u_char *njs_regexp_compile_trace_handler(nxt_trace_t *trace, + nxt_trace_data_t *td, u_char *start); +static u_char *njs_regexp_match_trace_handler(nxt_trace_t *trace, + nxt_trace_data_t *td, u_char *start); static njs_ret_t njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp, u_char *string, nxt_regex_match_data_t *match_data, nxt_uint_t utf8); static njs_ret_t njs_regexp_string_create(njs_vm_t *vm, njs_value_t *value, @@ -59,6 +63,8 @@ return NXT_ERROR; } + vm->regex_context->trace = &vm->trace; + return NXT_OK; } @@ -161,10 +167,11 @@ flags = njs_regexp_flags(&p, lexer->end, 0); if (nxt_slow_path(flags < 0)) { - lexer->text.start = lexer->start; - lexer->text.length = p - lexer->text.start; - return njs_parser_error(vm, parser, - NJS_PARSER_ERROR_REGEXP_FLAGS); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Invalid RegExp flags \"%.*s\"", + p - lexer->start, lexer->start); + + return NJS_TOKEN_ILLEGAL; } lexer->start = p; @@ -181,10 +188,11 @@ } } - lexer->text.start = lexer->start - 1; - lexer->text.length = p - lexer->text.start; + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Unterminated RegExp \"%.*s\"", + p - lexer->start - 1, lexer->start - 1); - return njs_parser_error(vm, parser, NJS_PARSER_ERROR_UNTERMINATED_REGEXP); + return NJS_TOKEN_ILLEGAL; } @@ -345,28 +353,97 @@ njs_regexp_pattern_compile(njs_vm_t *vm, nxt_regex_t *regex, u_char *source, int options) { - uint32_t size; - nxt_int_t ret; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; + nxt_int_t ret; + nxt_trace_handler_t handler; + + handler = vm->trace.handler; + vm->trace.handler = njs_regexp_compile_trace_handler; /* Zero length means a zero-terminated string. */ ret = nxt_regex_compile(regex, source, 0, options, vm->regex_context); + vm->trace.handler = handler; + if (nxt_fast_path(ret == NXT_OK)) { return regex->ncaptures; } + return ret; +} + + +static u_char * +njs_regexp_compile_trace_handler(nxt_trace_t *trace, nxt_trace_data_t *td, + u_char *start) +{ + int n; + u_char *p; + ssize_t size; + njs_vm_t *vm; + + size = sizeof("SyntaxError: ") - 1; + memcpy(start, "SyntaxError: ", size); + p = start + size; + + vm = trace->data; + + trace = trace->next; + p = trace->handler(trace, td, p); + if (vm->parser != NULL) { - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - "SyntaxError: %s in %u", - vm->regex_context->error, vm->parser->lexer->line); + size = td->end - start; + + n = snprintf((char *) p, size, " in %u", vm->parser->lexer->line); - } else { - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - "SyntaxError: %s", vm->regex_context->error); + if (n < size) { + p += n; + } } - return njs_vm_throw_exception(vm, buf, size); + njs_vm_throw_exception(vm, start, p - start); + + return p; +} + + +nxt_int_t +njs_regexp_match(njs_vm_t *vm, nxt_regex_t *regex, u_char *subject, size_t len, + nxt_regex_match_data_t *match_data) +{ + nxt_int_t ret; + nxt_trace_handler_t handler; + + handler = vm->trace.handler; + vm->trace.handler = njs_regexp_match_trace_handler; + + ret = nxt_regex_match(regex, subject, len, match_data, vm->regex_context); + + vm->trace.handler = handler; + + return ret; +} + + +static u_char * +njs_regexp_match_trace_handler(nxt_trace_t *trace, nxt_trace_data_t *td, + u_char *start) +{ + u_char *p; + size_t size; + njs_vm_t *vm; + + size = sizeof("RegExpError: ") - 1; + memcpy(start, "RegExpError: ", size); + p = start + size; + + vm = trace->data; + + trace = trace->next; + p = trace->handler(trace, td, p); + + njs_vm_throw_exception(vm, start, p - start); + + return p; } @@ -517,13 +594,13 @@ pattern = args[0].data.u.regexp->pattern; if (nxt_regex_is_valid(&pattern->regex[n])) { - ret = nxt_regex_match(&pattern->regex[n], string.start, string.size, - vm->single_match_data, vm->regex_context); + ret = njs_regexp_match(vm, &pattern->regex[n], string.start, + string.size, vm->single_match_data); if (ret >= 0) { retval = &njs_value_true; } else if (ret != NGX_REGEX_NOMATCH) { - return njs_regexp_match_error(vm); + return NXT_ERROR; } } @@ -589,8 +666,8 @@ return NXT_ERROR; } - ret = nxt_regex_match(&pattern->regex[n], string.start, string.size, - match_data, vm->regex_context); + ret = njs_regexp_match(vm, &pattern->regex[n], string.start, + string.size, match_data); if (ret >= 0) { return njs_regexp_exec_result(vm, regexp, string.start, match_data, utf8); @@ -599,7 +676,7 @@ if (nxt_slow_path(ret != NGX_REGEX_NOMATCH)) { nxt_regex_match_data_free(match_data, vm->regex_context); - return njs_regexp_match_error(vm); + return NXT_ERROR; } } @@ -736,19 +813,6 @@ } -njs_ret_t -njs_regexp_match_error(njs_vm_t *vm) -{ - uint32_t size; - u_char buf[NJS_EXCEPTION_BUF_LENGTH]; - - size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH, - "RegExpError: %s", vm->regex_context->error); - - return njs_vm_throw_exception(vm, buf, size); -} - - static const njs_object_prop_t njs_regexp_constructor_properties[] = { /* RegExp.name == "RegExp". */
--- a/njs/njs_regexp.h Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_regexp.h Thu Aug 04 16:05:38 2016 +0300 @@ -39,10 +39,11 @@ njs_value_t *value); njs_regexp_pattern_t *njs_regexp_pattern_create(njs_vm_t *vm, u_char *string, size_t length, njs_regexp_flags_t flags); +nxt_int_t njs_regexp_match(njs_vm_t *vm, nxt_regex_t *regex, u_char *subject, + size_t len, nxt_regex_match_data_t *match_data); njs_regexp_t *njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern); njs_ret_t njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); -njs_ret_t njs_regexp_match_error(njs_vm_t *vm); extern const njs_object_init_t njs_regexp_constructor_init;
--- a/njs/njs_string.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_string.c Thu Aug 04 16:05:38 2016 +0300 @@ -31,7 +31,6 @@ #include <njs_regexp.h> #include <njs_regexp_pattern.h> #include <string.h> -#include <stdio.h> static nxt_noinline void njs_string_slice_prop(njs_string_prop_t *string, @@ -1455,14 +1454,14 @@ n = (string.length != 0); if (nxt_regex_is_valid(&pattern->regex[n])) { - ret = nxt_regex_match(&pattern->regex[n], string.start, string.size, - vm->single_match_data, vm->regex_context); + ret = njs_regexp_match(vm, &pattern->regex[n], string.start, + string.size, vm->single_match_data); if (ret >= 0) { captures = nxt_regex_captures(vm->single_match_data); index = njs_string_index(&string, captures[0]); } else if (ret != NGX_REGEX_NOMATCH) { - return njs_regexp_match_error(vm); + return NXT_ERROR; } } } @@ -1555,8 +1554,8 @@ array = NULL; do { - ret = nxt_regex_match(&pattern->regex[n], string.start, string.size, - vm->single_match_data, vm->regex_context); + ret = njs_regexp_match(vm, &pattern->regex[n], string.start, + string.size, vm->single_match_data); if (ret >= 0) { if (array != NULL) { if (array->length == array->size) { @@ -1617,7 +1616,7 @@ break; } else { - return njs_regexp_match_error(vm); + return NXT_ERROR; } } while (string.size > 0); @@ -1756,8 +1755,8 @@ end = string.start + string.size; do { - ret = nxt_regex_match(&pattern->regex[n], start, end - start, - vm->single_match_data, vm->regex_context); + ret = njs_regexp_match(vm, &pattern->regex[n], start, + end - start, vm->single_match_data); if (ret >= 0) { captures = nxt_regex_captures(vm->single_match_data); @@ -1769,7 +1768,7 @@ next = (u_char *) end + 1; } else { - return njs_regexp_match_error(vm); + return NXT_ERROR; } /* Empty split regexp. */
--- a/njs/njs_variable.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_variable.c Thu Aug 04 16:05:38 2016 +0300 @@ -79,7 +79,9 @@ return var; } - (void) njs_parser_error(vm, parser, NJS_PARSER_ERROR_DUPLICATE_DECLARATION); + nxt_alert(&vm->trace, NXT_LEVEL_ERROR, + "SyntaxError: Duplicate declaration \"%.*s\"", + (int) parser->lexer->text.length, parser->lexer->text.start); return NULL; }
--- a/njs/njs_vm.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_vm.c Thu Aug 04 16:05:38 2016 +0300 @@ -3316,24 +3316,21 @@ } -njs_ret_t +void njs_vm_throw_exception(njs_vm_t *vm, u_char *buf, uint32_t size) { uint32_t length; njs_value_t *value; value = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_value_t)); - if (nxt_slow_path(value == NULL)) { - return NJS_TOKEN_ERROR; + + if (nxt_fast_path(value != NULL)) { + vm->exception = value; + + length = nxt_utf8_length(buf, size); + + (void) njs_string_new(vm, value, buf, size, length); } - - vm->exception = value; - - length = nxt_utf8_length(buf, size); - - (void) njs_string_new(vm, value, buf, size, length); - - return NXT_ERROR; }
--- a/njs/njs_vm.h Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njs_vm.h Thu Aug 04 16:05:38 2016 +0300 @@ -8,6 +8,7 @@ #define _NJS_VM_H_INCLUDED_ +#include <nxt_trace.h> #include <nxt_regex.h> @@ -799,6 +800,7 @@ nxt_array_t *code; /* of njs_vm_code_t */ + nxt_trace_t trace; nxt_random_t random; }; @@ -827,9 +829,6 @@ }; -#define NJS_EXCEPTION_BUF_LENGTH 2048 - - nxt_int_t njs_vmcode_interpreter(njs_vm_t *vm); void njs_value_retain(njs_value_t *value); @@ -969,7 +968,7 @@ const njs_value_t *src); void njs_number_set(njs_value_t *value, double num); -njs_ret_t njs_vm_throw_exception(njs_vm_t *vm, u_char *buf, uint32_t size); +void njs_vm_throw_exception(njs_vm_t *vm, u_char *buf, uint32_t size); nxt_int_t njs_builtin_objects_create(njs_vm_t *vm); nxt_int_t njs_builtin_objects_clone(njs_vm_t *vm);
--- a/njs/njscript.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/njscript.c Thu Aug 04 16:05:38 2016 +0300 @@ -155,6 +155,11 @@ if (externals != NULL) { vm->externals_hash = *externals; } + + vm->trace.level = NXT_LEVEL_TRACE; + vm->trace.size = 2048; + vm->trace.handler = njs_parser_trace_handler; + vm->trace.data = vm; } return vm; @@ -325,6 +330,11 @@ goto fail; } + nvm->trace.level = NXT_LEVEL_TRACE; + nvm->trace.size = 2048; + nvm->trace.handler = njs_parser_trace_handler; + nvm->trace.data = nvm; + return nvm; }
--- a/njs/test/njs_unit_test.c Thu Aug 04 14:45:27 2016 +0300 +++ b/njs/test/njs_unit_test.c Thu Aug 04 16:05:38 2016 +0300 @@ -3511,6 +3511,9 @@ { nxt_string("/(/.test('')"), nxt_string("SyntaxError: pcre_compile(\"(\") failed: missing ) in 1") }, + { nxt_string("/+/.test('')"), + nxt_string("SyntaxError: pcre_compile(\"+\") failed: nothing to repeat at \"+\" in 1") }, + { nxt_string("/^$/.test('')"), nxt_string("true") },
--- a/nxt/Makefile Thu Aug 04 14:45:27 2016 +0300 +++ b/nxt/Makefile Thu Aug 04 16:05:38 2016 +0300 @@ -12,6 +12,7 @@ $(NXT_BUILDDIR)/nxt_random.o \ $(NXT_BUILDDIR)/nxt_pcre.o \ $(NXT_BUILDDIR)/nxt_malloc.o \ + $(NXT_BUILDDIR)/nxt_trace.o \ $(NXT_BUILDDIR)/nxt_mem_cache_pool.o \ ar -r -c $(NXT_BUILDDIR)/libnxt.a \ @@ -23,6 +24,7 @@ $(NXT_BUILDDIR)/nxt_random.o \ $(NXT_BUILDDIR)/nxt_pcre.o \ $(NXT_BUILDDIR)/nxt_malloc.o \ + $(NXT_BUILDDIR)/nxt_trace.o \ $(NXT_BUILDDIR)/nxt_mem_cache_pool.o \ $(NXT_BUILDDIR)/nxt_murmur_hash.o: \ @@ -111,6 +113,7 @@ $(NXT_BUILDDIR)/nxt_pcre.o: \ $(NXT_LIB)/nxt_types.h \ $(NXT_LIB)/nxt_clang.h \ + $(NXT_LIB)/nxt_trace.h \ $(NXT_LIB)/nxt_regex.h \ $(NXT_LIB)/nxt_pcre.h \ $(NXT_LIB)/nxt_pcre.c \ @@ -130,6 +133,18 @@ -I$(NXT_LIB) \ $(NXT_LIB)/nxt_malloc.c +$(NXT_BUILDDIR)/nxt_trace.o: \ + $(NXT_LIB)/nxt_auto_config.h \ + $(NXT_LIB)/nxt_types.h \ + $(NXT_LIB)/nxt_clang.h \ + $(NXT_LIB)/nxt_malloc.h \ + $(NXT_LIB)/nxt_trace.h \ + $(NXT_LIB)/nxt_trace.c \ + + $(NXT_CC) -c -o $(NXT_BUILDDIR)/nxt_trace.o $(NXT_CFLAGS) \ + -I$(NXT_LIB) \ + $(NXT_LIB)/nxt_trace.c + $(NXT_BUILDDIR)/nxt_mem_cache_pool.o: \ $(NXT_LIB)/nxt_types.h \ $(NXT_LIB)/nxt_clang.h \
--- a/nxt/nxt_clang.h Thu Aug 04 14:45:27 2016 +0300 +++ b/nxt/nxt_clang.h Thu Aug 04 16:05:38 2016 +0300 @@ -8,6 +8,7 @@ #define _NXT_CLANG_H_INCLUDED_ +#include <stdarg.h> #include <stddef.h> /* offsetof(). */ #include <unistd.h> /* NULL. */
--- a/nxt/nxt_pcre.c Thu Aug 04 14:45:27 2016 +0300 +++ b/nxt/nxt_pcre.c Thu Aug 04 16:05:38 2016 +0300 @@ -7,9 +7,9 @@ #include <nxt_types.h> #include <nxt_clang.h> #include <nxt_stub.h> +#include <nxt_trace.h> #include <nxt_regex.h> #include <nxt_pcre.h> -#include <stdio.h> #include <string.h> @@ -53,7 +53,6 @@ char *pattern, *error; void *(*saved_malloc)(size_t size); void (*saved_free)(void *p); - size_t size; const char *errstr; ret = NXT_ERROR; @@ -82,22 +81,14 @@ if (nxt_slow_path(regex->code == NULL)) { error = pattern + erroff; - size = sizeof("pcre_compile(\"\") failed: at \"\"") - + strlen(errstr) + strlen(error) * 2 + erroff; - - ctx->error = ctx->private_malloc(size, ctx->memory_data); - if (nxt_slow_path(ctx->error == NULL)) { - goto done; - } + if (*error != '\0') { + nxt_alert(ctx->trace, NXT_LEVEL_ERROR, + "pcre_compile(\"%s\") failed: %s at \"%s\"", + pattern, errstr, error); - if (*error != '\0') { - (void) snprintf((char *) ctx->error, size, - "pcre_compile(\"%s\") failed: %s at \"%s\"", - pattern, errstr, error); } else { - (void) snprintf((char *) ctx->error, size, - "pcre_compile(\"%s\") failed: %s", - pattern, errstr); + nxt_alert(ctx->trace, NXT_LEVEL_ERROR, + "pcre_compile(\"%s\") failed: %s", pattern, errstr); } goto done; @@ -106,16 +97,8 @@ regex->extra = pcre_study(regex->code, 0, &errstr); if (nxt_slow_path(errstr != NULL)) { - size = sizeof("pcre_study(\"\") failed: ") - + strlen(pattern) + strlen(errstr); - - ctx->error = ctx->private_malloc(size, ctx->memory_data); - if (nxt_slow_path(ctx->error == NULL)) { - goto done; - } - - (void) snprintf((char *) ctx->error, size, - "pcre_study(\"%s\") failed: %s", pattern, errstr); + nxt_alert(ctx->trace, NXT_LEVEL_ERROR, + "pcre_study(\"%s\") failed: %s", pattern, errstr); goto done; } @@ -124,17 +107,9 @@ ®ex->ncaptures); if (nxt_slow_path(err < 0)) { - size = sizeof("pcre_fullinfo(\"\", PCRE_INFO_CAPTURECOUNT) failed: ") - + strlen(pattern) + sizeof("-2147483647"); - - ctx->error = ctx->private_malloc(size, ctx->memory_data); - if (nxt_slow_path(ctx->error == NULL)) { - goto done; - } - - (void) snprintf((char *) ctx->error, size, - "pcre_fullinfo(\"%s\", PCRE_INFO_CAPTURECOUNT) failed: %d", - pattern, err); + nxt_alert(ctx->trace, NXT_LEVEL_ERROR, + "pcre_fullinfo(\"%s\", PCRE_INFO_CAPTURECOUNT) failed: %d", + pattern, err); goto done; } @@ -229,8 +204,7 @@ nxt_regex_match(nxt_regex_t *regex, u_char *subject, size_t len, nxt_regex_match_data_t *match_data, nxt_regex_context_t *ctx) { - int ret; - size_t size; + int ret; ret = pcre_exec(regex->code, regex->extra, (char *) subject, len, 0, 0, match_data->captures, match_data->ncaptures); @@ -238,14 +212,7 @@ /* PCRE_ERROR_NOMATCH is -1. */ if (nxt_slow_path(ret < PCRE_ERROR_NOMATCH)) { - size = sizeof("pcre_exec() failed: ") + sizeof("-2147483647"); - - ctx->error = ctx->private_malloc(size, ctx->memory_data); - - if (nxt_fast_path(ctx->error != NULL)) { - (void) snprintf((char *) ctx->error, size, "pcre_exec() failed: %d", - ret); - } + nxt_alert(ctx->trace, NXT_LEVEL_ERROR, "pcre_exec() failed: %d", ret); } return ret; @@ -255,5 +222,5 @@ int * nxt_regex_captures(nxt_regex_match_data_t *match_data) { - return (match_data)->captures; + return match_data->captures; }
