Date: Fri, 8 Aug 2014 17:29:01 +0000 (UTC) From: Jean-Sebastien Pedron <dumbbell@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r269729 - in head/usr.bin/sed: . tests Message-ID: <53e508dd.23d7.7477a7f9@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dumbbell Date: Fri Aug 8 17:29:01 2014 New Revision: 269729 URL: http://svnweb.freebsd.org/changeset/base/269729 Log: 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 Modified: head/usr.bin/sed/defs.h head/usr.bin/sed/main.c head/usr.bin/sed/process.c head/usr.bin/sed/tests/regress.y.out Modified: head/usr.bin/sed/defs.h ============================================================================== --- head/usr.bin/sed/defs.h Fri Aug 8 17:12:03 2014 (r269728) +++ head/usr.bin/sed/defs.h Fri Aug 8 17:29:01 2014 (r269729) @@ -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; Modified: head/usr.bin/sed/main.c ============================================================================== --- head/usr.bin/sed/main.c Fri Aug 8 17:12:03 2014 (r269728) +++ head/usr.bin/sed/main.c Fri Aug 8 17:29:01 2014 (r269729) @@ -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); } Modified: head/usr.bin/sed/process.c ============================================================================== --- head/usr.bin/sed/process.c Fri Aug 8 17:12:03 2014 (r269728) +++ head/usr.bin/sed/process.c Fri Aug 8 17:29:01 2014 (r269729) @@ -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; } Modified: head/usr.bin/sed/tests/regress.y.out ============================================================================== --- head/usr.bin/sed/tests/regress.y.out Fri Aug 8 17:12:03 2014 (r269728) +++ head/usr.bin/sed/tests/regress.y.out Fri Aug 8 17:29:01 2014 (r269729) @@ -1 +1 @@ -fOO +fOO \ No newline at end of file
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53e508dd.23d7.7477a7f9>