Пример #1
0
static void
stack_trace_dump(int to, void *to_arg, Eterm *sp) {
    Eterm x = *sp;
    if (is_CP(x)) {
        erts_print(to, to_arg, "%p:", sp);
        erts_print(to, to_arg, "SReturn addr 0x%X (", cp_val(x));
        print_function_from_pc(to, to_arg, cp_val(x));
        erts_print(to, to_arg, ")\n");
    }
}
Пример #2
0
static __inline__ void hipe_pop_beam_trap_frame(Process *p)
{
    ASSERT(p->stop[1] == hipe_beam_catch_throw);
    p->cp = cp_val(p->stop[0]);
    --p->catches;
    p->stop += 2;
}
Пример #3
0
static void print_beam_cp(Eterm *pos, Eterm val)
{
    printf(" |%s|%s| BEAM ACTIVATION RECORD\r\n", dashes, dashes);
    printf(" | 0x%0*lx | 0x%0*lx | BEAM PC ",
	   2*(int)sizeof(long), (unsigned long)pos,
	   2*(int)sizeof(long), (unsigned long)val);
    print_beam_pc(cp_val(val));
    printf("\r\n");
}
Пример #4
0
static int
stack_element_dump(int to, void *to_arg, Eterm* sp, int yreg)
{
    Eterm x = *sp;

    if (yreg < 0 || is_CP(x)) {
        erts_print(to, to_arg, "%p:", sp);
    } else {
        erts_print(to, to_arg, "y%d:", yreg);
        yreg++;
    }

    if (is_CP(x)) {
        erts_print(to, to_arg, "SReturn addr 0x%X (", cp_val(x));
        print_function_from_pc(to, to_arg, cp_val(x));
        erts_print(to, to_arg, ")\n");
        yreg = 0;
    } else if is_catch(x) {
        erts_print(to, to_arg, "SCatch 0x%X (", catch_pc(x));
        print_function_from_pc(to, to_arg, catch_pc(x));
        erts_print(to, to_arg, ")\n");
    } else {
Пример #5
0
void
dbg_bt(Process* p, Eterm* sp)
{
    Eterm* stack = STACK_START(p);

    while (sp < stack) {
	if (is_CP(*sp)) {
	    BeamInstr* addr = find_function_from_pc(cp_val(*sp));
	    if (addr)
		erts_fprintf(stderr,
			     HEXF ": %T:%T/%bpu\n",
			     addr, (Eterm) addr[0], (Eterm) addr[1], addr[2]);
	}
	sp++;
    }
}
Пример #6
0
void
dbg_bt(Process* p, Eterm* sp)
{
    Eterm* stack = STACK_START(p);

    while (sp < stack) {
	if (is_CP(*sp)) {
	    ErtsCodeMFA* cmfa = find_function_from_pc(cp_val(*sp));
	    if (cmfa)
		erts_fprintf(stderr,
			     HEXF ": %T:%T/%bpu\n",
			     &cmfa->module, cmfa->module,
                             cmfa->function, cmfa->arity);
	}
	sp++;
    }
}
Пример #7
0
static Eterm
check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls)
{
    BeamInstr* start;
    char* literals;
    Uint lit_bsize;
    char* mod_start;
    Uint mod_size;
    Eterm* sp;
    int done_gc = 0;
    int need_gc = 0;
    ErtsMessage *msgp;
    ErlHeapFragment *hfrag;

#define ERTS_ORDINARY_GC__ (1 << 0)
#define ERTS_LITERAL_GC__  (1 << 1)

    /*
     * Pick up limits for the module.
     */
    start = (BeamInstr*) modp->old.code_hdr;
    mod_start = (char *) start;
    mod_size = modp->old.code_length;

    /*
     * Check if current instruction or continuation pointer points into module.
     */
    if (ErtsInArea(rp->i, mod_start, mod_size)
	|| ErtsInArea(rp->cp, mod_start, mod_size)) {
	return am_true;
    }

    /*
     * Check all continuation pointers stored on the stack.
     */
    for (sp = rp->stop; sp < STACK_START(rp); sp++) {
	if (is_CP(*sp) && ErtsInArea(cp_val(*sp), mod_start, mod_size)) {
	    return am_true;
	}
    }

    /* 
     * Check all continuation pointers stored in stackdump
     * and clear exception stackdump if there is a pointer
     * to the module.
     */
    if (rp->ftrace != NIL) {
	struct StackTrace *s;
	ASSERT(is_list(rp->ftrace));
	s = (struct StackTrace *) big_val(CDR(list_val(rp->ftrace)));
	if ((s->pc && ErtsInArea(s->pc, mod_start, mod_size)) ||
	    (s->current && ErtsInArea(s->current, mod_start, mod_size))) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	} else {
	    int i;
	    for (i = 0;  i < s->depth;  i++) {
		if (ErtsInArea(s->trace[i], mod_start, mod_size)) {
		    rp->freason = EXC_NULL;
		    rp->fvalue = NIL;
		    rp->ftrace = NIL;
		    break;
		}
	    }
	}
    }

    if (rp->flags & F_DISABLE_GC) {
	/*
	 * Cannot proceed. Process has disabled gc in order to
	 * safely leave inconsistent data on the heap and/or
	 * off heap lists. Need to wait for gc to be enabled
	 * again.
	 */ 
	return THE_NON_VALUE;
    }

    /*
     * Message queue can contains funs, but (at least currently) no
     * literals. If we got references to this module from the message
     * queue, a GC cannot remove these...
     */

    erts_smp_proc_lock(rp, ERTS_PROC_LOCK_MSGQ);
    ERTS_SMP_MSGQ_MV_INQ2PRIVQ(rp);
    erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MSGQ);

    literals = (char*) modp->old.code_hdr->literals_start;
    lit_bsize = (char*) modp->old.code_hdr->literals_end - literals;

    for (msgp = rp->msg.first; msgp; msgp = msgp->next) {
	if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG)
	    hfrag = &msgp->hfrag;
	else if (is_value(ERL_MESSAGE_TERM(msgp)) && msgp->data.heap_frag)
	    hfrag = msgp->data.heap_frag;
	else
	    continue;
	for (; hfrag; hfrag = hfrag->next) {
	    if (check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size))
		return am_true;
	    /* Should not contain any literals... */
	    ASSERT(!any_heap_refs(&hfrag->mem[0],
				  &hfrag->mem[hfrag->used_size],
                                  literals,
				  lit_bsize));
	}
    }

    while (1) {

	/* Check heap, stack etc... */
	if (check_mod_funs(rp, &rp->off_heap, mod_start, mod_size))
	    goto try_gc;
        if (!(flags & ERTS_CPC_COPY_LITERALS)) {
            /* Process ok. May contain old literals but we will be called
             * again before module is purged.
             */
            return am_false;
        }
	if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, literals, lit_bsize)) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	}
	if (any_heap_ref_ptrs(rp->stop, rp->hend, literals, lit_bsize))
	    goto try_literal_gc;
	if (any_heap_refs(rp->heap, rp->htop, literals, lit_bsize))
	    goto try_literal_gc;
	if (any_heap_refs(rp->old_heap, rp->old_htop, literals, lit_bsize))
	    goto try_literal_gc;

	/* Check dictionary */
	if (rp->dictionary) {
	    Eterm* start = ERTS_PD_START(rp->dictionary);
	    Eterm* end = start + ERTS_PD_SIZE(rp->dictionary);

	    if (any_heap_ref_ptrs(start, end, literals, lit_bsize))
		goto try_literal_gc;
	}

	/* Check heap fragments */
	for (hfrag = rp->mbuf; hfrag; hfrag = hfrag->next) {
	    Eterm *hp, *hp_end;
	    /* Off heap lists should already have been moved into process */
	    ASSERT(!check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size));

	    hp = &hfrag->mem[0];
	    hp_end = &hfrag->mem[hfrag->used_size];
	    if (any_heap_refs(hp, hp_end, literals, lit_bsize))
		goto try_literal_gc;
	}

