/*-------------------------------------------------------------------------*/ 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() */
/*-------------------------------------------------------------------------*/ 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() */