int add_exclude_fp (void (*add_func) (struct exclude *, char const *, int, void *), struct exclude *ex, FILE *fp, int options, char line_end, void *data) { char *buf = NULL; char *p; char *pattern; char const *lim; size_t buf_alloc = 0; size_t buf_count = 0; int c; int e = 0; while ((c = getc (fp)) != EOF) { if (buf_count == buf_alloc) buf = x2realloc (buf, &buf_alloc); buf[buf_count++] = c; } if (ferror (fp)) e = errno; buf = xrealloc (buf, buf_count + 1); buf[buf_count] = line_end; lim = buf + buf_count + ! (buf_count == 0 || buf[buf_count - 1] == line_end); exclude_add_pattern_buffer (ex, buf); pattern = buf; for (p = buf; p < lim; p++) if (*p == line_end) { char *pattern_end = p; if (isspace ((unsigned char) line_end)) { for (; ; pattern_end--) if (pattern_end == pattern) goto next_pattern; else if (! isspace ((unsigned char) pattern_end[-1])) break; } *pattern_end = '\0'; (*add_func) (ex, pattern, options, data); next_pattern: pattern = p + 1; } errno = e; return e ? -1 : 0; }
static void hg_addfn (struct exclude *ex, char const *pattern, int options, void *data) { int *hgopt = data; size_t len; while (isspace (*pattern)) ++pattern; if (*pattern == 0 || *pattern == '#') return; if (strncmp (pattern, "syntax:", 7) == 0) { for (pattern += 7; isspace (*pattern); ++pattern) ; if (strcmp (pattern, "regexp") == 0) /* FIXME: Regexps must be perl-style */ *hgopt = EXCLUDE_REGEX; else if (strcmp (pattern, "glob") == 0) *hgopt = EXCLUDE_WILDCARDS; /* Ignore unknown syntax */ return; } len = strlen(pattern); if (pattern[len-1] == '/') { char *p; --len; p = xmalloc (len+1); memcpy (p, pattern, len); p[len] = 0; pattern = p; exclude_add_pattern_buffer (ex, p); options |= FNM_LEADING_DIR|EXCLUDE_ALLOC; } add_exclude (ex, pattern, ((*hgopt == EXCLUDE_REGEX) ? (options & ~EXCLUDE_WILDCARDS) : (options & ~EXCLUDE_REGEX)) | *hgopt); }
void add_exclude (struct exclude *ex, char const *pattern, int options) { struct exclude_segment *seg; struct exclude_pattern *pat; struct patopts *patopts; if ((options & (EXCLUDE_REGEX|EXCLUDE_WILDCARDS)) && fnmatch_pattern_has_wildcards (pattern, options)) { if (! (ex->head && ex->head->type == exclude_pattern && ((ex->head->options & EXCLUDE_INCLUDE) == (options & EXCLUDE_INCLUDE)))) new_exclude_segment (ex, exclude_pattern, options); seg = ex->head; pat = &seg->v.pat; if (pat->exclude_count == pat->exclude_alloc) pat->exclude = x2nrealloc (pat->exclude, &pat->exclude_alloc, sizeof *pat->exclude); patopts = &pat->exclude[pat->exclude_count++]; patopts->options = options; if (options & EXCLUDE_REGEX) { int rc; int cflags = REG_NOSUB|REG_EXTENDED| ((options & FNM_CASEFOLD) ? REG_ICASE : 0); if (options & FNM_LEADING_DIR) { char *tmp; size_t len = strlen (pattern); while (len > 0 && ISSLASH (pattern[len-1])) --len; if (len == 0) rc = 1; else { tmp = xmalloc (len + 7); memcpy (tmp, pattern, len); strcpy (tmp + len, "(/.*)?"); rc = regcomp (&patopts->v.re, tmp, cflags); free (tmp); } } else rc = regcomp (&patopts->v.re, pattern, cflags); if (rc) { pat->exclude_count--; return; } } else { if (options & EXCLUDE_ALLOC) { pattern = xstrdup (pattern); exclude_add_pattern_buffer (ex, (char*) pattern); } patopts->v.pattern = pattern; } } else { char *str, *p; int exclude_hash_flags = (EXCLUDE_INCLUDE | EXCLUDE_ANCHORED | FNM_LEADING_DIR | FNM_CASEFOLD); if (! (ex->head && ex->head->type == exclude_hash && ((ex->head->options & exclude_hash_flags) == (options & exclude_hash_flags)))) new_exclude_segment (ex, exclude_hash, options); seg = ex->head; str = xstrdup (pattern); if ((options & (EXCLUDE_WILDCARDS | FNM_NOESCAPE)) == EXCLUDE_WILDCARDS) unescape_pattern (str); p = hash_insert (seg->v.table, str); if (p != str) free (str); } }