Пример #1
0
const char * interpreter::get_running_call_stack() const
{
    m_fk->rn.curcallstack.clear();
    int deps = 0;
    for (int i = ARRAY_SIZE(m_stack_list) - 1; i >= 0; i--)
    {
        m_fk->rn.curcallstack += "#";
        m_fk->rn.curcallstack += fkitoa(deps);
        m_fk->rn.curcallstack += "    ";
        stack & s = ARRAY_GET(m_stack_list, i);
        m_fk->rn.curcallstack += s.m_fb->m_name;
        m_fk->rn.curcallstack += " at ";
        m_fk->rn.curcallstack += s.m_fb->m_filename;
        m_fk->rn.curcallstack += ":";
        m_fk->rn.curcallstack += fkitoa(GET_CMD_LINENO((*s.m_fb), s.m_pos));
        m_fk->rn.curcallstack += "\n";
        for (int j = 0; j < s.m_fb->m_maxstack && j < (int)ARRAY_MAX_SIZE(s.m_stack_variant_list); j++)
        {
            m_fk->rn.curcallstack += "        [";
            m_fk->rn.curcallstack += fkitoa(j);
            m_fk->rn.curcallstack += "]\t";
            m_fk->rn.curcallstack += vartostring(&ARRAY_GET(s.m_stack_variant_list, j));
            m_fk->rn.curcallstack += "\n";
        }
        deps++;
    }
    return m_fk->rn.curcallstack.c_str();
}
Пример #2
0
/*
 * BIF implementations
 */