#ifdef DEBUG
	/*
	 * Message buffer fragments should not have any references
	 * to literals, and off heap lists should already have
	 * been moved into process off heap structure.
	 */
	for (msgp = rp->msg_frag; msgp; msgp = msgp->next) {
	    if (msgp->data.attached == ERTS_MSG_COMBINED_HFRAG)
		hfrag = &msgp->hfrag;
	    else
		hfrag = msgp->data.heap_frag;
	    for (; hfrag; hfrag = hfrag->next) {
		Eterm *hp, *hp_end;
		ASSERT(!check_mod_funs(rp, &hfrag->off_heap, mod_start, mod_size));

		hp = &hfrag->mem[0];
		hp_end = &hfrag->mem[hfrag->used_size];
		ASSERT(!any_heap_refs(hp, hp_end, literals, lit_bsize));
	    }
	}

#endif

	return am_false;

    try_literal_gc:
	need_gc |= ERTS_LITERAL_GC__;

    try_gc:
	need_gc |= ERTS_ORDINARY_GC__;

	if ((done_gc & need_gc) == need_gc)
	    return am_true;

	if (!(flags & ERTS_CPC_ALLOW_GC))
	    return am_aborted;

	need_gc &= ~done_gc;

	/*
	 * Try to get rid of literals by by garbage collecting.
	 * Clear both fvalue and ftrace.
	 */

	rp->freason = EXC_NULL;
	rp->fvalue = NIL;
	rp->ftrace = NIL;

	if (need_gc & ERTS_ORDINARY_GC__) {
	    FLAGS(rp) |= F_NEED_FULLSWEEP;
	    *redsp += erts_garbage_collect_nobump(rp, 0, rp->arg_reg, rp->arity, fcalls);
	    done_gc |= ERTS_ORDINARY_GC__;
	}
	if (need_gc & ERTS_LITERAL_GC__) {
	    struct erl_off_heap_header* oh;
	    oh = modp->old.code_hdr->literals_off_heap;
	    *redsp += lit_bsize / 64; /* Need, better value... */
	    erts_garbage_collect_literals(rp, (Eterm*)literals, lit_bsize, oh);
	    done_gc |= ERTS_LITERAL_GC__;
	}
	need_gc = 0;
    }

