diff options
Diffstat (limited to 'Src')
-rw-r--r-- | Src/Modules/parameter.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 2 | ||||
-rw-r--r-- | Src/hist.c | 30 | ||||
-rw-r--r-- | Src/lex.c | 53 | ||||
-rw-r--r-- | Src/subst.c | 29 |
6 files changed, 102 insertions, 16 deletions
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 38b462001..793249f32 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -1044,7 +1044,7 @@ histwgetfn(UNUSED(Param pm)) int i = addhistnum(curhist, -1, HIST_FOREIGN), iw; Histent he = gethistent(i, GETHIST_UPWARD); - if ((ll = bufferwords(NULL, NULL, NULL))) + if ((ll = bufferwords(NULL, NULL, NULL, 0))) for (n = firstnode(ll); n; incnode(n)) pushnode(l, getdata(n)); diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index 412644827..b5ff05cd1 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -677,7 +677,7 @@ insertlastword(char **args) * a deleted word, because that can only have come * from a non-empty line. I think. */ - if (!(l = bufferwords(NULL, NULL, NULL))) { + if (!(l = bufferwords(NULL, NULL, NULL, 0))) { unmetafy_line(); return 1; } diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 0beb43d6d..25404c1bd 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -843,7 +843,7 @@ copyprevshellword(UNUSED(char **args)) if (zmult <= 0) return 1; - if ((l = bufferwords(NULL, NULL, &i))) { + if ((l = bufferwords(NULL, NULL, &i, 0))) { i -= (zmult-1); if (i < 0) return 1; diff --git a/Src/hist.c b/Src/hist.c index e65ddb1b6..89db826b3 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -2345,7 +2345,7 @@ readhistfile(char *fn, int err, int readflags) /* * Attempt to do this using the lexer. */ - LinkList wordlist = bufferwords(NULL, pt, NULL); + LinkList wordlist = bufferwords(NULL, pt, NULL, 1); LinkNode wordnode; int nwords_max; nwords_max = 2 * countlinknodes(wordlist); @@ -2885,11 +2885,27 @@ histfileIsLocked(void) * which may not even be valid at this point. * * However, I'm so confused it could simply be baking Bakewell tarts. + * + * list may be an existing linked list (off the heap), in which case + * it will be appended to; otherwise it will be created. + * + * If buf is set we will take input from that string, else we will + * attempt to use ZLE directly in a way they tell you not to do on all + * programming courses. + * + * If index is non-NULL, and input is from a string in ZLE, *index + * is set to the position of the end of the current editor word. + * + * comments is used if buf is non-NULL (i.e. this is not a string + * from ZLE). + * If it is 0, comments are not parsed; they are treated as ordinary words. + * If it is 1, comments are treated as single strings, one per line. + * If it is 2, comments are removed. */ /**/ mod_export LinkList -bufferwords(LinkList list, char *buf, int *index) +bufferwords(LinkList list, char *buf, int *index, int comments) { int num = 0, cur = -1, got = 0, ne = noerrs; int owb = wb, owe = we, oadx = addedx, ozp = zleparse, onc = nocomments; @@ -2906,7 +2922,6 @@ bufferwords(LinkList list, char *buf, int *index) * string expression, we just turn the option off for this function. */ opts[RCQUOTES] = 0; - zleparse = 1; addedx = 0; noerrs = 1; lexsave(); @@ -2928,11 +2943,18 @@ bufferwords(LinkList list, char *buf, int *index) inpush(p, 0, NULL); zlemetall = strlen(p) ; zlemetacs = zlemetall + 1; - nocomments = 1; + + /* + * If comments is non-zero we are handling comments. + * zleparse indicates the mode to the lexer. + */ + zleparse = 1 + comments; + nocomments = !comments; } else { int ll, cs; char *linein; + zleparse = 1; linein = zleentry(ZLE_CMD_GET_LINE, &ll, &cs); zlemetall = ll + 1; /* length of line plus space added below */ zlemetacs = cs; diff --git a/Src/lex.c b/Src/lex.c index fdb4b98ac..44cfa17ca 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -116,7 +116,22 @@ mod_export int wb, we; /**/ mod_export int noaliases; -/* we are parsing a line sent to use by the editor */ +/* + * we are parsing a line sent to use by the editor, or some other string + * that's not part of standard command input (e.g. eval is part of + * normal command input). + * + * zleparse = 1 is the normal case. + * zleparse = 2 is used for word splitting; the difference is we + * preserve comments. + * zleparse = 3 is also for word splitting, here handling comments + * but stripping them. + * + * Note that although it is passed into the lexer as an input, the + * lexer can set it to zero after finding the word it's searching for. + * This only happens if the line being parsed actually does come from + * ZLE. + */ /**/ mod_export int zleparse; @@ -743,26 +758,50 @@ gettok(void) /* chars in initial position in word */ + /* + * Handle comments. There are some special cases when this + * is not normal command input: zleparse implies we are examining + * a line lexically without it being used for normal command input. + * If zleparse is 1 we treat comments as normal for interactive + * mode. + * If zleparse is 2 (which has actually got nothing to do with zle) + * we always handle comments and retain them. + * If zleparse is 3 we always handle comments and discard them. + */ if (c == hashchar && !nocomments && (isset(INTERACTIVECOMMENTS) || - (!zleparse && !expanding && + ((zleparse != 1) && !expanding && (!interact || unset(SHINSTDIN) || strin)))) { /* History is handled here to prevent extra * * newlines being inserted into the history. */ + if (zleparse == 2) { + len = 0; + bptr = tokstr = (char *)hcalloc(bsiz = 32); + add(c); + } while ((c = ingetc()) != '\n' && !lexstop) { hwaddc(c); addtoline(c); + if (zleparse == 2) + add(c); } if (errflag) peek = LEXERR; else { - hwend(); - hwbegin(0); - hwaddc('\n'); - addtoline('\n'); - peek = NEWLIN; + if (zleparse == 2) { + *bptr = '\0'; + if (!lexstop) + hungetc(c); + peek = STRING; + } else { + hwend(); + hwbegin(0); + hwaddc('\n'); + addtoline('\n'); + peek = NEWLIN; + } } return peek; } diff --git a/Src/subst.c b/Src/subst.c index 031a1affd..799682df2 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1556,6 +1556,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) * The (z) flag, nothing to do with SH_WORD_SPLIT which is tied * spbreak, see above; fairly straighforward in use but c.f. * the comment for mods. + * + * This ultimately becomes zleparse during lexical analysis, via + * the comments argument to bufferwords(). It's got nothing + * to do with zle. */ int shsplit = 0; /* @@ -1934,6 +1938,27 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) case 'z': shsplit = 1; + if (s[1] == '+') { + s += 2; + while (*s && *s != '+' && *s != ')' && *s != Outpar) { + switch (*s++) { + case 'c': + /* Parse and keep comments */ + shsplit = 2; + break; + + case 'C': + /* Parse and remove comments */ + shsplit = 3; + break; + + default: + goto flagerr; + } + } + if (*s != '+') + goto flagerr; + } break; case 'u': @@ -3207,10 +3232,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) if (isarr) { char **ap; for (ap = aval; *ap; ap++) - list = bufferwords(list, *ap, NULL); + list = bufferwords(list, *ap, NULL, shsplit-1); isarr = 0; } else - list = bufferwords(NULL, val, NULL); + list = bufferwords(NULL, val, NULL, shsplit-1); if (!list || !firstnode(list)) val = dupstring(""); |