static void pd_hash_erase(Process *p, Eterm id, Eterm *ret)
{
    unsigned int hval;
    Eterm old;
    Eterm tmp;
    unsigned int range;

    *ret = am_undefined;
    if (p->dictionary == NULL) {
	return;
    }
    hval = pd_hash_value(p->dictionary, id);
    old = ARRAY_GET(p->dictionary, hval);
    if (is_boxed(old)) {	/* Tuple */
	ASSERT(is_tuple(old));
	if (EQ(tuple_val(old)[1], id)) {
	    array_put(&(p->dictionary), hval, NIL);
	    --(p->dictionary->numElements);
	    *ret = tuple_val(old)[2];
	}
    } else if (is_list(old)) {
	/* Find cons cell for identical value */
	Eterm* prev = &p->dictionary->data[hval];

	for (tmp = *prev; tmp != NIL; prev = &TCDR(tmp), tmp = *prev) {
	    if (EQ(tuple_val(TCAR(tmp))[1], id)) {
		*prev = TCDR(tmp);
		*ret = tuple_val(TCAR(tmp))[2];
		--(p->dictionary->numElements);
	    }
	}

	/* If there is only one element left in the list we must remove the list. */
	old = ARRAY_GET(p->dictionary, hval);
	ASSERT(is_list(old));
	if (is_nil(TCDR(old))) {
	    array_put(&p->dictionary, hval, TCAR(old));
	}
    } else if (is_not_nil(old)) {
#ifdef DEBUG
	erts_fprintf(stderr,
		     "Process dictionary for process %T is broken, trying to "
		     "display term found in line %d:\n"
		     "%T\n", p->common.id, __LINE__, old);
#endif
	erl_exit(1, "Damaged process dictionary found during erase/1.");
    }
    if ((range = HASH_RANGE(p->dictionary)) > INITIAL_SIZE && 
	range / 2  > (p->dictionary->numElements)) {
	shrink(p, ret);
    }
}
Пример #3
0
Eterm erts_pd_hash_get(Process *p, Eterm id) 
{
    unsigned int hval;
    Eterm tmp;
    ProcDict *pd = p->dictionary;

    if (pd == NULL)
	return am_undefined;
    hval = pd_hash_value(pd, id);
    tmp = ARRAY_GET(pd, hval);
    if (is_boxed(tmp)) {	/* Tuple */
	ASSERT(is_tuple(tmp));
	if (EQ(tuple_val(tmp)[1], id)) {
	    return tuple_val(tmp)[2];
	}
    } else if (is_list(tmp)) {
	for (; tmp != NIL && !EQ(tuple_val(TCAR(tmp))[1], id); tmp = TCDR(tmp)) {
	    ;
	}
	if (tmp != NIL) {
	    return tuple_val(TCAR(tmp))[2];
	}
    } else if (is_not_nil(tmp)) {
#ifdef DEBUG
	erts_fprintf(stderr,
		     "Process dictionary for process %T is broken, trying to "
		     "display term found in line %d:\n"
		     "%T\n", p->common.id, __LINE__, tmp);
#endif
	erl_exit(1, "Damaged process dictionary found during get/1.");
    }
    return am_undefined;
}
Пример #4
0
void stringheap::clear()
{
	ARRAY_CLEAR(m_todelete);
    for (const fkhashmap<const char *, stringele>::ele * p = m_shh.first(); p != 0; p = m_shh.next())
    {
        stringele * e = p->t;
		if (!e->sysref)
		{
			safe_fkfree(m_fk, e->s);
			if (ARRAY_SIZE(m_todelete) >= ARRAY_MAX_SIZE(m_todelete))
			{
			    size_t newsize = ARRAY_MAX_SIZE(m_todelete) + 1 + ARRAY_MAX_SIZE(m_todelete) * (m_fk->cfg.array_grow_speed) / 100;
		        ARRAY_GROW(m_todelete, newsize, const char *);
		    }
			ARRAY_PUSH_BACK(m_todelete);
			ARRAY_BACK(m_todelete) = p->k;
		}
    }
    
	for (int i = 0; i < (int)ARRAY_SIZE(m_todelete); i++)
	{
		const char * str = ARRAY_GET(m_todelete, i);
		m_shh.del(str);
	}
	
	ARRAY_CLEAR(m_todelete);
}
Пример #5
0
static Eterm pd_hash_get_keys(Process *p, Eterm value) 
{
    Eterm *hp;
    Eterm res = NIL;
    ProcDict *pd = p->dictionary;
    unsigned int i, num;
    Eterm tmp, tmp2;

    if (pd == NULL) {
	return res;
    }

    num = HASH_RANGE(pd);
    for (i = 0; i < num; ++i) {
	tmp = ARRAY_GET(pd, i);
	if (is_boxed(tmp)) {
	    ASSERT(is_tuple(tmp));
	    if (EQ(tuple_val(tmp)[2], value)) {
		hp = HAlloc(p, 2);
		res = CONS(hp, tuple_val(tmp)[1], res);
	    }
	} else if (is_list(tmp)) {
	    while (tmp != NIL) {
		tmp2 = TCAR(tmp);
		if (EQ(tuple_val(tmp2)[2], value)) {
		    hp = HAlloc(p, 2);
		    res = CONS(hp, tuple_val(tmp2)[1], res);
		}
		tmp = TCDR(tmp);
	    }
	}
    }
    return res;
}
Пример #6
0
static Eterm
pd_hash_get_all(Process *p, ProcDict *pd)
{
    Eterm* hp;
    Eterm res = NIL;
    Eterm tmp, tmp2;
    unsigned int i;
    unsigned int num;

    if (pd == NULL) {
	return res;
    }
    num = HASH_RANGE(pd);
    hp = HAlloc(p, pd->numElements * 2);
    
    for (i = 0; i < num; ++i) {
	tmp = ARRAY_GET(pd, i);
	if (is_boxed(tmp)) {
	    ASSERT(is_tuple(tmp));
	    res = CONS(hp, tmp, res);
	    hp += 2;
	} else if (is_list(tmp)) {
	    while (tmp != NIL) {
		tmp2 = TCAR(tmp);
		res = CONS(hp, tmp2, res);
		hp += 2;
		tmp = TCDR(tmp);
	    }
	}
    }
    return res;
}
Пример #7
0
/* 
 * Called from process_info/1,2.
 */
Eterm erts_dictionary_copy(Process *p, ProcDict *pd) 
{
    Eterm* hp;
    Eterm* heap_start;
    Eterm res = NIL;
    Eterm tmp, tmp2;
    unsigned int i, num;

    if (pd == NULL) {
	return res;
    }

    PD_CHECK(pd);
    num = HASH_RANGE(pd);
    heap_start = hp = (Eterm *) erts_alloc(ERTS_ALC_T_TMP,
					   sizeof(Eterm) * pd->numElements * 2);
    for (i = 0; i < num; ++i) {
	tmp = ARRAY_GET(pd, i);
	if (is_boxed(tmp)) {
	    ASSERT(is_tuple(tmp));
	    res = CONS(hp, tmp, res);
	    hp += 2;
	} else if (is_list(tmp)) {
	    while (tmp != NIL) {
		tmp2 = TCAR(tmp);
		res = CONS(hp, tmp2, res);
		hp += 2;
		tmp = TCDR(tmp);
	    }
	}
    }
    res = copy_object(res, p);
    erts_free(ERTS_ALC_T_TMP, (void *) heap_start);
    return res;
}
Пример #8
0
/* state_machine_transition takes the state of the current state_machine to the
	next state as dictated by the state transition matrix. It sets the current
	state to this new state. */