#undef ERTS_ORDINARY_GC__
#undef ERTS_LITERAL_GC__

}
Пример #8
0
static Eterm
check_process_code(Process* rp, Module* modp)
{
    Eterm* start;
    char* mod_start;
    Uint mod_size;
    Eterm* end;
    Eterm* sp;
#ifndef HYBRID /* FIND ME! */
    ErlFunThing* funp;
    int done_gc = 0;
#endif

#define INSIDE(a) (start <= (a) && (a) < end)
    if (modp == NULL) {		/* Doesn't exist. */
	return am_false;
    } else if (modp->old_code == NULL) { /* No old code. */
	return am_false;
    }

    /*
     * Pick up limits for the module.
     */
    start = modp->old_code;
    end = (Eterm *)((char *)start + modp->old_code_length);
    mod_start = (char *) start;
    mod_size = modp->old_code_length;

    /*
     * Check if current instruction or continuation pointer points into module.
     */
    if (INSIDE(rp->i) || INSIDE(rp->cp)) {
	return am_true;
    }

    /*
     * Check all continuation pointers stored on the stack.
     */
    for (sp = rp->stop; sp < STACK_START(rp); sp++) {
	if (is_CP(*sp) && INSIDE(cp_val(*sp))) {
	    return am_true;
	}
    }

    /* 
     * Check all continuation pointers stored in stackdump
     * and clear exception stackdump if there is a pointer
     * to the module.
     */
    if (rp->ftrace != NIL) {
	struct StackTrace *s;
	ASSERT(is_list(rp->ftrace));
	s = (struct StackTrace *) big_val(CDR(list_val(rp->ftrace)));
	if ((s->pc && INSIDE(s->pc)) ||
	    (s->current && INSIDE(s->current))) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	} else {
	    int i;
	    for (i = 0;  i < s->depth;  i++) {
		if (INSIDE(s->trace[i])) {
		    rp->freason = EXC_NULL;
		    rp->fvalue = NIL;
		    rp->ftrace = NIL;
		    break;
		}
	    }
	}
    }

    /*
     * See if there are funs that refer to the old version of the module.
     */

