1/*	$NetBSD$	*/
2
3/* exclude.c -- exclude file names
4   Copyright 1992, 1993, 1994, 1997, 1999, 2000 Free Software Foundation, Inc.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; see the file COPYING.
18   If not, write to the Free Software Foundation,
19   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21/* Written by Paul Eggert <eggert@twinsun.com>  */
22
23#if HAVE_CONFIG_H
24# include <config.h>
25#endif
26
27#include <errno.h>
28#ifndef errno
29extern int errno;
30#endif
31#include <exclude.h>
32#include <fnmatch.h>
33#include <stdio.h>
34#include <sys/types.h>
35
36void *xmalloc PARAMS ((size_t));
37void *xrealloc PARAMS ((void *, size_t));
38
39/* Keep track of excluded file name patterns.  */
40
41struct exclude
42  {
43    char const **exclude;
44    int exclude_alloc;
45    int exclude_count;
46  };
47
48struct exclude *
49new_exclude (void)
50{
51  struct exclude *ex = (struct exclude *) xmalloc (sizeof (struct exclude));
52  ex->exclude_count = 0;
53  ex->exclude_alloc = 64;
54  ex->exclude = (char const **) xmalloc (ex->exclude_alloc * sizeof (char *));
55  return ex;
56}
57
58int
59excluded_filename (struct exclude const *ex, char const *f, int options)
60{
61  char const * const *exclude = ex->exclude;
62  int exclude_count = ex->exclude_count;
63  int i;
64
65  for (i = 0;  i < exclude_count;  i++)
66    if (fnmatch (exclude[i], f, options) == 0)
67      return 1;
68
69  return 0;
70}
71
72void
73add_exclude (struct exclude *ex, char const *pattern)
74{
75  if (ex->exclude_alloc <= ex->exclude_count)
76    ex->exclude = (char const **) xrealloc (ex->exclude,
77					    ((ex->exclude_alloc *= 2)
78					     * sizeof (char *)));
79
80  ex->exclude[ex->exclude_count++] = pattern;
81}
82
83int
84add_exclude_file (void (*add_func) PARAMS ((struct exclude *, char const *)),
85		  struct exclude *ex, char const *filename, char line_end)
86{
87  int use_stdin = filename[0] == '-' && !filename[1];
88  FILE *in;
89  char *buf;
90  char *p;
91  char const *pattern;
92  char const *lim;
93  size_t buf_alloc = 1024;
94  size_t buf_count = 0;
95  int c;
96  int e = 0;
97
98  if (use_stdin)
99    in = stdin;
100  else if (! (in = fopen (filename, "r")))
101    return -1;
102
103  buf = xmalloc (buf_alloc);
104
105  while ((c = getc (in)) != EOF)
106    {
107      buf[buf_count++] = c;
108      if (buf_count == buf_alloc)
109	buf = xrealloc (buf, buf_alloc *= 2);
110    }
111
112  buf = xrealloc (buf, buf_count + 1);
113
114  if (ferror (in))
115    e = errno;
116
117  if (!use_stdin && fclose (in) != 0)
118    e = errno;
119
120  for (pattern = p = buf, lim = buf + buf_count;  p <= lim;  p++)
121    if (p < lim ? *p == line_end : buf < p && p[-1])
122      {
123	*p = '\0';
124	(*add_func) (ex, pattern);
125	pattern = p + 1;
126      }
127
128  errno = e;
129  return e ? -1 : 0;
130}
131