Beispiel #1
0
/*-------------------------------------------------------------------------*/
svalue_t *
f_baseof (svalue_t *sp)

/* EFUN baseof()
 *
 *    int baseof(struct b, struct s)
 *
 * Test if the type of struct <b> is a base of struct <s> (the values of
 * <b> and <s> are irrelevant). Results are:
 *   0: <b> is not a base of <s>, nor is <b> of equal type as <s> (though <s>
 *      might be a base of <b>).
 *   1: <b> is a true base of <s>
 *   2: <b> and <s> are the same struct type
 */

{
    int rc;

    /* Get the arguments from the stack */
    rc = struct_baseof(sp[-1].u.strct->type, sp[0].u.strct->type);
    
    /* Remove the arguments and push the result */
    free_svalue(sp); sp--;
    free_svalue(sp);

    put_number(sp, rc);

    return sp;
} /* f_baseof() */
Beispiel #2
0
/*-------------------------------------------------------------------------*/
static lpctype_t *
internal_get_common_type(lpctype_t *t1, lpctype_t* t2, bool find_one)

/* Determine the intersection of both types.
 * Returns NULL if there is no common type.
 * If one of both types is TYPE_UNKNOWN, then
 * the result will by TYPE_UNKNOWN, too.
 *
 * If <find_one> is true, then it may finish even if only a part
 * of the result type was found (used for has_common_type()).
 */

{
    /* Hopefully the most common case. */
    if (t1 && t1 == t2)
        return ref_lpctype(t1);

    /* We can't return NULL, as this is an error condition. */
    if (t1 == NULL && t2 == NULL)
        return lpctype_mixed;
    else if (t1 == NULL)
        return ref_lpctype(t2);
    else if (t2 == NULL)
        return ref_lpctype(t1);

    if (t2->t_class == TCLASS_UNION && t1->t_class != TCLASS_UNION)
    {
        /* Switch them, so t2 is not a union unless t1 is one, too. */
        lpctype_t *temp; temp = t1; t1 = t2; t2 = temp;
    }
    /* Some shortcuts, before we're diving into t1.*/
    if (t2->t_class == TCLASS_PRIMARY)
    {
        switch (t2->t_primary)
        {
        case TYPE_UNKNOWN:
            return ref_lpctype(t2);
        case TYPE_ANY:
            return ref_lpctype(t1);
        default:
            break;
        }
    }

    switch (t1->t_class)
    {
    case TCLASS_PRIMARY:
        switch (t1->t_primary)
        {
        case TYPE_UNKNOWN:
            return ref_lpctype(t1);
        case TYPE_ANY:
            return ref_lpctype(t2);
        default:
            /* Primary types besides the above exceptions should
               be identical (checked at the beginning of this function). */
            return NULL;
        }

    case TCLASS_STRUCT:
        if (t2->t_class != TCLASS_STRUCT)
            return NULL;
        else if (t1->t_struct == NULL)
            return ref_lpctype(t2);
        else if (t2->t_struct == NULL)
            return ref_lpctype(t1);
        /* This is somewhat counterintuitive, but the derived struct
           is more specialized, so it is the result of the intersection. */
        else if (struct_baseof(t1->t_struct, t2->t_struct))
            return ref_lpctype(t2);
        else if (struct_baseof(t2->t_struct, t1->t_struct))
            return ref_lpctype(t1);
        else
            return NULL;

    case TCLASS_ARRAY:
        if (t2->t_class != TCLASS_ARRAY)
            return NULL;
        else
        {
            lpctype_t *common_element = get_common_type(t1->t_array.element, t2->t_array.element);
            lpctype_t *result = get_array_type(common_element);
            free_lpctype(common_element);
            return result;
        }

    case TCLASS_UNION:
        {
            lpctype_t *result = NULL;
            while (true)
            {
                lpctype_t *base = t1->t_class == TCLASS_UNION ? t1->t_union.member : t1;
                lpctype_t *common_base = get_common_type(t2, base);
                lpctype_t *oldresult = result;

                if (find_one && common_base)
                    return common_base;

                result = get_union_type(result, common_base);
                free_lpctype(common_base);
                free_lpctype(oldresult);

                if (t1->t_class == TCLASS_UNION)
                    t1 = t1->t_union.head;
                else
                    break;
            }

            return result;
        }

    default:
        fatal("Unknown type class %d!\n", t1->t_class);
        return NULL;
    }
} /* internal_get_common_type() */