]> Dogcows Code - chaz/tar/blob - src/tcexparg.c
Initial revision
[chaz/tar] / src / tcexparg.c
1 /* tcexparg.c - Unix-style command line wildcards for Turbo C 2.0
2
3 This file is in the public domain.
4
5 Compile your main program with -Dmain=_main and link with this file.
6
7 After that, it is just as if the operating system had expanded the
8 arguments, except that they are not sorted. The program name and all
9 arguments that are expanded from wildcards are lowercased.
10
11 Syntax for wildcards:
12 * Matches zero or more of any character (except a '.' at
13 the beginning of a name).
14 ? Matches any single character.
15 [r3z] Matches 'r', '3', or 'z'.
16 [a-d] Matches a single character in the range 'a' through 'd'.
17 [!a-d] Matches any single character except a character in the
18 range 'a' through 'd'.
19
20 The period between the filename root and its extension need not be
21 given explicitly. Thus, the pattern `a*e' will match 'abacus.exe'
22 and 'axyz.e' as well as 'apple'. Comparisons are not case sensitive.
23
24 Authors:
25 The expargs code is a modification of wildcard expansion code
26 written for Turbo C 1.0 by
27 Richard Hargrove
28 Texas Instruments, Inc.
29 P.O. Box 869305, m/s 8473
30 Plano, Texas 75086
31 214/575-4128
32 and posted to USENET in September, 1987.
33
34 The wild_match code was written by Rich Salz, rsalz@bbn.com,
35 posted to net.sources in November, 1986.
36
37 The code connecting the two is by Mike Slomin, bellcore!lcuxa!mike2,
38 posted to comp.sys.ibm.pc in November, 1988.
39
40 Major performance enhancements and bug fixes, and source cleanup,
41 by David MacKenzie, djm@ai.mit.edu. */
42
43 #include <stdio.h>
44 #include <string.h>
45 #include <stdlib.h>
46 #include <dos.h>
47 #include <dir.h>
48
49 /* Number of new arguments to allocate space for at a time. */
50 #define ARGS_INCREMENT 10
51
52 /* The name this program was run with, for error messages. */
53 static char *program_name;
54
55 static char **grow_argv (char **new_argv, int new_argc);
56 static void fatal_error (const char *message);
57
58 int wild_match (char *string, char *pattern);
59 char *basename (char *path);
60
61 char **expargs (int *, char **);
62
63 #ifdef main
64 #undef main
65 #endif
66
67 int
68 main (int argc, char **argv, char **envp)
69 {
70 argv = expargs (&argc, argv);
71 return _main (argc, argv, envp);
72 }
73
74 char **
75 expargs (int *pargc, char **argv)
76 {
77 char path[MAXPATH + 1];
78 char **new_argv;
79 struct ffblk block;
80 char *path_base;
81 char *arg_base;
82 int argind;
83 int new_argc;
84 int path_length;
85 int matched;
86
87 program_name = argv[0];
88 if (program_name && *program_name)
89 strlwr (program_name);
90 new_argv = grow_argv (NULL, 0);
91 new_argv[0] = argv[0];
92 new_argc = 1;
93
94 for (argind = 1; argind < *pargc; ++argind)
95 {
96 matched = 0;
97 if (strpbrk (argv[argind], "?*[") != NULL)
98 {
99 strncpy (path, argv[argind], MAXPATH - 3);
100 path_base = basename (path);
101 strcpy (path_base, "*.*");
102 arg_base = argv[argind] + (path_base - path);
103
104 if (!findfirst (path, &block, FA_DIREC))
105 {
106 strlwr (path);
107 do
108 {
109 /* Only match "." and ".." explicitly. */
110 if (*block.ff_name == '.' && *arg_base != '.')
111 continue;
112 path_length = stpcpy (path_base, block.ff_name) - path + 1;
113 strlwr (path_base);
114 if (wild_match (path, argv[argind]))
115 {
116 matched = 1;
117 new_argv[new_argc] = (char *) malloc (path_length);
118 if (new_argv[new_argc] == NULL)
119 fatal_error ("memory exhausted");
120 strcpy (new_argv[new_argc++], path);
121 new_argv = grow_argv (new_argv, new_argc);
122 }
123 }
124 while (!findnext (&block));
125 }
126 }
127 if (matched == 0)
128 new_argv[new_argc++] = argv[argind];
129 new_argv = grow_argv (new_argv, new_argc);
130 }
131
132 *pargc = new_argc;
133 new_argv[new_argc] = NULL;
134 return &new_argv[0];
135 }
136
137 /* Return a pointer to the last element of PATH. */
138
139 char *
140 basename (char *path)
141 {
142 char *tail;
143
144 for (tail = path; *path; ++path)
145 if (*path == ':' || *path == '\\')
146 tail = path + 1;
147 return tail;
148 }
149
150 static char **
151 grow_argv (char **new_argv, int new_argc)
152 {
153 if (new_argc % ARGS_INCREMENT == 0)
154 {
155 new_argv = (char **) realloc
156 (new_argv, sizeof (char *) * (new_argc + ARGS_INCREMENT));
157 if (new_argv == NULL)
158 fatal_error ("memory exhausted");
159 }
160 return new_argv;
161 }
162
163 static void
164 fatal_error (const char *message)
165 {
166 putc ('\n', stderr);
167 if (program_name && *program_name)
168 {
169 fputs (program_name, stderr);
170 fputs (": ", stderr);
171 }
172 fputs (message, stderr);
173 putc ('\n', stderr);
174 exit (1);
175 }
176
177 /* Shell-style pattern matching for ?, \, [], and * characters.
178 I'm putting this replacement in the public domain.
179
180 Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. */
181
182 /* The character that inverts a character class; '!' or '^'. */
183 #define INVERT '!'
184
185 static int star (char *string, char *pattern);
186
187 /* Return nonzero if `string' matches Unix-style wildcard pattern
188 `pattern'; zero if not. */
189
190 int
191 wild_match (char *string, char *pattern)
192 {
193 int prev; /* Previous character in character class. */
194 int matched; /* If 1, character class has been matched. */
195 int reverse; /* If 1, character class is inverted. */
196
197 for (; *pattern; string++, pattern++)
198 switch (*pattern)
199 {
200 case '\\':
201 /* Literal match with following character; fall through. */
202 pattern++;
203 default:
204 if (*string != *pattern)
205 return 0;
206 continue;
207 case '?':
208 /* Match anything. */
209 if (*string == '\0')
210 return 0;
211 continue;
212 case '*':
213 /* Trailing star matches everything. */
214 return *++pattern ? star (string, pattern) : 1;
215 case '[':
216 /* Check for inverse character class. */
217 reverse = pattern[1] == INVERT;
218 if (reverse)
219 pattern++;
220 for (prev = 256, matched = 0; *++pattern && *pattern != ']';
221 prev = *pattern)
222 if (*pattern == '-'
223 ? *string <= *++pattern && *string >= prev
224 : *string == *pattern)
225 matched = 1;
226 if (matched == reverse)
227 return 0;
228 continue;
229 }
230
231 return *string == '\0';
232 }
233
234 static int
235 star (char *string, char *pattern)
236 {
237 while (wild_match (string, pattern) == 0)
238 if (*++string == '\0')
239 return 0;
240 return 1;
241 }
This page took 0.042071 seconds and 4 git commands to generate.