Tweak comments.
[gnulib.git] / lib / exclude.c
index 5a1e1ee..7c038b2 100644 (file)
@@ -1,7 +1,7 @@
 /* exclude.c -- exclude file names
 
-   Copyright 1992, 1993, 1994, 1997, 1999, 2000, 2001 Free Software
-   Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003 Free
+   Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 # include <config.h>
 #endif
 
-#if HAVE_STDBOOL_H
-# include <stdbool.h>
-#else
-typedef enum {false = 0, true = 1} bool;
-#endif
+#include <stdbool.h>
 
+#include <ctype.h>
 #include <errno.h>
 #ifndef errno
 extern int errno;
 #endif
+#include <stddef.h>
 #include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
 #if HAVE_STDLIB_H
 # include <stdlib.h>
 #endif
@@ -55,20 +50,41 @@ extern int errno;
 # endif
 #endif
 
-#include <exclude.h>
-#include <fnmatch.h>
-#include <xalloc.h>
+#include "exclude.h"
+#include "fnmatch.h"
+#include "unlocked-io.h"
+#include "xalloc.h"
 
 #ifndef SIZE_MAX
 # define SIZE_MAX ((size_t) -1)
 #endif
 
+#if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII)
+# define IN_CTYPE_DOMAIN(c) true
+#else
+# define IN_CTYPE_DOMAIN(c) isascii (c)
+#endif
+
+static inline bool
+is_space (unsigned char c)
+{
+  return IN_CTYPE_DOMAIN (c) && isspace (c);
+}
+
 /* Verify a requirement at compile-time (unlike assert, which is runtime).  */
 #define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
 
+/* Non-GNU systems lack these options, so we don't need to check them.  */
+#ifndef FNM_CASEFOLD
+# define FNM_CASEFOLD 0
+#endif
+#ifndef FNM_LEADING_DIR
+# define FNM_LEADING_DIR 0
+#endif
+
 verify (EXCLUDE_macros_do_not_collide_with_FNM_macros,
        (((EXCLUDE_ANCHORED | EXCLUDE_INCLUDE | EXCLUDE_WILDCARDS)
-         & (FNM_FILE_NAME | FNM_NOESCAPE | FNM_PERIOD | FNM_LEADING_DIR
+         & (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD | FNM_LEADING_DIR
             | FNM_CASEFOLD))
         == 0));
 
@@ -95,11 +111,10 @@ struct exclude
 struct exclude *
 new_exclude (void)
 {
-  struct exclude *ex = (struct exclude *) xmalloc (sizeof *ex);
+  struct exclude *ex = xmalloc (sizeof *ex);
   ex->exclude_count = 0;
   ex->exclude_alloc = (1 << 6); /* This must be a power of 2.  */
-  ex->exclude = (struct patopts *) xmalloc (ex->exclude_alloc
-                                           * sizeof ex->exclude[0]);
+  ex->exclude = xmalloc (ex->exclude_alloc * sizeof ex->exclude[0]);
   return ex;
 }
 
@@ -118,17 +133,20 @@ free_exclude (struct exclude *ex)
 static int
 fnmatch_no_wildcards (char const *pattern, char const *f, int options)
 {
-  if (! (options & FNM_CASEFOLD))
-    return (options & FNM_LEADING_DIR ? strcasecmp : strcmp) (pattern, f);
+  if (! (options & FNM_LEADING_DIR))
+    return ((options & FNM_CASEFOLD)
+           ? strcasecmp (pattern, f)
+           : strcmp (pattern, f));
   else
     {
       size_t patlen = strlen (pattern);
-      int r = ((options & FNM_LEADING_DIR ? strncasecmp : strncmp)
-              (pattern, f, patlen));
+      int r = ((options & FNM_CASEFOLD)
+               ? strncasecmp (pattern, f, patlen)
+               : strncmp (pattern, f, patlen));
       if (! r)
        {
          r = f[patlen];
-         if (r == '/' && (options & FNM_LEADING_DIR))
+         if (r == '/')
            r = 0;
        }
       return r;
@@ -144,7 +162,7 @@ excluded_filename (struct exclude const *ex, char const *f)
 
   /* If no options are given, the default is to include.  */
   if (exclude_count == 0)
-    return 0;
+    return false;
   else
     {
       struct patopts const *exclude = ex->exclude;
@@ -161,7 +179,7 @@ excluded_filename (struct exclude const *ex, char const *f)
          int options = exclude[i].options;
          if (excluded == !! (options & EXCLUDE_INCLUDE))
            {
-             int (*matcher) PARAMS ((char const *, char const *, int)) =
+             int (*matcher) (char const *, char const *, int) =
                (options & EXCLUDE_WILDCARDS
                 ? fnmatch
                 : fnmatch_no_wildcards);
@@ -194,8 +212,7 @@ add_exclude (struct exclude *ex, char const *pattern, int options)
       if (! (0 < s && s <= SIZE_MAX / sizeof ex->exclude[0]))
        xalloc_die ();
       ex->exclude_alloc = s;
-      ex->exclude = (struct patopts *) xrealloc (ex->exclude,
-                                                s * sizeof ex->exclude[0]);
+      ex->exclude = xrealloc (ex->exclude, s * sizeof ex->exclude[0]);
     }
 
   patopts = &ex->exclude[ex->exclude_count++];
@@ -204,12 +221,12 @@ add_exclude (struct exclude *ex, char const *pattern, int options)
 }
 
 /* Use ADD_FUNC to append to EX the patterns in FILENAME, each with
-   OPTIONS.  LINE_END terminates each pattern in the file.  Return -1
-   on failure, 0 on success.  */
+   OPTIONS.  LINE_END terminates each pattern in the file.  If
+   LINE_END is a space character, ignore trailing spaces and empty
+   lines in FILE.  Return -1 on failure, 0 on success.  */
 
 int
-add_exclude_file (void (*add_func) PARAMS ((struct exclude *,
-                                           char const *, int)),
+add_exclude_file (void (*add_func) (struct exclude *, char const *, int),
                  struct exclude *ex, char const *filename, int options,
                  char line_end)
 {
@@ -250,12 +267,28 @@ add_exclude_file (void (*add_func) PARAMS ((struct exclude *,
     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);
+  pattern = buf;
 
-  for (pattern = p = buf, lim = buf + buf_count;  p <= lim;  p++)
-    if (p < lim ? *p == line_end : buf < p && p[-1])
+  for (p = buf; p < lim; p++)
+    if (*p == line_end)
       {
-       *p = '\0';
+       char *pattern_end = p;
+
+       if (is_space (line_end))
+         {
+           for (; ; pattern_end--)
+             if (pattern_end == pattern)
+               goto next_pattern;
+             else if (! is_space (pattern_end[-1]))
+               break;
+         }
+
+       *pattern_end = '\0';
        (*add_func) (ex, pattern, options);
+
+      next_pattern:
        pattern = p + 1;
       }