- */
- removerecordregions(startloc);
- goto again;
- }
-
- if (varlen < 0 && uflag)
- varunset(p, var, 0, 0);
-
- if (subtype == VSLENGTH) {
- cvtnum(varlen > 0 ? varlen : 0);
- goto record;
- }
-
- if (subtype == VSNORMAL) {
- record:
- if (!easy)
- goto end;
- recordregion(startloc, expdest - (char *)stackblock(), quoted);
- goto end;
- }
-
-#if DEBUG
- switch (subtype) {
- case VSTRIMLEFT:
- case VSTRIMLEFTMAX:
- case VSTRIMRIGHT:
- case VSTRIMRIGHTMAX:
-#if ENABLE_ASH_BASH_COMPAT
- case VSSUBSTR:
- case VSREPLACE:
- case VSREPLACEALL:
-#endif
- break;
- default:
- abort();
- }
-#endif
-
- if (varlen >= 0) {
- /*
- * Terminate the string and start recording the pattern
- * right after it
- */
- STPUTC('\0', expdest);
- patloc = expdest - (char *)stackblock();
- if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
- startloc, varflags, flag, var_str_list)) {
- int amount = expdest - (
- (char *)stackblock() + patloc - 1
- );
- STADJUST(-amount, expdest);
- }
- /* Remove any recorded regions beyond start of variable */
- removerecordregions(startloc);
- goto record;
- }
-
- end:
- if (subtype != VSNORMAL) { /* skip to end of alternative */
- int nesting = 1;
- for (;;) {
- unsigned char c = *p++;
- if (c == CTLESC)
- p++;
- else if (c == CTLBACKQ) {
- if (varlen >= 0)
- argbackq = argbackq->next;
- } else if (c == CTLVAR) {
- if ((*p++ & VSTYPE) != VSNORMAL)
- nesting++;
- } else if (c == CTLENDVAR) {
- if (--nesting == 0)
- break;
- }
- }
- }
- return p;
-}
-
-/*
- * Break the argument string into pieces based upon IFS and add the
- * strings to the argument list. The regions of the string to be
- * searched for IFS characters have been stored by recordregion.
- */
-static void
-ifsbreakup(char *string, struct arglist *arglist)
-{
- struct ifsregion *ifsp;
- struct strlist *sp;
- char *start;
- char *p;
- char *q;
- const char *ifs, *realifs;
- int ifsspc;
- int nulonly;
-
- start = string;
- if (ifslastp != NULL) {
- ifsspc = 0;
- nulonly = 0;
- realifs = ifsset() ? ifsval() : defifs;
- ifsp = &ifsfirst;
- do {
- p = string + ifsp->begoff;
- nulonly = ifsp->nulonly;
- ifs = nulonly ? nullstr : realifs;
- ifsspc = 0;
- while (p < string + ifsp->endoff) {
- q = p;
- if ((unsigned char)*p == CTLESC)
- p++;
- if (!strchr(ifs, *p)) {
- p++;
- continue;
- }
- if (!nulonly)
- ifsspc = (strchr(defifs, *p) != NULL);
- /* Ignore IFS whitespace at start */
- if (q == start && ifsspc) {
- p++;
- start = p;
- continue;
- }
- *q = '\0';
- sp = stzalloc(sizeof(*sp));
- sp->text = start;
- *arglist->lastp = sp;
- arglist->lastp = &sp->next;
- p++;
- if (!nulonly) {
- for (;;) {
- if (p >= string + ifsp->endoff) {
- break;
- }
- q = p;
- if ((unsigned char)*p == CTLESC)
- p++;
- if (strchr(ifs, *p) == NULL) {
- p = q;
- break;
- }
- if (strchr(defifs, *p) == NULL) {
- if (ifsspc) {
- p++;
- ifsspc = 0;
- } else {
- p = q;
- break;
- }
- } else
- p++;
- }
- }
- start = p;
- } /* while */
- ifsp = ifsp->next;
- } while (ifsp != NULL);
- if (nulonly)
- goto add;