1 /* File-name wildcard pattern matching for GNU.
2 Copyright (C) 1985, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 1, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* To whomever it may concern: I have never seen the code which most
19 Unix programs use to perform this function. I wrote this from scratch
20 based on specifications for the pattern matching. --RMS. */
26 #include <sys/types.h>
32 #define D_NAMLEN(d) strlen((d)->d_name)
33 #define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
35 #define bcopy(s, d, n) memcpy ((d), (s), (n))
37 #define rindex strrchr
40 #define alloca __builtin_alloca
43 int glob_pattern_p (char *);
44 int glob_match (char *, char *, int);
45 char **glob_vector (char *, const char *);
46 char **glob_filename (char *);
48 /* Nonzero if '*' and '?' do not match an initial '.' for glob_filename. */
49 int noglob_dot_filenames = 1;
51 static int glob_match_after_star (char *, char *);
54 collate_range_cmp (int a, int b)
59 if ((unsigned char)a == (unsigned char)b)
63 if ((r = strcoll(s[0], s[1])) == 0)
64 r = (unsigned char)a - (unsigned char)b;
68 /* Return nonzero if PATTERN has any special globbing chars in it. */
71 glob_pattern_p (char *pattern)
77 while ((c = *p++) != '\0')
84 case '[': /* Only accept an open brace if there is a close */
85 open++; /* brace to match it. Bracket expressions must be */
86 continue; /* complete, according to Posix.2 */
101 /* Match the pattern PATTERN against the string TEXT;
102 return 1 if it matches, 0 otherwise.
104 A match means the entire string TEXT is used up in matching.
106 In the pattern string, `*' matches any sequence of characters,
107 `?' matches any character, [SET] matches any character in the specified set,
108 [!SET] matches any character not in the specified set.
110 A set is composed of characters or ranges; a range looks like
111 character hyphen character (as in 0-9 or A-Z).
112 [0-9a-zA-Z_] is the set of characters allowed in C identifiers.
113 Any other character in the pattern must be matched exactly.
115 To suppress the special syntactic significance of any of `[]*?!-\',
116 and match the character exactly, precede it with a `\'.
118 If DOT_SPECIAL is nonzero,
119 `*' and `?' do not match `.' at the beginning of TEXT. */
122 glob_match (char *pattern, char *text, int dot_special)
124 char *p = pattern, *t = text;
127 while ((c = *p++) != '\0')
131 if (*t == '\0' || (dot_special && t == text && *t == '.'))
143 if (dot_special && t == text && *t == '.')
145 return glob_match_after_star (p, t);
156 invert = (*p == '!');
164 char cstart = c, cend = c;
177 /* matched a single bracket */
193 if ( collate_range_cmp (c1, cstart) >= 0
194 && collate_range_cmp (c1, cend) <= 0
205 /* Skip the rest of the [...] construct that already matched. */
230 /* Like glob_match, but match PATTERN against any final segment of TEXT. */
233 glob_match_after_star (char *pattern, char *text)
235 char *p = pattern, *t = text;
238 while ((c = *p++) == '?' || c == '*')
239 if (c == '?' && *t++ == '\0')
253 if ((c == '[' || *t == c1) && glob_match (p, t, 0))
260 /* Return a vector of names of files in directory DIR
261 whose names match glob pattern PAT.
262 The names are not in any particular order.
263 Wildcards at the beginning of PAT do not match an initial period
264 if noglob_dot_filenames is nonzero.
266 The vector is terminated by an element that is a null pointer.
268 To free the space allocated, first free the vector's elements,
269 then free the vector.
271 Return NULL if cannot get enough memory to hold the pointer
274 Return -1 if cannot access directory DIR.
275 Look in errno for more information. */
278 glob_vector (char *pat, const char *dir)
282 struct globval *next;
288 struct globval *lastlink;
289 struct globval *nextlink;
304 /* Scan the directory, finding all names that match.
305 For each name that matches, allocate a struct globval
306 on the stack and store the name in it.
307 Chain those structs together; lastlink is the front of the chain. */
311 /* Make globbing interruptible in the bash shell. */
312 extern int interrupt_state;
325 if (REAL_DIR_ENTRY (dp)
326 && glob_match (pat, dp->d_name, noglob_dot_filenames))
328 nextlink = (struct globval *) alloca (sizeof (struct globval));
329 nextlink->next = lastlink;
330 i = D_NAMLEN (dp) + 1;
331 nextname = (char *) malloc (i);
332 if (nextname == NULL)
338 nextlink->name = nextname;
339 bcopy (dp->d_name, nextname, i);
347 name_vector = (char **) malloc ((count + 1) * sizeof (char *));
348 lose |= name_vector == NULL;
351 /* Have we run out of memory? */
357 /* Here free the strings we have got. */
360 free (lastlink->name);
361 lastlink = lastlink->next;
366 /* Copy the name pointers from the linked list into the vector. */
367 for (i = 0; i < count; ++i)
369 name_vector[i] = lastlink->name;
370 lastlink = lastlink->next;
373 name_vector[count] = NULL;
377 /* Return a new array, replacing ARRAY, which is the concatenation
378 of each string in ARRAY to DIR.
379 Return NULL if out of memory. */
382 glob_dir_to_array (char *dir, char **array)
392 if (dir[l - 1] != '/')
395 for (i = 0; array[i] != NULL; i++)
398 result = (char **) malloc ((i + 1) * sizeof (char *));
402 for (i = 0; array[i] != NULL; i++)
404 result[i] = (char *) malloc (1 + l + add_slash + strlen (array[i]));
405 if (result[i] == NULL)
407 strcpy (result[i], dir);
410 strcpy (result[i] + l + add_slash, array[i]);
414 /* Free the input array. */
415 for (i = 0; array[i] != NULL; i++)
417 free ((char *) array);
421 /* Do globbing on PATHNAME. Return an array of pathnames that match,
422 marking the end of the array with a null-pointer as an element.
423 If no pathnames match, then the array is empty (first element is null).
424 If there isn't enough memory, then return NULL.
425 If a file system error occurs, return -1; `errno' has the error code.
427 Wildcards at the beginning of PAT, or following a slash,
428 do not match an initial period if noglob_dot_filenames is nonzero. */
431 glob_filename (char *pathname)
434 unsigned int result_size;
435 char *directory_name, *filename;
436 unsigned int directory_len;
438 result = (char **) malloc (sizeof (char *));
445 /* Find the filename. */
446 filename = rindex (pathname, '/');
447 if (filename == NULL)
450 directory_name = NULL;
455 directory_len = (filename - pathname) + 1;
456 directory_name = (char *) alloca (directory_len + 1);
457 bcopy (pathname, directory_name, directory_len);
458 directory_name[directory_len] = '\0';
462 /* If directory_name contains globbing characters, then we
463 have to expand the previous levels. Just recurse. */
464 if (glob_pattern_p (directory_name))
469 if (directory_name[directory_len - 1] == '/')
470 directory_name[directory_len - 1] = '\0';
472 directories = glob_filename (directory_name);
473 if (directories == NULL)
475 else if (directories == (char **) -1)
477 else if (*directories == NULL)
479 free ((char *) directories);
483 /* We have successfully globbed the preceding directory name.
484 For each name in DIRECTORIES, call glob_vector on it and
485 FILENAME. Concatenate the results together. */
486 for (i = 0; directories[i] != NULL; i++)
488 char **temp_results = glob_vector (filename, directories[i]);
489 if (temp_results == NULL)
491 else if (temp_results == (char **) -1)
492 /* This filename is probably not a directory. Ignore it. */
496 char **array = glob_dir_to_array (directories[i], temp_results);
500 while (array[l] != NULL)
503 result = (char **) realloc (result,
504 (result_size + l) * sizeof (char *));
508 for (l = 0; array[l] != NULL; ++l)
509 result[result_size++ - 1] = array[l];
510 result[result_size - 1] = NULL;
511 free ((char *) array);
514 /* Free the directories. */
515 for (i = 0; directories[i] != NULL; i++)
516 free (directories[i]);
517 free ((char *) directories);
522 /* If there is only a directory name, return it. */
523 if (*filename == '\0')
525 result = (char **) realloc ((char *) result, 2 * sizeof (char *));
528 result[0] = (char *) malloc (directory_len + 1);
529 if (result[0] == NULL)
533 bcopy (directory_name, result[0], directory_len + 1);
540 /* Otherwise, just return what glob_vector
541 returns appended to the directory name. */
542 char **temp_results = glob_vector (filename,
544 ? "." : directory_name));
546 if (temp_results == NULL || temp_results == (char **) -1)
551 temp_results = glob_dir_to_array (directory_name, temp_results);
555 /* We get to memory error if the program has run out of memory, or
556 if this is the shell, and we have been interrupted. */
561 for (i = 0; result[i] != NULL; ++i)
563 free ((char *) result);
567 extern int interrupt_state;
570 throw_to_top_level ();
579 main (int argc, char **argv)
584 for (optind = 1; optind < argc; optind++)
586 value = glob_filename (argv[optind]);
588 puts ("virtual memory exhausted");
589 else if (value == (char **) -1)
590 perror (argv[optind]);
592 for (i = 0; value[i] != NULL; i++)