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 \
-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
#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,
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 };
}
}
- 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:
}
}
- 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:
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);
-}
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,
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);
} 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;
}
-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_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;
}
}
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;
}
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);
}
if (hex_length == 0 || hex_length > 6) {
- return njs_parser_error(vm, parser,
- NJS_PARSER_ERROR_UNICODE);
+ goto invalid;
}
skip = 1;
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;
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;
}
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);
- }
-
- size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH,
- "SyntaxError: Unexpected end of input in %u",
- parser->lexer->line);
+ nxt_alert(&vm->trace, NXT_LEVEL_ERROR,
+ "SyntaxError: Unexpected token \"%.*s\"",
+ (int) parser->lexer->text.length, parser->lexer->text.start);
- (void) njs_vm_throw_exception(vm, buf, size);
+ } else {
+ nxt_alert(&vm->trace, NXT_LEVEL_ERROR,
+ "SyntaxError: Unexpected end of input");
+ }
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];
+ int n;
+ u_char *p;
+ ssize_t size;
+ njs_vm_t *vm;
- 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",
- };
+ p = start;
- msg = errors[err];
- lexer = parser->lexer;
+ if (td->level == NXT_LEVEL_CRIT) {
+ size = sizeof("InternalError: ") - 1;
+ memcpy(p, "InternalError: ", size);
+ p = start + size;
+ }
- size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH,
- msg, (int) lexer->text.length, lexer->text.start,
- lexer->line);
+ vm = trace->data;
- (void) njs_vm_throw_exception(vm, buf, size);
+ trace = trace->next;
+ p = trace->handler(trace, td, p);
- return NJS_TOKEN_ILLEGAL;
+ 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;
}
};
-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);
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);
#include <njs_variable.h>
#include <njs_parser.h>
#include <string.h>
-#include <stdio.h>
typedef struct {
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
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;
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;
}
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);
}
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);
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;
-
-}
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,
return NXT_ERROR;
}
+ vm->regex_context->trace = &vm->trace;
+
return NXT_OK;
}
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;
}
}
- 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;
}
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;
- } else {
- size = snprintf((char *) buf, NJS_EXCEPTION_BUF_LENGTH,
- "SyntaxError: %s", vm->regex_context->error);
+ n = snprintf((char *) p, size, " in %u", vm->parser->lexer->line);
+
+ 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;
}
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;
}
}
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);
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;
}
}
}
-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". */
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;
#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,
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;
}
}
}
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) {
break;
} else {
- return njs_regexp_match_error(vm);
+ return NXT_ERROR;
}
} while (string.size > 0);
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);
next = (u_char *) end + 1;
} else {
- return njs_regexp_match_error(vm);
+ return NXT_ERROR;
}
/* Empty split regexp. */
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;
}
}
-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;
- }
- vm->exception = value;
+ if (nxt_fast_path(value != NULL)) {
+ vm->exception = value;
- length = nxt_utf8_length(buf, size);
+ length = nxt_utf8_length(buf, size);
- (void) njs_string_new(vm, value, buf, size, length);
-
- return NXT_ERROR;
+ (void) njs_string_new(vm, value, buf, size, length);
+ }
}
#define _NJS_VM_H_INCLUDED_
+#include <nxt_trace.h>
#include <nxt_regex.h>
nxt_array_t *code; /* of njs_vm_code_t */
+ nxt_trace_t trace;
nxt_random_t random;
};
};
-#define NJS_EXCEPTION_BUF_LENGTH 2048
-
-
nxt_int_t njs_vmcode_interpreter(njs_vm_t *vm);
void njs_value_retain(njs_value_t *value);
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);
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;
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;
}
{ 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") },
$(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 \
$(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: \
$(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 \
-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 \
#define _NXT_CLANG_H_INCLUDED_
+#include <stdarg.h>
#include <stddef.h> /* offsetof(). */
#include <unistd.h> /* NULL. */
#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>
char *pattern, *error;
void *(*saved_malloc)(size_t size);
void (*saved_free)(void *p);
- size_t size;
const char *errstr;
ret = NXT_ERROR;
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') {
- (void) snprintf((char *) ctx->error, size,
- "pcre_compile(\"%s\") failed: %s at \"%s\"",
- pattern, errstr, error);
+ nxt_alert(ctx->trace, NXT_LEVEL_ERROR,
+ "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;
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;
}
®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;
}
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);
/* 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;
int *
nxt_regex_captures(nxt_regex_match_data_t *match_data)
{
- return (match_data)->captures;
+ return match_data->captures;
}
nxt_pcre_malloc_t private_malloc;
nxt_pcre_free_t private_free;
void *memory_data;
- u_char *error;
+ nxt_trace_t *trace;
} nxt_regex_context_t;