diff options
author | Rob Landley <rob@landley.net> | 2019-05-26 08:15:44 -0500 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2019-05-26 08:15:44 -0500 |
commit | 6d2205e8131e9524ea3c3bb8cfd410a412c9fcaf (patch) | |
tree | 745958581be22fa7ef5a37f1843040903a64eac3 /toys/posix | |
parent | 1dbd86ec825ba92be12e4aafad49804faaa86ec6 (diff) | |
download | toybox-6d2205e8131e9524ea3c3bb8cfd410a412c9fcaf.tar.gz |
Teach sed about +N range ending.
Diffstat (limited to 'toys/posix')
-rw-r--r-- | toys/posix/sed.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/toys/posix/sed.c b/toys/posix/sed.c index 4e81001a..979a6eb8 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -49,7 +49,7 @@ config SED address matches one line, a pair of comma separated addresses match everything from the first address to the second address (inclusive). If both addresses are regular expressions, more than one range of lines in - each file can match. + each file can match. The second address can be +N to end N lines later. REGULAR EXPRESSIONS in sed are started and ended by the same character (traditionally / but anything except a backslash or a newline works). @@ -214,7 +214,7 @@ static int emit(char *line, long len, int eol) l = writeall(TT.fdout, line, len); if (eol) line[len-1] = old; if (l != len) { - perror_msg("short write"); + if (TT.fdout != 1) perror_msg("short write"); return 1; } @@ -304,20 +304,23 @@ static void sed_line(char **pline, long plen) if (line && !regexec0(rm, line, len, 0, 0, 0)) miss = 1; } } else if (lm > 0 && lm < TT.count) command->hit = 0; + else if (lm < -1 && TT.count == command->hit+(-lm-1)) command->hit = 0; // Start a new match? } else { if (!(lm = *command->lmatch)) { void *rm = get_regex(command, *command->rmatch); - if (line && !regexec0(rm, line, len, 0, 0, 0)) command->hit++; - } else if (lm == TT.count || (lm == -1 && !pline)) command->hit++; + if (line && !regexec0(rm, line, len, 0, 0, 0)) + command->hit = TT.count; + } else if (lm == TT.count || (lm == -1 && !pline)) + command->hit = TT.count; if (!command->lmatch[1] && !command->rmatch[1]) miss = 1; } // Didn't match? - lm = !(command->hit ^ command->not); + lm = !(command->not^!!command->hit); // Deferred disable from regex end match if (miss || command->lmatch[1] == TT.count) command->hit = 0; @@ -779,8 +782,7 @@ static void parse_pattern(char **pline, long len) } if (!*line) return; - // We start by writing data into toybuf. Later we'll allocate the - // ex + // Start by writing data into toybuf. errstart = line; memset(toybuf, 0, sizeof(struct sedcmd)); @@ -792,7 +794,10 @@ static void parse_pattern(char **pline, long len) if (*line == ',') line++; else if (i) break; - if (isdigit(*line)) command->lmatch[i] = strtol(line, &line, 0); + if (i && *line == '+' && isdigit(line[1])) { + line++; + command->lmatch[i] = -2-strtol(line, &line, 0); + } else if (isdigit(*line)) command->lmatch[i] = strtol(line, &line, 0); else if (*line == '$') { command->lmatch[i] = -1; line++; @@ -823,7 +828,7 @@ static void parse_pattern(char **pline, long len) if (strchr("}:", c) && i) break; if (strchr("aiqr=", c) && i>1) break; - // Add step to pattern + // Allocate memory and copy out of toybuf now that we know how big it is command = xmemdup(toybuf, reg-toybuf); reg = (reg-toybuf) + (char *)command; |