int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
                  const char *name)
{
    X509_ATTRIBUTE *attr;
    ASN1_TYPE *av;
    char *value;
    int i, attr_nid;
    if (!attrlst) {
        BIO_printf(out, "%s: <No Attributes>\n", name);
        return 1;
    }
    if (!sk_X509_ATTRIBUTE_num(attrlst)) {
        BIO_printf(out, "%s: <Empty Attributes>\n", name);
        return 1;
    }
    BIO_printf(out, "%s\n", name);
    for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
        ASN1_OBJECT *attr_obj;
        attr = sk_X509_ATTRIBUTE_value(attrlst, i);
        attr_obj = X509_ATTRIBUTE_get0_object(attr);
        attr_nid = OBJ_obj2nid(attr_obj);
        BIO_printf(out, "    ");
        if (attr_nid == NID_undef) {
            i2a_ASN1_OBJECT(out, attr_obj);
            BIO_printf(out, ": ");
        } else {
            BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
        }
        if (X509_ATTRIBUTE_count(attr)) {
            av = X509_ATTRIBUTE_get0_type(attr, 0);
            switch (av->type) {
            case V_ASN1_BMPSTRING:
                value = OPENSSL_uni2asc(av->value.bmpstring->data,
                                        av->value.bmpstring->length);
                BIO_printf(out, "%s\n", value);
                OPENSSL_free(value);
                break;
            case V_ASN1_OCTET_STRING:
                hex_prin(out, av->value.octet_string->data,
                         av->value.octet_string->length);
                BIO_printf(out, "\n");
                break;
            case V_ASN1_BIT_STRING:
                hex_prin(out, av->value.bit_string->data,
                         av->value.bit_string->length);
                BIO_printf(out, "\n");
                break;
            default:
                BIO_printf(out, "<Unsupported tag %d>\n", av->type);
                break;
            }
        } else {
            BIO_printf(out, "<No Values>\n");
        }
    }
    return 1;
}
['int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,\n                  const char *name)\n{\n    X509_ATTRIBUTE *attr;\n    ASN1_TYPE *av;\n    char *value;\n    int i, attr_nid;\n    if (!attrlst) {\n        BIO_printf(out, "%s: <No Attributes>\\n", name);\n        return 1;\n    }\n    if (!sk_X509_ATTRIBUTE_num(attrlst)) {\n        BIO_printf(out, "%s: <Empty Attributes>\\n", name);\n        return 1;\n    }\n    BIO_printf(out, "%s\\n", name);\n    for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {\n        ASN1_OBJECT *attr_obj;\n        attr = sk_X509_ATTRIBUTE_value(attrlst, i);\n        attr_obj = X509_ATTRIBUTE_get0_object(attr);\n        attr_nid = OBJ_obj2nid(attr_obj);\n        BIO_printf(out, "    ");\n        if (attr_nid == NID_undef) {\n            i2a_ASN1_OBJECT(out, attr_obj);\n            BIO_printf(out, ": ");\n        } else {\n            BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));\n        }\n        if (X509_ATTRIBUTE_count(attr)) {\n            av = X509_ATTRIBUTE_get0_type(attr, 0);\n            switch (av->type) {\n            case V_ASN1_BMPSTRING:\n                value = OPENSSL_uni2asc(av->value.bmpstring->data,\n                                        av->value.bmpstring->length);\n                BIO_printf(out, "%s\\n", value);\n                OPENSSL_free(value);\n                break;\n            case V_ASN1_OCTET_STRING:\n                hex_prin(out, av->value.octet_string->data,\n                         av->value.octet_string->length);\n                BIO_printf(out, "\\n");\n                break;\n            case V_ASN1_BIT_STRING:\n                hex_prin(out, av->value.bit_string->data,\n                         av->value.bit_string->length);\n                BIO_printf(out, "\\n");\n                break;\n            default:\n                BIO_printf(out, "<Unsupported tag %d>\\n", av->type);\n                break;\n            }\n        } else {\n            BIO_printf(out, "<No Values>\\n");\n        }\n    }\n    return 1;\n}', 'int OPENSSL_sk_num(const OPENSSL_STACK *st)\n{\n    return st == NULL ? -1 : st->num;\n}', 'void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)\n{\n    if (st == NULL || i < 0 || i >= st->num)\n        return NULL;\n    return (void *)st->data[i];\n}', 'ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr)\n{\n    if (attr == NULL)\n        return NULL;\n    return attr->object;\n}', 'int OBJ_obj2nid(const ASN1_OBJECT *a)\n{\n    const unsigned int *op;\n    ADDED_OBJ ad, *adp;\n    if (a == NULL)\n        return NID_undef;\n    if (a->nid != 0)\n        return a->nid;\n    if (a->length == 0)\n        return NID_undef;\n    if (added != NULL) {\n        ad.type = ADDED_DATA;\n        ad.obj = (ASN1_OBJECT *)a;\n        adp = lh_ADDED_OBJ_retrieve(added, &ad);\n        if (adp != NULL)\n            return adp->obj->nid;\n    }\n    op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ);\n    if (op == NULL)\n        return NID_undef;\n    return nid_objs[*op].nid;\n}', 'DEFINE_LHASH_OF(ADDED_OBJ)', 'void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data)\n{\n    unsigned long hash;\n    OPENSSL_LH_NODE **rn;\n    void *ret;\n    tsan_store((TSAN_QUALIFIER int *)&lh->error, 0);\n    rn = getrn(lh, data, &hash);\n    if (*rn == NULL) {\n        tsan_counter(&lh->num_retrieve_miss);\n        return NULL;\n    } else {\n        ret = (*rn)->data;\n        tsan_counter(&lh->num_retrieve);\n    }\n    return ret;\n}', 'const char *OBJ_nid2ln(int n)\n{\n    ADDED_OBJ ad, *adp;\n    ASN1_OBJECT ob;\n    if ((n >= 0) && (n < NUM_NID)) {\n        if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {\n            OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID);\n            return NULL;\n        }\n        return nid_objs[n].ln;\n    } else if (added == NULL)\n        return NULL;\n    else {\n        ad.type = ADDED_NID;\n        ad.obj = &ob;\n        ob.nid = n;\n        adp = lh_ADDED_OBJ_retrieve(added, &ad);\n        if (adp != NULL)\n            return adp->obj->ln;\n        else {\n            OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID);\n            return NULL;\n        }\n    }\n}', 'int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr)\n{\n    if (attr == NULL)\n        return 0;\n    return sk_ASN1_TYPE_num(attr->set);\n}', 'ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)\n{\n    if (attr == NULL)\n        return NULL;\n    return sk_ASN1_TYPE_value(attr->set, idx);\n}']