static void pword(struct blk_buf *bb, struct Strbuf *word) { Char *s; s = Strbuf_finish(word); bb_append(bb, s); *word = Strbuf_init; }
static int globbrace(const Char *s, Char ***bl) { struct Strbuf gbuf = Strbuf_INIT; struct blk_buf bb = BLK_BUF_INIT; int i; const Char *p, *pm, *pe, *pl; size_t prefix_len; /* copy part up to the brace */ for (p = s; *p != LBRC; p++) ; prefix_len = p - s; /* check for balanced braces */ for (i = 0, pe = ++p; *pe; pe++) if (*pe == LBRK) { /* Ignore everything between [] */ for (++pe; *pe != RBRK && *pe != EOS; pe++) continue; if (*pe == EOS) return (-RBRK); } else if (*pe == LBRC) i++; else if (*pe == RBRC) { if (i == 0) break; i--; } if (i != 0 || *pe == '\0') return (-RBRC); Strbuf_appendn(&gbuf, s, prefix_len); for (i = 0, pl = pm = p; pm <= pe; pm++) switch (*pm) { case LBRK: for (++pm; *pm != RBRK && *pm != EOS; pm++) continue; if (*pm == EOS) { bb_cleanup(&bb); xfree(gbuf.s); return (-RBRK); } break; case LBRC: i++; break; case RBRC: if (i) { i--; break; } /* FALLTHROUGH */ case ',': if (i && *pm == ',') break; else { gbuf.len = prefix_len; Strbuf_appendn(&gbuf, pl, pm - pl); Strbuf_append(&gbuf, pe + 1); Strbuf_terminate(&gbuf); bb_append(&bb, Strsave(gbuf.s)); pl = pm + 1; } break; default: break; } *bl = bb_finish(&bb); xfree(gbuf.s); return bb.len; }
/* * Get a word. This routine is analogous to the routine * word() in sh.lex.c for the main lexical input. One difference * here is that we don't get a newline to terminate our expansion. * Rather, DgetC will return a DEOF when we hit the end-of-input. */ static int Dword(struct blk_buf *bb) { eChar c, c1; struct Strbuf *wbuf = Strbuf_alloc(); int dolflg; int sofar = 0; Char *str; cleanup_push(wbuf, Strbuf_free); for (;;) { c = DgetC(DODOL); switch (c) { case DEOF: if (sofar == 0) { cleanup_until(wbuf); return (0); } /* finish this word and catch the code above the next time */ unDredc(c); /*FALLTHROUGH*/ case '\n': goto end; case ' ': case '\t': continue; case '`': /* We preserve ` quotations which are done yet later */ Strbuf_append1(wbuf, (Char) c); /*FALLTHROUGH*/ case '\'': case '"': /* * Note that DgetC never returns a QUOTES character from an * expansion, so only true input quotes will get us here or out. */ c1 = c; dolflg = c1 == '"' ? DODOL : 0; for (;;) { c = DgetC(dolflg); if (c == c1) break; if (c == '\n' || c == DEOF) { cleanup_until(bb); stderror(ERR_UNMATCHED, (int)c1); } if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE)) { if (wbuf->len != 0 && (wbuf->s[wbuf->len - 1] & TRIM) == '\\') wbuf->len--; } switch (c1) { case '"': /* * Leave any `s alone for later. Other chars are all * quoted, thus `...` can tell it was within "...". */ Strbuf_append1(wbuf, c == '`' ? '`' : c | QUOTE); break; case '\'': /* Prevent all further interpretation */ Strbuf_append1(wbuf, c | QUOTE); break; case '`': /* Leave all text alone for later */ Strbuf_append1(wbuf, (Char) c); break; default: break; } } if (c1 == '`') Strbuf_append1(wbuf, '`'); sofar = 1; if (Dpack(wbuf) != 0) goto end; continue; case '\\': c = DgetC(0); /* No $ subst! */ if (c == '\n' || c == DEOF) continue; c |= QUOTE; break; default: break; } unDgetC(c); sofar = 1; if (Dpack(wbuf) != 0) goto end; } end: cleanup_ignore(wbuf); cleanup_until(wbuf); str = Strbuf_finish(wbuf); bb_append(bb, str); xfree(wbuf); return 1; }