diff options
author | sjg <sjg@FreeBSD.org> | 2014-11-19 01:07:58 +0000 |
---|---|---|
committer | sjg <sjg@FreeBSD.org> | 2014-11-19 01:07:58 +0000 |
commit | b137080f19736ee33fede2e88bb54438604cf86b (patch) | |
tree | 377ac0ac449528621eb192cd245adadb5fd53668 /usr.bin/sed | |
parent | ab21a29eb607d4dfe389b965fbdee27558e791aa (diff) | |
parent | 4a8d07956d121238d006d34ffe7d6269744e8b1a (diff) | |
download | FreeBSD-src-b137080f19736ee33fede2e88bb54438604cf86b.zip FreeBSD-src-b137080f19736ee33fede2e88bb54438604cf86b.tar.gz |
Merge from head@274682
Diffstat (limited to 'usr.bin/sed')
-rw-r--r-- | usr.bin/sed/defs.h | 1 | ||||
-rw-r--r-- | usr.bin/sed/main.c | 50 | ||||
-rw-r--r-- | usr.bin/sed/process.c | 60 | ||||
-rw-r--r-- | usr.bin/sed/tests/regress.y.out | 2 |
4 files changed, 87 insertions, 26 deletions
diff --git a/usr.bin/sed/defs.h b/usr.bin/sed/defs.h index d4f434e..fb33676 100644 --- a/usr.bin/sed/defs.h +++ b/usr.bin/sed/defs.h @@ -143,6 +143,7 @@ typedef struct { char *space; /* Current space pointer. */ size_t len; /* Current length. */ int deleted; /* If deleted. */ + int append_newline; /* If originally terminated by \n. */ char *back; /* Backing memory. */ size_t blen; /* Backing memory length. */ } SPACE; diff --git a/usr.bin/sed/main.c b/usr.bin/sed/main.c index 6cdfcda..76e186f 100644 --- a/usr.bin/sed/main.c +++ b/usr.bin/sed/main.c @@ -439,8 +439,14 @@ mf_fgets(SPACE *sp, enum e_spflag spflag) len = getline(&p, &plen, infile); if (len == -1) err(1, "%s", fname); - if (len != 0 && p[len - 1] == '\n') + if (len != 0 && p[len - 1] == '\n') { + sp->append_newline = 1; len--; + } else if (!lastline()) { + sp->append_newline = 1; + } else { + sp->append_newline = 0; + } cspace(sp, p, len, spflag); linenum++; @@ -481,15 +487,49 @@ add_file(char *s) fl_nextp = &fp->next; } +static int +next_files_have_lines() +{ + struct s_flist *file; + FILE *file_fd; + int ch; + + file = files; + while ((file = file->next) != NULL) { + if ((file_fd = fopen(file->fname, "r")) == NULL) + continue; + + if ((ch = getc(file_fd)) != EOF) { + /* + * This next file has content, therefore current + * file doesn't contains the last line. + */ + ungetc(ch, file_fd); + fclose(file_fd); + return (1); + } + + fclose(file_fd); + } + + return (0); +} + int lastline(void) { int ch; - if (files->next != NULL && (inplace == NULL || ispan)) - return (0); - if ((ch = getc(infile)) == EOF) - return (1); + if (feof(infile)) { + return !( + (inplace == NULL || ispan) && + next_files_have_lines()); + } + if ((ch = getc(infile)) == EOF) { + return !( + (inplace == NULL || ispan) && + next_files_have_lines()); + } ungetc(ch, infile); return (0); } diff --git a/usr.bin/sed/process.c b/usr.bin/sed/process.c index 5e2618a..9cd2c2e 100644 --- a/usr.bin/sed/process.c +++ b/usr.bin/sed/process.c @@ -63,6 +63,7 @@ static SPACE HS, PS, SS, YS; #define pd PS.deleted #define ps PS.space #define psl PS.len +#define psanl PS.append_newline #define hs HS.space #define hsl HS.len @@ -85,7 +86,10 @@ static regex_t *defpreg; size_t maxnsub; regmatch_t *match; -#define OUT() do {fwrite(ps, 1, psl, outfile); fputc('\n', outfile);} while (0) +#define OUT() do { \ + fwrite(ps, 1, psl, outfile); \ + if (psanl) fputc('\n', outfile); \ +} while (0) void process(void) @@ -94,6 +98,7 @@ process(void) SPACE tspace; size_t oldpsl = 0; char *p; + int oldpsanl; p = NULL; @@ -190,11 +195,15 @@ redirect: break; if ((p = memchr(ps, '\n', psl)) != NULL) { oldpsl = psl; + oldpsanl = psanl; psl = p - ps; + psanl = 1; } OUT(); - if (p != NULL) + if (p != NULL) { psl = oldpsl; + psanl = oldpsanl; + } break; case 'q': if (!nflag && !pd) @@ -244,6 +253,7 @@ redirect: cspace(&HS, "", 0, REPLACE); tspace = PS; PS = HS; + psanl = tspace.append_newline; HS = tspace; break; case 'y': @@ -288,24 +298,32 @@ applies(struct s_command *cp) r = 1; else if (cp->a2) if (cp->startline > 0) { - if (MATCH(cp->a2)) { - cp->startline = 0; - lastaddr = 1; - r = 1; - } else if (linenum - cp->startline <= cp->a2->u.l) - r = 1; - else if ((cp->a2->type == AT_LINE && - linenum > cp->a2->u.l) || - (cp->a2->type == AT_RELLINE && - linenum - cp->startline > cp->a2->u.l)) { - /* - * We missed the 2nd address due to a branch, - * so just close the range and return false. - */ - cp->startline = 0; - r = 0; - } else - r = 1; + switch (cp->a2->type) { + case AT_RELLINE: + if (linenum - cp->startline <= cp->a2->u.l) + r = 1; + else { + cp->startline = 0; + r = 0; + } + break; + default: + if (MATCH(cp->a2)) { + cp->startline = 0; + lastaddr = 1; + r = 1; + } else if (cp->a2->type == AT_LINE && + linenum > cp->a2->u.l) { + /* + * We missed the 2nd address due to a + * branch, so just close the range and + * return false. + */ + cp->startline = 0; + r = 0; + } else + r = 1; + } } else if (MATCH(cp->a1)) { /* * If the second address is a number less than or @@ -444,6 +462,7 @@ substitute(struct s_command *cp) */ tspace = PS; PS = SS; + psanl = tspace.append_newline; SS = tspace; SS.space = SS.back; @@ -513,6 +532,7 @@ do_tr(struct s_tr *y) /* Swap the translation space and the pattern space. */ tmp = PS; PS = YS; + psanl = tmp.append_newline; YS = tmp; YS.space = YS.back; } diff --git a/usr.bin/sed/tests/regress.y.out b/usr.bin/sed/tests/regress.y.out index 829a681..22f4f05 100644 --- a/usr.bin/sed/tests/regress.y.out +++ b/usr.bin/sed/tests/regress.y.out @@ -1 +1 @@ -fOO +fOO
\ No newline at end of file |