print_tree_node(u_char ** buf, size_t * buf_len,
                     size_t * out_len, int allow_realloc,
                     struct tree *tp, int width)
{
    const char     *cp;
    char            str[MAXTOKEN];
    int             i, prevmod, pos, len;

    if (tp) {
        module_name(tp->modid, str);
        if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "  -- FROM\t") ||
            !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
            return 0;
        pos = 16+strlen(str);
        for (i = 1, prevmod = tp->modid; i < tp->number_modules; i++) {
            if (prevmod != tp->module_list[i]) {
                module_name(tp->module_list[i], str);
                len = strlen(str);
                if (pos + len + 2 > width) {
                    if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                                     ",\n  --\t\t"))
                        return 0;
                    pos = 16;
                }
                else {
                    if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", "))
                        return 0;
                    pos += 2;
                }
                if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
                    return 0;
                pos += len;
            }
            prevmod = tp->module_list[i];
        }
        if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
            return 0;
        if (tp->tc_index != -1) {
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                              "  -- TEXTUAL CONVENTION ") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                              get_tc_descriptor(tp->tc_index)) ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
                return 0;
        }
        switch (tp->type) {
        case TYPE_OBJID:
            cp = "OBJECT IDENTIFIER";
            break;
        case TYPE_OCTETSTR:
            cp = "OCTET STRING";
            break;
        case TYPE_INTEGER:
            cp = "INTEGER";
            break;
        case TYPE_NETADDR:
            cp = "NetworkAddress";
            break;
        case TYPE_IPADDR:
            cp = "IpAddress";
            break;
        case TYPE_COUNTER:
            cp = "Counter32";
            break;
        case TYPE_GAUGE:
            cp = "Gauge32";
            break;
        case TYPE_TIMETICKS:
            cp = "TimeTicks";
            break;
        case TYPE_OPAQUE:
            cp = "Opaque";
            break;
        case TYPE_NULL:
            cp = "NULL";
            break;
        case TYPE_COUNTER64:
            cp = "Counter64";
            break;
        case TYPE_BITSTRING:
            cp = "BITS";
            break;
        case TYPE_NSAPADDRESS:
            cp = "NsapAddress";
            break;
        case TYPE_UINTEGER:
            cp = "UInteger32";
            break;
        case TYPE_UNSIGNED32:
            cp = "Unsigned32";
            break;
        case TYPE_INTEGER32:
            cp = "Integer32";
            break;
        default:
            cp = NULL;
            break;
        }
