struct regexp * regexp_union_n(struct info *info, int n, struct regexp **r) { size_t len = 0; char *pat = NULL, *p, *expanded = NULL; int nnocase = 0, npresent = 0; int ret; for (int i=0; i < n; i++) if (r[i] != NULL) { len += strlen(r[i]->pattern->str) + strlen("()|"); npresent += 1; if (r[i]->nocase) nnocase += 1; } bool mixedcase = nnocase > 0 && nnocase < npresent; if (len == 0) return NULL; if (ALLOC_N(pat, len) < 0) return NULL; p = pat; int added = 0; for (int i=0; i < n; i++) { if (r[i] == NULL) continue; if (added > 0) *p++ = '|'; *p++ = '('; if (mixedcase && r[i]->nocase) { expanded = regexp_expand_nocase(r[i]); ERR_BAIL(r[i]->info); len += strlen(expanded) - strlen(r[i]->pattern->str); ret = REALLOC_N(pat, len); ERR_NOMEM(ret < 0, info); p = pat + strlen(pat); p = stpcpy(p, expanded); FREE(expanded); } else { p = stpcpy(p, r[i]->pattern->str); } *p++ = ')'; added += 1; } *p = '\0'; return make_regexp(info, pat, nnocase == npresent); error: FREE(expanded); FREE(pat); return NULL; }
static char *append_expanded(struct regexp *r, char **pat, char *p, size_t *len) { char *expanded = NULL; size_t ofs = p - *pat; int ret; expanded = regexp_expand_nocase(r); ERR_BAIL(r->info); *len += strlen(expanded) - strlen(r->pattern->str); ret = REALLOC_N(*pat, *len); ERR_NOMEM(ret < 0, r->info); p = stpcpy(*pat + ofs, expanded); error: FREE(expanded); return p; }