[njs] Interactive shell.
Dmitry Volyntsev
xeioex at nginx.com
Mon Jul 17 18:01:34 UTC 2017
details: http://hg.nginx.org/njs/rev/f2ecbe1c2261
branches:
changeset: 388:f2ecbe1c2261
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Mon Jul 17 20:38:00 2017 +0300
description:
Interactive shell.
diffstat:
Makefile | 26 ++
njs/njs.c | 466 ++++++++++++++++++++++++++++++++++++++++
njs/njs_array.c | 2 +
njs/njs_boolean.c | 2 +
njs/njs_builtin.c | 235 +++++++++++++++++--
njs/njs_date.c | 2 +
njs/njs_function.c | 3 +
njs/njs_lexer_keyword.c | 9 +-
njs/njs_math.c | 1 +
njs/njs_number.c | 2 +
njs/njs_object.c | 2 +
njs/njs_object.h | 1 +
njs/njs_parser.c | 45 +++-
njs/njs_parser.h | 13 +-
njs/njs_regexp.c | 2 +
njs/njs_string.c | 2 +
njs/njs_variable.c | 47 ++-
njs/njs_vm.h | 1 +
njs/njscript.c | 43 +++-
njs/njscript.h | 7 +-
njs/test/njs_interactive_test.c | 197 ++++++++++++++++
nxt/auto/configure | 1 +
nxt/auto/editline | 25 ++
23 files changed, 1071 insertions(+), 63 deletions(-)
diffs (truncated from 1569 to 1000 lines):
diff -r 182d765687ee -r f2ecbe1c2261 Makefile
--- a/Makefile Mon Jul 17 15:29:02 2017 +0300
+++ b/Makefile Mon Jul 17 20:38:00 2017 +0300
@@ -74,11 +74,15 @@ NXT_BUILDDIR = build
all: test lib_test
+njs: $(NXT_BUILDDIR)/njs
+
test: \
$(NXT_BUILDDIR)/njs_unit_test \
+ $(NXT_BUILDDIR)/njs_interactive_test \
$(NXT_BUILDDIR)/njs_benchmark \
$(NXT_BUILDDIR)/njs_unit_test d
+ $(NXT_BUILDDIR)/njs_interactive_test
clean:
rm -rf $(NXT_BUILDDIR)
@@ -386,6 +390,17 @@ dist:
-I$(NXT_LIB) -Injs \
njs/njs_disassembler.c
+$(NXT_BUILDDIR)/njs: \
+ $(NXT_BUILDDIR)/libnxt.a \
+ $(NXT_BUILDDIR)/libnjs.a \
+ njs/njs.c \
+
+ $(NXT_CC) -o $(NXT_BUILDDIR)/njs $(NXT_CFLAGS) \
+ -I$(NXT_LIB) -Injs \
+ njs/njs.c \
+ $(NXT_BUILDDIR)/libnjs.a \
+ -lm $(NXT_PCRE_LIB) $(NXT_EDITLINE_LIB)
+
$(NXT_BUILDDIR)/njs_unit_test: \
$(NXT_BUILDDIR)/libnxt.a \
$(NXT_BUILDDIR)/libnjs.a \
@@ -397,6 +412,17 @@ dist:
$(NXT_BUILDDIR)/libnjs.a \
-lm $(NXT_PCRE_LIB)
+$(NXT_BUILDDIR)/njs_interactive_test: \
+ $(NXT_BUILDDIR)/libnxt.a \
+ $(NXT_BUILDDIR)/libnjs.a \
+ njs/test/njs_interactive_test.c \
+
+ $(NXT_CC) -o $(NXT_BUILDDIR)/njs_interactive_test $(NXT_CFLAGS) \
+ -I$(NXT_LIB) -Injs \
+ njs/test/njs_interactive_test.c \
+ $(NXT_BUILDDIR)/libnjs.a \
+ -lm $(NXT_PCRE_LIB)
+
$(NXT_BUILDDIR)/njs_benchmark: \
$(NXT_BUILDDIR)/libnxt.a \
$(NXT_BUILDDIR)/libnjs.a \
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/njs/njs.c Mon Jul 17 20:38:00 2017 +0300
@@ -0,0 +1,466 @@
+
+/*
+ * Copyright (C) Dmitry Volyntsev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include <nxt_auto_config.h>
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_string.h>
+#include <nxt_stub.h>
+#include <nxt_malloc.h>
+#include <nxt_array.h>
+#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
+#include <nxt_mem_cache_pool.h>
+#include <njscript.h>
+#include <njs_vm.h>
+#include <njs_variable.h>
+#include <njs_parser.h>
+
+#include <editline/readline.h>
+
+
+typedef enum {
+ NJS_COMPLETION_GLOBAL = 0,
+ NJS_COMPLETION_SUFFIX,
+} njs_completion_phase_t;
+
+
+typedef struct {
+ char *file;
+ nxt_int_t disassemble;
+ nxt_int_t interactive;
+} njs_opts_t;
+
+
+typedef struct {
+ size_t index;
+ size_t length;
+ njs_vm_t *vm;
+ const char **completions;
+ nxt_lvlhsh_each_t lhe;
+ njs_completion_phase_t phase;
+} njs_completion_t;
+
+
+static nxt_int_t njs_get_options(njs_opts_t *opts, int argc, char **argv);
+static nxt_int_t njs_interactive_shell(njs_opts_t *opts,
+ njs_vm_opt_t *vm_options);
+static nxt_int_t njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options);
+static nxt_int_t njs_process_script(njs_vm_t *vm, njs_opts_t *opts,
+ const nxt_str_t *script, nxt_str_t *out);
+static nxt_int_t njs_editline_init(njs_vm_t *vm);
+static char **njs_completion_handler(const char *text, int start, int end);
+static char *njs_completion_generator(const char *text, int state);
+
+
+static njs_completion_t njs_completion;
+
+
+int
+main(int argc, char **argv)
+{
+ nxt_int_t ret;
+ njs_opts_t opts;
+ njs_vm_opt_t vm_options;
+ nxt_mem_cache_pool_t *mcp;
+
+ memset(&opts, 0, sizeof(njs_opts_t));
+ opts.interactive = 1;
+
+ ret = njs_get_options(&opts, argc, argv);
+ if (ret != NXT_OK) {
+ return (ret == NXT_DONE) ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+
+ mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL,
+ NULL, 2 * nxt_pagesize(), 128, 512, 16);
+ if (nxt_slow_path(mcp == NULL)) {
+ return EXIT_FAILURE;
+ }
+
+ memset(&vm_options, 0, sizeof(njs_vm_opt_t));
+
+ vm_options.mcp = mcp;
+ vm_options.accumulative = 1;
+
+ if (opts.interactive) {
+ ret = njs_interactive_shell(&opts, &vm_options);
+
+ } else {
+ ret = njs_process_file(&opts, &vm_options);
+ }
+
+ return (ret == NXT_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+
+static nxt_int_t
+njs_get_options(njs_opts_t *opts, int argc, char** argv)
+{
+ char *p;
+ nxt_int_t i, ret;
+
+ ret = NXT_DONE;
+
+ for (i = 1; i < argc; i++) {
+
+ p = argv[i];
+
+ if (p[0] != '-' || (p[0] == '-' && p[1] == '\0')) {
+ opts->interactive = 0;
+ opts->file = argv[i];
+ continue;
+ }
+
+ p++;
+
+ switch (*p) {
+ case 'd':
+ opts->disassemble = 1;
+ break;
+
+ default:
+ fprintf(stderr, "Unknown argument: \"%s\"\n", argv[i]);
+ ret = NXT_ERROR;
+
+ /* Fall through. */
+
+ case 'h':
+ case '?':
+ printf("Usage: %s [<file>|-] [-d]\n", argv[0]);
+ return ret;
+ }
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+njs_interactive_shell(njs_opts_t *opts, njs_vm_opt_t *vm_options)
+{
+ njs_vm_t *vm;
+ nxt_int_t ret;
+ nxt_str_t line, out;
+
+ vm = njs_vm_create(vm_options);
+ if (vm == NULL) {
+ fprintf(stderr, "failed to create vm\n");
+ return NXT_ERROR;
+ }
+
+ if (njs_editline_init(vm) != NXT_OK) {
+ fprintf(stderr, "failed to init completions\n");
+ return NXT_ERROR;
+ }
+
+ printf("interactive njscript\n");
+
+ for ( ;; ) {
+ line.start = (u_char *) readline(">> ");
+ if (line.start == NULL) {
+ break;
+ }
+
+ line.length = strlen((char *) line.start);
+ if (line.length == 0) {
+ continue;
+ }
+
+ add_history((char *) line.start);
+
+ ret = njs_process_script(vm, opts, &line, &out);
+ if (ret != NXT_OK) {
+ printf("njs_process_script() failed\n");
+ return NXT_ERROR;
+ }
+
+ printf("%.*s\n", (int) out.length, out.start);
+
+ /* editline allocs a new buffer every time. */
+ free(line.start);
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options)
+{
+ int fd;
+ char *file;
+ u_char buf[4096], *p, *end;
+ size_t size;
+ ssize_t n;
+ njs_vm_t *vm;
+ nxt_int_t ret;
+ nxt_str_t out, script;
+ struct stat sb;
+
+ file = opts->file;
+
+ if (file[0] == '-' && file[1] == '\0') {
+ fd = STDIN_FILENO;
+
+ } else {
+ fd = open(file, O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "failed to open file: '%s' (%s)\n",
+ file, strerror(errno));
+ return NXT_ERROR;
+ }
+ }
+
+ fstat(fd, &sb);
+
+ size = sizeof(buf);
+
+ if (S_ISREG(sb.st_mode) && sb.st_size) {
+ size = sb.st_size;
+ }
+
+ script.length = 0;
+ script.start = realloc(NULL, size);
+ if (script.start == NULL) {
+ fprintf(stderr, "alloc failed while reading '%s'\n", file);
+ return NXT_ERROR;
+ }
+
+ p = script.start;
+ end = p + size;
+
+ for ( ;; ) {
+ n = read(fd, buf, sizeof(buf));
+
+ if (n == 0) {
+ break;
+ }
+
+ if (n < 0) {
+ fprintf(stderr, "failed to read file: '%s' (%s)\n",
+ file, strerror(errno));
+ return NXT_ERROR;
+ }
+
+ if (p + n > end) {
+ size *= 2;
+
+ script.start = realloc(script.start, size);
+ if (script.start == NULL) {
+ fprintf(stderr, "alloc failed while reading '%s'\n", file);
+ return NXT_ERROR;
+ }
+
+ p = script.start;
+ end = p + size;
+ }
+
+ memcpy(p, buf, n);
+
+ p += n;
+ script.length += n;
+ }
+
+ vm = njs_vm_create(vm_options);
+ if (vm == NULL) {
+ fprintf(stderr, "failed to create vm\n");
+ return NXT_ERROR;
+ }
+
+ ret = njs_process_script(vm, opts, &script, &out);
+ if (ret != NXT_OK) {
+ fprintf(stderr, "njs_process_script() failed\n");
+ return NXT_ERROR;
+ }
+
+ if (!opts->disassemble) {
+ printf("%.*s\n", (int) out.length, out.start);
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+njs_process_script(njs_vm_t *vm, njs_opts_t *opts, const nxt_str_t *script,
+ nxt_str_t *out)
+{
+ u_char *start;
+ nxt_int_t ret;
+
+ start = script->start;
+
+ ret = njs_vm_compile(vm, &start, start + script->length);
+
+ if (ret == NXT_OK) {
+ if (opts->disassemble) {
+ njs_disassembler(vm);
+ printf("\n");
+ }
+
+ ret = njs_vm_run(vm);
+
+ if (ret == NXT_OK) {
+ if (njs_vm_retval(vm, out) != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ } else {
+ njs_vm_exception(vm, out);
+ }
+
+ } else {
+ njs_vm_exception(vm, out);
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+njs_editline_init(njs_vm_t *vm)
+{
+ rl_completion_append_character = '\0';
+ rl_attempted_completion_function = njs_completion_handler;
+ rl_basic_word_break_characters = (char *) " \t\n\"\\'`@$><=;,|&{(";
+
+ njs_completion.completions = njs_vm_completions(vm);
+ if (njs_completion.completions == NULL) {
+ return NXT_ERROR;
+ }
+
+ njs_completion.vm = vm;
+
+ return NXT_OK;
+}
+
+
+static char **
+njs_completion_handler(const char *text, int start, int end)
+{
+ rl_attempted_completion_over = 1;
+
+ return rl_completion_matches(text, njs_completion_generator);
+}
+
+
+static char *
+njs_completion_generator(const char *text, int state)
+{
+ char *completion;
+ size_t len;
+ const char *name, *p;
+ njs_variable_t *var;
+ njs_completion_t *cmpl;
+
+ cmpl = &njs_completion;
+
+ if (state == 0) {
+ cmpl->index = 0;
+ cmpl->length = strlen(text);
+ cmpl->phase = NJS_COMPLETION_GLOBAL;
+
+ nxt_lvlhsh_each_init(&cmpl->lhe, &njs_variables_hash_proto);
+ }
+
+ if (cmpl->phase == NJS_COMPLETION_GLOBAL) {
+ for ( ;; ) {
+ name = cmpl->completions[cmpl->index];
+ if (name == NULL) {
+ break;
+ }
+
+ cmpl->index++;
+
+ if (name[0] == '.') {
+ continue;
+ }
+
+ if (strncmp(name, text, cmpl->length) == 0) {
+ /* editline frees the buffer every time. */
+ return strdup(name);
+ }
+ }
+
+ if (cmpl->vm->parser != NULL) {
+ for ( ;; ) {
+ var = nxt_lvlhsh_each(&cmpl->vm->parser->scope->variables,
+ &cmpl->lhe);
+ if (var == NULL) {
+ break;
+ }
+
+ if (strncmp((char *) var->name.start, text, cmpl->length)
+ == 0)
+ {
+ completion = malloc(var->name.length + 1);
+ if (completion == NULL) {
+ return NULL;
+ }
+
+ memcpy(completion, var->name.start, var->name.length);
+ completion[var->name.length] = '\0';
+
+ return completion;
+ }
+ }
+ }
+
+ if (cmpl->length == 0) {
+ return NULL;
+ }
+
+ cmpl->index = 0;
+ cmpl->phase = NJS_COMPLETION_SUFFIX;
+ }
+
+ len = 1;
+ p = &text[cmpl->length - 1];
+
+ while (p > text && *p != '.') {
+ p--;
+ len++;
+ }
+
+ if (*p != '.') {
+ return NULL;
+ }
+
+ for ( ;; ) {
+ name = cmpl->completions[cmpl->index++];
+ if (name == NULL) {
+ break;
+ }
+
+ if (name[0] != '.') {
+ continue;
+ }
+
+ if (strncmp(name, p, len) != 0) {
+ continue;
+ }
+
+ len = strlen(name) + (p - text) + 2;
+ completion = malloc(len);
+ if (completion == NULL) {
+ return NULL;
+ }
+
+ snprintf(completion, len, "%.*s%s", (int) (p - text), text, name);
+ return completion;
+ }
+
+ return NULL;
+}
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_array.c
--- a/njs/njs_array.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_array.c Mon Jul 17 20:38:00 2017 +0300
@@ -373,6 +373,7 @@ static const njs_object_prop_t njs_arra
const njs_object_init_t njs_array_constructor_init = {
+ nxt_string("Array"),
njs_array_constructor_properties,
nxt_nitems(njs_array_constructor_properties),
};
@@ -2234,6 +2235,7 @@ static const njs_object_prop_t njs_arra
const njs_object_init_t njs_array_prototype_init = {
+ nxt_string("Array"),
njs_array_prototype_properties,
nxt_nitems(njs_array_prototype_properties),
};
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_boolean.c
--- a/njs/njs_boolean.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_boolean.c Mon Jul 17 20:38:00 2017 +0300
@@ -78,6 +78,7 @@ static const njs_object_prop_t njs_bool
const njs_object_init_t njs_boolean_constructor_init = {
+ nxt_string("Boolean"),
njs_boolean_constructor_properties,
nxt_nitems(njs_boolean_constructor_properties),
};
@@ -156,6 +157,7 @@ static const njs_object_prop_t njs_bool
const njs_object_init_t njs_boolean_prototype_init = {
+ nxt_string("Boolean"),
njs_boolean_prototype_properties,
nxt_nitems(njs_boolean_prototype_properties),
};
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_builtin.c
--- a/njs/njs_builtin.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_builtin.c Mon Jul 17 20:38:00 2017 +0300
@@ -27,6 +27,7 @@
#include <njs_date.h>
#include <njs_math.h>
#include <string.h>
+#include <stdio.h>
typedef struct {
@@ -35,6 +36,40 @@ typedef struct {
} njs_function_init_t;
+static nxt_int_t njs_builtin_completions(njs_vm_t *vm, size_t *size,
+ const char **completions);
+
+
+static const njs_object_init_t *object_init[] = {
+ NULL, /* global this */
+ &njs_math_object_init, /* Math */
+};
+
+
+static const njs_object_init_t *prototype_init[] = {
+ &njs_object_prototype_init,
+ &njs_array_prototype_init,
+ &njs_boolean_prototype_init,
+ &njs_number_prototype_init,
+ &njs_string_prototype_init,
+ &njs_function_prototype_init,
+ &njs_regexp_prototype_init,
+ &njs_date_prototype_init,
+};
+
+
+static const njs_object_init_t *constructor_init[] = {
+ &njs_object_constructor_init,
+ &njs_array_constructor_init,
+ &njs_boolean_constructor_init,
+ &njs_number_constructor_init,
+ &njs_string_constructor_init,
+ &njs_function_constructor_init,
+ &njs_regexp_constructor_init,
+ &njs_date_constructor_init,
+};
+
+
static njs_ret_t
njs_prototype_function(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
@@ -54,17 +89,6 @@ njs_builtin_objects_create(njs_vm_t *vm)
njs_function_t *functions, *constructors;
njs_object_prototype_t *prototypes;
- static const njs_object_init_t *prototype_init[] = {
- &njs_object_prototype_init,
- &njs_array_prototype_init,
- &njs_boolean_prototype_init,
- &njs_number_prototype_init,
- &njs_string_prototype_init,
- &njs_function_prototype_init,
- &njs_regexp_prototype_init,
- &njs_date_prototype_init,
- };
-
static const njs_object_prototype_t prototype_values[] = {
/*
* GCC 4 complains about uninitialized .shared field,
@@ -97,17 +121,6 @@ njs_builtin_objects_create(njs_vm_t *vm)
.object = { .type = NJS_DATE } } },
};
- static const njs_object_init_t *constructor_init[] = {
- &njs_object_constructor_init,
- &njs_array_constructor_init,
- &njs_boolean_constructor_init,
- &njs_number_constructor_init,
- &njs_string_constructor_init,
- &njs_function_constructor_init,
- &njs_regexp_constructor_init,
- &njs_date_constructor_init,
- };
-
static const njs_function_init_t native_constructors[] = {
/* SunC does not allow empty array initialization. */
{ njs_object_constructor, { 0 } },
@@ -121,11 +134,6 @@ njs_builtin_objects_create(njs_vm_t *vm)
{ njs_date_constructor, { 0 } },
};
- static const njs_object_init_t *object_init[] = {
- NULL, /* global this */
- &njs_math_object_init, /* Math */
- };
-
static const njs_object_init_t *function_init[] = {
&njs_eval_function_init, /* eval */
NULL, /* toString */
@@ -333,3 +341,176 @@ njs_builtin_objects_clone(njs_vm_t *vm)
return NXT_OK;
}
+
+
+const char **
+njs_vm_completions(njs_vm_t *vm)
+{
+ size_t size;
+ const char **completions;
+
+ if (njs_builtin_completions(vm, &size, NULL) != NXT_OK) {
+ return NULL;
+ }
+
+ completions = nxt_mem_cache_zalloc(vm->mem_cache_pool,
+ sizeof(char *) * (size + 1));
+
+ if (completions == NULL) {
+ return NULL;
+ }
+
+ if (njs_builtin_completions(vm, NULL, completions) != NXT_OK) {
+ return NULL;
+ }
+
+ return completions;
+}
+
+
+static nxt_int_t
+njs_builtin_completions(njs_vm_t *vm, size_t *size, const char **completions)
+{
+ char *compl;
+ size_t n, len;
+ nxt_str_t string;
+ nxt_uint_t i, k;
+ njs_object_t *objects;
+ njs_keyword_t *keyword;
+ njs_function_t *constructors;
+ njs_object_prop_t *prop;
+ nxt_lvlhsh_each_t lhe;
+ njs_object_prototype_t *prototypes;
+
+ n = 0;
+
+ nxt_lvlhsh_each_init(&lhe, &njs_keyword_hash_proto);
+
+ for ( ;; ) {
+ keyword = nxt_lvlhsh_each(&vm->shared->keywords_hash, &lhe);
+
+ if (keyword == NULL) {
+ break;
+ }
+
+ if (completions != NULL) {
+ completions[n++] = (char *) keyword->name.start;
+
+ } else {
+ n++;
+ }
+ }
+
+ objects = vm->shared->objects;
+
+ for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) {
+ if (object_init[i] == NULL) {
+ continue;
+ }
+
+ nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
+
+ for ( ;; ) {
+ prop = nxt_lvlhsh_each(&objects[i].shared_hash, &lhe);
+
+ if (prop == NULL) {
+ break;
+ }
+
+ if (completions != NULL) {
+ njs_string_get(&prop->name, &string);
+ len = object_init[i]->name.length + string.length + 2;
+
+ compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
+ if (compl == NULL) {
+ return NXT_ERROR;
+ }
+
+ snprintf(compl, len, "%s.%s", object_init[i]->name.start,
+ string.start);
+
+ completions[n++] = (char *) compl;
+
+ } else {
+ n++;
+ }
+ }
+ }
+
+ prototypes = vm->shared->prototypes;
+
+ for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
+ nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
+
+ for ( ;; ) {
+ prop = nxt_lvlhsh_each(&prototypes[i].object.shared_hash, &lhe);
+
+ if (prop == NULL) {
+ break;
+ }
+
+ if (completions != NULL) {
+ njs_string_get(&prop->name, &string);
+ len = string.length + 2;
+
+ compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
+ if (compl == NULL) {
+ return NXT_ERROR;
+ }
+
+ snprintf(compl, len, ".%s", string.start);
+
+ for (k = 0; k < n; k++) {
+ if (strncmp(completions[k], compl, len) == 0) {
+ break;
+ }
+ }
+
+ if (k == n) {
+ completions[n++] = (char *) compl;
+ }
+
+ } else {
+ n++;
+ }
+ }
+ }
+
+ constructors = vm->shared->constructors;
+
+ for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
+ nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
+
+ for ( ;; ) {
+ prop = nxt_lvlhsh_each(&constructors[i].object.shared_hash, &lhe);
+
+ if (prop == NULL) {
+ break;
+ }
+
+ if (completions != NULL) {
+ njs_string_get(&prop->name, &string);
+ len = constructor_init[i]->name.length + string.length + 2;
+
+ compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
+ if (compl == NULL) {
+ return NXT_ERROR;
+ }
+
+ snprintf(compl, len, "%s.%s", constructor_init[i]->name.start,
+ string.start);
+
+ completions[n++] = (char *) compl;
+
+ } else {
+ n++;
+ }
+ }
+ }
+
+ if (size) {
+ *size = n;
+ }
+
+ return NXT_OK;
+}
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_date.c
--- a/njs/njs_date.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_date.c Mon Jul 17 20:38:00 2017 +0300
@@ -931,6 +931,7 @@ static const njs_object_prop_t njs_date
const njs_object_init_t njs_date_constructor_init = {
+ nxt_string("Date"),
njs_date_constructor_properties,
nxt_nitems(njs_date_constructor_properties),
};
@@ -2244,6 +2245,7 @@ static const njs_object_prop_t njs_date
const njs_object_init_t njs_date_prototype_init = {
+ nxt_string("Date"),
njs_date_prototype_properties,
nxt_nitems(njs_date_prototype_properties),
};
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_function.c
--- a/njs/njs_function.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_function.c Mon Jul 17 20:38:00 2017 +0300
@@ -497,6 +497,7 @@ static const njs_object_prop_t njs_func
const njs_object_init_t njs_function_constructor_init = {
+ nxt_string("Function"),
njs_function_constructor_properties,
nxt_nitems(njs_function_constructor_properties),
};
@@ -692,6 +693,7 @@ static const njs_object_prop_t njs_func
const njs_object_init_t njs_function_prototype_init = {
+ nxt_string("Function"),
njs_function_prototype_properties,
nxt_nitems(njs_function_prototype_properties),
};
@@ -724,6 +726,7 @@ static const njs_object_prop_t njs_eval
const njs_object_init_t njs_eval_function_init = {
+ nxt_string("Function"),
njs_eval_function_properties,
nxt_nitems(njs_eval_function_properties),
};
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_lexer_keyword.c Mon Jul 17 20:38:00 2017 +0300
@@ -23,13 +23,6 @@
#include <string.h>
-typedef struct {
- nxt_str_t name;
- njs_token_t token;
- double number;
-} njs_keyword_t;
-
-
static const njs_keyword_t njs_keywords[] = {
/* Values. */
@@ -150,7 +143,7 @@ njs_keyword_hash_test(nxt_lvlhsh_query_t
}
-static const nxt_lvlhsh_proto_t njs_keyword_hash_proto
+const nxt_lvlhsh_proto_t njs_keyword_hash_proto
nxt_aligned(64) =
{
NXT_LVLHSH_DEFAULT,
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_math.c
--- a/njs/njs_math.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_math.c Mon Jul 17 20:38:00 2017 +0300
@@ -1088,6 +1088,7 @@ static const njs_object_prop_t njs_math
const njs_object_init_t njs_math_object_init = {
+ nxt_string("Math"),
njs_math_object_properties,
nxt_nitems(njs_math_object_properties),
};
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_number.c
--- a/njs/njs_number.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_number.c Mon Jul 17 20:38:00 2017 +0300
@@ -528,6 +528,7 @@ static const njs_object_prop_t njs_numb
const njs_object_init_t njs_number_constructor_init = {
+ nxt_string("Number"),
njs_number_constructor_properties,
nxt_nitems(njs_number_constructor_properties),
};
@@ -687,6 +688,7 @@ static const njs_object_prop_t njs_numb
const njs_object_init_t njs_number_prototype_init = {
+ nxt_string("Number"),
njs_number_prototype_properties,
nxt_nitems(njs_number_prototype_properties),
};
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_object.c
--- a/njs/njs_object.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_object.c Mon Jul 17 20:38:00 2017 +0300
@@ -1153,6 +1153,7 @@ static const njs_object_prop_t njs_obje
const njs_object_init_t njs_object_constructor_init = {
+ nxt_string("Object"),
njs_object_constructor_properties,
nxt_nitems(njs_object_constructor_properties),
};
@@ -1477,6 +1478,7 @@ static const njs_object_prop_t njs_obje
const njs_object_init_t njs_object_prototype_init = {
+ nxt_string("Object"),
njs_object_prototype_properties,
nxt_nitems(njs_object_prototype_properties),
};
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_object.h
--- a/njs/njs_object.h Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_object.h Mon Jul 17 20:38:00 2017 +0300
@@ -32,6 +32,7 @@ typedef struct {
struct njs_object_init_s {
+ nxt_str_t name;
const njs_object_prop_t *properties;
nxt_uint_t items;
};
diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_parser.c
--- a/njs/njs_parser.c Mon Jul 17 15:29:02 2017 +0300
+++ b/njs/njs_parser.c Mon Jul 17 20:38:00 2017 +0300
@@ -14,6 +14,7 @@
#include <nxt_lvlhsh.h>
#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
+#include <nxt_djb_hash.h>
#include <njscript.h>
#include <njs_vm.h>
#include <njs_number.h>
@@ -95,17 +96,53 @@ static njs_token_t njs_parser_unexpected
njs_parser_node_t *
-njs_parser(njs_vm_t *vm, njs_parser_t *parser)
+njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev)
{
- njs_ret_t ret;
- njs_token_t token;
- njs_parser_node_t *node;
+ njs_ret_t ret;
+ njs_token_t token;
+ nxt_lvlhsh_t *variables, *prev_variables;
+ njs_variable_t *var;
+ njs_parser_node_t *node;
+ nxt_lvlhsh_each_t lhe;
+ nxt_lvlhsh_query_t lhq;
More information about the nginx-devel
mailing list