/* * Perform expansions on an argument, placing the resulting list of arguments * in arglist. Parameter expansion, command substitution and arithmetic * expansion are always performed; additional expansions can be requested * via flag (EXP_*). * The result is left in the stack string. * When arglist is NULL, perform here document expansion. * * When doing something that may cause this to be re-entered, make sure * the stack string is empty via grabstackstr() and do not assume expdest * remains valid. */ void expandarg(union node *arg, struct arglist *arglist, int flag) { struct worddest exparg; struct nodelist *argbackq; if (fflag) flag &= ~EXP_GLOB; argbackq = arg->narg.backquote; exparg.list = arglist; exparg.state = WORD_IDLE; STARTSTACKSTR(expdest); argstr(arg->narg.text, &argbackq, flag, &exparg); if (arglist == NULL) { STACKSTRNUL(expdest); return; /* here document expanded */ } if ((flag & EXP_SPLIT) == 0 || expdest != stackblock() || exparg.state == WORD_QUOTEMARK) { STPUTC('\0', expdest); if (flag & EXP_SPLIT) { if (flag & EXP_GLOB) expandmeta(grabstackstr(expdest), exparg.list); else appendarglist(exparg.list, grabstackstr(expdest)); } } if ((flag & EXP_SPLIT) == 0) appendarglist(arglist, grabstackstr(expdest)); }
/* * Perform expansions on an argument, placing the resulting list of arguments * in arglist. Parameter expansion, command substitution and arithmetic * expansion are always performed; additional expansions can be requested * via flag (EXP_*). * The result is left in the stack string. * When arglist is NULL, perform here document expansion. * * Caution: this function uses global state and is not reentrant. * However, a new invocation after an interrupted invocation is safe * and will reset the global state for the new call. */ void expandarg(union node* arg, struct arglist* arglist, int32_t flag) { struct strlist* sp; cstring_t p; argbackq = arg->narg.backquote; STARTSTACKSTR(expdest); ifsfirst.next = NULL; ifslastp = NULL; argstr(arg->narg.text, flag); if (arglist == NULL) { STACKSTRNUL(expdest); return; /* here document expanded */ } STPUTC('\0', expdest); p = grabstackstr(expdest); exparg.lastp = &exparg.list; /* * TODO - EXP_REDIR */ if (flag & EXP_FULL) { ifsbreakup(p, &exparg); *exparg.lastp = NULL; exparg.lastp = &exparg.list; expandmeta(exparg.list, flag); } else { if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ rmescapes(p); sp = (struct strlist*)stalloc(sizeof(struct strlist)); sp->text = p; *exparg.lastp = sp; exparg.lastp = &sp->next; } while (ifsfirst.next != NULL) { pifsregion_t ifsp; INTOFF; ifsp = ifsfirst.next->next; ckfree(ifsfirst.next); ifsfirst.next = ifsp; INTON; } *exparg.lastp = NULL; if (exparg.list) { *arglist->lastp = exparg.list; arglist->lastp = exparg.lastp; } }
/* * Perform expansions on an argument, placing the resulting list of arguments * in arglist. Parameter expansion, command substitution and arithmetic * expansion are always performed; additional expansions can be requested * via flag (EXP_*). * The result is left in the stack string. * When arglist is NULL, perform here document expansion. * * Caution: this function uses global state and is not reentrant. * However, a new invocation after an interrupted invocation is safe * and will reset the global state for the new call. */ void expandarg(union node *arg, struct arglist *arglist, int flag) { struct strlist *sp; char *p; argbackq = arg->narg.backquote; STARTSTACKSTR(expdest); ifsfirst.next = NULL; ifslastp = NULL; argstr(arg->narg.text, flag); if (arglist == NULL) { STACKSTRNUL(expdest); return; /* here document expanded */ } STPUTC('\0', expdest); p = grabstackstr(expdest); exparg.lastp = &exparg.list; if (flag & EXP_FULL) { ifsbreakup(p, &exparg); *exparg.lastp = NULL; exparg.lastp = &exparg.list; expandmeta(exparg.list); } else { sp = (struct strlist *)stalloc(sizeof (struct strlist)); sp->text = p; *exparg.lastp = sp; exparg.lastp = &sp->next; } while (ifsfirst.next != NULL) { struct ifsregion *ifsp; INTOFF; ifsp = ifsfirst.next->next; ckfree(ifsfirst.next); ifsfirst.next = ifsp; INTON; } *exparg.lastp = NULL; if (exparg.list) { *arglist->lastp = exparg.list; arglist->lastp = exparg.lastp; } }
void expandarg(shinstance *psh, union node *arg, struct arglist *arglist, int flag) { struct strlist *sp; char *p; psh->argbackq = arg->narg.backquote; STARTSTACKSTR(psh, psh->expdest); psh->ifsfirst.next = NULL; psh->ifslastp = NULL; argstr(psh, arg->narg.text, flag); if (arglist == NULL) { return; /* here document expanded */ } STPUTC(psh, '\0', psh->expdest); p = grabstackstr(psh, psh->expdest); TRACE2((psh, "expandarg: p='%s'\n", p)); psh->exparg.lastp = &psh->exparg.list; /* * TODO - EXP_REDIR */ if (flag & EXP_FULL) { ifsbreakup(psh, p, &psh->exparg); *psh->exparg.lastp = NULL; psh->exparg.lastp = &psh->exparg.list; expandmeta(psh, psh->exparg.list, flag); } else { if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ rmescapes(psh, p); sp = (struct strlist *)stalloc(psh, sizeof (struct strlist)); sp->text = p; *psh->exparg.lastp = sp; psh->exparg.lastp = &sp->next; } ifsfree(psh); *psh->exparg.lastp = NULL; if (psh->exparg.list) { *arglist->lastp = psh->exparg.list; arglist->lastp = psh->exparg.lastp; } }
static char * nextword(char c, int flag, char *p, struct worddest *dst) { int is_ws; is_ws = c == '\t' || c == '\n' || c == ' '; if (p != stackblock() || (is_ws ? dst->state == WORD_QUOTEMARK : dst->state != WORD_WS_DELIMITED) || c == '\0') { STPUTC('\0', p); if (flag & EXP_GLOB) expandmeta(grabstackstr(p), dst->list); else appendarglist(dst->list, grabstackstr(p)); dst->state = is_ws ? WORD_WS_DELIMITED : WORD_IDLE; } else if (!is_ws && dst->state == WORD_WS_DELIMITED) dst->state = WORD_IDLE; /* Reserve space while the stack string is empty. */ appendarglist(dst->list, NULL); dst->list->count--; STARTSTACKSTR(p); return p; }