Exemple #1
0
int Visit (register Object *p) {
    register Object *tag;
    register int t, size, reloc = 0;

again:
    t = TYPE(*p);
    if (!Types[t].haspointer)
        return 0;
    tag = (Object *)POINTER(*p);
    if ((char *)tag >= Free_Start && (char *)tag < Free_End)
        return 0;
    if (TYPE(*tag) == T_Broken_Heart) {
        SETPOINTER(*p, POINTER(*tag));
        return 0;
    }
    ELK_ALIGN(To);
    switch (t) {
    case T_Bignum:
        size = sizeof (struct S_Bignum) - sizeof (gran_t)
               + BIGNUM(*p)->size * sizeof (gran_t);
        memcpy (To, tag, size);
        break;
    case T_Flonum:
        size = sizeof (struct S_Flonum);
        *(struct S_Flonum *)To = *(struct S_Flonum *)tag;
        break;
    case T_Symbol:
        size = sizeof (struct S_Symbol);
        *(struct S_Symbol *)To = *(struct S_Symbol *)tag;
        break;
    case T_Pair:
    case T_Environment:
        size = sizeof (struct S_Pair);
        *(struct S_Pair *)To = *(struct S_Pair *)tag;
        break;
    case T_String:
        size = sizeof (struct S_String) + STRING(*p)->size - 1;
        memcpy (To, tag, size);
        break;
    case T_Vector:
        size = sizeof (struct S_Vector) + (VECTOR(*p)->size - 1) *
            sizeof (Object);
        memcpy (To, tag, size);
        break;
    case T_Primitive:
        size = sizeof (struct S_Primitive);
        *(struct S_Primitive *)To = *(struct S_Primitive *)tag;
        break;
    case T_Compound:
        size = sizeof (struct S_Compound);
        *(struct S_Compound *)To = *(struct S_Compound *)tag;
        break;
    case T_Control_Point:
        size = sizeof (struct S_Control) + CONTROL(*p)->size - 1;
        reloc = To - (char *)tag;
        memcpy (To, tag, size);
        break;
    case T_Promise:
        size = sizeof (struct S_Promise);
        *(struct S_Promise *)To = *(struct S_Promise *)tag;
        break;
    case T_Port:
        size = sizeof (struct S_Port);
        *(struct S_Port *)To = *(struct S_Port *)tag;
        break;
    case T_Autoload:
        size = sizeof (struct S_Autoload);
        *(struct S_Autoload *)To = *(struct S_Autoload *)tag;
        break;
    case T_Macro:
        size = sizeof (struct S_Macro);
        *(struct S_Macro *)To = *(struct S_Macro *)tag;
        break;
    case T_Broken_Heart:
        Panic ("broken heart in GC");
    default:
        if (t < 0 || t >= Num_Types)
            Panic ("bad type in GC");
        if (Types[t].size == NOFUNC)
            size = Types[t].const_size;
        else
            size = (Types[t].size)(*p);
        memcpy (To, tag, size);
    }
    SETPOINTER(*p, To);
    SET(*tag, T_Broken_Heart, To);
    To += size;
    if (To > Free_End)
        Panic ("free exhausted in GC");
    switch (t) {
    case T_Symbol:
        Recursive_Visit (&SYMBOL(*p)->next);
        Recursive_Visit (&SYMBOL(*p)->name);
        Recursive_Visit (&SYMBOL(*p)->value);
        p = &SYMBOL(*p)->plist;
        goto again;
    case T_Pair:
    case T_Environment:
        Recursive_Visit (&PAIR(*p)->car);
        p = &PAIR(*p)->cdr;
        goto again;
    case T_Vector: {
            register int i, n;
            for (i = 0, n = VECTOR(*p)->size; i < n; i++)
                Recursive_Visit (&VECTOR(*p)->data[i]);
            break;
        }
    case T_Compound:
        Recursive_Visit (&COMPOUND(*p)->closure);
        Recursive_Visit (&COMPOUND(*p)->env);
        p = &COMPOUND(*p)->name;
        goto again;
    case T_Control_Point:
        Recursive_Visit (&CONTROL(*p)->memsave);
        CONTROL(*p)->delta += reloc;
#ifdef HAVE_ALLOCA
        Visit_GC_List (CONTROL(*p)->gclist, CONTROL(*p)->delta);
#else
        Recursive_Visit (&CONTROL(*p)->gcsave);
#endif
        Visit_Wind (CONTROL(*p)->firstwind, CONTROL(*p)->delta);
        p = &CONTROL(*p)->env;
        goto again;
    case T_Promise:
        Recursive_Visit (&PROMISE(*p)->env);
        p = &PROMISE(*p)->thunk;
        goto again;
    case T_Port:
        p = &PORT(*p)->name;
        goto again;
    case T_Autoload:
        Recursive_Visit (&AUTOLOAD(*p)->files);
        p = &AUTOLOAD(*p)->env;
        goto again;
    case T_Macro:
        Recursive_Visit (&MACRO(*p)->body);
        p = &MACRO(*p)->name;
        goto again;
    default:
        if (Types[t].visit)
            (Types[t].visit)(p, Visit);
    }

    return 0;
}
Exemple #2
0
LispObj *
Lisp_ParseInteger(LispBuiltin *builtin)
/*
 parse-integer string &key start end radix junk-allowed
 */
{
    GC_ENTER();
    char *ptr, *string;
    int character, junk, sign, overflow;
    long i, start, end, radix, length, integer, check;
    LispObj *result;

    LispObj *ostring, *ostart, *oend, *oradix, *junk_allowed;

    junk_allowed = ARGUMENT(4);
    oradix = ARGUMENT(3);
    oend = ARGUMENT(2);
    ostart = ARGUMENT(1);
    ostring = ARGUMENT(0);

    start = end = radix = 0;
    result = NIL;

    CHECK_STRING(ostring);
    LispCheckSequenceStartEnd(builtin, ostring, ostart, oend,
			      &start, &end, &length);
    string = THESTR(ostring);
    if (oradix == UNSPEC)
	radix = 10;
    else {
	CHECK_INDEX(oradix);
	radix = FIXNUM_VALUE(oradix);
    }
    if (radix < 2 || radix > 36)
	LispDestroy("%s: :RADIX %ld must be in the range 2 to 36",
		    STRFUN(builtin), radix);

    integer = check = 0;
    ptr = string + start;
    sign = overflow = 0;

    /* Skip leading white spaces */
    for (i = start; i < end && *ptr && isspace(*ptr); ptr++, i++)
	;

    /* Check for sign specification */
    if (i < end && (*ptr == '-' || *ptr == '+')) {
	sign = *ptr == '-';
	++ptr;
	++i;
    }

    for (junk = 0; i < end; i++, ptr++) {
	character = *ptr;
	if (islower(character))
	    character = toupper(character);
	if (character >= '0' && character <= '9') {
	    if (character - '0' >= radix)
		junk = 1;
	    else {
		check = integer;
		integer = integer * radix + character - '0';
	    }
	}
	else if (character >= 'A' && character <= 'Z') {
	    if (character - 'A' + 10 >= radix)
		junk = 1;
	    else {
		check = integer;
		integer = integer * radix + character - 'A' + 10;
	    }
	}
	else {
	    if (isspace(character))
		break;
	    junk = 1;
	}

	if (junk)
	    break;

	if (!overflow && check > integer)
	    overflow = 1;
	/* keep looping just to count read bytes */
    }

    if (!junk)
	/* Skip white spaces */
	for (; i < end && *ptr && isspace(*ptr); ptr++, i++)
	    ;

    if ((junk || ptr == string) &&
	(junk_allowed == UNSPEC || junk_allowed == NIL))
	LispDestroy("%s: %s has a bad integer representation",
		    STRFUN(builtin), STROBJ(ostring));
    else if (ptr == string)
	result = NIL;
    else if (overflow) {
	mpi *bigi = LispMalloc(sizeof(mpi));
	char *str;

	length = end - start + sign;
	str = LispMalloc(length + 1);

	strncpy(str, string - sign, length + sign);
	str[length + sign] = '\0';
	mpi_init(bigi);
	mpi_setstr(bigi, str, radix);
	LispFree(str);
	result = BIGNUM(bigi);
    }
    else
	result = INTEGER(sign ? -integer : integer);

    GC_PROTECT(result);
    RETURN(0) = FIXNUM(i);
    RETURN_COUNT = 1;
    GC_LEAVE();

    return (result);
}