summaryrefslogtreecommitdiffstats
path: root/usr.bin/sed
diff options
context:
space:
mode:
authordumbbell <dumbbell@FreeBSD.org>2014-08-08 17:29:01 +0000
committerdumbbell <dumbbell@FreeBSD.org>2014-08-08 17:29:01 +0000
commit9dd857db3dc558dc61dc8674d204ebc83cac0739 (patch)
tree56fad7945f924294efc11e0543b0c26cd444943a /usr.bin/sed
parent094158b3f2a6f1f1c94fd8c1357192c5d7486a79 (diff)
downloadFreeBSD-src-9dd857db3dc558dc61dc8674d204ebc83cac0739.zip
FreeBSD-src-9dd857db3dc558dc61dc8674d204ebc83cac0739.tar.gz
sed(1): Don't force a newline on last line, if input stream doesn't have one
While here, change how we check if the current line is the last one. Before, we just checked if there were more files after the current one. Now, we check the actual content of those files: they files may not have a line at all. This matches the definition of the "last line" by the Open Group. The new behavior is closer to GNU sed. PR: 160745 Phabric: https://phabric.freebsd.org/D431 Reviewed by: jilles Approved by: jilles Exp-run by: antoine
Diffstat (limited to 'usr.bin/sed')
-rw-r--r--usr.bin/sed/defs.h1
-rw-r--r--usr.bin/sed/main.c50
-rw-r--r--usr.bin/sed/process.c16
-rw-r--r--usr.bin/sed/tests/regress.y.out2
4 files changed, 61 insertions, 8 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 a500200..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':
@@ -452,6 +462,7 @@ substitute(struct s_command *cp)
*/
tspace = PS;
PS = SS;
+ psanl = tspace.append_newline;
SS = tspace;
SS.space = SS.back;
@@ -521,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
OpenPOWER on IntegriCloud