#ifndef HYBRID /* FIND ME! */
 rescan:
    for (funp = MSO(rp).funs; funp; funp = funp->next) {
	Eterm* fun_code;

	fun_code = funp->fe->address;

	if (INSIDE((Eterm *) funp->fe->address)) {
	    if (done_gc) {
		return am_true;
	    } else {
		/*
		 * Try to get rid of this fun by garbage collecting.
		 * Clear both fvalue and ftrace to make sure they
		 * don't hold any funs.
		 */
		rp->freason = EXC_NULL;
		rp->fvalue = NIL;
		rp->ftrace = NIL;
		done_gc = 1;
                FLAGS(rp) |= F_NEED_FULLSWEEP;
		(void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
		goto rescan;
	    }
	}
    }
#endif

    /*
     * See if there are constants inside the module referenced by the process.
     */
    done_gc = 0;
    for (;;) {
	ErlMessage* mp;

	if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, mod_start, mod_size)) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	}
	if (any_heap_ref_ptrs(rp->stop, rp->hend, mod_start, mod_size)) {
	    goto need_gc;
	}
	if (any_heap_refs(rp->heap, rp->htop, mod_start, mod_size)) {
	    goto need_gc;
	}

	if (any_heap_refs(rp->old_heap, rp->old_htop, mod_start, mod_size)) {
	    goto need_gc;
	}

	if (rp->dictionary != NULL) {
	    Eterm* start = rp->dictionary->data;
	    Eterm* end = start + rp->dictionary->used;

	    if (any_heap_ref_ptrs(start, end, mod_start, mod_size)) {
		goto need_gc;
	    }
	}

	for (mp = rp->msg.first; mp != NULL; mp = mp->next) {
	    if (any_heap_ref_ptrs(mp->m, mp->m+2, mod_start, mod_size)) {
		goto need_gc;
	    }
	}
	break;

    need_gc:
	if (done_gc) {
	    return am_true;
	} else {
	    Eterm* literals;
	    Uint lit_size;

	    /*
	     * Try to get rid of constants by by garbage collecting.
	     * Clear both fvalue and ftrace.
	     */
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	    done_gc = 1;
	    FLAGS(rp) |= F_NEED_FULLSWEEP;
	    (void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
	    literals = (Eterm *) modp->old_code[MI_LITERALS_START];
	    lit_size = (Eterm *) modp->old_code[MI_LITERALS_END] - literals;
	    erts_garbage_collect_literals(rp, literals, lit_size);
	}
    }
    return am_false;
#undef INSIDE
}
Пример #9
0
/*
 * Entry point called by the trace wrap functions in erl_bif_wrap.c
 *
 * The trace wrap functions are themselves called through the export
 * entries instead of the original BIF functions.
 */