#if NETSNMP_ENABLE_TESTING_CODE
        if (!cp && (tp->ranges || tp->enums)) { /* ranges without type ? */
            sprintf(str, "?0 with %s %s ?",
                    tp->ranges ? "Range" : "", tp->enums ? "Enum" : "");
            cp = str;
        }
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
        if (cp)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                             "  SYNTAX\t") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp))
                return 0;
        if (tp->ranges) {
            struct range_list *rp = tp->ranges;
            int             first = 1;
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ("))
                return 0;
            while (rp) {
                switch (tp->type) {
                case TYPE_INTEGER:
                case TYPE_INTEGER32:
                    if (rp->low == rp->high)
                        sprintf(str, "%s%d", (first ? "" : " | "), rp->low );
                    else
                        sprintf(str, "%s%d..%d", (first ? "" : " | "),
                                rp->low, rp->high);
                    break;
                case TYPE_UNSIGNED32:
                case TYPE_OCTETSTR:
                case TYPE_GAUGE:
                case TYPE_UINTEGER:
                    if (rp->low == rp->high)
                        sprintf(str, "%s%u", (first ? "" : " | "),
                                (unsigned)rp->low );
                    else
                        sprintf(str, "%s%u..%u", (first ? "" : " | "),
                                (unsigned)rp->low, (unsigned)rp->high);
                    break;
                default:
                    /* No other range types allowed */
                    break;
                }
                if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
                    return 0;
                if (first)
                    first = 0;
                rp = rp->next;
            }
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ") "))
                return 0;
        }
        if (tp->enums) {
            struct enum_list *ep = tp->enums;
            int             first = 1;
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " {"))
                return 0;
            pos = 16 + strlen(cp) + 2;
            while (ep) {
                if (first)
                    first = 0;
                else
                    if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", "))
                        return 0;
                snprintf(str, sizeof(str), "%s(%d)", ep->label, ep->value);
                str[ sizeof(str)-1 ] = 0;
                len = strlen(str);
                if (pos + len + 2 > width) {
                    if (!snmp_cstrcat(buf, buf_len, out_len,
                                     allow_realloc, "\n\t\t  "))
                        return 0;
                    pos = 18;
                }
                if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
                    return 0;
                pos += len + 2;
                ep = ep->next;
            }
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "} "))
                return 0;
        }
        if (cp)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
                return 0;
        if (tp->hint)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                             "  DISPLAY-HINT\t\"") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->hint) ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
                return 0;
        if (tp->units)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                             "  UNITS\t\t\"") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->units) ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
                return 0;
        switch (tp->access) {
        case MIB_ACCESS_READONLY:
            cp = "read-only";
            break;
        case MIB_ACCESS_READWRITE:
            cp = "read-write";
            break;
        case MIB_ACCESS_WRITEONLY:
            cp = "write-only";
            break;
        case MIB_ACCESS_NOACCESS:
            cp = "not-accessible";
            break;
        case MIB_ACCESS_NOTIFY:
            cp = "accessible-for-notify";
            break;
        case MIB_ACCESS_CREATE:
            cp = "read-create";
            break;
        case 0:
            cp = NULL;
            break;
        default:
            sprintf(str, "access_%d", tp->access);
            cp = str;
        }
        if (cp)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                             "  MAX-ACCESS\t") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp) ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
                return 0;
        switch (tp->status) {
        case MIB_STATUS_MANDATORY:
            cp = "mandatory";
            break;
        case MIB_STATUS_OPTIONAL:
            cp = "optional";
            break;
        case MIB_STATUS_OBSOLETE:
            cp = "obsolete";
            break;
        case MIB_STATUS_DEPRECATED:
            cp = "deprecated";
            break;
        case MIB_STATUS_CURRENT:
            cp = "current";
            break;
        case 0:
            cp = NULL;
            break;
        default:
            sprintf(str, "status_%d", tp->status);
            cp = str;
        }
#if NETSNMP_ENABLE_TESTING_CODE
        if (!cp && (tp->indexes)) {     /* index without status ? */
            sprintf(str, "?0 with %s ?", tp->indexes ? "Index" : "");
            cp = str;
        }
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
        if (cp)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                             "  STATUS\t") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp) ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n"))
                return 0;
        if (tp->augments)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                             "  AUGMENTS\t{ ") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->augments) ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n"))
                return 0;
        if (tp->indexes) {
            struct index_list *ip = tp->indexes;
            int             first = 1;
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                             "  INDEX\t\t{ "))
                return 0;
            pos = 16 + 2;
            while (ip) {
                if (first)
                    first = 0;
                else
                    if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", "))
                        return 0;
                snprintf(str, sizeof(str), "%s%s",
                        ip->isimplied ? "IMPLIED " : "",
                        ip->ilabel);
                str[ sizeof(str)-1 ] = 0;
                len = strlen(str);
                if (pos + len + 2 > width) {
                    if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n\t\t  "))
                        return 0;
                    pos = 16 + 2;
                }
                if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
                    return 0;
                pos += len + 2;
                ip = ip->next;
            }
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n"))
                return 0;
        }
        if (tp->varbinds) {
            struct varbind_list *vp = tp->varbinds;
            int             first = 1;

            if (tp->type == TYPE_TRAPTYPE) {
                if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                    "  VARIABLES\t{ "))
                    return 0;
            } else {
                if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                    "  OBJECTS\t{ "))
                    return 0;
            }
            pos = 16 + 2;
            while (vp) {
                if (first)
                    first = 0;
                else
                    if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", "))
                        return 0;
                strlcpy(str, vp->vblabel, sizeof(str));
                len = strlen(str);
                if (pos + len + 2 > width) {
                    if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                                    "\n\t\t  "))
                        return 0;
                    pos = 16 + 2;
                }
                if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str))
                    return 0;
                pos += len + 2;
                vp = vp->next;
            }
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n"))
                return 0;
        }
        if (tp->description)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                              "  DESCRIPTION\t\"") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->description) ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n"))
                return 0;
        if (tp->defaultValue)
            if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc,
                              "  DEFVAL\t{ ") ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->defaultValue) ||
                !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n"))
                return 0;
    } else
        if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "No description\n"))
            return 0;
    return 1;
}