_add_strings_to_oid(void *tp, char *cp,
                    oid * objid, size_t * objidlen, size_t maxlen)
#endif /* NETSNMP_DISABLE_MIB_LOADING */
{
    oid             subid;
    char           *fcp, *ecp, *cp2 = NULL;
    char            doingquote;
    int             len = -1;
#ifndef NETSNMP_DISABLE_MIB_LOADING
    struct tree    *tp2 = NULL;
    struct index_list *in_dices = NULL;
    int             pos = -1;
    int             check =
        !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE);
    int             do_hint = !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT);
    int             len_index = 1000000;

    while (cp && tp && tp->child_list) {
        fcp = cp;
        tp2 = tp->child_list;
        /*
         * Isolate the next entry 
         */
        cp2 = strchr(cp, '.');
        if (cp2)
            *cp2++ = '\0';

        /*
         * Search for the appropriate child 
         */
        if (isdigit((unsigned char)(*cp))) {
            subid = strtoul(cp, &ecp, 0);
            if (*ecp)
                goto bad_id;
            while (tp2 && tp2->subid != subid)
                tp2 = tp2->next_peer;
        } else {
            while (tp2 && strcmp(tp2->label, fcp))
                tp2 = tp2->next_peer;
            if (!tp2)
                goto bad_id;
            subid = tp2->subid;
        }
        if (*objidlen >= maxlen)
            goto bad_id;
	while (tp2 && tp2->next_peer && tp2->next_peer->subid == subid)
	    tp2 = tp2->next_peer;
        objid[*objidlen] = subid;
        (*objidlen)++;

        cp = cp2;
        if (!tp2)
            break;
        tp = tp2;
    }

    if (tp && !tp->child_list) {
        if ((tp2 = tp->parent)) {
            if (tp2->indexes)
                in_dices = tp2->indexes;
            else if (tp2->augments) {
                tp2 = find_tree_node(tp2->augments, -1);
                if (tp2)
                    in_dices = tp2->indexes;
            }
        }
        tp = NULL;
    }

    while (cp && in_dices) {
        fcp = cp;

        tp = find_tree_node(in_dices->ilabel, -1);
        if (!tp)
            break;
        switch (tp->type) {
        case TYPE_INTEGER:
        case TYPE_INTEGER32:
        case TYPE_UINTEGER:
        case TYPE_UNSIGNED32:
        case TYPE_TIMETICKS:
            /*
             * Isolate the next entry 
             */
            cp2 = strchr(cp, '.');
            if (cp2)
                *cp2++ = '\0';
            if (isdigit((unsigned char)(*cp))) {
                subid = strtoul(cp, &ecp, 0);
                if (*ecp)
                    goto bad_id;
            } else {
                if (tp->enums) {
                    struct enum_list *ep = tp->enums;
                    while (ep && strcmp(ep->label, cp))
                        ep = ep->next;
                    if (!ep)
                        goto bad_id;
                    subid = ep->value;
                } else
                    goto bad_id;
            }
            if (check && tp->ranges) {
                struct range_list *rp = tp->ranges;
                int             ok = 0;
                if (tp->type == TYPE_INTEGER ||
                    tp->type == TYPE_INTEGER32) {
                  while (!ok && rp) {
                    if ((rp->low <= (int) subid)
                        && ((int) subid <= rp->high))
                        ok = 1;
                    else
                        rp = rp->next;
                  }
                } else { /* check unsigned range */
                  while (!ok && rp) {
                    if (((unsigned int)rp->low <= subid)
                        && (subid <= (unsigned int)rp->high))
                        ok = 1;
                    else
                        rp = rp->next;
                  }
                }
                if (!ok)
                    goto bad_id;
            }
            if (*objidlen >= maxlen)
                goto bad_id;
            objid[*objidlen] = subid;
            (*objidlen)++;
            break;
        case TYPE_IPADDR:
            if (*objidlen + 4 > maxlen)
                goto bad_id;
            for (subid = 0; cp && subid < 4; subid++) {
                fcp = cp;
                cp2 = strchr(cp, '.');
                if (cp2)
                    *cp2++ = 0;
                objid[*objidlen] = strtoul(cp, &ecp, 0);
                if (*ecp)
                    goto bad_id;
                if (check && objid[*objidlen] > 255)
                    goto bad_id;
                (*objidlen)++;
                cp = cp2;
            }
            break;
        case TYPE_OCTETSTR:
            if (tp->ranges && !tp->ranges->next
                && tp->ranges->low == tp->ranges->high)
                len = tp->ranges->low;
            else
                len = -1;
            pos = 0;
            if (*cp == '"' || *cp == '\'') {
                doingquote = *cp++;
                /*
                 * insert length if requested 
                 */
                if (!in_dices->isimplied && len == -1) {
                    if (doingquote == '\'') {
                        snmp_set_detail
                            ("'-quote is for fixed length strings");
                        return 0;
                    }
                    if (*objidlen >= maxlen)
                        goto bad_id;
                    len_index = *objidlen;
                    (*objidlen)++;
                } else if (doingquote == '"') {
                    snmp_set_detail
                        ("\"-quote is for variable length strings");
                    return 0;
                }

		cp2 = _apply_escapes(cp, doingquote);
		if (!cp2) goto bad_id;
		else {
		    unsigned char *new_val;
		    int new_val_len;
		    int parsed_hint = 0;
		    const char *parsed_value;

		    if (do_hint && tp->hint) {
			parsed_value = parse_octet_hint(tp->hint, cp,
			                                &new_val, &new_val_len);
			parsed_hint = parsed_value == NULL;
		    }
		    if (parsed_hint) {
			int i;
			for (i = 0; i < new_val_len; i++) {
			    if (*objidlen >= maxlen) goto bad_id;
			    objid[ *objidlen ] = new_val[i];
			    (*objidlen)++;
			    pos++;
			}
			SNMP_FREE(new_val);
		    } else {
			while(*cp) {
			    if (*objidlen >= maxlen) goto bad_id;
			    objid[ *objidlen ] = *cp++;
			    (*objidlen)++;
			    pos++;
			}
		    }
		}
		
		cp2++;
                if (!*cp2)
                    cp2 = NULL;
                else if (*cp2 != '.')
                    goto bad_id;
                else
                    cp2++;
		if (check) {
                    if (len == -1) {
                        struct range_list *rp = tp->ranges;
                        int             ok = 0;
                        while (rp && !ok)
                            if (rp->low <= pos && pos <= rp->high)
                                ok = 1;
                            else
                                rp = rp->next;
                        if (!ok)
                            goto bad_id;
                        if (!in_dices->isimplied)
                            objid[len_index] = pos;
                    } else if (pos != len)
                        goto bad_id;
		}
		else if (len == -1 && !in_dices->isimplied)
		    objid[len_index] = pos;
            } else {
                if (!in_dices->isimplied && len == -1) {
                    fcp = cp;
                    cp2 = strchr(cp, '.');
                    if (cp2)
                        *cp2++ = 0;
                    len = strtoul(cp, &ecp, 0);
                    if (*ecp)
                        goto bad_id;
                    if (*objidlen + len + 1 >= maxlen)
                        goto bad_id;
                    objid[*objidlen] = len;
                    (*objidlen)++;
                    cp = cp2;
                }
                while (len && cp) {
                    fcp = cp;
                    cp2 = strchr(cp, '.');
                    if (cp2)
                        *cp2++ = 0;
                    objid[*objidlen] = strtoul(cp, &ecp, 0);
                    if (*ecp)
                        goto bad_id;
                    if (check && objid[*objidlen] > 255)
                        goto bad_id;
                    (*objidlen)++;
                    len--;
                    cp = cp2;
                }
            }
            break;
        case TYPE_OBJID:
            in_dices = NULL;
            cp2 = cp;
            break;
	case TYPE_NETADDR:
	    fcp = cp;
	    cp2 = strchr(cp, '.');
	    if (cp2)
		*cp2++ = 0;
	    subid = strtoul(cp, &ecp, 0);
	    if (*ecp)
		goto bad_id;
	    if (*objidlen + 1 >= maxlen)
		goto bad_id;
	    objid[*objidlen] = subid;
	    (*objidlen)++;
	    cp = cp2;
	    if (subid == 1) {
		for (len = 0; cp && len < 4; len++) {
		    fcp = cp;
		    cp2 = strchr(cp, '.');
		    if (cp2)
			*cp2++ = 0;
		    subid = strtoul(cp, &ecp, 0);
		    if (*ecp)
			goto bad_id;
		    if (*objidlen + 1 >= maxlen)
			goto bad_id;
		    if (check && subid > 255)
			goto bad_id;
		    objid[*objidlen] = subid;
		    (*objidlen)++;
		    cp = cp2;
		}
	    }
	    else {
		in_dices = NULL;
	    }
	    break;
        default:
            snmp_log(LOG_ERR, "Unexpected index type: %d %s %s\n",
                     tp->type, in_dices->ilabel, cp);
            in_dices = NULL;
            cp2 = cp;
            break;
        }
        cp = cp2;
        if (in_dices)
            in_dices = in_dices->next;
    }

