aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2014-11-16 18:58:22 -0600
committerRob Landley <rob@landley.net>2014-11-16 18:58:22 -0600
commit4a6eb58382c38274193d029f58c94da6f67daca5 (patch)
tree7eb2a97a0042de32b3696e39c4be0b2e2f669da9
parent7928b0d28b7e8fe8b7cb7eeb5ddde4d4840db9e4 (diff)
downloadtoybox-4a6eb58382c38274193d029f58c94da6f67daca5.tar.gz
Fix more sed bugs.
-rw-r--r--toys/pending/sed.c91
1 files changed, 35 insertions, 56 deletions
diff --git a/toys/pending/sed.c b/toys/pending/sed.c
index 7a9500c4..cf5e9c4a 100644
--- a/toys/pending/sed.c
+++ b/toys/pending/sed.c
@@ -204,32 +204,36 @@ static int emit(char *line, long len, int eol)
// Do regex matching handling embedded NUL bytes in string. Note that
// neither the pattern nor the match can currently include NUL bytes
-// (even with wildcards) and string must be nul terminated.
+// (even with wildcards) and string must be null terminated.
static int ghostwheel(regex_t *preg, char *string, long len, int nmatch,
regmatch_t pmatch[], int eflags)
{
-/*
- while (len && !*string) {
- string++;
- len--;
- int l = strlen(string);
- if (len != strlen(string))
-
- // todo: this
- long start = 0, rc = 0, matches = 0;
+ char *s = string;
for (;;) {
- long new = strlen(string+start);
+ long ll = 0;
+ int rc;
- // eflags nobegin noend
- rc |= regexec(preg, string+start, nmatch-matches, pmatch+matches, eflags);
- if ((start += end + 1) >= len) break;
- }
+ while (len && !*s) {
+ s++;
+ len--;
+ }
+ while (s[ll] && ll<len) ll++;
- return rc;
-*/
+ rc = regexec(preg, s, nmatch, pmatch, eflags);
+ if (!rc) {
+ for (rc = 0; rc<nmatch && pmatch[rc].rm_so!=-1; rc++) {
+ pmatch[rc].rm_so += s-string;
+ pmatch[rc].rm_eo += s-string;
+ }
+
+ return 0;
+ }
+ if (ll==len) return rc;
- return regexec(preg, string, nmatch, pmatch, eflags);
+ s += ll;
+ len -= ll;
+ }
}
// Extend allocation to include new string, with newline between if newlen<0
@@ -402,8 +406,10 @@ static void walk_pattern(char **pline, long plen)
// Pending append goes out right after N
goto done;
- } else if (c=='p') {
- if (emit(line, len, eol)) break;
+ } else if (c=='p' || c=='P') {
+ char *l = (c=='P') ? strchr(line, '\n') : 0;
+
+ if (emit(line, l ? l-line : len, eol)) break;
} else if (c=='q') break;
else if (c=='s') {
char *rline = line, *new = logrus->arg2 + (char *)logrus, *swap, *rswap;
@@ -438,15 +444,11 @@ static void walk_pattern(char **pline, long plen)
// newlen = strlen(new) but with \1 and & and printf escapes
for (off = newlen = 0; new[off]; off++) {
- int cc = 0;
+ int cc = -1;
- if (new[off] == '\\') {
- cc = new[++off] - '0';
- if (cc < 0 || cc > 9) {
- newlen += 1+!unescape(new[off]);
- continue;
- }
- } else if (new[off] != '&') {
+ if (new[off] == '&') cc = 0;
+ else if (new[off] == '\\') cc = new[++off] - '0';
+ if (cc < 0 || cc > 9) {
newlen++;
continue;
}
@@ -470,9 +472,8 @@ static void walk_pattern(char **pline, long plen)
if ((rswap[mlen++] = new[off]) == '\\') {
cc = new[++off] - '0';
if (cc<0 || cc>9) {
- cc = unescape(new[off]);
- if (cc) rswap[mlen-1] = cc;
- else rswap[mlen++] = new[off];
+ if (!(rswap[mlen-1] = unescape(new[off])))
+ rswap[mlen-1] = new[off];
continue;
} else if (match[cc].rm_so == -1) error_exit("no s//\\%d/", cc);
@@ -589,27 +590,6 @@ static void do_lines(int fd, char *name, void (*call)(char **pline, long len))
if (fd) fclose(fp);
}
-// Iterate over newline delimited data blob (potentially with embedded NUL),
-// call function on each line.
-static void chop_lines(char *data, long len, void (*call)(char **p, long l))
-{
- long ll;
-
- for (ll = 0; ll < len; ll++) {
- if (data[ll] == '\n') {
- char *c = data;
-
- data[ll] = 0;
- call(&c, len);
- data[ll++] = '\n';
- data += ll;
- len -= ll;
- ll = -1;
- }
- }
- if (len) call(&data, len);
-}
-
static void do_sed(int fd, char *name)
{
int i = toys.optflags & FLAG_i;
@@ -828,9 +808,8 @@ writenow:
fd = xcreate(line, O_WRONLY|O_CREAT|O_TRUNC, 0644);
*cc = delim;
- delim = cc-line;
corwin->w = reg - (char *)corwin;
- corwin = xrealloc(corwin, corwin->w + delim + 6);
+ corwin = xrealloc(corwin, corwin->w+(cc-line)+6);
reg = corwin->w + (char *)corwin;
memcpy(reg, &fd, 4);
@@ -864,7 +843,7 @@ writenow:
while (isspace(*line)) line++;
append:
class = !strchr("btT:", c);
- end = strcspn(line, class ? "" : "; \t\r\n\v\f");
+ end = strcspn(line, class ? "\n" : "; \t\r\n\v\f");
if (!end) {
if (!strchr("btT", c)) break;
@@ -916,7 +895,7 @@ void sed_main(void)
// so handle all -e, then all -f. (At least the behavior's consistent.)
for (dworkin = TT.e; dworkin; dworkin = dworkin->next)
- chop_lines(dworkin->arg, strlen(dworkin->arg), jewel_of_judgement);
+ jewel_of_judgement(&dworkin->arg, strlen(dworkin->arg));
for (dworkin = TT.f; dworkin; dworkin = dworkin->next)
do_lines(xopen(dworkin->arg, O_RDONLY), dworkin->arg, jewel_of_judgement);
dlist_terminate(TT.pattern);