예제 #1
0
파일: njs_array.c 프로젝트: AsamQi/njs
nxt_noinline njs_array_t *
njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare)
{
    uint32_t     size;
    njs_array_t  *array;

    array = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
                                sizeof(njs_array_t));

    if (nxt_slow_path(array == NULL)) {
        return NULL;
    }

    size = length + spare;

    array->data = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
                                      size * sizeof(njs_value_t));
    if (nxt_slow_path(array->data == NULL)) {
        return NULL;
    }

    array->start = array->data;
    nxt_lvlhsh_init(&array->object.hash);
    nxt_lvlhsh_init(&array->object.shared_hash);
    array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY];
    array->size = size;
    array->length = length;

    return array;
}
예제 #2
0
static njs_token_t
njs_parser_inc_dec_expression(njs_vm_t *vm, njs_parser_t *parser,
    njs_token_t token)
{
    njs_token_t             next;
    njs_parser_node_t       *node;
    njs_vmcode_operation_t  operation;

    switch (token) {

    case NJS_TOKEN_INCREMENT:
        operation = njs_vmcode_increment;
        break;

    case NJS_TOKEN_DECREMENT:
        operation = njs_vmcode_decrement;
        break;

    default:
        return njs_parser_post_inc_dec_expression(vm, parser, token);
    }

    next = njs_parser_token(parser);
    if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) {
        return next;
    }

    next = njs_parser_call_expression(vm, parser, next);
    if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) {
        return next;
    }

    if (parser->node->lvalue == NJS_LVALUE_NONE) {
        nxt_thread_log_error(NXT_LOG_ALERT, "lvalue required");
        return NJS_TOKEN_ILLEGAL;
    }

    node = njs_parser_node_alloc(vm);
    if (nxt_slow_path(node == NULL)) {
        return NJS_TOKEN_ERROR;
    }

    node->token = token;
    node->u.operation = operation;
    node->left = parser->node;
    parser->node = node;

    parser->code_size += (parser->node->token == NJS_TOKEN_NAME) ?
                             sizeof(njs_vmcode_3addr_t):
                             sizeof(njs_vmcode_prop_get_t)
                             + sizeof(njs_vmcode_3addr_t)
                             + sizeof(njs_vmcode_prop_set_t);

    return next;
}
예제 #3
0
파일: njs_regexp.c 프로젝트: nginx/njs
njs_token_t
njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value)
{
    u_char                *p;
    njs_lexer_t           *lexer;
    njs_regexp_flags_t    flags;
    njs_regexp_pattern_t  *pattern;

    lexer = parser->lexer;

    for (p = lexer->start; p < lexer->end; p++) {

        if (*p == '\\') {
            p++;
            continue;
        }

        if (*p == '/') {
            lexer->text.start = lexer->start;
            lexer->text.length = p - lexer->text.start;
            p++;
            lexer->start = p;

            flags = njs_regexp_flags(&p, lexer->end, 0);

            if (nxt_slow_path(flags < 0)) {
                nxt_alert(&vm->trace, NXT_LEVEL_ERROR,
                          "SyntaxError: Invalid RegExp flags \"%.*s\"",
                          p - lexer->start, lexer->start);

                return NJS_TOKEN_ILLEGAL;
            }

            lexer->start = p;

            pattern = njs_regexp_pattern_create(vm, lexer->text.start,
                                                lexer->text.length, flags);
            if (nxt_slow_path(pattern == NULL)) {
                return NJS_TOKEN_ILLEGAL;
            }

            value->data.u.data = pattern;

            return NJS_TOKEN_REGEXP;
        }
    }

    nxt_alert(&vm->trace, NXT_LEVEL_ERROR,
              "SyntaxError: Unterminated RegExp \"%.*s\"",
              p - lexer->start - 1, lexer->start - 1);

    return NJS_TOKEN_ILLEGAL;
}
예제 #4
0
static njs_token_t
njs_parser_property_expression(njs_vm_t *vm, njs_parser_t *parser,
    njs_token_t token)
{
    njs_token_t        next;
    njs_parser_node_t  *node;

    for ( ;; ) {
        if (token != NJS_TOKEN_DOT
            && token != NJS_TOKEN_OPEN_BRACKET)
        {
            return token;
        }

        node = njs_parser_node_alloc(vm);
        if (nxt_slow_path(node == NULL)) {
            return NJS_TOKEN_ERROR;
        }

        node->token = NJS_TOKEN_PROPERTY;
        node->lvalue = NJS_LVALUE_ENABLED;
        node->u.operation = njs_vmcode_property_get;
        node->left = parser->node;

        next = njs_parser_token(parser);
        if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) {
            return next;
        }

        if (token == NJS_TOKEN_DOT) {

            if (next != NJS_TOKEN_NAME) {
                return NJS_TOKEN_ILLEGAL;
            }

            token = njs_parser_property_name(vm, parser, next);

        } else {
            token = njs_parser_property_brackets(vm, parser, next);
        }

        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            return token;
        }

        node->right = parser->node;
        parser->node = node;

        parser->code_size += sizeof(njs_vmcode_prop_get_t);
    }
}
njs_token_t
njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value)
{
    u_char                *p;
    njs_lexer_t           *lexer;
    njs_regexp_flags_t    flags;
    njs_regexp_pattern_t  *pattern;

    lexer = parser->lexer;

    for (p = lexer->start; p < lexer->end; p++) {

        if (*p == '\\') {
            p++;
            continue;
        }

        if (*p == '/') {
            lexer->text.data = lexer->start;
            lexer->text.len = p - lexer->text.data;
            p++;
            lexer->start = p;

            flags = njs_regexp_flags(&p, lexer->end, 0);

            if (nxt_slow_path(flags < 0)) {
                lexer->text.data = lexer->start;
                lexer->text.len = p - lexer->text.data;
                return njs_parser_error(vm, parser,
                                        NJS_PARSER_ERROR_REGEXP_FLAGS);
            }

            lexer->start = p;

            pattern = njs_regexp_pattern_create(vm, lexer->text.data,
                                                lexer->text.len, flags);
            if (nxt_slow_path(pattern == NULL)) {
                return NJS_TOKEN_ILLEGAL;
            }

            value->data.u.data = pattern;

            return NJS_TOKEN_REGEXP;
        }
    }

    lexer->text.data = lexer->start - 1;
    lexer->text.len = p - lexer->text.data;

    return njs_parser_error(vm, parser, NJS_PARSER_ERROR_UNTERMINATED_REGEXP);
}
예제 #6
0
njs_token_t
njs_parser_arguments(njs_vm_t *vm, njs_parser_t *parser,
    njs_parser_node_t *parent)
{
    njs_token_t        token;
    njs_index_t        index;
    njs_parser_node_t  *node;

    index = NJS_SCOPE_CALLEE_ARGUMENTS;

    do {
        token = njs_parser_token(parser);
        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            return token;
        }

        if (token == NJS_TOKEN_CLOSE_PARENTHESIS) {
            break;
        }

        token = njs_parser_assignment_expression(vm, parser, NULL, token);
        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            return token;
        }

        node = njs_parser_node_alloc(vm);
        if (nxt_slow_path(node == NULL)) {
            return NJS_TOKEN_ERROR;
        }

        node->token = NJS_TOKEN_ARGUMENT;
        node->index = index;
        index += sizeof(njs_value_t);

        node->left = parser->node;
        parser->node->dest = node;
        parent->right = node;
        parent = node;

        parser->code_size += sizeof(njs_vmcode_move_t);

    } while (token == NJS_TOKEN_COMMA);

    if (nxt_slow_path(token != NJS_TOKEN_CLOSE_PARENTHESIS)) {
        return NJS_TOKEN_ILLEGAL;
    }

    return token;
}
예제 #7
0
static njs_token_t
njs_parser_property_brackets(njs_vm_t *vm, njs_parser_t *parser,
    njs_token_t token)
{
    token = njs_parser_expression(vm, parser, token);
    if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
        return token;
    }

    if (nxt_slow_path(token != NJS_TOKEN_CLOSE_BRACKET)) {
        return NJS_TOKEN_ERROR;
    }

    return njs_parser_token(parser);
}
예제 #8
0
파일: njs_regexp.c 프로젝트: nginx/njs
njs_ret_t
njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
                       njs_index_t unused)
{
    njs_string_prop_t   string;
    njs_regexp_flags_t  flags;

    flags = 0;

    switch (nargs) {

    case 1:
        string.start = NULL;
        string.size = 0;
        break;

    default:
        (void) njs_string_prop(&string, &args[2]);

        flags = njs_regexp_flags(&string.start, string.start + string.size, 1);
        if (nxt_slow_path(flags < 0)) {
            return NXT_ERROR;
        }

    /* Fall through. */

    case 2:
        (void) njs_string_prop(&string, &args[1]);
        break;
    }

    return njs_regexp_create(vm, &vm->retval, string.start, string.size, flags);
}
예제 #9
0
static nxt_int_t
njs_parser_statement_semicolon(njs_vm_t *vm, njs_parser_t *parser,
    void *data)
{
    njs_token_t        token;
    njs_parser_node_t  *node;

    node = data;

    switch (parser->lexer->token) {

    case NJS_TOKEN_SEMICOLON:
        token = njs_parser_token(parser);
        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            /* TODO: NJS_TOKEN_AGAIN */
            return NXT_ERROR;
        }

        /* Fall through. */

    case NJS_TOKEN_END:

        node->right = parser->node;
        parser->node = node;

        return NXT_OK;

    default:
        break;
    }

    return NXT_ERROR;
}
예제 #10
0
njs_token_t
njs_parser_token(njs_parser_t *parser)
{
    njs_token_t  token;

    do {
        token = njs_lexer_token(parser->lexer);

        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            return token;
        }

    } while (nxt_slow_path(token == NJS_TOKEN_LINE_END));

    return token;
}
예제 #11
0
njs_ret_t
njs_regexp_init(njs_vm_t *vm)
{
    vm->regex_context = nxt_regex_context_create(njs_regexp_malloc,
                                          njs_regexp_free, vm->mem_cache_pool);
    if (nxt_slow_path(vm->regex_context == NULL)) {
        return NXT_ERROR;
    }

    vm->single_match_data = nxt_regex_match_data(NULL, vm->regex_context);
    if (nxt_slow_path(vm->single_match_data == NULL)) {
        return NXT_ERROR;
    }

    return NXT_OK;
}
예제 #12
0
파일: njs_array.c 프로젝트: AsamQi/njs
static njs_ret_t
njs_array_prototype_push(njs_vm_t *vm, njs_param_t *param)
{
    uintptr_t    i, nargs;
    njs_ret_t    ret;
    njs_value_t  *args;
    njs_array_t  *array;

    if (njs_is_array(param->object)) {
        array = param->object->data.u.array;
        nargs = param->nargs;

        if (nargs != 0) {
            if (nargs > array->size - array->length) {
                ret = njs_array_realloc(vm, array, 0, array->size + nargs);
                if (nxt_slow_path(ret != NXT_OK)) {
                    return ret;
                }
            }

            args = param->args;

            for (i = 0; i < nargs; i++) {
                /* GC: njs_retain(&args[i]); */
                array->start[array->length++] = args[i];
            }
        }

        njs_number_set(&vm->retval, array->length);
    }

    return NXT_OK;
}
예제 #13
0
파일: njs_regexp.c 프로젝트: nginx/njs
nxt_int_t
njs_regexp_create(njs_vm_t *vm, njs_value_t *value, u_char *start,
                  size_t length, njs_regexp_flags_t flags)
{
    njs_regexp_t          *regexp;
    njs_regexp_pattern_t  *pattern;

    if (length != 0) {
        pattern = njs_regexp_pattern_create(vm, start, length, flags);
        if (nxt_slow_path(pattern == NULL)) {
            return NXT_ERROR;
        }

    } else {
        pattern = vm->shared->empty_regexp_pattern;
    }

    regexp = njs_regexp_alloc(vm, pattern);

    if (nxt_fast_path(regexp != NULL)) {
        value->data.u.regexp = regexp;
        value->type = NJS_REGEXP;
        value->data.truth = 1;

        return NXT_OK;
    }

    return NXT_ERROR;
}
예제 #14
0
static nxt_int_t
njs_parser_name_expression(njs_vm_t *vm, njs_parser_t *parser,
    njs_token_t token, const void *data)
{
    nxt_uint_t         level;
    njs_extern_t       *ext;
    njs_variable_t     *var;
    njs_parser_node_t  *node;

    node = njs_parser_node_alloc(vm);

    if (nxt_fast_path(node != NULL)) {
        ext = njs_parser_external(vm, parser);

        if (ext != NULL) {
            node->token = NJS_TOKEN_EXTERNAL;
            node->u.value.type = NJS_EXTERNAL;
            node->u.value.data.truth = 1;
            node->index = (njs_index_t) ext;

        } else {
            node->token = token;

            var = njs_parser_variable(vm, parser, &level);
            if (nxt_slow_path(var == NULL)) {
                return NJS_TOKEN_ERROR;
            }

            switch (var->state) {

            case NJS_VARIABLE_CREATED:
                var->state = NJS_VARIABLE_PENDING;
                parser->code_size += sizeof(njs_vmcode_1addr_t);
                break;

            case NJS_VARIABLE_PENDING:
                var->state = NJS_VARIABLE_USED;
                parser->code_size += sizeof(njs_vmcode_1addr_t);
                break;

            case NJS_VARIABLE_USED:
                parser->code_size += sizeof(njs_vmcode_1addr_t);
                break;

            case NJS_VARIABLE_SET:
            case NJS_VARIABLE_DECLARED:
                break;
            }

            node->lvalue = NJS_LVALUE_ENABLED;
            node->u.variable = var;
        }
    }

    parser->node = node;

    return NXT_OK;
}
예제 #15
0
static nxt_int_t
njs_parser_switch(njs_vm_t *vm, njs_parser_t *parser, void *data)
{
    nxt_int_t                    ret;
    nxt_uint_t                   n;
    njs_token_t                  token;
    njs_parser_switch_t          *swtch;
    const njs_parser_terminal_t  *term;

    swtch = data;
    token = parser->lexer->token;

    n = swtch->count;
    term = swtch->terminal;

    do {
        if (token == term->token || term->token == NJS_TOKEN_ANY) {
            ret = term->operation(vm, parser, token, term->data);
            if (nxt_slow_path(ret != NXT_OK)) {
                return NXT_ERROR;
            }

            ret = njs_parser_stack_push(vm, parser, term->primed);
            if (nxt_slow_path(ret != NXT_OK)) {
                return NXT_ERROR;
            }

            if (term->token != NJS_TOKEN_ANY) {
                token = njs_parser_token(parser);
                if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
                    /* TODO: NJS_TOKEN_AGAIN */
                    return NXT_ERROR;
                }
            }

            return NXT_OK;
        }

        term++;
        n--;

    } while (n != 0);

    return NXT_OK;
}
예제 #16
0
파일: njs_object.c 프로젝트: hongzhidao/njs
njs_ret_t
njs_object_constructor(njs_vm_t *vm, njs_param_t *param)
{
    nxt_uint_t    type;
    njs_value_t   *value;
    njs_object_t  *object;

    type = NJS_OBJECT;

    if (param->nargs == 0 || njs_is_null_or_void(&param->args[0])) {

        object = njs_object_alloc(vm);
        if (nxt_slow_path(object == NULL)) {
            return NXT_ERROR;
        }

    } else {
        value = &param->args[0];

        if (njs_is_object(value)) {
            object = value->data.u.object;

        } else if (njs_is_primitive(value)) {

            /* value->type is the same as prototype offset. */
            object = njs_object_value_alloc(vm, value, value->type);
            if (nxt_slow_path(object == NULL)) {
                return NXT_ERROR;
            }

            type = NJS_OBJECT + value->type;

        } else {
            vm->exception = &njs_exception_type_error;

            return NXT_ERROR;
        }
    }

    vm->retval.data.u.object = object;
    vm->retval.type = type;
    vm->retval.data.truth = 1;

    return NXT_OK;
}
예제 #17
0
njs_ret_t
njs_regexp_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
    njs_index_t unused)
{
    size_t                length;
    njs_regexp_t          *regexp;
    njs_string_prop_t     string;
    njs_regexp_flags_t    flags;
    njs_regexp_pattern_t  *pattern;

    flags = 0;

    switch (nargs) {

    default:
        length = njs_string_prop(&string, &args[2]);

        flags = njs_regexp_flags(&string.start, string.start + length, 1);
        if (nxt_slow_path(flags < 0)) {
            return NXT_ERROR;
        }

        /* Fall through. */

    case 2:
        string.length = njs_string_prop(&string, &args[1]);

        if (string.length != 0) {
            break;
        }

        /* Fall through. */

    case 1:
        string.start = (u_char *) "(?:)";
        string.length = sizeof("(?:)") - 1;
        break;
    }

    pattern = njs_regexp_pattern_create(vm, string.start, string.length, flags);

    if (nxt_fast_path(pattern != NULL)) {

        regexp = njs_regexp_alloc(vm, pattern);

        if (nxt_fast_path(regexp != NULL)) {
            vm->retval.data.u.regexp = regexp;
            vm->retval.type = NJS_REGEXP;
            vm->retval.data.truth = 1;

            return NXT_OK;
        }
    }

    return NXT_ERROR;
}
예제 #18
0
파일: njs_array.c 프로젝트: AsamQi/njs
njs_value_t *
njs_array_add(njs_vm_t *vm, njs_value_t *value, u_char *start, size_t size)
{
    njs_ret_t    ret;
    njs_array_t  *array;

    if (value != NULL) {
        array = value->data.u.array;

        if (array->size == array->length) {
            ret = njs_array_realloc(vm, array, 0, array->size + 1);
            if (nxt_slow_path(ret != NXT_OK)) {
                return NULL;
            }
        }

    } else {
        value = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
                                    sizeof(njs_value_t));

        if (nxt_slow_path(value == NULL)) {
            return NULL;
        }

        array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
        if (nxt_slow_path(array == NULL)) {
            return NULL;
        }

        value->data.u.array = array;
        value->type = NJS_ARRAY;
        value->data.truth = 1;
    }

    ret = njs_string_create(vm, &array->start[array->length++], start, size, 0);

    if (nxt_fast_path(ret == NXT_OK)) {
        return value;
    }

    return NULL;
}
예제 #19
0
njs_token_t
njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
{
    nxt_int_t          ret;
    njs_parser_node_t  *node;

    node = njs_parser_node_alloc(vm);
    if (nxt_slow_path(node == NULL)) {
        return NJS_TOKEN_ERROR;
    }

    node->token = NJS_TOKEN_STRING;

    ret = njs_parser_string_create(vm, &node->u.value);
    if (nxt_slow_path(ret != NXT_OK)) {
        return NJS_TOKEN_ERROR;
    }

    parser->node = node;

    return njs_parser_token(parser);
}
예제 #20
0
파일: njs_array.c 프로젝트: AsamQi/njs
njs_ret_t
njs_array_realloc(njs_vm_t *vm, njs_array_t *array, uint32_t prepend,
    uint32_t size)
{
    nxt_uint_t    n;
    njs_value_t  *value;

    if (size != array->size) {
        if (size < 16) {
            size *= 2;

        } else {
            size += size / 2;
        }
    }

    value = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
                                (prepend + size) * sizeof(njs_value_t));
    if (nxt_slow_path(value == NULL)) {
        return NXT_ERROR;
    }

    /* GC: old = array->data */

    array->data = value;

    while (prepend != 0) {
        njs_set_invalid(value);
        value++;
        prepend--;
    }

    memcpy(value, array->start, array->size * sizeof(njs_value_t));

    array->start = value;
    n = array->size;
    array->size = size;

    value += n;
    size -= n;

    while (size != 0) {
        njs_set_invalid(value);
        value++;
        size--;
    }

    /* GC: free old pointer. */

    return NXT_OK;
}
예제 #21
0
파일: njs_object.c 프로젝트: hongzhidao/njs
njs_ret_t
njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value)
{
    int32_t                    index;
    nxt_int_t                  ret;
    njs_function_t             *function;
    njs_object_prop_t          *prop;
    nxt_lvlhsh_query_t         lhq;

    static const njs_value_t   prototype = njs_string("prototype");

    function = value->data.u.function;
    index = function - vm->functions;

    if (index < 0 && index > NJS_PROTOTYPE_MAX) {
        vm->retval = njs_value_void;
        return NXT_OK;
    }

    prop = njs_object_prop_alloc(vm, &prototype);
    if (nxt_slow_path(prop == NULL)) {
        return NXT_ERROR;
    }

    prop->value.data.u.object = &vm->prototypes[index];
    prop->value.type = NJS_OBJECT;
    prop->value.data.truth = 1;

    prop->enumerable = 0;
    prop->writable = 0;
    prop->configurable = 0;

    lhq.value = prop;
    lhq.key_hash = NJS_PROTOTYPE_HASH;
    lhq.key.len = sizeof("prototype") - 1;
    lhq.key.data = (u_char *) "prototype";
    lhq.replace = 0;
    lhq.pool = vm->mem_cache_pool;
    lhq.proto = &njs_object_hash_proto;

    ret = nxt_lvlhsh_insert(&function->object.hash, &lhq);

    if (nxt_fast_path(ret == NXT_OK)) {
        vm->retval = prop->value;
    }

    /* TODO: exception NXT_ERROR. */

    return ret;
}
예제 #22
0
파일: njs_array.c 프로젝트: AsamQi/njs
static njs_ret_t
njs_array_prototype_concat(njs_vm_t *vm, njs_param_t *param)
{
    size_t       length;
    uintptr_t    nargs;
    nxt_uint_t    i;
    njs_value_t  *object, *args, *value;
    njs_array_t  *array;

    object = param->object;

    if (njs_is_array(object)) {
        length = object->data.u.array->length;

    } else {
        length = 1;
    }

    nargs = param->nargs;
    args = param->args;

    for (i = 0; i < nargs; i++) {
        if (njs_is_array(&args[i])) {
            length += args[i].data.u.array->length;

        } else {
            length++;
        }
    }

    array = njs_array_alloc(vm, length, NJS_ARRAY_SPARE);
    if (nxt_slow_path(array == NULL)) {
        return NXT_ERROR;
    }

    vm->retval.data.u.array = array;
    vm->retval.type = NJS_ARRAY;
    vm->retval.data.truth = 1;

    value = njs_array_copy(array->start, object);

    for (i = 0; i < nargs; i++) {
        value = njs_array_copy(value, &args[i]);
    }

    return NXT_OK;
}
예제 #23
0
static nxt_int_t
njs_parser_test_token(njs_vm_t *vm, njs_parser_t *parser, void *data)
{
    njs_token_t  token;

    token = (njs_token_t) data;

    if (parser->lexer->token == token) {
        token = njs_parser_token(parser);
        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            /* TODO: NJS_TOKEN_AGAIN */
            return NXT_ERROR;
        }

        return NXT_OK;
    }

    vm->exception = &njs_exception_syntax_error;

    return NXT_ERROR;
}
예제 #24
0
njs_parser_node_t *
njs_nonrecursive_parser(njs_vm_t *vm, njs_parser_t *parser)
{
    nxt_int_t                     ret;
    njs_token_t                   token;
    njs_parser_stack_operation_t  operation;

    if (top < 0) {
        njs_parser_stack_push(vm, parser, njs_parser_statement);
    }

    token = njs_parser_token(parser);
    if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
        /* TODO: NJS_TOKEN_AGAIN */
        return NULL;
    }

    do {
        operation = (njs_parser_stack_operation_t) njs_parser_stack_pop(parser);

        if (operation == NULL) {

            if (parser->lexer->token == NJS_TOKEN_END) {
                return parser->node;
            }

            break;
        }

        ret = operation(vm, parser, njs_parser_stack_pop(parser));

    } while (ret == NXT_OK);

    nxt_thread_log_error(NXT_LOG_ERR, "unexpected token");

    return NULL;
}
예제 #25
0
파일: njs_object.c 프로젝트: hongzhidao/njs
static njs_ret_t
njs_object_create(njs_vm_t *vm, njs_param_t *param)
{
    njs_value_t   *args;
    njs_object_t  *object;

    if (param->nargs != 0) {
        args = param->args;

        if (njs_is_object(&args[0]) || njs_is_null(&args[0])) {

            object = njs_object_alloc(vm);
            if (nxt_slow_path(object == NULL)) {
                return NXT_ERROR;
            }

            if (!njs_is_null(&args[0])) {
                /* GC */
                object->__proto__ = args[0].data.u.object;

            } else {
                object->shared_hash = vm->shared->null_proto_hash;
                object->__proto__ = NULL;
            }

            vm->retval.data.u.object = object;
            vm->retval.type = NJS_OBJECT;
            vm->retval.data.truth = 1;

            return NXT_OK;
        }
    }

    vm->exception = &njs_exception_type_error;

    return NXT_ERROR;
}
예제 #26
0
파일: njs_array.c 프로젝트: AsamQi/njs
static njs_ret_t
njs_array_prototype_unshift(njs_vm_t *vm, njs_param_t *param)
{
    uintptr_t    nargs;
    njs_ret_t    ret;
    njs_value_t  *args;
    njs_array_t  *array;

    if (njs_is_array(param->object)) {
        array = param->object->data.u.array;
        nargs = param->nargs;

        if (nargs != 0) {
            if ((intptr_t) nargs > (array->start - array->data)) {
                ret = njs_array_realloc(vm, array, nargs, array->size);
                if (nxt_slow_path(ret != NXT_OK)) {
                    return ret;
                }
            }

            array->length += nargs;
            args = param->args;

            do {
                nargs--;
                /* GC: njs_retain(&args[nargs]); */
                array->start--;
                array->start[0] = args[nargs];
            } while (nargs != 0);
        }

        njs_number_set(&vm->retval, array->length);
    }

    return NXT_OK;
}
예제 #27
0
파일: njs_object.c 프로젝트: hongzhidao/njs
nxt_int_t
njs_object_hash_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
    const njs_object_prop_t *prop, nxt_uint_t n)
{
    nxt_int_t           ret;
    nxt_lvlhsh_query_t  lhq;

    lhq.replace = 0;
    lhq.proto = &njs_object_hash_proto;
    lhq.pool = vm->mem_cache_pool;

    do {
        lhq.key.len = prop->name.short_string.size;

        if (lhq.key.len != NJS_STRING_LONG) {
            lhq.key.data = (u_char *) prop->name.short_string.start;

        } else {
            lhq.key.len = prop->name.data.string_size;
            lhq.key.data = prop->name.data.u.string->start;
        }

        lhq.key_hash = nxt_djb_hash(lhq.key.data, lhq.key.len);
        lhq.value = (void *) prop;

        ret = nxt_lvlhsh_insert(hash, &lhq);
        if (nxt_slow_path(ret != NXT_OK)) {
            return NXT_ERROR;
        }

        prop++;
        n--;
    } while (n != 0);

    return NXT_OK;
}
예제 #28
0
static nxt_int_t
njs_parser_string_expression(njs_vm_t *vm, njs_parser_t *parser,
    njs_token_t token, const void *data)
{
    nxt_int_t          ret;
    njs_parser_node_t  *node;

    node = njs_parser_node_alloc(vm);

    if (nxt_fast_path(node != NULL)) {
        node->token = token;

        ret = njs_parser_string_create(vm, &node->u.value);
        if (nxt_slow_path(ret != NXT_OK)) {
            return NJS_TOKEN_ERROR;
        }

        parser->node = node;

        return NXT_OK;
    }

    return NXT_ERROR;
}
예제 #29
0
파일: njs_array.c 프로젝트: AsamQi/njs
static njs_ret_t
njs_array_prototype_join(njs_vm_t *vm, njs_param_t *param)
{
    u_char             *p;
    size_t             size, length;
    nxt_int_t          ret;
    nxt_uint_t         i, n, max;
    njs_array_t        *array;
    njs_value_t        *value, *values;
    njs_string_prop_t  separator, string;

    if (!njs_is_array(param->object)) {
        goto empty;
    }

    array = param->object->data.u.array;

    if (array->length == 0) {
        goto empty;
    }

    if (param->nargs != 0) {
        value = &param->args[0];

    } else {
        value = (njs_value_t *) &njs_string_comma;
    }

    (void) njs_string_prop(&separator, value);

    max = 0;

    for (i = 0; i < array->length; i++) {
        value = &array->start[i];
        if (njs_is_valid(value) && !njs_is_string(value)) {
            max++;
        }
    }

    values = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
                                 sizeof(njs_value_t) * max);
    if (nxt_slow_path(values == NULL)) {
        return NXT_ERROR;
    }

    size = separator.size * (array->length - 1);
    length = separator.length * (array->length - 1);
    n = 0;

    for (i = 0; i < array->length; i++) {
        value = &array->start[i];

        if (njs_is_valid(value)) {

            if (!njs_is_string(value)) {
                ret = njs_value_to_string(vm, &values[n], value);
                if (nxt_slow_path(ret != NXT_OK)) {
                    return NXT_ERROR;
                }

                value = &values[n++];
            }

            (void) njs_string_prop(&string, value);

            size += string.size;
            length += string.length;
        }
    }

    p = njs_string_alloc(vm, &vm->retval, size, length);
    if (nxt_slow_path(p == NULL)) {
        return NXT_ERROR;
    }

    n = 0;

    for (i = 0; i < array->length; i++) {
        value = &array->start[i];

        if (njs_is_valid(value)) {
            if (!njs_is_string(value)) {
                value = &values[n++];
            }

            (void) njs_string_prop(&string, value);

            p = memcpy(p, string.start, string.size);
            p += string.size;
        }

        if (i < array->length - 1) {
            p = memcpy(p, separator.start, separator.size);
            p += separator.size;
        }
    }

    for (i = 0; i < max; i++) {
        njs_release(vm, &values[i]);
    }

    nxt_mem_cache_free(vm->mem_cache_pool, values);

    return NXT_OK;

