8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sh / expand.c
blobb9b1458edaf3404d49584cbdf3ede2b51b0d5199
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 1995 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 * UNIX shell
36 #include "defs.h"
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <dirent.h>
44 * globals (file name generation)
46 * "*" in params matches r.e ".*"
47 * "?" in params matches r.e. "."
48 * "[...]" in params matches character class
49 * "[...a-z...]" in params matches a through z.
52 static void addg(unsigned char *, unsigned char *, unsigned char *,
53 unsigned char *);
54 void makearg(struct argnod *);
56 int
57 expand(unsigned char *as, int rcnt)
59 int count;
60 DIR *dirf;
61 BOOL dir = 0;
62 unsigned char *rescan = 0;
63 unsigned char *slashsav = 0;
64 unsigned char *s, *cs;
65 unsigned char *s2 = 0;
66 struct argnod *schain = gchain;
67 BOOL slash;
68 int len;
69 wchar_t wc;
71 if (trapnote & SIGSET)
72 return (0);
73 s = cs = as;
75 * check for meta chars
78 BOOL open;
80 slash = 0;
81 open = 0;
84 if ((len = mbtowc(&wc, (char *)cs, MB_LEN_MAX)) <= 0) {
85 len = 1;
86 wc = (unsigned char)*cs;
89 cs += len;
90 switch (wc) {
91 case 0:
92 if (rcnt && slash)
93 break;
94 else
95 return (0);
97 case '/':
98 slash++;
99 open = 0;
100 continue;
102 case '[':
103 open++;
104 continue;
106 case ']':
107 if (open == 0)
108 continue;
110 case '?':
111 case '*':
112 if (rcnt > slash)
113 continue;
114 else
115 cs--;
116 break;
118 case '\\':
119 cs++;
120 default:
121 continue;
123 break;
124 } while (TRUE);
127 for (;;) {
128 if (cs == s) {
129 s = (unsigned char *)nullstr;
130 break;
131 } else if (*--cs == '/') {
132 *cs = 0;
133 if (s == cs)
134 s = (unsigned char *)"/";
135 else {
137 * push trimmed copy of directory prefix
138 * onto stack
140 s2 = cpystak(s);
141 trim(s2);
142 s = s2;
144 break;
148 if ((dirf = opendir(*s ? (char *)s : (char *)".")) != 0)
149 dir++;
151 /* Let s point to original string because it will be trimmed later */
152 if (s2)
153 s = as;
154 count = 0;
155 if (*cs == 0)
156 slashsav = cs++; /* remember where first slash in as is */
158 /* check for rescan */
159 if (dir) {
160 unsigned char *rs;
161 struct dirent *e;
163 rs = cs;
164 do /* find next / in as */
166 if (*rs == '/') {
167 rescan = rs;
168 *rs = 0;
169 gchain = 0;
171 } while (*rs++);
173 while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0) {
174 if (e->d_name[0] == '.' && *cs != '.')
175 continue;
177 if (gmatch(e->d_name, cs)) {
178 addg(s, (unsigned char *)e->d_name, rescan,
179 slashsav);
180 count++;
183 (void) closedir(dirf);
185 if (rescan) {
186 struct argnod *rchain;
188 rchain = gchain;
189 gchain = schain;
190 if (count) {
191 count = 0;
192 while (rchain) {
193 count += expand(rchain->argval,
194 slash + 1);
195 rchain = rchain->argnxt;
198 *rescan = '/';
202 if (slashsav)
203 *slashsav = '/';
204 return (count);
207 static void
208 addg(unsigned char *as1, unsigned char *as2, unsigned char *as3,
209 unsigned char *as4)
211 unsigned char *s1, *s2;
212 int c;
213 int len;
214 wchar_t wc;
216 s2 = locstak() + BYTESPERWORD;
217 s1 = as1;
218 if (as4) {
219 while (c = *s1++) {
220 if (s2 >= brkend)
221 growstak(s2);
222 *s2++ = c;
225 * Restore first slash before the first metacharacter
226 * if as1 is not "/"
228 if (as4 + 1 == s1) {
229 if (s2 >= brkend)
230 growstak(s2);
231 *s2++ = '/';
234 /* add matched entries, plus extra \\ to escape \\'s */
235 s1 = as2;
236 for (;;) {
237 if ((len = mbtowc(&wc, (char *)s1, MB_LEN_MAX)) <= 0) {
238 len = 1;
239 wc = (unsigned char)*s1;
241 if (s2 >= brkend)
242 growstak(s2);
244 if (wc == 0) {
245 *s2 = *s1++;
246 break;
249 if (wc == '\\') {
250 *s2++ = '\\';
251 if (s2 >= brkend)
252 growstak(s2);
253 *s2++ = '\\';
254 s1++;
255 continue;
257 if ((s2 + len) >= brkend)
258 growstak(s2 + len);
259 memcpy(s2, s1, len);
260 s2 += len;
261 s1 += len;
263 if (s1 = as3) {
264 if (s2 >= brkend)
265 growstak(s2);
266 *s2++ = '/';
269 if (s2 >= brkend)
270 growstak(s2);
272 while (*s2++ = *++s1);
274 makearg((struct argnod *)endstak(s2));
277 void
278 makearg(struct argnod *args)
280 args->argnxt = gchain;
281 gchain = args;