NM nm_new_str(const char *str, int flags) {
    char *p, buf[2048];
    NM self;

    if((p = strchr(str, '/'))) { /* mask separator */
        strncpy(buf, str, p - str);
        buf[p - str] = '\0';
        self = parse_addr(buf, flags);
        if(!self)
            return NULL;
        if(!parse_mask(self, p + 1, flags)) {
            free(self);
            return NULL;
        }
        return self;
    } else if((p = strchr(str, ','))) { /* new range character */
        NM top;
        int add;

        strncpy(buf, str, p - str);
        buf[p - str] = '\0';
        self = parse_addr(buf, flags);
        if(!self)
            return NULL;
        if(p[1] == '+')
            add = 1;
        else
            add = 0;
        top = parse_addr(p + add + 1, flags);
        if(!top) {
            free(self);
            return NULL;
        }
        if(add) {
            int carry;
            if(is_v4(top))
                top->neta.l &= 0xffffffffULL;
            top->neta = u128_add(self->neta, top->neta, &carry);
            if(carry) {
                free(self);
                free(top);
                return NULL;
            }
        }
        return nm_seq(self, top);
    } else if((self = parse_addr(str, flags))) {
        return self;
    } else if((p = strchr(str, ':'))) { /* old range character (sloppy) */
        NM top;
        int add;
        strncpy(buf, str, p - str);
        buf[p - str] = '\0';
        self = parse_addr(buf, flags);
        if(!self)
            return NULL;
        if(p[1] == '+') {
            add = 1;
            if(p[2] == '-') {
                /* this is a pretty special reverse compatibility
                 * situation.  N:+-5" would actually emit the range from
                 * N-5 to N because strtoul() hilariously accepts
                 * negative numbers and the original code never detected
                 * overflow and things just happened to work out. */
                struct in_addr s;
                char *endp;
                uint32_t v = self->neta.l + strtoul(p + 2, &endp, 0);
                if(*endp == '\0') {
                    s.s_addr = htonl(v);
                    top = nm_new_v4(&s);
                    if(!top) {
                        free(self);
                        return NULL;
                    }
                    return nm_seq(self, top);
                }
            }
        } else {
            add = 0;
        }

        top = parse_addr(p + add + 1, flags);
        if(!top) {
            free(self);
            return NULL;
        }
        if(add) {
            int carry;
            if(is_v4(top))
                top->neta.l &= 0xffffffffULL;
            top->neta = u128_add(self->neta, top->neta, &carry);
            if(carry) {
                free(self);
                free(top);
                return NULL;
            }
        }
        return nm_seq(self, top);
    } else {
        return NULL;
    }
}
NM nm_new_str(const char *str, int flags) {
    char *p, buf[2048];
    NM self;

    if((p = strchr(str, '/'))) {  
        strncpy(buf, str, p - str);
        buf[p - str] = '\0';
        self = parse_addr(buf, flags);
        if(!self)
            return NULL;
        if(!parse_mask(self, p + 1, flags)) {
            free(self);
            return NULL;
        }
        return self;
    } else if((p = strchr(str, ','))) {  
        NM top;
        int add;

        strncpy(buf, str, p - str);
        buf[p - str] = '\0';
        self = parse_addr(buf, flags);
        if(!self)
            return NULL;
        if(p[1] == '+')
            add = 1;
        else
            add = 0;
        top = parse_addr(p + add + 1, flags);
        if(!top) {
            free(self);
            return NULL;
        }
        if(add) {
            int carry;
            if(is_v4(top))
                top->neta.l &= 0xffffffffULL;
            top->neta = u128_add(self->neta, top->neta, &carry);
            if(carry) {
                free(self);
                free(top);
                return NULL;
            }
        }
        return nm_seq(self, top);
    } else if((self = parse_addr(str, flags))) {
        return self;
    } else if((p = strchr(str, ':'))) {  
        NM top;
        int add;
        strncpy(buf, str, p - str);
        buf[p - str] = '\0';
        self = parse_addr(buf, flags);
        if(!self)
            return NULL;
        if(p[1] == '+') {
            add = 1;
            if(p[2] == '-') {
                 
                struct in_addr s;
                char *endp;
                uint32_t v = self->neta.l + strtoul(p + 2, &endp, 0);
                if(*endp == '\0') {
                    s.s_addr = htonl(v);
                    top = nm_new_v4(&s);
                    if(!top) {
                        free(self);
                        return NULL;
                    }
                    return nm_seq(self, top);
                }
            }
        } else {
            add = 0;
        }

        top = parse_addr(p + add + 1, flags);
        if(!top) {
            free(self);
            return NULL;
        }
        if(add) {
            int carry;
            if(is_v4(top))
                top->neta.l &= 0xffffffffULL;
            top->neta = u128_add(self->neta, top->neta, &carry);
            if(carry) {
                free(self);
                free(top);
                return NULL;
            }
        }
        return nm_seq(self, top);
    } else {
        return NULL;
    }
}