]> git.saurik.com Git - apple/libc.git/blob - gen/wordexp.c
a75b9441a40502678da991474cc4016049ab5ab2
[apple/libc.git] / gen / wordexp.c
1 /*
2 * Copyright 1994, University Corporation for Atmospheric Research
3 * See ../COPYRIGHT file for copying and redistribution conditions.
4 */
5 /*
6 * Reproduction of ../COPYRIGHT file:
7 *
8 *********************************************************************
9
10 Copyright 1995-2002 University Corporation for Atmospheric Research/Unidata
11
12 Portions of this software were developed by the Unidata Program at the
13 University Corporation for Atmospheric Research.
14
15 Access and use of this software shall impose the following obligations
16 and understandings on the user. The user is granted the right, without
17 any fee or cost, to use, copy, modify, alter, enhance and distribute
18 this software, and any derivative works thereof, and its supporting
19 documentation for any purpose whatsoever, provided that this entire
20 notice appears in all copies of the software, derivative works and
21 supporting documentation. Further, UCAR requests that the user credit
22 UCAR/Unidata in any publications that result from the use of this
23 software or in any product that includes this software. The names UCAR
24 and/or Unidata, however, may not be used in any advertising or publicity
25 to endorse or promote any products or commercial entity unless specific
26 written permission is obtained from UCAR/Unidata. The user also
27 understands that UCAR/Unidata is not obligated to provide the user with
28 any support, consulting, training or assistance of any kind with regard
29 to the use, operation and performance of this software nor to provide
30 the user with any updates, revisions, new versions or "bug fixes."
31
32 THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
33 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
36 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
37 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
38 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
39 WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
40
41 *********************************************************************
42 */
43
44 /* $Id: wordexp.c,v 1.13 2002/12/26 16:46:46 steve Exp $ */
45
46 #if 0
47 #include "ldmconfig.h"
48 #endif
49
50 /*
51 * Hack to provide POSIX 1003.2-1992 _interface_.
52 * NOT fully functional
53 */
54
55 #include <stdlib.h>
56 #include <string.h>
57 #include <ctype.h>
58
59 #include "wordexp.h"
60
61
62
63 /*
64 * Translate return value from wordexp() into a string
65 */
66 const char *
67 s_wrde_err(int wrde_err)
68 {
69 switch(wrde_err) {
70 case 0: return "No Error";
71 case WRDE_BADCHAR: return "WRDE_BADCHAR";
72 case WRDE_BADVAL: return "WRDE_BADVAL";
73 case WRDE_CMDSUB: return "WRDE_CMDSUB";
74 case WRDE_NOSPACE: return "WRDE_NOSPACE";
75 case WRDE_SYNTAX: return "WRDE_SYNTAX";
76 }
77 /* default */
78 return "Unknown Error";
79 }
80
81
82 /*ARGSUSED*/
83 int
84 wordexp(const char *words, wordexp_t *pwordexp, int flags)
85 {
86 const char *ccp;
87 char **argv;
88 const char *buf;
89 size_t argc;
90 enum states {ARGSTART, IN_QUOTE, NOT_IN_QUOTE, DONE};
91 enum classes {EOS, SPACE, QUOTE, OTHER};
92 int state = ARGSTART;
93 char *argbuf;
94 const char *sp;
95 char *dp;
96 int status = 0;
97
98 /* devour leading white space */
99 for(ccp = words; *ccp != 0 && isspace(*ccp); )
100 ccp++;
101 /* skip comments */
102 if(*ccp == '#')
103 {
104 pwordexp->we_wordc = 0;
105 pwordexp->we_wordv = NULL;
106 return 0;
107 }
108
109 /* If every other character was a space ... */
110 #define MAXNARGS(str) ((strlen(str) +1)/2 +1)
111 argv = (char **)calloc(MAXNARGS(ccp), sizeof(char *));
112 if(argv == NULL)
113 return WRDE_NOSPACE;
114
115 buf = ccp;
116
117 argbuf = malloc(strlen(words)+1); /* where each arg is built */
118 if (argbuf == NULL)
119 {
120 free(argv);
121 return WRDE_NOSPACE;
122 }
123
124 sp = buf;
125 dp = argbuf;
126 argc = 0;
127 while(state != DONE)
128 {
129 int class;
130
131 if (*sp == 0)
132 class = EOS;
133 else if (isspace(*sp))
134 class = SPACE;
135 else if (*sp == '"')
136 class = QUOTE;
137 else
138 class = OTHER;
139 switch (state) {
140 case ARGSTART:
141 switch(class) {
142 case EOS:
143 state = DONE;
144 break;
145 case SPACE:
146 sp++;
147 break;
148 case QUOTE:
149 sp++;
150 state = IN_QUOTE;
151 break;
152 case OTHER:
153 *dp++ = *sp++;
154 state = NOT_IN_QUOTE;
155 break;
156 }
157 break;
158 case IN_QUOTE:
159 switch(class) {
160 case EOS: /* unmatched quote */
161 state = DONE;
162 status = WRDE_SYNTAX;
163 break;
164 case QUOTE:
165 sp++;
166 state = NOT_IN_QUOTE;
167 break;
168 case SPACE:
169 case OTHER:
170 *dp++ = *sp++;
171 break;
172 }
173 break;
174 case NOT_IN_QUOTE:
175 switch(class) {
176 case EOS:
177 *dp = 0;
178 dp = argbuf;
179 argv[argc++] = strdup(argbuf);
180 state = DONE;
181 break;
182 case SPACE:
183 *dp = 0;
184 dp = argbuf;
185 argv[argc++] = strdup(argbuf);
186 sp++;
187 state = ARGSTART;
188 break;
189 case QUOTE:
190 sp++;
191 state = IN_QUOTE;
192 break;
193 case OTHER:
194 *dp++ = *sp++;
195 break;
196 }
197 break;
198 }
199 }
200 argv[argc] = NULL;
201
202 pwordexp->we_wordc = argc;
203 pwordexp->we_wordv = argv;
204
205 free(argbuf);
206
207 return status;
208 }
209
210
211 void
212 wordfree(wordexp_t *pwordexp)
213 {
214 if(pwordexp == NULL || pwordexp->we_wordv == NULL)
215 return;
216 if(*pwordexp->we_wordv)
217 free(*pwordexp->we_wordv);
218 free(pwordexp->we_wordv);
219 }
220
221
222 #if TEST
223
224 #include <stdio.h>
225 #include <stdlib.h>
226 #include <string.h>
227
228 int
229 main(int argc, char *argv[])
230 {
231 char strbuf[1024];
232 wordexp_t wrdexp;
233 int status;
234 char **cpp;
235
236 while(fgets(strbuf, sizeof(strbuf), stdin) != NULL)
237 {
238 {
239 char *cp = strrchr(strbuf,'\n');
240 if(cp)
241 *cp = 0;
242 }
243 fprintf(stdout, "\t%s\n", strbuf);
244 status = wordexp(strbuf, &wrdexp, WRDE_SHOWERR);
245 if(status)
246 {
247 fprintf(stderr, "wordexp: %s\n", s_wrde_err(status));
248 continue;
249 }
250 /* else */
251 fprintf(stdout, "\t%d:\n", wrdexp.we_wordc);
252 for(cpp = wrdexp.we_wordv;
253 cpp < &wrdexp.we_wordv[wrdexp.we_wordc]; cpp++)
254 {
255 fprintf(stdout, "\t\t%s\n", *cpp);
256 }
257 wordfree(&wrdexp);
258
259 }
260 exit(EXIT_SUCCESS);
261 }
262
263 #endif /* TEST */