empty:

    vm->retval = njs_string_empty;

    return NXT_OK;
}
예제 #30
0
파일: njs_array.c 프로젝트: AsamQi/njs
static njs_ret_t
njs_array_prototype_slice(njs_vm_t *vm, njs_param_t *param)
{
    int32_t      start, end, length;
    uint32_t     n;
    uintptr_t    nargs;
    njs_array_t  *array;
    njs_value_t  *object, *args, *value;

    start = 0;
    length = 0;
    object = param->object;

    if (njs_is_array(object)) {
        length = object->data.u.array->length;
        nargs = param->nargs;

        if (nargs != 0) {
            args = param->args;
            start = njs_value_to_number(&args[0]);

            if (start < 0) {
                start += length;

                if (start < 0) {
                    start = 0;
                }
            }

            end = length;

            if (nargs > 1) {
                end = njs_value_to_number(&args[1]);

                if (end < 0) {
                    end += length;
                }
            }

            length = end - start;

            if (length < 0) {
                start = 0;
                length = 0;
            }
        }
    }

    array = njs_array_alloc(vm, length, NJS_ARRAY_SPARE);
    if (nxt_slow_path(array == NULL)) {
        return NXT_ERROR;
    }

    vm->retval.data.u.array = array;
    vm->retval.type = NJS_ARRAY;
    vm->retval.data.truth = 1;

    if (length != 0) {
        value = object->data.u.array->start;
        n = 0;

        do {
            /* GC: retain long string and object in values[start]. */
            array->start[n++] = value[start++];
            length--;
        } while (length != 0);
    }

    return NXT_OK;
}