print_mib_leaves(FILE * f, struct tree *tp, int width)
{
    struct tree    *ntp;
    char           *ip = leave_indent + strlen(leave_indent) - 1;
    char            last_ipch = *ip;

    *ip = '+';
    if (tp->type == TYPE_OTHER || tp->type > TYPE_SIMPLE_LAST) {
        fprintf(f, "%s--%s(%ld)\n", leave_indent, tp->label, tp->subid);
        if (tp->indexes) {
            struct index_list *xp = tp->indexes;
            int             first = 1, cpos = 0, len, cmax =
                width - strlen(leave_indent) - 12;
            *ip = last_ipch;
            fprintf(f, "%s  |  Index: ", leave_indent);
            while (xp) {
                if (first)
                    first = 0;
                else
                    fprintf(f, ", ");
                cpos += (len = strlen(xp->ilabel) + 2);
                if (cpos > cmax) {
                    fprintf(f, "\n");
                    fprintf(f, "%s  |         ", leave_indent);
                    cpos = len;
                }
                fprintf(f, "%s", xp->ilabel);
                xp = xp->next;
            }
            fprintf(f, "\n");
            *ip = '+';
        }
    } else {
        const char     *acc, *typ;
        int             size = 0;
        switch (tp->access) {
        case MIB_ACCESS_NOACCESS:
            acc = "----";
            break;
        case MIB_ACCESS_READONLY:
            acc = "-R--";
            break;
        case MIB_ACCESS_WRITEONLY:
            acc = "--W-";
            break;
        case MIB_ACCESS_READWRITE:
            acc = "-RW-";
            break;
        case MIB_ACCESS_NOTIFY:
            acc = "---N";
            break;
        case MIB_ACCESS_CREATE:
            acc = "CR--";
            break;
        default:
            acc = "    ";
            break;
        }
        switch (tp->type) {
        case TYPE_OBJID:
            typ = "ObjID    ";
            break;
        case TYPE_OCTETSTR:
            typ = "String   ";
            size = 1;
            break;
        case TYPE_INTEGER:
            if (tp->enums)
                typ = "EnumVal  ";
            else
                typ = "INTEGER  ";
            break;
        case TYPE_NETADDR:
            typ = "NetAddr  ";
            break;
        case TYPE_IPADDR:
            typ = "IpAddr   ";
            break;
        case TYPE_COUNTER:
            typ = "Counter  ";
            break;
        case TYPE_GAUGE:
            typ = "Gauge    ";
            break;
        case TYPE_TIMETICKS:
            typ = "TimeTicks";
            break;
        case TYPE_OPAQUE:
            typ = "Opaque   ";
            size = 1;
            break;
        case TYPE_NULL:
            typ = "Null     ";
            break;
        case TYPE_COUNTER64:
            typ = "Counter64";
            break;
        case TYPE_BITSTRING:
            typ = "BitString";
            break;
        case TYPE_NSAPADDRESS:
            typ = "NsapAddr ";
            break;
        case TYPE_UNSIGNED32:
            typ = "Unsigned ";
            break;
        case TYPE_UINTEGER:
            typ = "UInteger ";
            break;
        case TYPE_INTEGER32:
            typ = "Integer32";
            break;
        default:
            typ = "         ";
            break;
        }
        fprintf(f, "%s-- %s %s %s(%ld)\n", leave_indent, acc, typ,
                tp->label, tp->subid);
        *ip = last_ipch;
        if (tp->tc_index >= 0)
            fprintf(f, "%s        Textual Convention: %s\n", leave_indent,
                    tclist[tp->tc_index].descriptor);
        if (tp->enums) {
            struct enum_list *ep = tp->enums;
            int             cpos = 0, cmax =
                width - strlen(leave_indent) - 16;
            fprintf(f, "%s        Values: ", leave_indent);
            while (ep) {
                char            buf[80];
                int             bufw;
                if (ep != tp->enums)
                    fprintf(f, ", ");
                snprintf(buf, sizeof(buf), "%s(%d)", ep->label, ep->value);
                buf[ sizeof(buf)-1 ] = 0;
                cpos += (bufw = strlen(buf) + 2);
                if (cpos >= cmax) {
                    fprintf(f, "\n%s                ", leave_indent);
                    cpos = bufw;
                }
                fprintf(f, "%s", buf);
                ep = ep->next;
            }
            fprintf(f, "\n");
        }
        if (tp->ranges) {
            struct range_list *rp = tp->ranges;
            if (size)
                fprintf(f, "%s        Size: ", leave_indent);
            else
                fprintf(f, "%s        Range: ", leave_indent);
            while (rp) {
                if (rp != tp->ranges)
                    fprintf(f, " | ");
                print_range_value(f, tp->type, rp);
                rp = rp->next;
            }
            fprintf(f, "\n");
        }
    }
    *ip = last_ipch;
    strcat(leave_indent, "  |");
    leave_was_simple = tp->type != TYPE_OTHER;

    {
        int             i, j, count = 0;
        struct leave {
            oid             id;
            struct tree    *tp;
        }              *leaves, *lp;

        for (ntp = tp->child_list; ntp; ntp = ntp->next_peer)
            count++;
        if (count) {
            leaves = (struct leave *) calloc(count, sizeof(struct leave));
            if (!leaves)
                return;
            for (ntp = tp->child_list, count = 0; ntp;
                 ntp = ntp->next_peer) {
                for (i = 0, lp = leaves; i < count; i++, lp++)
                    if (lp->id >= ntp->subid)
                        break;
                for (j = count; j > i; j--)
                    leaves[j] = leaves[j - 1];
                lp->id = ntp->subid;
                lp->tp = ntp;
                count++;
            }
            for (i = 1, lp = leaves; i <= count; i++, lp++) {
                if (!leave_was_simple || lp->tp->type == 0)
                    fprintf(f, "%s\n", leave_indent);
                if (i == count)
                    ip[3] = ' ';
                print_mib_leaves(f, lp->tp, width);
            }
            free(leaves);
            leave_was_simple = 0;
        }
    }
    ip[1] = 0;
}
print_mib_leaves(FILE * f, struct tree *tp, int width)
{
    struct tree    *ntp;
    char           *ip = leave_indent + strlen(leave_indent) - 1;
    char            last_ipch = *ip;

    *ip = '+';
    if (tp->type == TYPE_OTHER || tp->type > TYPE_SIMPLE_LAST) {
        fprintf(f, "%s--%s(%ld)\n", leave_indent, tp->label, tp->subid);
        if (tp->indexes) {
            struct index_list *xp = tp->indexes;
            int             first = 1, cpos = 0, len, cmax =
                width - strlen(leave_indent) - 12;
            *ip = last_ipch;
            fprintf(f, "%s  |  Index: ", leave_indent);
            while (xp) {
                if (first)
                    first = 0;
                else
                    fprintf(f, ", ");
                cpos += (len = strlen(xp->ilabel) + 2);
                if (cpos > cmax) {
                    fprintf(f, "\n");
                    fprintf(f, "%s  |         ", leave_indent);
                    cpos = len;
                }
                fprintf(f, "%s", xp->ilabel);
                xp = xp->next;
            }
            fprintf(f, "\n");
            *ip = '+';
        }
    } else {
        const char     *acc, *typ;
        int             size = 0;
        switch (tp->access) {
        case MIB_ACCESS_NOACCESS:
            acc = "----";
            break;
        case MIB_ACCESS_READONLY:
            acc = "-R--";
            break;
        case MIB_ACCESS_WRITEONLY:
            acc = "--W-";
            break;
        case MIB_ACCESS_READWRITE:
            acc = "-RW-";
            break;
        case MIB_ACCESS_NOTIFY:
            acc = "---N";
            break;
        case MIB_ACCESS_CREATE:
            acc = "CR--";
            break;
        default:
            acc = "    ";
            break;
        }
        switch (tp->type) {
        case TYPE_OBJID:
            typ = "ObjID    ";
            break;
        case TYPE_OCTETSTR:
            typ = "String   ";
            size = 1;
            break;
        case TYPE_INTEGER:
            if (tp->enums)
                typ = "EnumVal  ";
            else
                typ = "INTEGER  ";
            break;
        case TYPE_NETADDR:
            typ = "NetAddr  ";
            break;
        case TYPE_IPADDR:
            typ = "IpAddr   ";
            break;
        case TYPE_COUNTER:
            typ = "Counter  ";
            break;
        case TYPE_GAUGE:
            typ = "Gauge    ";
            break;
        case TYPE_TIMETICKS:
            typ = "TimeTicks";
            break;
        case TYPE_OPAQUE:
            typ = "Opaque   ";
            size = 1;
            break;
        case TYPE_NULL:
            typ = "Null     ";
            break;
        case TYPE_COUNTER64:
            typ = "Counter64";
            break;
        case TYPE_BITSTRING:
            typ = "BitString";
            break;
        case TYPE_NSAPADDRESS:
            typ = "NsapAddr ";
            break;
        case TYPE_UNSIGNED32:
            typ = "Unsigned ";
            break;
        case TYPE_UINTEGER:
            typ = "UInteger ";
            break;
        case TYPE_INTEGER32:
            typ = "Integer32";
            break;
        default:
            typ = "         ";
            break;
        }
        fprintf(f, "%s-- %s %s %s(%ld)\n", leave_indent, acc, typ,
                tp->label, tp->subid);
        *ip = last_ipch;
        if (tp->tc_index >= 0)
            fprintf(f, "%s        Textual Convention: %s\n", leave_indent,
                    tclist[tp->tc_index].descriptor);
        if (tp->enums) {
            struct enum_list *ep = tp->enums;
            int             cpos = 0, cmax =
                width - strlen(leave_indent) - 16;
            fprintf(f, "%s        Values: ", leave_indent);
            while (ep) {
                char            buf[80];
                int             bufw;
                if (ep != tp->enums)
                    fprintf(f, ", ");
                snprintf(buf, sizeof(buf), "%s(%d)", ep->label, ep->value);
                buf[ sizeof(buf)-1 ] = 0;
                cpos += (bufw = strlen(buf) + 2);
                if (cpos >= cmax) {
                    fprintf(f, "\n%s                ", leave_indent);
                    cpos = bufw;
                }
                fprintf(f, "%s", buf);
                ep = ep->next;
            }
            fprintf(f, "\n");
        }
        if (tp->ranges) {
            struct range_list *rp = tp->ranges;
            if (size)
                fprintf(f, "%s        Size: ", leave_indent);
            else
                fprintf(f, "%s        Range: ", leave_indent);
            while (rp) {
                if (rp != tp->ranges)
                    fprintf(f, " | ");
                print_range_value(f, tp->type, rp);
                rp = rp->next;
            }
            fprintf(f, "\n");
        }
    }
    *ip = last_ipch;
    strcat(leave_indent, "  |");
    leave_was_simple = tp->type != TYPE_OTHER;

    {
        int             i, j, count = 0;
        struct leave {
            oid             id;
            struct tree    *tp;
        }              *leaves, *lp;

        for (ntp = tp->child_list; ntp; ntp = ntp->next_peer)
            count++;
        if (count) {
            leaves = (struct leave *) calloc(count, sizeof(struct leave));
            if (!leaves)
                return;
            for (ntp = tp->child_list, count = 0; ntp;
                 ntp = ntp->next_peer) {
                for (i = 0, lp = leaves; i < count; i++, lp++)
                    if (lp->id >= ntp->subid)
                        break;
                for (j = count; j > i; j--)
                    leaves[j] = leaves[j - 1];
                lp->id = ntp->subid;
                lp->tp = ntp;
                count++;
            }
            for (i = 1, lp = leaves; i <= count; i++, lp++) {
                if (!leave_was_simple || lp->tp->type == 0)
                    fprintf(f, "%s\n", leave_indent);
                if (i == count)
                    ip[3] = ' ';
                print_mib_leaves(f, lp->tp, width);
            }
            free(leaves);
            leave_was_simple = 0;
        }
    }
    ip[1] = 0;
}