1% Copyright (C) 2012-2017,2018 John E. Davis
2%
3% This file is part of the S-Lang Library and may be distributed under the
4% terms of the GNU General Public License.  See the file COPYING for
5% more information.
6%---------------------------------------------------------------------------
7private define needs_globbing (path)
8{
9   return (path != str_delete_chars (path, "*?["));
10}
11
12private define do_the_glob (dir, pat)
13{
14   variable files;
15
16   if (dir == "")
17     files = listdir (".");
18   else
19     files = listdir (dir);
20
21   if (files == NULL)
22     return String_Type[0];
23
24   files = [files, ".", ".."];
25
26   if ((pat[0] == '?') || (pat[0] == '*'))
27     {
28	files = files [where (strncmp (files, ".", 1))];
29     }
30
31   if (length (files) == 0)
32     return files;
33
34   pat = glob_to_regexp (pat);
35
36   variable i = where (array_map (Int_Type, &string_match, files, pat, 1));
37   if (length (i) == 0)
38     return String_Type[0];
39
40   files = files[i];
41   if (dir == "")
42     return files;
43
44   return array_map (String_Type, &path_concat, dir, files);
45}
46
47private define is_dir (dirs)
48{
49   variable n = length(dirs);
50   variable ok = Char_Type[n];
51   _for (0, n-1, 1)
52     {
53	variable i = ();
54	variable st = stat_file (dirs[i]);
55	if (st == NULL)
56	  continue;
57	ok[i] = stat_is ("dir", st.st_mode);
58     }
59   return ok;
60}
61
62define glob ();		       %  recursion
63define glob ()
64{
65   variable patterns = __pop_args (_NARGS);
66   if (length (patterns) == 0)
67     throw UsageError, "files = glob (patterns...)";
68
69   patterns = [__push_args (patterns)];
70
71   variable list = String_Type[0];
72   foreach (patterns)
73     {
74	variable pat = ();
75
76	!if (needs_globbing (pat))
77	  {
78	     if (NULL != stat_file (pat))
79	       list = [list, pat];
80
81	     continue;
82	  }
83
84	variable base = path_basename (pat);
85	variable dir = "";
86	if (base != pat)
87	  dir = path_dirname (pat);
88
89	if (needs_globbing (dir))
90	  {
91	     variable dirs = glob (dir);
92	     !if (strlen (base))
93	       {
94		  list = [list, dirs[where(is_dir (dirs))]];
95		  continue;
96	       }
97
98	     foreach dir (glob (dir))
99	       list = [list, do_the_glob (dir, base)];
100
101	     continue;
102	  }
103
104	list = [list, do_the_glob (dir, base)];
105     }
106   return list;
107}
108
109#ifntrue
110define slsh_main ()
111{
112   variable files = glob (__argv[[1:]]);
113   foreach (files)
114     {
115	variable f = ();
116	fprintf (stdout, "%s\n", f);
117     }
118}
119#endif
120
121$1 = path_concat (path_dirname (__FILE__), "help/glob.hlp");
122if (NULL != stat_file ($1))
123  add_doc_file ($1);
124
125provide ("glob");
126