#endif /* NETSNMP_DISABLE_MIB_LOADING */
    while (cp) {
        fcp = cp;
        switch (*cp) {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            cp2 = strchr(cp, '.');
            if (cp2)
                *cp2++ = 0;
            subid = strtoul(cp, &ecp, 0);
            if (*ecp)
                goto bad_id;
            if (*objidlen >= maxlen)
                goto bad_id;
            objid[*objidlen] = subid;
            (*objidlen)++;
            break;
        case '"':
        case '\'':
            doingquote = *cp++;
            /*
             * insert length if requested 
             */
            if (doingquote == '"') {
                if (*objidlen >= maxlen)
                    goto bad_id;
                objid[*objidlen] = len = strchr(cp, doingquote) - cp;
                (*objidlen)++;
            }

            while (*cp && *cp != doingquote) {
                if (*objidlen >= maxlen)
                    goto bad_id;
                objid[*objidlen] = *cp++;
                (*objidlen)++;
            }
            cp2 = cp + 1;
            if (!*cp2)
                cp2 = NULL;
            else if (*cp2 == '.')
                cp2++;
            else
                goto bad_id;
            break;
        default:
            goto bad_id;
        }
        cp = cp2;
    }
    return 1;

  bad_id:
    {
        char            buf[256];
#ifndef NETSNMP_DISABLE_MIB_LOADING
        if (in_dices)
            snprintf(buf, sizeof(buf), "Index out of range: %s (%s)",
                    fcp, in_dices->ilabel);
        else if (tp)
            snprintf(buf, sizeof(buf), "Sub-id not found: %s -> %s", tp->label, fcp);
        else
#endif /* NETSNMP_DISABLE_MIB_LOADING */
            snprintf(buf, sizeof(buf), "%s", fcp);
        buf[ sizeof(buf)-1 ] = 0;

        snmp_set_detail(buf);
    }
    return 0;
}