1 #ifndef LINT
2 /* @(#) makelist.c 2.3 88/01/24 12:46:44 */
3 static char sccsid[]="@(#) makelist.c 2.3 88/01/24 12:46:44";
4 #endif /* LINT */
5
6 /*
7 Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
8 (C) Copyright 1988 Rahul Dhesi -- All rights reserved
9 */
10
11 #include "options.h"
12 #include "portable.h"
13 #include "errors.i"
14 #include "zoo.h"
15 #include "zooio.h"
16 #include "various.h"
17
18 #include "zoofns.h"
19 #include "assert.h"
20 #include "debug.h"
21
22 char *nameptr PARMS((char *));
23 void modpath PARMS((char *));
24
25 /*******************/
26 /*
27 makelist() gets all pathnames corresponding to a set of filespecs and
28 adds them to a list. Not more than "flistsize" pathnames are added.
29 Into `longest' it returns the length of the longest name added, or
30 zero if none added.
31
32 Files ignore1, ignore2, and ignore3 are not added to the list.
33 A file that is a device/directory is also not added to the list.
34
35 However, if ignore1 is NULL, both these tests are skipped and all files
36 will be added to the list.
37 */
38
makelist(argc,argv,flist,flistsize,ignore1,ignore2,ignore3,longest)39 void makelist (argc, argv, flist, flistsize, ignore1, ignore2, ignore3, longest)
40 int argc; /* number of filespec supplied */
41 char *argv[]; /* array of pointers to supplied filespecs */
42 register char *flist[]; /* array of pointers to filenames we will add */
43 int flistsize; /* home many names we can use */
44 char *ignore1, *ignore2, *ignore3; /* files to exclude from list */
45 int *longest; /* length of longest name in list */
46 {
47 char *this_path; /* current pathname */
48 int fptr; /* pointer to within flist */
49 register int i, j; /* loop counters */
50
51 #ifdef WILDCARD
52 char *pat_name; /* filename part of pattern */
53 #endif
54
55 int gap; /* for Shell sort */
56
57 flistsize--; /* allow for one terminating NULL entry */
58 fptr = *longest = 0;
59
60 assert(argc > 0);
61
62 #define WCLEN 4 /* length needed for wildcard, and a little extra */
63
64 while (argc > 0) {
65 #ifdef WILDCARD
66 int argok = 0; /* arg not matched yet */
67 #endif
68 char *this_arg;
69 this_arg = emalloc (strlen (*argv) + WCLEN);
70 strcpy (this_arg, *argv);
71
72 /* Initialize fileset 0. Select all files -- we will later
73 filter out the ones wanted */
74 #ifdef FOLD
75 str_lwr (this_arg);
76 #endif
77
78 #ifdef WILDCARD
79 pat_name = str_dup (nameptr (this_arg)); /* pattern without path */
80 #ifdef VER_CH /* trailing version field */
81 {
82 static char version_field[] = " *";
83 char *p;
84 p = strrchr (pat_name, VER_CH);
85 if (p == NULL) {
86 *version_field = VER_CH;
87 pat_name = newcat (pat_name, version_field); /* adds trailing ";*" */
88 }
89 }
90 #endif
91 /*
92 replace filename by wildcard; however, if argument ends in slash,
93 then simply append wildcard so we get all files in that directory
94 */
95 #ifdef FORCESLASH
96 fixslash (this_arg); /* convert backslashes to slashes */
97 #endif
98
99 if (*lastptr(this_arg) == *(char *) PATH_CH) {
100 strcat (this_arg, WILDCARD);
101 pat_name = "*"; /* and select all files */
102 } else
103 #ifdef SPEC_WILD
104 spec_wild (this_arg);
105 #else
106 strcpy (nameptr (this_arg), WILDCARD);
107 #endif /* SPEC_WILD */
108 #endif /* WILDCARD */
109
110 nextfile (0, this_arg, 0);
111 while (fptr < flistsize &&
112 (this_path = nextfile(1, (char *) NULL, 0)) != NULL) {
113 char *this_name = nameptr (this_path);
114 modpath (this_path); /* do any needed changes to path */
115
116 #ifdef IGNORECASE
117 #define COMPARE str_icmp
118 #else
119 #define COMPARE strcmp
120 #endif
121 if (ignore1 != NULL) {
122 if (samefile (this_name,ignore1) || /* exclude ignored files */
123 samefile (this_name,ignore2) ||
124 samefile (this_name,ignore3))
125 continue;
126
127 #ifdef CHEKUDIR
128 if (isuadir(this_path))
129 continue;
130 #else /* CHEKUDIR */
131 # ifdef CHEKDIR
132 if (isfdir(this_path))
133 continue;
134 # endif /* CHEKDIR */
135 #endif /* CHEKUDIR */
136 } /* end if ignore1 ! = NULL */
137
138 /*
139 If WILDCARD is defined (e.g. AmigaDOS, MS-DOS, VAX/VMS), then nextfile()
140 returns all filenames and we must now select the ones we need by pattern
141 matching. If WILDCARD is not defined (e.g. **IX), filenames have already been
142 selected by the shell and need not be tested again.
143 */
144 #ifdef WILDCARD
145 if (match_half (this_name,pat_name) ||
146 match_half (pat_name, "?-?") && /* character range */
147 *this_name >= *pat_name && *this_name <= pat_name[2])
148 #endif
149 {
150 #ifdef WILDCARD
151 argok = 1; /* remember arg matched */
152 #endif
153 flist[fptr++] = str_dup (this_path);
154 if (*longest < strlen(this_path))
155 *longest = strlen(this_path);
156 }
157
158 } /* end while */
159 #ifdef WILDCARD
160 if (argok == 0) { /* no match for argument */
161 prterror ('e', "Could not open %s\n", *argv);
162 }
163 #endif
164 argc--;
165 argv++;
166 }
167 /* fptr is now 1 + index of last item in array */
168
169 if (this_path != NULL && fptr >= flistsize)
170 prterror ('w', too_many_files, flistsize);
171 #ifndef DONT_SORT
172 /* Shell sort -- K&R p. 58 */
173 for (gap = fptr/2; gap > 0; gap /= 2)
174 for (i = gap; i < fptr; i++)
175 for (j = i - gap; j >= 0 &&
176 strcmp(flist[j],flist[j+gap]) > 0; j -= gap) {
177 char *t = flist[j]; flist[j] = flist[j+gap]; flist[j+gap] = t;
178 }
179 #endif /* DONT_SORT */
180
181 fptr--; /* fptr is now index of last item in array */
182
183 /* Remove duplicates */
184 for (i = 0; i < fptr; i++) {
185 while (i<fptr && COMPARE(flist[i],flist[i+1]) == 0) {
186 for (j = i; j < fptr; j++)
187 flist[j] = flist[j+1];
188 fptr--;
189 }
190 }
191
192 flist[++fptr] = NULL; /* NULL entry terminates list */
193 }
194
195 /*******
196 modpath() makes any changes needed before pathname is stored;
197 currently these could involve folding it to lower case and
198 converting backslashes to forward slashes
199 */
200
201 /*ARGSUSED*/
modpath(path)202 void modpath (path)
203 char *path;
204 {
205 #ifdef FOLD
206 str_lwr (path);
207 #endif
208
209 #ifdef FORCESLASH
210 fixslash (path); /* convert backslashes to slashes */
211 #endif
212 }
213
214 #ifdef CHEKDIR
215 /* Function isfdir returns 1 if pathname is a directory else 0 */
isfdir(this_path)216 int isfdir (this_path)
217 char *this_path;
218 {
219 int dir;
220 ZOOFILE f;
221 f = zooopen (this_path, Z_READ);
222 if (f == NOFILE)
223 return 0;
224 else {
225 dir = isadir(f); zooclose(f);
226 }
227 return (dir);
228 }
229 #endif
230