static void insert_successors(trie_tree* tree, int base_index, int check_index) { assert(tree); assert(base_index >= 0); assert(check_index>0); trie_node* check_node = (trie_node*)get_array_elem(&tree->node_array, check_index); check_node->base = check_node->base < 0 ? -base_index : base_index; for(int succ_index=0; succ_index<successor_array.len; succ_index++) { trie_successor* succ = (trie_successor*)get_array_elem(&successor_array, succ_index); int insert_index = base_index + (int)succ->c; trie_node* node = (trie_node*)get_array_elem(&tree->node_array, insert_index); assert( is_empty_trie_node(node) ); unlink_trie_node(tree, insert_index); node->check = check_index; node->base = insert_index; if( succ->active ) { node->base = succ->base; node->son = succ->son; //node->attr = succ->attr; change_son_check_index(tree, insert_index); } if( check_node->son == 0 ) check_node->son = insert_index; else link_trie_node_next(tree, check_node->son, insert_index); } }
void trie_tree_insert_end(trie_tree* tree) { assert(!be_creating); assert(be_inserting); init_array(&successor_array, sizeof(trie_successor)); for(int input_index = 0; input_index<input_cache.len; input_index++) { int prefix_index, node_index; trie_input* input_node = (trie_input*)get_array_elem(&input_cache, input_index); while( find_prefix(tree, input_node->str, &prefix_index, &node_index) ) { int base_index = abs(((trie_node*)get_array_elem(&tree->node_array, node_index))->base); get_all_successors(input_node->str, prefix_index, input_index); delete_existing_successors(tree, node_index); if(base_index == node_index || !check_insert_successors(tree, node_index) ) { reset_successors(tree, node_index); base_index = find_base_index_by_successors(tree, node_index); } insert_successors(tree, base_index, node_index); } mark_word_node(tree, node_index); } print_node(tree, 1, 0); empty_array(&input_cache); empty_array(&successor_array); be_inserting = false; }
static void print_node(trie_tree* tree, int index, int tail) { trie_node* node = (trie_node*)get_array_elem(&tree->node_array, index); if( node->check > 0) { trie_node* prev_node = (trie_node*)get_array_elem(&tree->node_array, node->check); tchar c = index - abs(prev_node->base); out_char[tail-1] = c; } if( node->base < 0 && tail>0) { out_char[tail] = 0; wprintf(L"%s; ", out_char); } int son_index = node->son; if( node->son > 0 ) { do { print_node(tree, son_index, tail+1); son_index = ((trie_node*)get_array_elem(&tree->node_array, son_index))->next; assert(son_index>0); } while(son_index != node->son); } }
trie_tree* trie_tree_create_end() { assert(be_creating); assert(!be_inserting); trie_tree* tree = (trie_tree*)malloc(sizeof(trie_tree)); init_array(&tree->node_array, sizeof(trie_node)); init_array(&successor_array, sizeof(trie_successor)); append_array(&tree->node_array, 2); memset(get_array_elem(&tree->node_array, 0), 0, sizeof(trie_node)*2); trie_node* head_node = (trie_node*)get_array_elem(&tree->node_array, HEAD_INDEX); head_node->check = HEAD_CHECK; head_node->base = HEAD_INDEX; for(int input_index = 0; input_index<input_cache.len; input_index++) { int prefix_index, node_index, base_index; trie_input* input_node = (trie_input*)get_array_elem(&input_cache, input_index); while( find_prefix(tree, input_node->str, &prefix_index, &node_index) ) { get_all_successors(input_node->str, prefix_index, input_index); base_index = find_base_index_by_successors(tree, node_index); insert_successors(tree, base_index, node_index); } mark_word_node(tree, node_index); } empty_array(&input_cache); empty_array(&successor_array); be_creating = false; return tree; }
TRIE_STATE trie_tree_check_state(trie_tree* tree, tchar c) { assert(tree); assert(checking_index>0); trie_node* checking_node = (trie_node*)get_array_elem(&tree->node_array, checking_index); int next_index = abs(checking_node->base) + (int)c; TRIE_STATE state = STATE_NULL; if( next_index < tree->node_array.len ) { trie_node* next_node = (trie_node*)get_array_elem(&tree->node_array, next_index); if( next_node->check == checking_index ) { checking_index = next_index; assert( next_node->base != 0); if(next_node->base == -next_index) state = STATE_WORD; else if( next_node->base < 0 ) state = STATE_WORD_PREFIX; else { assert(next_node->base != next_index); state = STATE_PREFIX; } } } return state; }
static bool find_prefix(trie_tree* tree, tchar* str, int* out_prefix_index, int* out_node_index) { assert(tree); assert(tree->node_array.len > HEAD_INDEX); assert(str); int prefix_index = 0; int check_index = HEAD_INDEX; while( str[prefix_index] ) { trie_node* check_node = (trie_node*)get_array_elem(&tree->node_array, check_index); if( check_node->base == check_index ) break; int next_index = abs(check_node->base) + (int)str[prefix_index]; if( next_index >= tree->node_array.len ) break; trie_node* next_node = (trie_node*)get_array_elem(&tree->node_array, next_index); if( next_node->check != check_index ) break; check_index = next_index; prefix_index++; } *out_prefix_index = prefix_index; *out_node_index = check_index; if( str && str[prefix_index] == 0) // 已成词 { assert(prefix_index>0); assert(check_index>HEAD_INDEX); return false; } return true; }
static void reset_successors(trie_tree* tree, int check_index) { assert(tree); assert(check_index>0); trie_node* check_node = (trie_node*)get_array_elem(&tree->node_array, check_index); int son_index = check_node->son; if(son_index > 0) { int unlink_index; do { int append_index = append_array(&successor_array, 1); trie_successor* succ = (trie_successor*)get_array_elem(&successor_array, append_index); trie_node* son_node = (trie_node*)get_array_elem(&tree->node_array, son_index); unlink_index = son_index; assert( son_index > abs(check_node->base) ) ; succ->active = true; succ->base = son_node->base; succ->son = son_node->son; succ->c = son_index - abs(check_node->base); //succ->attr = son_node->attr; assert(son_node->next>0); son_index = son_node->next; unlink_trie_node(tree, unlink_index); empty_trie_node(tree, unlink_index); } while(son_index != unlink_index); check_node->son = 0; if( successor_array.len > 1 ) qsort(get_array_elem(&successor_array, 0), successor_array.len, sizeof(trie_successor), successors_cmp); } }
static void link_trie_node_next(trie_tree* tree, int base_index, int next_index) { assert( tree ); trie_node* base_node = (trie_node*)get_array_elem(&tree->node_array, base_index); trie_node* next_node = (trie_node*)get_array_elem(&tree->node_array, next_index); next_node->next = base_node->next; next_node->prev = base_index; trie_node* next_next_node = (trie_node*)get_array_elem(&tree->node_array, next_node->next); base_node->next = next_next_node->prev = next_index; }
static void unlink_trie_node(trie_tree* tree, int index) { assert( tree ); assert( index > 0 ); trie_node* node = (trie_node*)get_array_elem(&tree->node_array, index); trie_node* prev_node = (trie_node*)get_array_elem(&tree->node_array, node->prev); trie_node* next_node = (trie_node*)get_array_elem(&tree->node_array, node->next); prev_node->next = node->next; next_node->prev = node->prev; node->next = node->prev = index; }
static void change_son_check_index(trie_tree* tree, int node_index) { assert(tree); assert(node_index>HEAD_INDEX); int first_index = ((trie_node*)get_array_elem(&tree->node_array, node_index))->son; int son_index = first_index; do { assert(son_index>0); trie_node* node = (trie_node*)get_array_elem(&tree->node_array, son_index); node->check = node_index; son_index = node->next; } while(son_index != first_index); }
void trie_tree_set_input(int index, tchar* str) { assert( str ); assert( be_creating || be_inserting ); trie_input* input_node = (trie_input*)get_array_elem(&input_cache, index); input_node->str = str; //input_node->attr = attr; }
static int find_base_index_by_successors(trie_tree* tree, int forbidden_index) { assert(tree); assert(tree->node_array.len > 0); assert(successor_array.len > 0); tchar min_char = ((trie_successor*)get_array_elem(&successor_array, 0))->c; int base_index; int empty_index = 0; while( true ) { empty_index = append_empty_node(tree, empty_index); //trie_node* node = (trie_node*)get_array_elem(&tree->node_array, empty_index); base_index = empty_index - (int)min_char; if( base_index > 0 && base_index != forbidden_index) { int succ_index = 0; for( ; succ_index<successor_array.len; succ_index++) { tchar check_char = ((trie_successor*)get_array_elem(&successor_array, succ_index))->c; int check_index = base_index + (int)check_char; if( check_index < tree->node_array.len ) { trie_node* check_node = (trie_node*)get_array_elem(&tree->node_array, check_index); if( check_node->base != 0 ) { assert(check_node->check != 0); break; } } else // 增加长度 { tchar last_char = ((trie_successor*)get_array_elem(&successor_array, successor_array.len-1))->c; int append_len = base_index + (int)last_char - tree->node_array.len + 1; int tail_index = append_array(&tree->node_array, append_len); for( ;tail_index < tree->node_array.len; tail_index++) empty_trie_node(tree, tail_index); succ_index = successor_array.len; break; } } if( succ_index == successor_array.len ) break; } } return base_index; }
static bool check_successors_unique(tchar c) { for(int i = 0; i<successor_array.len; i++) { if(((trie_successor*)get_array_elem(&successor_array, i))->c == c) return false; } return true; }
// link to empty_node list // index 0 always empty; static void empty_trie_node(trie_tree* tree, int node_index) { assert( tree ); assert( node_index >= 0); assert( node_index < tree->node_array.len ); trie_node* node = (trie_node*)get_array_elem(&tree->node_array, node_index); //node->attr = 0; node->base = node->check = node->son = 0; int pre_index = node_index-1; while( pre_index >= 0 ) { trie_node* prev_node = (trie_node*)get_array_elem(&tree->node_array, pre_index); if( is_empty_trie_node(prev_node) ) { link_trie_node_next(tree, pre_index, node_index); break; } pre_index--; } assert(pre_index>=0); }
bool check_insert_successors(trie_tree* tree, int check_index) { assert(tree); assert(check_index>=HEAD_INDEX); trie_node* check_node = (trie_node*)get_array_elem(&tree->node_array, check_index); int succ_index=0; for(; succ_index<successor_array.len; succ_index++) { trie_successor* succ = (trie_successor*)get_array_elem(&successor_array, succ_index); assert(!succ->active); int insert_index = abs(check_node->base) + (int)succ->c; if( insert_index >= tree->node_array.len ) // 此处暂时纳入重新设定base的流程,可优化 break; trie_node* node = (trie_node*)get_array_elem(&tree->node_array, insert_index); if( !is_empty_trie_node(node) ) { assert(node->check != check_index); break; } } return (succ_index == successor_array.len); }
static void get_all_successors(tchar* str, int prefix_end, int search_begin_pos) { assert( search_begin_pos >= 0); assert( search_begin_pos < input_cache.len ); successor_array.len = 0; for(int i = search_begin_pos; i<input_cache.len; i++) { tchar* check_str = ((trie_input*)get_array_elem(&input_cache, i))->str; int check_ptr = 0; while( check_ptr < prefix_end && check_str[check_ptr] && check_str[check_ptr] == str[check_ptr] ) check_ptr++; if( check_ptr == prefix_end && check_str[prefix_end] && check_successors_unique(check_str[prefix_end])) { int index = append_array(&successor_array, 1); trie_successor* succ = (trie_successor*)get_array_elem(&successor_array, index); succ->c = check_str[prefix_end]; succ->active = false; } } if( successor_array.len > 1 && be_creating ) // 插入时的排序操作在reset_successor函数 qsort(get_array_elem(&successor_array, 0), successor_array.len, sizeof(trie_successor), successors_cmp); }
static void mark_word_node(trie_tree* tree, int index) { assert(tree); assert(tree->node_array.len > HEAD_INDEX); assert(index > HEAD_INDEX); trie_node* node = (trie_node*)get_array_elem(&tree->node_array, index); assert(node->check != 0); assert(node->base != 0); //assert(node->attr == 0); //node->attr = attr; if( node->base > 0 ) node->base = -node->base; }
void delete_existing_successors(trie_tree* tree, int check_index) { assert(tree); assert(check_index>=HEAD_INDEX); trie_node* check_node = (trie_node*)get_array_elem(&tree->node_array, check_index); int move_index = 0; for(int succ_index=0; succ_index<successor_array.len; succ_index++) { trie_successor* succ = (trie_successor*)get_array_elem(&successor_array, succ_index); bool existing = false; int son_index = check_node->son; if(son_index>0) { do { trie_node* son_node = (trie_node*)get_array_elem(&tree->node_array, son_index); assert(son_index > abs(check_node->base) ); if( (son_index-abs(check_node->base)) == succ->c ) { existing = true; break; } assert(son_node->next>0); son_index = son_node->next; } while(son_index != check_node->son); } if( !existing ) { trie_successor* move_succ = (trie_successor*)get_array_elem(&successor_array, move_index); move_succ->c = succ->c; move_index += 1; } } successor_array.len = move_index; }
static int append_empty_node(trie_tree* tree, int node_index) { assert( tree ); assert( node_index >= 0); assert( node_index < tree->node_array.len ); trie_node* node = (trie_node*)get_array_elem(&tree->node_array, node_index); assert( is_empty_trie_node(node) ); int empty_index = node->next; if(empty_index == 0) { int append_index = append_array(&tree->node_array, 1); empty_trie_node(tree, append_index); empty_index = append_index; } return empty_index; }
tree_cell* nasl_exec(lex_ctxt* lexic, tree_cell* st) { tree_cell *ret = NULL, *ret2 = NULL, *tc1 = NULL, *tc2 = NULL, *tc3 = NULL, *idx = NULL, *args; int flag, x, y, z; char *s1 = NULL, *s2 = NULL, *s3 = NULL, *p = NULL; char *p1, *p2; int len1, len2; nasl_func *pf = NULL; int i, n; unsigned long sz; #if 0 nasl_dump_tree(st); /* See rt.value, rt.type, rt.length */ #endif /* return */ if (lexic->ret_val != NULL) { ref_cell(lexic->ret_val); return lexic->ret_val; } /* break or continue */ if (lexic->break_flag || lexic->cont_flag) return FAKE_CELL; if (st == FAKE_CELL) return FAKE_CELL; if (st == NULL) { #if NASL_DEBUG > 0 nasl_perror(lexic, "nasl_exec: st == NULL\n"); #endif return NULL; } if (nasl_trace_fp != NULL) nasl_short_dump(nasl_trace_fp, st); switch(st->type) { case NODE_IF_ELSE: ret = nasl_exec(lexic, st->link[0]); #ifdef STOP_AT_FIRST_ERROR if (ret == NULL) return NULL; #endif if (cvt_bool(lexic, ret)) ret2 = nasl_exec(lexic, st->link[1]); else if (st->link[2] != NULL) /* else branch */ ret2 = nasl_exec(lexic, st->link[2]); else /* No else */ ret2 = FAKE_CELL; deref_cell(ret); return ret2; case NODE_INSTR_L: /* Block. [0] = first instr, [1] = tail */ ret = nasl_exec(lexic, st->link[0]); #if NASL_DEBUG > 1 if (ret == NULL) nasl_perror(lexic, "Instruction failed. Going on in block\n"); #endif if (st->link[1] == NULL || lexic->break_flag || lexic->cont_flag) return ret; deref_cell(ret); ret = nasl_exec(lexic, st->link[1]); return ret; case NODE_FOR: /* [0] = start expr, [1] = cond, [2] = end_expr, [3] = block */ ret2 = nasl_exec(lexic, st->link[0]); #ifdef STOP_AT_FIRST_ERROR if (ret2 == NULL) return NULL; #endif deref_cell(ret2); for (;;) { /* Break the loop if 'return' */ if (lexic->ret_val != NULL) { ref_cell(lexic->ret_val); return lexic->ret_val; } /* condition */ if ((ret = nasl_exec(lexic, st->link[1])) == NULL) return NULL; /* We can return here, as NULL is false */ flag = cvt_bool(lexic, ret); deref_cell(ret); if (! flag) break; /* block */ ret = nasl_exec(lexic, st->link[3]); #ifdef STOP_AT_FIRST_ERROR if (ret == NULL) return NULL; #endif deref_cell(ret); /* break */ if (lexic->break_flag) { lexic->break_flag = 0; return FAKE_CELL; } lexic->cont_flag = 0; /* No need to test if set */ /* end expression */ ret = nasl_exec(lexic, st->link[2]); #ifdef STOP_AT_FIRST_ERROR if (ret == NULL) return NULL; #endif deref_cell(ret); } return FAKE_CELL; case NODE_WHILE: /* [0] = cond, [1] = block */ for (;;) { /* return? */ if (lexic->ret_val != NULL) { ref_cell(lexic->ret_val); return lexic->ret_val; } /* Condition */ if ((ret = nasl_exec(lexic, st->link[0])) == NULL) return NULL; /* NULL is false */ flag = cvt_bool(lexic, ret); deref_cell(ret); if (! flag) break; /* Block */ ret = nasl_exec(lexic, st->link[1]); #ifdef STOP_AT_FIRST_ERROR if (ret == NULL) return NULL; #endif deref_cell(ret); /* break */ if (lexic->break_flag) { lexic->break_flag = 0; return FAKE_CELL; } lexic->cont_flag = 0; } return FAKE_CELL; case NODE_REPEAT_UNTIL: /* [0] = block, [1] = cond */ for (;;) { /* return? */ if (lexic->ret_val != NULL) { ref_cell(lexic->ret_val); return lexic->ret_val; } /* Block */ ret = nasl_exec(lexic, st->link[0]); #ifdef STOP_AT_FIRST_ERROR if (ret == NULL) return NULL; #endif deref_cell(ret); /* break */ if (lexic->break_flag) { lexic->break_flag = 0; return FAKE_CELL; } lexic->cont_flag = 0; /* Condition */ ret = nasl_exec(lexic, st->link[1]); #ifdef STOP_AT_FIRST_ERROR if (ret == NULL) return NULL; #endif flag = cvt_bool(lexic, ret); deref_cell(ret); if (flag) break; } return FAKE_CELL; case NODE_FOREACH: /* str_val = index name, [0] = array, [1] = block */ { nasl_iterator ai; tree_cell *v, *a, *val; v = get_variable_by_name(lexic, st->x.str_val); if (v == NULL) return NULL; /* We cannot go on if we have no variable to iterate */ a = nasl_exec(lexic, st->link[0]); ai = nasl_array_iterator(a); while ((val = nasl_iterate_array(&ai)) != NULL) { tc1 = nasl_affect(v, val); ret = nasl_exec(lexic, st->link[1]); deref_cell(val); deref_cell(tc1); #ifdef STOP_AT_FIRST_ERROR if (ret == NULL) break; #endif deref_cell(ret); /* return */ if (lexic->ret_val != NULL) break; /* break */ if (lexic->break_flag) { lexic->break_flag = 0; break; } lexic->cont_flag = 0; } deref_cell(a); deref_cell(v); } return FAKE_CELL; case NODE_FUN_DEF: /* x.str_val = function name, [0] = argdecl, [1] = block */ ret = decl_nasl_func(lexic, st); return ret; case NODE_FUN_CALL: pf = get_func_ref_by_name(lexic, st->x.str_val); if (pf == NULL) { nasl_perror(lexic, "Undefined function '%s'\n", st->x.str_val); return NULL; } args = st->link[0]; #if 0 printf("****************\n"); nasl_dump_tree(args); printf("****************\n"); #endif ret = nasl_func_call(lexic, pf, args); return ret; case NODE_REPEATED: n = cell2intW(lexic, st->link[1]); if (n <= 0) return NULL; #ifdef STOP_AT_FIRST_ERROR for (tc1 = NULL, i = 1; i <= n; i ++) { deref_cell(tc1); if ((tc1 = nasl_exec(lexic, st->link[0])) == NULL) return NULL; } return tc1; #else for (i = 1; i <= n; i ++) { tc1 = nasl_exec(lexic, st->link[0]); deref_cell(tc1); } return FAKE_CELL; #endif /* * I wonder... * Will nasl_exec be really called with NODE_EXEC or NODE_ARG? */ case NODE_DECL: /* Used in function declarations */ /* [0] = next arg in list */ /* TBD? */ return st; /* ? */ case NODE_ARG: /* Used function calls */ /* val = name can be NULL, [0] = val, [1] = next arg */ ret = nasl_exec(lexic, st->link[0]); /* Is this wise? */ return ret; case NODE_RETURN: /* [0] = ret val */ ret = nasl_return(lexic, st->link[0]); return ret; case NODE_BREAK: lexic->break_flag = 1; return FAKE_CELL; case NODE_CONTINUE: lexic->cont_flag = 1; return FAKE_CELL; case NODE_ARRAY_EL: /* val = array name, [0] = index */ idx = cell2atom(lexic, st->link[0]); ret = get_array_elem(lexic, st->x.str_val, idx); deref_cell(idx); return ret; case NODE_AFF: /* [0] = lvalue, [1] = rvalue */ tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); ret = nasl_affect(tc1, tc2); deref_cell(tc1); /* Must free VAR_REF */ deref_cell(ret); return tc2; /* So that "a = b = e;" works */ case NODE_PLUS_EQ: tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); tc3 = alloc_expr_cell(0, EXPR_PLUS, tc1, tc2); ret2 = nasl_exec(lexic, tc3); ret = nasl_affect(tc1, ret2); deref_cell(tc3); /* Frees tc1 and tc2 */ deref_cell(ret); return ret2; /* So that "a = b += e;" works */ case NODE_MINUS_EQ: tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); tc3 = alloc_expr_cell(0, EXPR_MINUS, tc1, tc2); ret2 = nasl_exec(lexic, tc3); ret = nasl_affect(tc1, ret2); deref_cell(tc3); /* Frees tc1 and tc2 */ deref_cell(ret); return ret2; /* So that "a = b -= e;" works */ case NODE_MULT_EQ: tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); tc3 = alloc_expr_cell(0, EXPR_MULT, tc1, tc2); ret2 = nasl_exec(lexic, tc3); ret = nasl_affect(tc1, ret2); deref_cell(tc3); /* Frees tc1 and tc2 */ deref_cell(ret); return ret2; case NODE_DIV_EQ: tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); tc3 = alloc_expr_cell(0, EXPR_DIV, tc1, tc2); ret2 = nasl_exec(lexic, tc3); ret = nasl_affect(tc1, ret2); deref_cell(tc3); /* Frees tc1 and tc2 */ deref_cell(ret); return ret2; case NODE_MODULO_EQ: tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); tc3 = alloc_expr_cell(0, EXPR_MODULO, tc1, tc2); ret2 = nasl_exec(lexic, tc3); ret = nasl_affect(tc1, ret2); deref_cell(tc3); /* Frees tc1 and tc2 */ deref_cell(ret); return ret2; case NODE_L_SHIFT_EQ: tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); tc3 = alloc_expr_cell(0, EXPR_L_SHIFT, tc1, tc2); ret2 = nasl_exec(lexic, tc3); ret = nasl_affect(tc1, ret2); deref_cell(tc3); /* Frees tc1 and tc2 */ deref_cell(ret); return ret2; case NODE_R_SHIFT_EQ: tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); tc3 = alloc_expr_cell(0, EXPR_R_SHIFT, tc1, tc2); ret2 = nasl_exec(lexic, tc3); ret = nasl_affect(tc1, ret2); deref_cell(tc3); /* Frees tc1 and tc2 */ deref_cell(ret); return ret2; case NODE_R_USHIFT_EQ: tc1 = nasl_exec(lexic, st->link[0]); tc2 = nasl_exec(lexic, st->link[1]); tc3 = alloc_expr_cell(0, EXPR_R_USHIFT, tc1, tc2); ret2 = nasl_exec(lexic, tc3); ret = nasl_affect(tc1, ret2); deref_cell(tc3); /* Frees tc1 and tc2 */ deref_cell(ret); return ret2; case NODE_VAR: /* val = variable name */ ret = get_variable_by_name(lexic, st->x.str_val); return ret; case NODE_LOCAL: /* [0] = argdecl */ ret = decl_local_variables(lexic, st->link[0]); return ret; case NODE_GLOBAL: /* [0] = argdecl */ ret = decl_global_variables(lexic, st->link[0]); return ret; case EXPR_AND: x = cell2bool(lexic, st->link[0]); if(! x) return bool2cell(0); y = cell2bool(lexic, st->link[1]); return bool2cell(y); case EXPR_OR: x = cell2bool(lexic, st->link[0]); if(x) return bool2cell(x); y = cell2bool(lexic, st->link[1]); return bool2cell(y); case EXPR_NOT: x = cell2bool(lexic, st->link[0]); return bool2cell(! x); case EXPR_INCR: case EXPR_DECR: x = (st->type == EXPR_INCR) ? 1 : -1; if (st->link[0] == NULL) { y = 1; /* pre */ tc1 = st->link[1]; } else { y = 0; /* post */ tc1 = st->link[0]; } tc2 = nasl_exec(lexic, tc1); if (tc2 == NULL) return NULL; ret = nasl_incr_variable(lexic, tc2, y, x); deref_cell(tc2); return ret; if (st->link[0] == NULL) ret = nasl_incr_variable(lexic, st->link[1], 1, 1); else ret = nasl_incr_variable(lexic, st->link[1], 0, 1); break; case EXPR_PLUS: s1 = s2 = NULL; tc1 = cell2atom(lexic, st->link[0]); #ifdef STOP_AT_FIRST_ERROR if (tc1 == NULL || tc1 == FAKE_CELL) return NULL; #endif tc2 = cell2atom(lexic, st->link[1]); if (tc2 == NULL || tc2 == FAKE_CELL) { #ifdef STOP_AT_FIRST_ERROR deref_cell(tc1); return NULL; #else return tc1; #endif } if (tc1 == NULL || tc1 == FAKE_CELL) return tc2; /* * Anything added to a string is converted to a string * Otherwise anything added to an intger is converted into an integer */ if (tc1->type == CONST_DATA || tc2->type == CONST_DATA) flag = CONST_DATA; else if (tc1->type == CONST_STR || tc2->type == CONST_STR) flag = CONST_STR; else if (tc1->type == CONST_INT || tc2->type == CONST_INT) flag = CONST_INT; else flag = NODE_EMPTY; #if NASL_DEBUG > 0 if ((flag == CONST_DATA || flag == CONST_STR) && (tc1->type == CONST_INT || tc2->type == CONST_INT)) nasl_perror(lexic, "Horrible type conversion (int -> str) for operator + %s\n", get_line_nb(st)); #endif switch (flag) { case CONST_INT: x = tc1->x.i_val; y = cell2int(lexic, tc2); ret = int2cell(x + y); break; case CONST_STR: case CONST_DATA: s1 = s2 = NULL; if (tc1->type == CONST_STR || tc1->type == CONST_DATA) len1 = tc1->size; else { s1 = cell2str(lexic, tc1); len1 = (s1 == NULL ? 0 : strlen(s1)); } if (tc2->type == CONST_STR || tc2->type == CONST_DATA) len2 = tc2->size; else { s2 = cell2str(lexic, tc2); len2 = (s2 == NULL ? 0 : strlen(s2)); } sz = len1 + len2; s3 = emalloc(sz); if (len1 > 0) memcpy(s3, s1 != NULL ? s1 : tc1->x.str_val, len1); if (len2 > 0) memcpy(s3 + len1, s2 != NULL ? s2 : tc2->x.str_val, len2); efree(&s1); efree(&s2); ret = alloc_tree_cell(0, s3); ret->type = flag; ret->size = sz; break; default: ret = NULL; break; } deref_cell(tc1); deref_cell(tc2); return ret; case EXPR_MINUS: /* Infamous duplicated code */ s1 = s2 = NULL; tc1 = cell2atom(lexic, st->link[0]); #ifdef STOP_AT_FIRST_ERROR if (tc1 == NULL || tc1 == FAKE_CELL) return NULL; #endif tc2 = cell2atom(lexic, st->link[1]); if (tc2 == NULL || tc2 == FAKE_CELL) { #ifdef STOP_AT_FIRST_ERROR deref_cell(tc1); return NULL; #else return tc1; #endif } if (tc1 == NULL || tc1 == FAKE_CELL) { if (tc2->type == CONST_INT) { y = cell2int(lexic, tc2); ret = int2cell(- y); } else ret = NULL; deref_cell(tc2); return ret; } /* * Anything substracted from a string is converted to a string * Otherwise anything substracted from integer is converted into an * integer */ if (tc1->type == CONST_DATA || tc2->type == CONST_DATA) flag = CONST_DATA; else if (tc1->type == CONST_STR || tc2->type == CONST_STR) flag = CONST_STR; else if (tc1->type == CONST_INT || tc2->type == CONST_INT) flag = CONST_INT; else flag = NODE_EMPTY; #if NASL_DEBUG > 0 if ((flag == CONST_DATA || flag == CONST_STR) && (tc1->type == CONST_INT || tc2->type == CONST_INT)) nasl_perror(lexic, "Horrible type conversion (int -> str) for operator - %s\n", get_line_nb(st)); #endif switch (flag) { case CONST_INT: x = cell2int(lexic, tc1); y = cell2int(lexic, tc2); ret = int2cell(x - y); break; case CONST_STR: case CONST_DATA: if (tc1->type == CONST_STR || tc1->type == CONST_DATA) { p1 = tc1->x.str_val; len1 = tc1->size; } else { p1 = s1 = cell2str(lexic, tc1); len1 = (s1 == NULL ? 0 : strlen(s1)); } if (tc2->type == CONST_STR || tc2->type == CONST_DATA) { p2 = tc2->x.str_val; len2 = tc2->size; } else { p2 = s2 = cell2str(lexic, tc2); len2 = (s2 == NULL ? 0 : strlen(s2)); } if (len2 == 0 || len1 < len2 || (p = (char*)nasl_memmem(p1, len1, p2, len2)) == NULL) { s3 = emalloc(len1); memcpy(s3, p1, len1); ret = alloc_tree_cell(0, s3); ret->type = flag; ret->size = len1; } else { sz = len1 - len2; if (sz <= 0) { sz = 0; s3 = estrdup(""); } else { s3 = emalloc(sz); if (p - p1 > 0) memcpy(s3, p1, p - p1); if (sz > p - p1) memcpy(s3 + (p - p1), p + len2, sz - (p - p1)); } ret = alloc_tree_cell(0, s3); ret->size = sz; ret->type = flag; } efree(&s1); efree(&s2); break; default: ret = NULL; break; } deref_cell(tc1); deref_cell(tc2); return ret; case EXPR_MULT: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); return int2cell(x * y); case EXPR_DIV: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); if( y != 0 ) return int2cell(x / y); else return int2cell(0); case EXPR_EXPO: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); return int2cell(expo(x, y)); case EXPR_MODULO: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); if( y != 0) return int2cell(x % y); else return int2cell(0); case EXPR_BIT_AND: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); return int2cell(x & y); case EXPR_BIT_OR: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); return int2cell(x | y); case EXPR_BIT_XOR: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); return int2cell(x ^ y); case EXPR_BIT_NOT: x = cell2intW(lexic, st->link[0]); return int2cell(~ x); case EXPR_U_MINUS: x = cell2intW(lexic, st->link[0]); return int2cell(- x); /* TBD: Handle shift for strings and arrays */ case EXPR_L_SHIFT: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); return int2cell(x << y); case EXPR_R_SHIFT: /* arithmetic right shift */ x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); #if NASL_DEBUG > 0 if (y < 0) nasl_perror(lexic, "Warning: Negative count in right shift!\n"); #endif z = x >> y; #ifndef __GNUC__ if (x < 0 && z >= 0) /* Fix it */ { #if NASL_DEBUG > 1 nasl_perror(lexic, "Warning: arithmetic right shift is buggy! Fixing...\n"); #endif z |= (~0) << (sizeof(x) * 8 - y); } #endif return int2cell(z); case EXPR_R_USHIFT: x = cell2intW(lexic, st->link[0]); y = cell2intW(lexic, st->link[1]); #if NASL_DEBUG > 0 if (y < 0) nasl_perror(lexic, "Warning: Negative count in right shift!\n"); #endif z = (unsigned)x >> (unsigned)y; #ifndef __GNUC__ if (x < 0 && z <= 0) /* Fix it! */ { #if NASL_DEBUG > 1 nasl_perror(lexic, "Warning: Logical right shift is buggy! Fixing...\n"); #endif z &= ~((~0) << (sizeof(x) * 8 - y)); } #endif return int2cell(z); case COMP_MATCH: case COMP_NOMATCH: tc1 = cell2atom(lexic, st->link[0]); tc2 = cell2atom(lexic, st->link[1]); s1 = s2 = NULL; if (tc1 == NULL || tc1 == FAKE_CELL) { p1 = ""; len1 = 0; } else if (tc1->type == CONST_STR || tc1->type == CONST_DATA) { p1 = tc1->x.str_val; len1 = tc1->size; } else { #if NASL_DEBUG > 0 nasl_perror(lexic, "Horrible type conversion (%s -> str) for operator >< or >!< %s\n", nasl_type_name(tc1->type), get_line_nb(st)); #endif p1 = s1 = cell2str(lexic, tc1); len1 = strlen(s1); } if (tc2 == NULL || tc2 == FAKE_CELL) { p2 = ""; len2 = 0; } else if (tc2->type == CONST_STR || tc2->type == CONST_DATA) { p2 = tc2->x.str_val; len2 = tc2->size; } else { #if NASL_DEBUG > 0 nasl_perror(lexic, "Horrible type conversion (%s -> str) for operator >< or >!< %s\n", nasl_type_name(tc2->type), get_line_nb(st)); #endif p2 = s2 = cell2str(lexic, tc2); len2 = strlen(s2); } if(len1 <= len2) flag = ((void*)nasl_memmem(p2, len2, p1, len1) != NULL); else flag = 0; efree(&s1); efree(&s2); deref_cell(tc1); deref_cell(tc2); if (st->type == COMP_MATCH) return bool2cell(flag); else return bool2cell(! flag); case COMP_RE_MATCH: case COMP_RE_NOMATCH: if (st->x.ref_val == NULL) { nasl_perror(lexic, "nasl_exec: bad regex at or near line %d\n", st->line_nb); return NULL; } s1 = cell2str(lexic, st->link[0]); if (s1 == NULL) return 0; flag = nasl_regexec(st->x.ref_val, s1, 0, NULL, 0); free(s1); if (st->type == COMP_RE_MATCH) return bool2cell(flag != REG_NOMATCH); else return bool2cell(flag == REG_NOMATCH); case COMP_LT: return bool2cell(cell_cmp(lexic, st->link[0], st->link[1]) < 0); case COMP_LE: return bool2cell(cell_cmp(lexic, st->link[0], st->link[1]) <= 0); case COMP_EQ: return bool2cell(cell_cmp(lexic, st->link[0], st->link[1]) == 0); case COMP_NE: return bool2cell(cell_cmp(lexic, st->link[0], st->link[1]) != 0); case COMP_GT: return bool2cell(cell_cmp(lexic, st->link[0], st->link[1]) > 0); case COMP_GE: return bool2cell(cell_cmp(lexic, st->link[0], st->link[1]) >= 0); case REF_ARRAY: case DYN_ARRAY: case CONST_INT: case CONST_STR: case CONST_DATA: ref_cell(st); /* nasl_exec returns a cell that should be deref-ed */ return st; case REF_VAR: ret = nasl_read_var_ref(lexic, st); return ret; default: nasl_perror(lexic, "nasl_exec: unhandled node type %d\n", st->type); abort(); return NULL; } deref_cell(ret); deref_cell(ret2); return NULL; }