int state_machine_transition(state_machine_t machine, transition_e t){

	transitioning_t transitioning = ARRAY_GET(machine->transition_matrix, machine->current_state, t);	
	machine->current_state = transitioning->next_state;

	if(transitioning->action)
		return transitioning->action(machine->argument);	
	return NO_TRANSITION;
}
Пример #9
0
static void
async_free_handles (array_cmd_async * async_handles)
{
  command_async *cmd_async;
  int i;

  for (i = 0; i < ARRAY_N (async_handles); i++)
    {
      cmd_async = ARRAY_GET (async_handles, i);
      cmd_free_async (cmd_async);
    }
}
Пример #10
0
/*
 * Called from break handler
 */
void
erts_dictionary_dump(int to, void *to_arg, ProcDict *pd)
{
    unsigned int i;
#ifdef DEBUG

    /*PD_CHECK(pd);*/
    if (pd == NULL)
	return;
    erts_print(to, to_arg, "(size = %d, used = %d, homeSize = %d, "
	       "splitPosition = %d, numElements = %d)\n",
	       pd->size, pd->used, pd->homeSize, 
	       pd->splitPosition, (unsigned int) pd->numElements);
    for (i = 0; i < HASH_RANGE(pd); ++i) {
	erts_print(to, to_arg, "%d: %T\n", i, ARRAY_GET(pd, i));
    }

#else /* !DEBUG */

    int written = 0;
    Eterm t;

    erts_print(to, to_arg, "[");
    if (pd != NULL) {
	for (i = 0; i < HASH_RANGE(pd); ++i) {
	    t = ARRAY_GET(pd, i);
	    if (is_list(t)) {
		for (; t != NIL; t = TCDR(t)) {
		    erts_print(to, to_arg, written++ ? ",%T" : "%T", TCAR(t));
		}
	    } else if (is_tuple(t)) {
		erts_print(to, to_arg, written++ ? ",%T" : "%T", t);
	    }
	}
    }
    erts_print(to, to_arg, "]");

#endif /* DEBUG (else) */
}
Пример #11
0
void processor::run()
{
	while (m_routine_num > 0)
	{
		for (int i = 0; i < (int)ARRAY_SIZE(m_pl.l); i++)
		{
			pool<routine>::node * n = ARRAY_GET(m_pl.l, i);
			if (UNLIKE(!n))
			{
				continue;
			}
			// 注意:此函数内部可能会调用到add接口
			ROUTINE_RUN(n->t, m_fk->cfg.per_frame_cmd_num);
			if (UNLIKE(ROUTINE_ISEND(n->t)))
			{
				POOL_PUSH(m_pl.p, n);
				ARRAY_GET(m_pl.l, i) = 0;
				m_routine_num--;
			}
		}
	}
	ARRAY_CLEAR(m_pl.l);
}
Пример #12
0
void
erts_deep_dictionary_dump(int to, void *to_arg,
			  ProcDict* pd, void (*cb)(int, void *, Eterm))
{
    unsigned int i;
    Eterm t;

    if (pd != NULL) {
	for (i = 0; i < HASH_RANGE(pd); ++i) {
	    t = ARRAY_GET(pd, i);
	    if (is_list(t)) {
		for (; t != NIL; t = TCDR(t)) {
		    (*cb)(to, to_arg, TCAR(t));
		}
	    } else if (is_tuple(t)) {
		(*cb)(to, to_arg, t);
	    }
	}
    }
}
Пример #13
0
static struct RequestData send_nodes(uint8_t type, Array ip4array) {
	assert(ip4array);
	assert(Array_checkType(ip4array, sizeof(uint32_t)));

	size_t count = Array_length(ip4array);
	if (count == 0) {
		struct RequestData result = {0, NULL};
		return result;
	}

	int len = count * (ITEM_SIZE) + 5;
	uint8_t *buffer = malloc(len);
	uint8_t *ptr = buffer;

	AddToBuffer8(&ptr, type);
	AddToBuffer32(&ptr, count);
	for (int i = 0; i < count; i++) {
		AddToBuffer32NoOrder(&ptr, ARRAY_GET(ip4array, uint32_t, i));
	}

