1 /* POSIX.2 wordexp implementation.
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
25 #include <sys/types.h>
30 #include <sys/types.h>
37 #include <sys/param.h>
41 #include <stdio-common/_itoa.h>
43 /* Undefine the following line for the production version. */
44 /* #define NDEBUG 1 */
48 * This is a recursive-descent-style word expansion routine.
51 /* Some forward declarations */
52 static int parse_dollars (char **word
, size_t *word_length
, size_t *max_length
,
53 const char *words
, size_t *offset
, int flags
,
56 static int parse_backtick (char **word
, size_t *word_length
,
57 size_t *max_length
, const char *words
,
58 size_t *offset
, int flags
, wordexp_t
*pwordexp
)
60 static int eval_expr (char *expr
, int *result
) internal_function
;
62 /* The w_*() functions manipulate word lists. */
67 w_addchar (char *buffer
, size_t *actlen
, size_t *maxlen
, char ch
)
68 /* (lengths exclude trailing zero) */
70 /* Add a character to the buffer, allocating room for it if needed.
73 if (*actlen
== *maxlen
)
75 char *old_buffer
= buffer
;
76 assert (buffer
== NULL
|| *maxlen
!= 0);
78 buffer
= realloc (buffer
, 1 + *maxlen
);
87 buffer
[++(*actlen
)] = '\0';
94 w_addstr (char *buffer
, size_t *actlen
, size_t *maxlen
, const char *str
)
95 /* (lengths exclude trailing zero) */
97 /* Add a string to the buffer, allocating room for it if needed.
101 assert (str
!= NULL
); /* w_addstr only called from this file */
104 if (*actlen
+ len
> *maxlen
)
106 char *old_buffer
= buffer
;
107 assert (buffer
== NULL
|| *maxlen
!= 0);
108 *maxlen
+= MAX (2 * len
, W_CHUNK
);
109 buffer
= realloc (old_buffer
, 1 + *maxlen
);
117 *((char *) __mempcpy (&buffer
[*actlen
], str
, len
)) = '\0';
125 w_addword (wordexp_t
*pwordexp
, char *word
)
127 /* Add a word to the wordlist */
130 num_p
= 2 + pwordexp
->we_wordc
+ pwordexp
->we_offs
;
131 pwordexp
->we_wordv
= realloc (pwordexp
->we_wordv
, sizeof (char *) * num_p
);
132 if (pwordexp
->we_wordv
!= NULL
)
134 pwordexp
->we_wordv
[pwordexp
->we_wordc
++] = word
;
135 pwordexp
->we_wordv
[pwordexp
->we_wordc
] = NULL
;
142 /* The parse_*() functions should leave *offset being the offset in 'words'
143 * to the last character processed.
148 parse_backslash (char **word
, size_t *word_length
, size_t *max_length
,
149 const char *words
, size_t *offset
)
151 /* We are poised _at_ a backslash, not in quotes */
153 switch (words
[1 + *offset
])
156 /* Backslash is last character of input words */
164 *word
= w_addchar (*word
, word_length
, max_length
, words
[1 + *offset
]);
177 parse_qtd_backslash (char **word
, size_t *word_length
, size_t *max_length
,
178 const char *words
, size_t *offset
)
180 /* We are poised _at_ a backslash, inside quotes */
182 switch (words
[1 + *offset
])
185 /* Backslash is last character of input words */
196 *word
= w_addchar (*word
, word_length
, max_length
, words
[1 + *offset
]);
204 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
206 *word
= w_addchar (*word
, word_length
, max_length
, words
[1 + *offset
]);
220 parse_tilde (char **word
, size_t *word_length
, size_t *max_length
,
221 const char *words
, size_t *offset
, size_t wordc
)
223 /* We are poised _at_ a tilde */
226 if (*word_length
!= 0)
228 if (!((*word
)[*word_length
- 1] == '=' && wordc
== 0))
230 if (!((*word
)[*word_length
- 1] == ':' &&
231 strchr (*word
, '=') && wordc
== 0))
233 *word
= w_addchar (*word
, word_length
, max_length
, '~');
234 return *word
? 0 : WRDE_NOSPACE
;
239 for (i
= 1 + *offset
; words
[i
]; i
++)
241 if (words
[i
] == ':' || words
[i
] == '/' || words
[i
] == ' ' ||
242 words
[i
] == '\t' || words
[i
] == 0 )
245 if (words
[i
] == '\\')
247 *word
= w_addchar (*word
, word_length
, max_length
, '~');
248 return *word
? 0 : WRDE_NOSPACE
;
252 if (i
== 1 + *offset
)
254 /* Tilde appears on its own */
256 struct passwd pwd
, *tpwd
;
258 char* buffer
= __alloca (buflen
);
263 while ((result
= __getpwuid_r (uid
, &pwd
, buffer
, buflen
, &tpwd
)) != 0
267 buffer
= __alloca (buflen
);
270 if (result
== 0 && pwd
.pw_dir
!= NULL
)
272 *word
= w_addstr (*word
, word_length
, max_length
, pwd
.pw_dir
);
278 *word
= w_addchar (*word
, word_length
, max_length
, '~');
285 /* Look up user name in database to get home directory */
286 char *user
= __strndup (&words
[1 + *offset
], i
- *offset
);
287 struct passwd pwd
, *tpwd
;
289 char* buffer
= __alloca (buflen
);
292 while ((result
= __getpwnam_r (user
, &pwd
, buffer
, buflen
, &tpwd
)) != 0
296 buffer
= __alloca (buflen
);
299 if (result
== 0 && pwd
.pw_dir
)
300 *word
= w_addstr (*word
, word_length
, max_length
, pwd
.pw_dir
);
303 /* (invalid login name) */
304 *word
= w_addchar (*word
, word_length
, max_length
, '~');
306 *word
= w_addstr (*word
, word_length
, max_length
, user
);
311 return *word
? 0 : WRDE_NOSPACE
;
316 parse_glob (char **word
, size_t *word_length
, size_t *max_length
,
317 const char *words
, size_t *offset
, int flags
,
318 wordexp_t
*pwordexp
, char *ifs
)
320 /* We are poised just after a '*' or a '{'. */
326 for (; words
[*offset
]; (*offset
)++)
327 switch (words
[*offset
])
334 error
= parse_dollars (word
, word_length
, max_length
, words
, offset
,
342 if (ifs
== NULL
|| strchr (ifs
, words
[*offset
]) == NULL
)
344 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
354 error
= glob (*word
, GLOB_NOCHECK
, NULL
, &globbuf
);
358 /* We can only run into memory problems. */
359 assert (error
== GLOB_NOSPACE
);
366 /* No field splitting allowed */
367 size_t length
= strlen (globbuf
.gl_pathv
[0]);
368 *word
= realloc (*word
, length
+ 1);
372 memcpy (*word
, globbuf
.gl_pathv
[0], length
+ 1);
373 *word_length
= length
;
375 for (match
= 1; match
< globbuf
.gl_pathc
&& *word
!= NULL
; ++match
)
377 *word
= w_addchar (*word
, word_length
, max_length
, ' ');
379 *word
= w_addstr (*word
, word_length
, max_length
,
380 globbuf
.gl_pathv
[match
]);
383 /* Re-parse white space on return */
386 return *word
? 0 : WRDE_NOSPACE
;
394 matching_word
= __strdup (globbuf
.gl_pathv
[0]);
395 if (matching_word
== NULL
)
398 if (w_addword (pwordexp
, matching_word
) == WRDE_NOSPACE
)
401 for (match
= 1; match
< globbuf
.gl_pathc
; ++match
)
403 matching_word
= __strdup (globbuf
.gl_pathv
[match
]);
404 if (matching_word
== NULL
)
407 if (w_addword (pwordexp
, matching_word
) == WRDE_NOSPACE
)
413 /* Re-parse white space on return */
423 parse_squote (char **word
, size_t *word_length
, size_t *max_length
,
424 const char *words
, size_t *offset
)
426 /* We are poised just after a single quote */
427 for (; words
[*offset
]; ++(*offset
))
429 if (words
[*offset
] != '\'')
431 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
438 /* Unterminated string */
442 /* Functions to evaluate an arithmetic expression */
445 eval_expr_val (char **expr
, int *result
)
450 /* Skip white space */
451 for (digit
= *expr
; digit
&& *digit
&& isspace (*digit
); ++digit
);
457 /* Scan for closing paren */
458 for (++digit
; **expr
&& **expr
!= ')'; ++(*expr
));
466 if (eval_expr (digit
, result
))
471 case '+': /* Positive value */
475 case '-': /* Negative value */
481 if (!isdigit (*digit
))
486 for (; *digit
&& isdigit (*digit
); ++digit
)
487 *result
= (*result
* 10) + (*digit
- '0');
496 eval_expr_multdiv (char **expr
, int *result
)
501 if (eval_expr_val (expr
, result
))
506 /* Skip white space */
507 for (; *expr
&& **expr
&& isspace (**expr
); ++(*expr
));
512 if ((eval_expr_val (expr
, &arg
)) != 0)
517 else if (**expr
== '/')
520 if ((eval_expr_val (expr
, &arg
)) != 0)
533 eval_expr (char *expr
, int *result
)
538 if ((eval_expr_multdiv (&expr
, result
)) != 0)
543 /* Skip white space */
544 for (; expr
&& *expr
&& isspace (*expr
); ++expr
);
549 if ((eval_expr_multdiv (&expr
, &arg
)) != 0)
554 else if (*expr
== '-')
557 if ((eval_expr_multdiv (&expr
, &arg
)) != 0)
570 parse_arith (char **word
, size_t *word_length
, size_t *max_length
,
571 const char *words
, size_t *offset
, int flags
, int bracket
)
573 /* We are poised just after "$((" or "$[" */
576 size_t expr_length
= 0;
577 size_t expr_maxlen
= 0;
580 for (; words
[*offset
]; ++(*offset
))
582 switch (words
[*offset
])
585 error
= parse_dollars (&expr
, &expr_length
, &expr_maxlen
,
586 words
, offset
, flags
, NULL
);
587 /* The NULL here is to tell parse_dollars not to
599 error
= parse_backtick (&expr
, &expr_length
, &expr_maxlen
,
600 words
, offset
, flags
, NULL
);
601 /* The NULL here is to tell parse_backtick not to
612 error
= parse_qtd_backslash (&expr
, &expr_length
, &expr_maxlen
,
619 /* I think that a backslash within an
620 * arithmetic expansion is bound to
621 * cause an error sooner or later anyway though.
626 if (--paren_depth
== 0)
628 char result
[21]; /* 21 = ceil(log10(2^64)) + 1 */
631 if (bracket
|| words
[1 + *offset
] != ')')
638 eval_expr (expr
, &numresult
) != 0)
642 *word
= w_addstr (*word
, word_length
, max_length
,
643 _itoa_word (numresult
, &result
[20], 10, 0));
645 return *word
? 0 : WRDE_NOSPACE
;
647 expr
= w_addchar (expr
, &expr_length
, &expr_maxlen
, words
[*offset
]);
654 if (bracket
&& paren_depth
== 1)
656 char result
[21]; /* 21 = ceil(log10(2^64)) + 1 */
660 if (*expr
&& eval_expr (expr
, &numresult
) != 0)
664 *word
= w_addstr (*word
, word_length
, max_length
,
665 _itoa_word (numresult
, &result
[20], 10, 0));
667 return *word
? 0 : WRDE_NOSPACE
;
683 expr
= w_addchar (expr
, &expr_length
, &expr_maxlen
, words
[*offset
]);
694 /* Function to execute a command and retrieve the results */
695 /* pwordexp contains NULL if field-splitting is forbidden */
698 exec_comm (char *comm
, char **word
, size_t *word_length
, size_t *max_length
,
699 int flags
, wordexp_t
*pwordexp
)
709 * 0 until first non-(whitespace-ifs)
711 * 2 after non-(whitespace-ifs)
714 /* Don't fork() unless necessary */
722 if ((pid
= fork ()) < 0)
731 const char *args
[4] = { _PATH_BSHELL
, "-c", comm
, NULL
};
733 /* Redirect input and output */
736 /* Close stderr if we have to */
737 if ((flags
& WRDE_SHOWERR
) == 0)
740 __execve (_PATH_BSHELL
, (char *const *) args
, __environ
);
749 buffer
= __alloca (bufsize
);
752 { /* Quoted - no field splitting */
756 if ((buflen
= read (fildes
[0], buffer
, bufsize
)) < 1)
758 if (__waitpid (pid
, NULL
, WNOHANG
) == 0)
760 if ((buflen
= read (fildes
[0], buffer
, bufsize
)) < 1)
764 for (i
= 0; i
< buflen
; ++i
)
766 *word
= w_addchar (*word
, word_length
, max_length
, buffer
[i
]);
779 /* Not quoted - split fields.
780 * NB. This isn't done properly yet.
784 if ((buflen
= read (fildes
[0], buffer
, bufsize
)) < 1)
786 if (__waitpid (pid
, NULL
, WNOHANG
) == 0)
788 if ((read (fildes
[0], buffer
, bufsize
)) < 1)
792 for (i
= 0; i
< buflen
; ++i
)
794 /* What if these aren't field separators? FIX */
795 if (buffer
[i
] == ' ' || buffer
[i
] == '\t' || buffer
[i
] == '\n')
805 if (w_addword (pwordexp
, *word
) == WRDE_NOSPACE
)
816 *word
= w_addchar (*word
, word_length
, max_length
, buffer
[i
]);
830 parse_comm (char **word
, size_t *word_length
, size_t *max_length
,
831 const char *words
, size_t *offset
, int flags
, wordexp_t
*pwordexp
)
833 /* We are poised just after "$(" */
836 size_t comm_length
= 0;
837 size_t comm_maxlen
= 0;
840 for (; words
[*offset
]; ++(*offset
))
842 switch (words
[*offset
])
845 if (--paren_depth
== 0)
847 /* Go -- give script to the shell */
848 error
= exec_comm (comm
, word
, word_length
, max_length
, flags
,
854 /* This is just part of the script */
855 comm
= w_addchar (comm
, &comm_length
, &comm_maxlen
, words
[*offset
]);
864 comm
= w_addchar (comm
, &comm_length
, &comm_maxlen
, words
[*offset
]);
879 parse_param (char **word
, size_t *word_length
, size_t *max_length
,
880 const char *words
, size_t *offset
, int flags
, wordexp_t
*pwordexp
)
882 /* We are poised just after "$" */
883 enum remove_pattern_enum
891 size_t start
= *offset
;
892 size_t env_length
= 0;
893 size_t env_maxlen
= 0;
894 size_t pat_length
= 0;
895 size_t pat_maxlen
= 0;
897 char *pattern
= NULL
;
900 enum remove_pattern_enum remove
= RP_NONE
;
905 for (; words
[*offset
]; ++(*offset
))
907 switch (words
[*offset
])
912 if (action
!= '\0' || remove
!= RP_NONE
)
914 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
922 if (*offset
== start
)
925 /* Otherwise evaluate */
926 /* (and re-parse this character) */
931 if (words
[start
] != '{')
934 if (action
!= '\0' || remove
!= RP_NONE
)
938 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
951 /* At the start? (ie. 'string length') */
952 if (*offset
== start
+ 1)
953 /* FIXME: This isn't written yet! */
956 if (words
[start
] != '{')
959 /* (and re-parse this character) */
964 /* Separating variable name from prefix pattern? */
966 if (remove
== RP_NONE
)
968 remove
= RP_SHORT_LEFT
;
971 else if (remove
== RP_SHORT_LEFT
)
973 remove
= RP_LONG_LEFT
;
977 /* Must be part of prefix/suffix pattern. */
978 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
989 /* Separating variable name from suffix pattern? */
990 if (remove
== RP_NONE
)
992 remove
= RP_SHORT_RIGHT
;
995 else if (remove
== RP_SHORT_RIGHT
)
997 remove
= RP_LONG_RIGHT
;
1001 /* Must be part of prefix/suffix pattern. */
1002 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1004 if (pattern
== NULL
)
1013 if (action
!= '\0' || remove
!= RP_NONE
)
1015 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1017 if (pattern
== NULL
)
1023 if ((words
[1 + *offset
] == '-') || (words
[1 + *offset
] == '=') ||
1024 (words
[1 + *offset
] == '?') || (words
[1 + *offset
] == '+'))
1039 if (action
!= '\0' || remove
!= RP_NONE
)
1041 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1043 if (pattern
== NULL
)
1049 action
= words
[*offset
];
1053 if (action
!= '\0' || remove
!= RP_NONE
)
1055 /* Um. Is this right? */
1056 error
= parse_qtd_backslash (word
, word_length
, max_length
,
1063 error
= WRDE_SYNTAX
;
1069 if (pattern
!= NULL
)
1075 if (action
!= '\0' || remove
!= RP_NONE
)
1077 pattern
= w_addchar (pattern
, &pat_length
, &pat_maxlen
,
1079 if (pattern
== NULL
)
1085 if ((words
[start
] == '{') || isalpha (words
[*offset
]))
1087 env
= w_addchar (env
, &env_length
, &env_maxlen
, words
[*offset
]);
1099 /* End of input string */
1103 if (words
[start
] == '{' && words
[*offset
] != '}')
1108 *offset
= start
- 1;
1109 *word
= w_addchar (*word
, word_length
, max_length
, '$');
1112 return *word
? 0 : WRDE_NOSPACE
;
1115 value
= getenv (env
);
1117 if (action
!= '\0' || remove
!= RP_NONE
)
1127 if (!pattern
|| !*pattern
)
1130 end
= value
+ strlen (value
);
1138 for (p
= value
; p
<= end
; p
++)
1142 if (fnmatch (pattern
, value
, 0) != FNM_NOMATCH
)
1154 for (p
= end
; p
>= value
; p
--)
1158 if (fnmatch (pattern
, value
, 0) != FNM_NOMATCH
)
1169 case RP_SHORT_RIGHT
:
1170 for (p
= end
; p
>= value
; p
--)
1172 if (fnmatch (pattern
, p
, 0) != FNM_NOMATCH
)
1182 for (p
= value
; p
<= end
; p
++)
1184 if (fnmatch (pattern
, p
, 0) != FNM_NOMATCH
)
1194 assert (! "Unexpected `remove' value\n");
1201 if (value
&& *value
)
1204 if (!colon_seen
&& value
)
1206 /* Substitute NULL */
1213 fprintf (stderr
, "%s: ", env
);
1217 /* Expand 'pattern' and write it to stderr */
1220 error
= wordexp (pattern
, &we
, flags
);
1226 for (i
= 0; i
< we
.we_wordc
; ++i
)
1228 fprintf (stderr
, "%s%s", i
? " " : "", we
.we_wordv
[i
]);
1231 fprintf (stderr
, "\n");
1232 error
= WRDE_BADVAL
;
1241 fprintf (stderr
, "parameter null or not set\n");
1247 printf ("warning: parameter substitution does not yet support \"%s%c\"\n", colon_seen
?":":"", action
);
1256 /* Variable not defined */
1257 if (flags
& WRDE_UNDEF
)
1263 if (pwordexp
== NULL
)
1264 /* Quoted - no field split */
1265 *word
= w_addstr (*word
, word_length
, max_length
, value
);
1267 /* Should field-split here - FIX */
1268 *word
= w_addstr (*word
, word_length
, max_length
, value
);
1270 return *word
? 0 : WRDE_NOSPACE
;
1279 return WRDE_NOSPACE
;
1293 parse_dollars (char **word
, size_t *word_length
, size_t *max_length
,
1294 const char *words
, size_t *offset
, int flags
,
1295 wordexp_t
*pwordexp
)
1297 /* We are poised _at_ "$" */
1298 switch (words
[1 + *offset
])
1303 *word
= w_addchar (*word
, word_length
, max_length
, '$');
1304 return *word
? 0 : WRDE_NOSPACE
;
1307 if (words
[2 + *offset
] == '(')
1310 /* Call parse_arith -- 0 is for "no brackets" */
1311 return parse_arith (word
, word_length
, max_length
, words
, offset
,
1315 if (flags
& WRDE_NOCMD
)
1319 return parse_comm (word
, word_length
, max_length
, words
, offset
, flags
,
1324 /* Call parse_arith -- 1 is for "brackets" */
1325 return parse_arith (word
, word_length
, max_length
, words
, offset
, flags
,
1330 ++(*offset
); /* parse_param needs to know if "{" is there */
1331 return parse_param (word
, word_length
, max_length
, words
, offset
, flags
,
1337 parse_backtick (char **word
, size_t *word_length
, size_t *max_length
,
1338 const char *words
, size_t *offset
, int flags
,
1339 wordexp_t
*pwordexp
)
1341 /* We are poised just after "`" */
1343 size_t comm_length
= 0;
1344 size_t comm_maxlen
= 0;
1348 for (; words
[*offset
]; ++(*offset
))
1350 switch (words
[*offset
])
1353 /* Go -- give the script to the shell */
1354 error
= exec_comm (comm
, word
, word_length
, max_length
, flags
,
1362 error
= parse_qtd_backslash (&comm
, &comm_length
, &comm_maxlen
,
1375 error
= parse_backslash (&comm
, &comm_length
, &comm_maxlen
, words
,
1387 squoting
= 1 - squoting
;
1389 comm
= w_addchar (comm
, &comm_length
, &comm_maxlen
, words
[*offset
]);
1391 return WRDE_NOSPACE
;
1402 parse_dquote (char **word
, size_t *word_length
, size_t *max_length
,
1403 const char *words
, size_t *offset
, int flags
)
1405 /* We are poised just after a double-quote */
1408 for (; words
[*offset
]; ++(*offset
))
1410 switch (words
[*offset
])
1416 error
= parse_dollars (word
, word_length
, max_length
, words
, offset
,
1418 /* The NULL here is to tell parse_dollars not to
1427 if (flags
& WRDE_NOCMD
)
1431 error
= parse_backtick (word
, word_length
, max_length
, words
,
1432 offset
, flags
, NULL
);
1433 /* The NULL here is to tell parse_backtick not to
1442 error
= parse_qtd_backslash (word
, word_length
, max_length
, words
,
1451 *word
= w_addchar (*word
, word_length
, max_length
, words
[*offset
]);
1453 return WRDE_NOSPACE
;
1457 /* Unterminated string */
1462 * wordfree() is to be called after pwordexp is finished with.
1466 wordfree (wordexp_t
*pwordexp
)
1469 /* wordexp can set pwordexp to NULL */
1470 if (pwordexp
&& pwordexp
->we_wordv
)
1472 char **wordv
= pwordexp
->we_wordv
;
1474 for (wordv
+= pwordexp
->we_offs
; *wordv
; ++wordv
)
1477 free (pwordexp
->we_wordv
);
1478 pwordexp
->we_wordv
= NULL
;
1487 wordexp (const char *words
, wordexp_t
*pwordexp
, int flags
)
1489 size_t wordv_offset
;
1490 size_t words_offset
;
1491 size_t word_length
= 0;
1492 size_t max_length
= 0;
1497 char **old_wordv
= pwordexp
->we_wordv
;
1498 size_t old_wordc
= pwordexp
->we_wordc
;
1500 if (flags
& WRDE_REUSE
)
1501 /* Minimal implementation of WRDE_REUSE for now */
1502 wordfree (pwordexp
);
1504 if (flags
& WRDE_DOOFFS
)
1506 pwordexp
->we_wordv
= calloc (1 + pwordexp
->we_offs
, sizeof (char *));
1507 if (pwordexp
->we_wordv
== NULL
)
1508 return WRDE_NOSPACE
;
1512 pwordexp
->we_wordv
= calloc (1, sizeof (char *));
1513 if (pwordexp
->we_wordv
== NULL
)
1514 return WRDE_NOSPACE
;
1516 pwordexp
->we_offs
= 0;
1519 if ((flags
& WRDE_APPEND
) == 0)
1520 pwordexp
->we_wordc
= 0;
1522 wordv_offset
= pwordexp
->we_offs
+ pwordexp
->we_wordc
;
1524 /* Find out what the field separators are.
1525 * There are two types: whitespace and non-whitespace.
1527 ifs
= getenv ("IFS");
1530 ifs
= strcpy (ifs_white
, " \t\n");
1534 char *whch
= ifs_white
;
1536 while (*ifsch
!= '\0')
1537 if ((*ifsch
== ' ') || (*ifsch
== '\t') || (*ifsch
== '\n'))
1539 /* White space IFS. See first whether it is already in our
1541 char *runp
= ifs_white
;
1543 while (runp
< whch
&& *runp
!= '\0' && *runp
!= *ifsch
)
1552 for (words_offset
= 0 ; words
[words_offset
] ; ++words_offset
)
1553 switch (words
[words_offset
])
1565 wordfree (pwordexp
);
1566 pwordexp
->we_wordc
= 0;
1567 pwordexp
->we_wordv
= old_wordv
;
1568 return WRDE_BADCHAR
;
1571 error
= parse_backslash (&word
, &word_length
, &max_length
, words
,
1580 error
= parse_dollars (&word
, &word_length
, &max_length
, words
,
1581 &words_offset
, flags
, pwordexp
);
1589 if (flags
& WRDE_NOCMD
)
1593 error
= parse_backtick (&word
, &word_length
, &max_length
, words
,
1594 &words_offset
, flags
, pwordexp
);
1603 error
= parse_dquote (&word
, &word_length
, &max_length
, words
,
1604 &words_offset
, flags
);
1613 error
= parse_squote (&word
, &word_length
, &max_length
, words
,
1622 error
= parse_tilde (&word
, &word_length
, &max_length
, words
,
1623 &words_offset
, pwordexp
->we_wordc
);
1632 error
= parse_glob (&word
, &word_length
, &max_length
, words
,
1633 &words_offset
, flags
, pwordexp
, ifs
);
1641 /* Is it a field separator? */
1642 if (strchr (ifs
, words
[words_offset
]) == NULL
)
1644 /* "Ordinary" character -- add it to word */
1646 word
= w_addchar (word
, &word_length
, &max_length
,
1647 words
[words_offset
]);
1650 error
= WRDE_NOSPACE
;
1657 /* Field separator */
1658 if (strchr (ifs_white
, words
[words_offset
]))
1660 /* It's a whitespace IFS char. Ignore it at the beginning
1661 of a line and ignore multiple instances. */
1662 if (!word
|| !*word
)
1665 if (w_addword (pwordexp
, word
) == WRDE_NOSPACE
)
1667 error
= WRDE_NOSPACE
;
1676 /* It's a non-whitespace IFS char */
1678 /* Multiple non-whitespace IFS chars are treated as one;
1683 if (w_addword (pwordexp
, word
) == WRDE_NOSPACE
)
1685 error
= WRDE_NOSPACE
;
1697 /* There was a field separator at the end */
1701 /* There was no field separator at the end */
1702 return w_addword (pwordexp
, word
);
1706 free memory used, set we_wordc and wd_wordv back to what they were.
1711 wordfree (pwordexp
);
1712 pwordexp
->we_wordv
= old_wordv
;
1713 pwordexp
->we_wordc
= old_wordc
;