Eterm
erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr* I)
{
    Eterm result;
    Eterm (*func)(Process*, Eterm*, BeamInstr*);
    Export* ep = bif_export[bif_index];
    Uint32 flags = 0, flags_meta = 0;
    ErtsTracer meta_tracer = erts_tracer_nil;
    int applying = (I == &(ep->code[3])); /* Yup, the apply code for a bif
					   * is actually in the
					   * export entry */
    BeamInstr *cp = p->cp;
    GenericBp* g;
    GenericBpData* bp = NULL;
    Uint bp_flags = 0;

    ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);

    g = (GenericBp *) ep->fake_op_func_info_for_hipe[1];
    if (g) {
	bp = &g->data[erts_active_bp_ix()];
	bp_flags = bp->flags;
    }

    /*
     * Make continuation pointer OK, it is not during direct BIF calls,
     * but it is correct during apply of bif.
     */
    if (!applying) {
	p->cp = I;
    }
    if (bp_flags & (ERTS_BPF_LOCAL_TRACE|ERTS_BPF_GLOBAL_TRACE) &&
	IS_TRACED_FL(p, F_TRACE_CALLS)) {
	int local = !!(bp_flags & ERTS_BPF_LOCAL_TRACE);
	flags = erts_call_trace(p, ep->code, bp->local_ms, args,
				local, &ERTS_TRACER(p));
    }
    if (bp_flags & ERTS_BPF_META_TRACE) {
	ErtsTracer old_tracer;

        meta_tracer = erts_smp_atomic_read_nob(&bp->meta_tracer->tracer);
        old_tracer = meta_tracer;
	flags_meta = erts_call_trace(p, ep->code, bp->meta_ms, args,
				     0, &meta_tracer);

	if (!ERTS_TRACER_COMPARE(old_tracer, meta_tracer)) {
            ErtsTracer new_tracer = erts_tracer_nil;
            erts_tracer_update(&new_tracer, meta_tracer);
	    if (old_tracer == erts_smp_atomic_cmpxchg_acqb(
                    &bp->meta_tracer->tracer,
                    (erts_aint_t)new_tracer,
                    (erts_aint_t)old_tracer)) {
                ERTS_TRACER_CLEAR(&old_tracer);
            } else {
                ERTS_TRACER_CLEAR(&new_tracer);
            }
	}
    }
    if (bp_flags & ERTS_BPF_TIME_TRACE_ACTIVE &&
	IS_TRACED_FL(p, F_TRACE_CALLS)) {
	BeamInstr *pc = (BeamInstr *)ep->code+3;
	erts_trace_time_call(p, pc, bp->time);
    }

    /* Restore original continuation pointer (if changed). */
    p->cp = cp;

    func = bif_table[bif_index].f;

    result = func(p, args, I);

    if (applying && (flags & MATCH_SET_RETURN_TO_TRACE)) {
	BeamInstr i_return_trace      = beam_return_trace[0];
	BeamInstr i_return_to_trace   = beam_return_to_trace[0];
	BeamInstr i_return_time_trace = beam_return_time_trace[0];
	Eterm *cpp;
	/* Maybe advance cp to skip trace stack frames */
	for (cpp = p->stop;  ;  cp = cp_val(*cpp++)) {
	    if (*cp == i_return_trace) {
		/* Skip stack frame variables */
		while (is_not_CP(*cpp)) cpp++;
		cpp += 2; /* Skip return_trace parameters */
	    } else if (*cp == i_return_time_trace) {
		/* Skip stack frame variables */
		while (is_not_CP(*cpp)) cpp++;
		cpp += 1; /* Skip return_time_trace parameters */
	    } else if (*cp == i_return_to_trace) {
		/* A return_to trace message is going to be generated
		 * by normal means, so we do not have to.
		 */
		cp = NULL;
		break;
	    } else break;
	}
    }

    /* Try to get these in the order
     * they usually appear in normal code... */
    if (is_non_value(result)) {
	Uint reason = p->freason;
	if (reason != TRAP) {
	    Eterm class;
	    Eterm value = p->fvalue;
	    /* Expand error value like in handle_error() */
	    if (reason & EXF_ARGLIST) {
		Eterm *tp;
		ASSERT(is_tuple(value));
		tp = tuple_val(value);
		value = tp[1];
	    }
	    if ((reason & EXF_THROWN) && (p->catches <= 0)) {
                Eterm *hp = HAlloc(p, 3);
		value = TUPLE2(hp, am_nocatch, value);
		reason = EXC_ERROR;
	    }
	    /* Note: expand_error_value() could theoretically
	     * allocate on the heap, but not for any error
	     * returned by a BIF, and it would do no harm,
	     * just be annoying.
	     */
	    value = expand_error_value(p, reason, value);
	    class = exception_tag[GET_EXC_CLASS(reason)];

	    if (flags_meta & MATCH_SET_EXCEPTION_TRACE) {
		erts_trace_exception(p, ep->code, class, value,
				     &meta_tracer);
	    }
	    if (flags & MATCH_SET_EXCEPTION_TRACE) {
		erts_trace_exception(p, ep->code, class, value,
				     &ERTS_TRACER(p));
	    }
Пример #10
0
static Eterm
check_process_code(Process* rp, Module* modp, int *redsp, int fcalls)
{
    BeamInstr* start;
    char* mod_start;
    Uint mod_size;
    Eterm* sp;
#ifdef HIPE
    void *nat_start = NULL;
    Uint nat_size = 0;
#endif

    *redsp += 1;

    /*
     * Pick up limits for the module.
     */
    start = (BeamInstr*) modp->old.code_hdr;
    mod_start = (char *) start;
    mod_size = modp->old.code_length;

    /*
     * Check if current instruction or continuation pointer points into module.
     */
    if (ErtsInArea(rp->i, mod_start, mod_size)
	|| ErtsInArea(rp->cp, mod_start, mod_size)) {
	return am_true;
    }

    *redsp += (STACK_START(rp) - rp->stop) / 32;

    /*
     * Check all continuation pointers stored on the stack.
     */
    for (sp = rp->stop; sp < STACK_START(rp); sp++) {
	if (is_CP(*sp) && ErtsInArea(cp_val(*sp), mod_start, mod_size)) {
	    return am_true;
	}
    }

#ifdef HIPE
    /*
     * Check all continuation pointers stored on the native stack if the module
     * has native code.
     */
    if (modp->old.hipe_code) {
	nat_start = modp->old.hipe_code->text_segment;
	nat_size = modp->old.hipe_code->text_segment_size;
	if (nat_size && nstack_any_cps_in_segment(rp, nat_start, nat_size)) {
	    return am_true;
	}
    }
#endif

    /* 
     * Check all continuation pointers stored in stackdump
     * and clear exception stackdump if there is a pointer
     * to the module.
     */
    if (rp->ftrace != NIL) {
	struct StackTrace *s;
	ASSERT(is_list(rp->ftrace));
	s = (struct StackTrace *) big_val(CDR(list_val(rp->ftrace)));
	if ((s->pc && ErtsInArea(s->pc, mod_start, mod_size)) ||
	    (s->current && ErtsInArea(s->current, mod_start, mod_size))) {
	    rp->freason = EXC_NULL;
	    rp->fvalue = NIL;
	    rp->ftrace = NIL;
	} else {
	    int i;
	    char *area_start = mod_start;
	    Uint area_size = mod_size;
#ifdef HIPE
	    if (rp->freason & EXF_NATIVE) {
		area_start = nat_start;
		area_size = nat_size;
	    }
#endif
	    for (i = 0;  i < s->depth;  i++) {
		if (ErtsInArea(s->trace[i], area_start, area_size)) {
		    rp->freason = EXC_NULL;
		    rp->fvalue = NIL;
		    rp->ftrace = NIL;
		    break;
		}
	    }
	}
    }

    return am_false;
}
Пример #11
0
static __inline__ void hipe_pop_beam_trap_frame(Process *p)
{
    p->cp = cp_val(p->stop[0]);
    --p->catches;
    p->stop += 2;
}
Пример #12
0
Файл: conf.c Проект: rvs/libtc
static int
getentry(tcconf_section_t *ts, tcc_entry *te, char *fmt,
	 va_list args, char **tail)
{
    char *f = fmt, *p;
    int n = 0;
    tclist_item_t *li = NULL;
    tcc_value *tv;
    va_list ac;

    while((p = strchr(f, '%')) != NULL){
	void *dest;
	int type = 0;

	if((tv = tclist_next(te->value.values, &li)) == NULL)
	    break;

	f = p;

	if(tv->type == TCC_REF && strcmp(tv->value.string, "NULL")){
	    tcconf_section_t *rs = tcref(ts);
	    tcc_entry *re;
	    int r;

	    if(!(re = getvalue(rs->sec, tv->value.string, &rs))){
		n = -n;
		break;
	    }
#ifdef __va_copy
	    __va_copy(ac, args);
#else
	    ac = args;
#endif
	    r = getentry(ts, re, f, ac, &f);
	    tcfree(rs);
	    if(r < 0){
		n += -r;
		break;
	    }
	    n += r;
	    while(r--)
		va_arg(args, void *);
	    continue;
	}

	dest = va_arg(args, void *);
	f++;

	while(!(type & TCC_TYPEMASK) && *f){
	    switch(*f){
	    case 's':
		type |= TCC_STRING;
		break;

	    case 'd':
	    case 'i':
		type |= TCC_INTEGER;
		break;

	    case 'f':
		type |= TCC_FLOAT;
		break;

	    case 'l':
		type |= TCC_LONG;
		break;

	    case 'u':
		type |= TCC_UNSIGNED;
		break;

	    case 'z':
		type |= TCC_IGNORE;
		break;
	    }
	    f++;
	}

	if(cp_val(ts, tv, type, dest) < 0){
	    fprintf(stderr, "Type mismatch in '%s'.\n", te->value.key);
	    n = -n;
	    break;
	} else {
	    n++;
	}
    }

    if(tail)
	*tail = f;

    if(li)
	tclist_unlock(te->value.values, li);

    return n;
}
Пример #13
0
Файл: conf.c Проект: rvs/libtc
static char *
vtostr(char *name, void *_ts)
{
    tcconf_section_t *ts = _ts;
    tclist_item_t *li = NULL;
    tcc_value *tv;
    tcc_entry *te;
    int l = 0;
    char *s = NULL;
    char *p = s;
    int sp = 0;

#define ext(n) do {				\
    int o = p - s;				\
    s = realloc(s, l += n);			\
    p = s + o;					\
} while(0)

    tcref(ts);

    if(!(te = getvalue(ts->sec, name, &ts)))
	return NULL;

    while((tv = tclist_next(te->value.values, &li))){
	union {
	    uint64_t i;
	    double d;
	    char *s;
	} v;
	int sl;

	cp_val(ts, tv, tv->type | TCC_LONG, &v);

	if(sp)
	    *p++ = ' ';

	switch(tv->type & TCC_TYPEMASK){
	case TCC_INTEGER:
	    ext(22);
	    p += snprintf(p, 22, "%lli", v.i);
	    break;
	case TCC_FLOAT:
	    ext(40);
	    p += snprintf(p, 40, "%lf", v.d);
	    break;
	case TCC_REF:
	    v.s = vtostr(tv->value.string, ts);
	case TCC_STRING:
	    sl = strlen(v.s);
	    ext(sl + 1);
	    strcpy(p, v.s);
	    free(v.s);
	    p += sl;
	    break;
	}
	sp = 1;
    }

    *p = 0;

#undef ext
    tcfree(ts);
    return s;
}
Пример #14
0
Eterm
erts_bif_trace_epilogue(Process *p, Eterm result, int applying,
			Export* ep, BeamInstr *cp, Uint32 flags,
			Uint32 flags_meta, BeamInstr* I,
			ErtsTracer meta_tracer)
{
    if (applying && (flags & MATCH_SET_RETURN_TO_TRACE)) {
	BeamInstr i_return_trace      = beam_return_trace[0];
	BeamInstr i_return_to_trace   = beam_return_to_trace[0];
	BeamInstr i_return_time_trace = beam_return_time_trace[0];
	Eterm *cpp;
	/* Maybe advance cp to skip trace stack frames */
	for (cpp = p->stop;  ;  cp = cp_val(*cpp++)) {
	    if (*cp == i_return_trace) {
		/* Skip stack frame variables */
		while (is_not_CP(*cpp)) cpp++;
		cpp += 2; /* Skip return_trace parameters */
	    } else if (*cp == i_return_time_trace) {
		/* Skip stack frame variables */
		while (is_not_CP(*cpp)) cpp++;
		cpp += 1; /* Skip return_time_trace parameters */
	    } else if (*cp == i_return_to_trace) {
		/* A return_to trace message is going to be generated
		 * by normal means, so we do not have to.
		 */
		cp = NULL;
		break;
	    } else break;
	}
    }

    /* Try to get these in the order
     * they usually appear in normal code... */
    if (is_non_value(result)) {
	Uint reason = p->freason;
	if (reason != TRAP) {
	    Eterm class;
	    Eterm value = p->fvalue;
	    /* Expand error value like in handle_error() */
	    if (reason & EXF_ARGLIST) {
		Eterm *tp;
		ASSERT(is_tuple(value));
		tp = tuple_val(value);
		value = tp[1];
	    }
	    if ((reason & EXF_THROWN) && (p->catches <= 0)) {
                Eterm *hp = HAlloc(p, 3);
		value = TUPLE2(hp, am_nocatch, value);
		reason = EXC_ERROR;
	    }
	    /* Note: expand_error_value() could theoretically
	     * allocate on the heap, but not for any error
	     * returned by a BIF, and it would do no harm,
	     * just be annoying.
	     */
	    value = expand_error_value(p, reason, value);
	    class = exception_tag[GET_EXC_CLASS(reason)];

	    if (flags_meta & MATCH_SET_EXCEPTION_TRACE) {
		erts_trace_exception(p, &ep->info.mfa, class, value,
				     &meta_tracer);
	    }
	    if (flags & MATCH_SET_EXCEPTION_TRACE) {
		erts_trace_exception(p, &ep->info.mfa, class, value,
				     &ERTS_TRACER(p));
	    }