	struct RequestData result = {len, buffer};
	return result;
}
Пример #14
0
static void grow(Process *p)
{
    unsigned int i,j;
    unsigned int steps = p->dictionary->homeSize / 5;
    Eterm l1,l2;
    Eterm l;
    Eterm *hp;
    unsigned int pos;
    unsigned int homeSize;
    int needed = 0;
    ProcDict *pd;
#ifdef DEBUG
    Eterm *hp_limit;
#endif

    HDEBUGF(("grow: steps = %d", steps));
    if (steps == 0)
	steps = 1;
    /* Dont grow over MAX_HASH */
    if ((MAX_HASH - steps) <= HASH_RANGE(p->dictionary)) {
	return;
    }

    /*
     * Calculate total number of heap words needed, and garbage collect
     * if necessary.
     */

    pd = p->dictionary;
    pos = pd->splitPosition;
    homeSize = pd->homeSize;
    for (i = 0; i < steps; ++i) {
	if (pos == homeSize) {
	    homeSize *= 2;
	    pos = 0;
	}
	l = ARRAY_GET(pd, pos);
	pos++;
	if (is_not_tuple(l)) {
	    while (l != NIL) {
		needed += 2;
		l = TCDR(l);
	    }
	}
    }
    if (HeapWordsLeft(p) < needed) {
	BUMP_REDS(p, erts_garbage_collect(p, needed, 0, 0));
    }
#ifdef DEBUG
    hp_limit = p->htop + needed;
#endif

    /*
     * Now grow.
     */

    for (i = 0; i < steps; ++i) {
	ProcDict *pd = p->dictionary;
	if (pd->splitPosition == pd->homeSize) {
	    pd->homeSize *= 2;
	    pd->splitPosition = 0;
	}
	pos = pd->splitPosition;
	++pd->splitPosition; /* For the hashes */
	l = ARRAY_GET(pd, pos);
	if (is_tuple(l)) {
	    if (pd_hash_value(pd, tuple_val(l)[1]) != pos) {
		array_put(&(p->dictionary), pos + 
			  p->dictionary->homeSize, l);
		array_put(&(p->dictionary), pos, NIL);
	    }
	} else {
	    l2 = NIL;
	    l1 = l;
	    for (j = 0; l1 != NIL; l1 = TCDR(l1))
		j += 2;
	    hp = HeapOnlyAlloc(p, j);
	
	    while (l != NIL) {
		if (pd_hash_value(pd, tuple_val(TCAR(l))[1]) == pos) 
		    l1 = CONS(hp, TCAR(l), l1);
		else
		    l2 = CONS(hp, TCAR(l), l2);
		hp += 2;
		l = TCDR(l);
	    }
	    if (l1 != NIL && TCDR(l1) == NIL)
		l1 = TCAR(l1);
	    if (l2 != NIL && TCDR(l2) == NIL)
		l2 = TCAR(l2);
	    ASSERT(hp <= hp_limit);
	    /* After array_put pd is no longer valid */
	    array_put(&(p->dictionary), pos, l1);
	    array_put(&(p->dictionary), pos + 
		      p->dictionary->homeSize, l2);
	}
    }

#ifdef HARDDEBUG
    dictionary_dump(p->dictionary,CERR);
#endif
}
Пример #15
0
static void shrink(Process *p, Eterm* ret) 
{
    unsigned int range = HASH_RANGE(p->dictionary);
    unsigned int steps = (range*3) / 10;
    Eterm hi, lo, tmp;
    unsigned int i;
    Eterm *hp;
#ifdef DEBUG
    Eterm *hp_limit;
#endif

    if (range - steps < INITIAL_SIZE) {
	steps = range - INITIAL_SIZE; 
    }

    for (i = 0; i < steps; ++i) {
	ProcDict *pd = p->dictionary;
	if (pd->splitPosition == 0) {
	    pd->homeSize /= 2;
	    pd->splitPosition = pd->homeSize;
	}
	--(pd->splitPosition);
	hi = ARRAY_GET(pd, (pd->splitPosition + pd->homeSize));
	lo = ARRAY_GET(pd, pd->splitPosition);
	if (hi != NIL) {
	    if (lo == NIL) {
		array_put(&(p->dictionary), pd->splitPosition, hi);
	    } else {
		int needed = 4;
		if (is_list(hi) && is_list(lo)) {
		    needed = 2*erts_list_length(hi);
		}
		if (HeapWordsLeft(p) < needed) {
		    BUMP_REDS(p, erts_garbage_collect(p, needed, ret, 1));
		    hi = pd->data[(pd->splitPosition + pd->homeSize)];
		    lo = pd->data[pd->splitPosition];
		}
#ifdef DEBUG
		hp_limit = p->htop + needed;
#endif
		if (is_tuple(lo)) {
		    if (is_tuple(hi)) {
			hp = HeapOnlyAlloc(p, 4);
			tmp = CONS(hp, hi, NIL);
			hp += 2;
			array_put(&(p->dictionary), pd->splitPosition, 
				  CONS(hp,lo,tmp));
			hp += 2;
			ASSERT(hp <= hp_limit);
		    } else { /* hi is a list */
			hp = HeapOnlyAlloc(p, 2);
			array_put(&(p->dictionary), pd->splitPosition, 
				  CONS(hp, lo, hi));
			hp += 2;
			ASSERT(hp <= hp_limit);
		    }
		} else { /* lo is a list */
		    if (is_tuple(hi)) {
			hp = HeapOnlyAlloc(p, 2);
			array_put(&(p->dictionary), pd->splitPosition, 
				  CONS(hp, hi, lo));
			hp += 2;
			ASSERT(hp <= hp_limit);

		    } else { /* Two lists */
			hp = HeapOnlyAlloc(p, needed);
			for (tmp = hi; tmp != NIL; tmp = TCDR(tmp)) {
			    lo = CONS(hp, TCAR(tmp), lo);
			    hp += 2;
			}
			ASSERT(hp <= hp_limit);
			array_put(&(p->dictionary), pd->splitPosition, lo);
		    }
		}
	    }
	}
	array_put(&(p->dictionary), (pd->splitPosition + pd->homeSize), NIL);
    }
    if (HASH_RANGE(p->dictionary) <= (p->dictionary->size / 4)) {
	array_shrink(&(p->dictionary), (HASH_RANGE(p->dictionary) * 3) / 2);
    }
}
Пример #16
0
static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
{ 
    unsigned int hval;
    Eterm *hp;
    Eterm tpl;
    Eterm old;
    Eterm tmp;
    int needed;
    int i = 0;
#ifdef DEBUG
    Eterm *hp_limit;
#endif

    if (p->dictionary == NULL) {
	/* Create it */
	array_put(&(p->dictionary), INITIAL_SIZE - 1, NIL);
	p->dictionary->homeSize = INITIAL_SIZE;
    }	
    hval = pd_hash_value(p->dictionary, id);
    old = ARRAY_GET(p->dictionary, hval);

    /*
     * Calculate the number of heap words needed and garbage
     * collect if necessary. (Might be a slight overestimation.)
     */
    needed = 3;			/* {Key,Value} tuple */
    if (is_boxed(old)) {
	/*
	 * We don't want to compare keys twice, so we'll always
	 * reserve the space for two CONS cells.
	 */
	needed += 2+2;
    } else if (is_list(old)) {
	i = 0;
	for (tmp = old; tmp != NIL && !EQ(tuple_val(TCAR(tmp))[1], id); tmp = TCDR(tmp)) {
	    ++i;
	}
	if (is_nil(tmp)) {
	    i = -1;
	    needed += 2;
	} else {
	    needed += 2*(i+1);
	}
    }
    if (HeapWordsLeft(p) < needed) {
	Eterm root[3];
	root[0] = id;
	root[1] = value;
	root[2] = old;
	BUMP_REDS(p, erts_garbage_collect(p, needed, root, 3));
	id = root[0];
	value = root[1];
	old = root[2];
    }
#ifdef DEBUG
    hp_limit = p->htop + needed;
#endif

    /*
     * Create the {Key,Value} tuple.
     */
    hp = HeapOnlyAlloc(p, 3);
    tpl = TUPLE2(hp, id, value);

    /*
     * Update the dictionary.
     */
    if (is_nil(old)) {
	array_put(&(p->dictionary), hval, tpl);
	++(p->dictionary->numElements);
    } else if (is_boxed(old)) {
	ASSERT(is_tuple(old));
	if (EQ(tuple_val(old)[1],id)) {
	    array_put(&(p->dictionary), hval, tpl);
	    return tuple_val(old)[2];
	} else {
	    hp = HeapOnlyAlloc(p, 4);
	    tmp = CONS(hp, old, NIL);
	    hp += 2;
	    ++(p->dictionary->numElements);
	    array_put(&(p->dictionary), hval, CONS(hp, tpl, tmp));
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	}
    } else if (is_list(old)) {
	if (i == -1) {
	    /*
	     * New key. Simply prepend the tuple to the beginning of the list.
	     */
	    hp = HeapOnlyAlloc(p, 2);
	    array_put(&(p->dictionary), hval, CONS(hp, tpl, old));
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	    ++(p->dictionary->numElements);
	} else {
	    /*
	     * i = Number of CDRs to skip to reach the changed element in the list.
	     *
	     * Replace old value in list. To avoid pointers from the old generation
	     * to the new, we must rebuild the list from the beginning up to and
	     * including the changed element.
	     */
	    Eterm nlist;
	    int j;

	    hp = HeapOnlyAlloc(p, (i+1)*2);
	    
	    /* Find the list element to change. */
	    for (j = 0, nlist = old; j < i; j++, nlist = TCDR(nlist)) {
		;
	    }
	    ASSERT(EQ(tuple_val(TCAR(nlist))[1], id));
	    nlist = TCDR(nlist); /* Unchanged part of list. */

	    /* Rebuild list before the updated element. */
	    for (tmp = old; i-- > 0; tmp = TCDR(tmp)) {
		nlist = CONS(hp, TCAR(tmp), nlist);
		hp += 2;
	    }
	    ASSERT(EQ(tuple_val(TCAR(tmp))[1], id));

	    /* Put the updated element first in the new list. */
	    nlist = CONS(hp, tpl, nlist);
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	    array_put(&(p->dictionary), hval, nlist);
	    return tuple_val(TCAR(tmp))[2];
	}
    } else {
#ifdef DEBUG
	erts_fprintf(stderr,
		     "Process dictionary for process %T is broken, trying to "
		     "display term found in line %d:\n"
		     "%T\n", p->common.id, __LINE__, old);
#endif

	erl_exit(1, "Damaged process dictionary found during put/2.");
    }
    if (HASH_RANGE(p->dictionary) <= p->dictionary->numElements) {
	grow(p);
    }
    return am_undefined;
}
Пример #17
0
// range
void buildin_range(fake * fk, interpreter * inter)
{
	BIF_CHECK_ARG_NUM(2);

	// pos
	int pos = fkpspop<int>(fk);

	// container
	bool err = false;
	variant * v = 0;
	PS_POP_AND_GET(fk->ps, v);

	if (v->type == variant::STRING)
	{
		if (pos >= 0 && pos < (int)v->data.str->sz)
		{
			char data[2];
			data[0] = v->data.str->s[pos];
			data[1] = 0;
			fkpspush<const char *>(fk, data);
		}
		else
		{
			fkpspush<const char *>(fk, "");
		}
	}
	else if (v->type == variant::ARRAY)
	{
		if (pos >= 0 && pos < (int)ARRAY_SIZE(v->data.va->va) && ARRAY_GET(v->data.va->va, pos))
		{
			variant * ret = 0;
			PS_PUSH_AND_GET(fk->ps, ret);
			if (ARRAY_GET(v->data.va->va, pos))
			{
				*ret = *(ARRAY_GET(v->data.va->va, pos));
			}
			else
			{
				*ret = NILV;
			}
		}
		else
		{
			fkpspush<bool>(fk, false);
		}
	}
	else if (v->type == variant::MAP)
	{
		if (pos >= 0 && pos < (int)v->data.vm->vm.size())
		{
			variant * key = 0;
			PS_PUSH_AND_GET(fk->ps, key);
			
			variant * value = 0;
			PS_PUSH_AND_GET(fk->ps, value);
			
			const fkhashmap<variant, variant *>::ele * e = v->data.vm->vm.at(pos);
			*key = e->k;
			*value = *(*e->t);
		}
		else
		{
			fkpspush<bool>(fk, false);
			fkpspush<bool>(fk, false);
		}
	}
	else
	{
		fkpspush<bool>(fk, false);
	}
}
Пример #18
0
static void
read_file (struct buffer *buffer)
{
  int fd;
  void *map = MAP_FAILED;

  struct line line_buffer;
  size_t line_length;

  const char *line_begin, *line_end, *end;

  char newline[8];
  size_t newline_length = 0;

  off_t size = 0;
  uint32_t digest = 0;

  if (-1 == (fd = open (buffer->path + 7, O_RDONLY)))
    {
      if (errno != ENOENT)
        {
          set_error (_("Failed to open '%s' for reading: %s"),
                     buffer->path, strerror (errno));

          goto failed;
        }

      buffer->charset = CHARSET_UTF8;
      buffer->line_ending = LINE_ENDING_LF;

      buffer->log = log_open (buffer->undo_path, buffer, 0);

      if (!buffer->log)
        goto failed;

      return;
    }

  if (-1 == (size = lseek (fd, 0, SEEK_END)))
    {
      static const size_t readbuf_size = 65536;
      char *readbuf;
      const char *begin, *end;
      int ret;

      struct line encoded_buffer;

      readbuf = malloc (readbuf_size);

      ARRAY_INIT (&encoded_buffer);

      while (0 < (ret = read (fd, readbuf, readbuf_size)))
        {
          digest = crc32 (digest, readbuf, ret);

          if (!buffer->charset)
            {
              charset_detect (&buffer->charset, &buffer->line_ending, readbuf, ret);

              newline_length = charset_encode_line_ending (newline, buffer->charset, buffer->line_ending);
            }

          begin = readbuf;
          end = readbuf + ret;

          while (begin != end)
            {
              line_end = memmem (begin, end - begin, newline, newline_length);

              if (!line_end)
                {
                  ARRAY_ADD_SEVERAL (&encoded_buffer, begin, end - begin);

                  break;
                }

              ARRAY_ADD_SEVERAL (&encoded_buffer, begin, line_end - begin);

              begin = line_end + newline_length;

              line_length = charset_decode (0, buffer->charset,
                                            &ARRAY_GET (&encoded_buffer, 0),
                                            ARRAY_COUNT (&encoded_buffer));

              ARRAY_INIT (&line_buffer);
              ARRAY_RESERVE (&line_buffer, line_length);

              charset_decode (&ARRAY_GET (&line_buffer, 0), buffer->charset,
                              &ARRAY_GET (&encoded_buffer, 0),
                              ARRAY_COUNT (&encoded_buffer));

              ARRAY_COUNT (&line_buffer) = line_length;

              pthread_mutex_lock (&buffer->lock);

              ARRAY_ADD (&buffer->lines, line_buffer);

              pthread_mutex_unlock (&buffer->lock);

              ARRAY_RESET (&encoded_buffer);
            }
        }
    }
  else if (size > 0)
    {
      if (MAP_FAILED == (map = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0)))
        {
          set_error (_("Failed to mmap '%s': %s"), buffer->path, strerror (errno));

          goto failed;
        }

      digest = crc32 (0, map, size);

      charset_detect (&buffer->charset, &buffer->line_ending, map, size);

      newline_length = charset_encode_line_ending (newline, buffer->charset, buffer->line_ending);

      end = (char *) map + size;

      for (line_begin = map; line_begin < end; line_begin = line_end + newline_length)
        {
          line_end = memmem (line_begin, end - line_begin,
                             newline, newline_length);

          if (!line_end)
            line_end = end;

          line_length = charset_decode (0, buffer->charset, line_begin,
                                        line_end - line_begin);

          ARRAY_INIT (&line_buffer);
          ARRAY_RESERVE (&line_buffer, line_length);

          charset_decode (&ARRAY_GET (&line_buffer, 0), buffer->charset,
                          line_begin, line_end - line_begin);

          ARRAY_COUNT (&line_buffer) = line_length;

          pthread_mutex_lock (&buffer->lock);

          ARRAY_ADD (&buffer->lines, line_buffer);

          pthread_mutex_unlock (&buffer->lock);

          /* XXX: Avoid issuing full repaints when nothing really happens onscreen */

          gui_repaint ();
        }
    }
  else
    {
      buffer->charset = CHARSET_UTF8;
      buffer->line_ending = LINE_ENDING_LF;
    }

  buffer->log = log_open (buffer->undo_path, buffer, digest);

