Example #1
0
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);
  }
}
Example #2
0
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;
}
Example #3
0
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);
  }

}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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);
  }
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
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);

}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
// 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);
}
Example #15
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);
}
Example #16
0
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);
}
Example #17
0
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;
}
Example #18
0
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;
}
Example #19
0
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;
}
Example #20
0
File: exec.c Project: OPSF/uClinux
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;
}