failed:

  if (fd != -1)
    close (fd);

  if (map != MAP_FAILED)
    munmap (map, size);
}
Пример #19
0
void interpreter::call(const variant & func, int retnum, int * retpos)
{
	fake * fk = m_fk;
	paramstack * ps = getps(m_fk);
	const funcunion * f = m_fk->fm.get_func(func);
	bool & err = m_isend;
	USE(err);
	if (UNLIKE(!f))
	{
		FKERR("fkrun no func %s fail", vartostring(&func).c_str());
		m_isend = true;
		seterror(m_fk, efk_run_no_func_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "fkrun no func %s fail", vartostring(&func).c_str());
		return;
	}

	// 常规函数
	if (LIKE(f->havefb))
	{
		const func_binary * fb = &f->fb;
		variant * v = 0;

		// 准备栈大小
		int needsize = m_sp + BP_SIZE + retnum + FUNC_BINARY_MAX_STACK(*fb);
		if (UNLIKE(needsize > (int)ARRAY_MAX_SIZE(m_stack)))
		{
			int newsize = needsize + needsize * m_fk->cfg.array_grow_speed / 100;
			ARRAY_GROW(m_stack, newsize, variant);
		}

		// 老的bp
		int oldbp = m_bp;
		m_bp = m_sp;

		// 记录返回位置
		for (int i = 0; i < retnum; i++)
		{
			v = &ARRAY_GET(m_stack, m_bp);
			v->type = variant::NIL;
			v->data.buf = retpos[i];
			m_bp++;
		}

		// 记录返回值数目
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = retnum;
		m_bp++;

		// 记录老的ip
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = m_ip;
		m_bp++;

		// 记录profile
		if (UNLIKE(m_fk->pf.isopen()))
		{
			v = &ARRAY_GET(m_stack, m_bp);
			v->data.buf = fkgetmstick();
		}
		v->type = variant::NIL;
		m_bp++;

		// 记录老的fb
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = (uint64_t)m_fb;
		m_bp++;

		// 记录老的bp
		v = &ARRAY_GET(m_stack, m_bp);
		v->type = variant::NIL;
		v->data.buf = oldbp;
		m_bp++;

		// 设置sp
		m_sp = m_bp + FUNC_BINARY_MAX_STACK(*fb);
		
		if (UNLIKE((int)ps->m_variant_list_num != FUNC_BINARY_PARAMNUM(*fb)))
		{
			FKERR("call func %s param not match", vartostring(&func).c_str());
			m_isend = true;
			seterror(m_fk, efk_run_param_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "call func %s param not match", vartostring(&func).c_str());
			return;
		}

		assert(FUNC_BINARY_PARAMNUM(*fb) <= REAL_MAX_FAKE_PARAM_NUM);
		assert(m_bp + FUNC_BINARY_PARAMNUM(*fb) <= (int)ARRAY_MAX_SIZE(m_stack));

		// 分配入参
		memcpy(&ARRAY_GET(m_stack, m_bp), ps->m_variant_list, FUNC_BINARY_PARAMNUM(*fb) * sizeof(variant));
		PS_CLEAR(*ps);

		// 重置ret
		V_SET_NIL(&m_ret[0]);

		// 标记
		FUNC_BINARY_USE(*fb)++;

		// 新函数
		m_fb = fb;
		m_ip = 0;

		return;
	}

	// 记录profile
	uint32_t s = 0;
	if (UNLIKE(m_fk->pf.isopen()))
	{
		s = fkgetmstick();
	}

	// 绑定函数
	if (f->haveff)
	{
		BIND_FUNC_CALL(f, this);
		FKLOG("call C func %s", vartostring(&func).c_str());
	}
	// 内置函数
	else if (f->havebif)
	{
		BUILDIN_FUNC_CALL(f, this);
		FKLOG("call buildin func %s", vartostring(&func).c_str());
	}
	else
	{
		assert(0);
		FKERR("fkrun no inter func %s fail", vartostring(&func).c_str());
		m_isend = true;
		seterror(m_fk, efk_run_no_func_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "fkrun no inter func %s fail", vartostring(&func).c_str());
		return;
	}

	// 返回值
	// 这种情况是直接跳过脚本调用了C函数
	if (UNLIKE(BP_END(m_bp)))
	{
		variant * cret;
		PS_POP_AND_GET(*ps, cret);
		m_isend = true;
		// 直接塞返回值
		m_ret[0] = *cret;
	}
	// 否则塞到当前堆栈上
	else
	{
		// 检查返回值数目对不对
		if (UNLIKE((int)ps->m_variant_list_num != retnum))
		{
			FKERR("native func %s param not match, give %d need %d", vartostring(&func).c_str(), (int)ps->m_variant_list_num, retnum);
			m_isend = true;
			seterror(m_fk, efk_run_param_error, fkgetcurfile(fk), fkgetcurline(fk), fkgetcurfunc(fk), "native func %s param not match, give %d need %d", vartostring(&func).c_str(), (int)ps->m_variant_list_num, retnum);
			return;
		}
		
		// 塞返回值
		for (int i = 0; i < retnum; i++)
		{
			variant * ret;
			GET_VARIANT(*m_fb, m_bp, ret, retpos[i]);
			
			variant * cret;
			PS_GET(*ps, cret, i);
			
			*ret = *cret;
		}
	}
	
	if (UNLIKE(m_fk->pf.isopen()))
	{
		const char * name = 0;
		V_GET_STRING(&func, name);
		m_fk->pf.add_func_sample(name, fkgetmstick() - s);
	}

	return;
}