Hello community, here is the log from the commit of package diffstat for openSUSE:Factory checked in at 2020-01-01 14:56:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/diffstat (Old) and /work/SRC/openSUSE:Factory/.diffstat.new.6675 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "diffstat" Wed Jan 1 14:56:28 2020 rev:29 rq:758173 version:1.63 Changes: -------- --- /work/SRC/openSUSE:Factory/diffstat/diffstat.changes 2019-01-03 18:05:21.760207846 +0100 +++ /work/SRC/openSUSE:Factory/.diffstat.new.6675/diffstat.changes 2020-01-01 14:56:42.901881475 +0100 @@ -1,0 +2,16 @@ +Thu Dec 19 13:11:21 UTC 2019 - [email protected] + +- version update to 1.63 + + eliminate fixed buffer when decoding range. + + use locale in computing filename column-width. + + improve parsing for git diffs. + + use terminal-width as default for -w to tty. + + minor fix in do_merging (Miloslaw Smyk). + + improve relative-pathname matching in count_lines() + + add a parsing-case for svn diff. + + quote filenames in -t/-T output. + + fix cppcheck warnings about sscanf. + + update configure macros + + update config.guess, config.sub + +------------------------------------------------------------------- Old: ---- diffstat-1.62.tgz diffstat-1.62.tgz.asc New: ---- diffstat-1.63.tgz diffstat-1.63.tgz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ diffstat.spec ++++++ --- /var/tmp/diff_new_pack.TIvYYQ/_old 2020-01-01 14:56:44.129882116 +0100 +++ /var/tmp/diff_new_pack.TIvYYQ/_new 2020-01-01 14:56:44.149882126 +0100 @@ -1,7 +1,7 @@ # # spec file for package diffstat # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,12 +17,12 @@ Name: diffstat -Version: 1.62 +Version: 1.63 Release: 0 Summary: Utility That Provides Statistics Based on the Output of diff License: MIT Group: Productivity/Text/Utilities -Url: http://dickey.his.com/diffstat/diffstat.html +URL: https://dickey.his.com/diffstat/diffstat.html Source0: https://invisible-mirror.net/archives/diffstat/diffstat-%{version}.tgz Source1: https://invisible-mirror.net/archives/diffstat/diffstat-%{version}.tgz.asc Source2: %{name}.keyring ++++++ diffstat-1.62.tgz -> diffstat-1.63.tgz ++++++ ++++ 8265 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/CHANGES new/diffstat-1.63/CHANGES --- old/diffstat-1.62/CHANGES 2018-08-15 02:36:08.000000000 +0200 +++ new/diffstat-1.63/CHANGES 2019-11-29 21:59:03.000000000 +0100 @@ -1,4 +1,27 @@ --- $Id: CHANGES,v 1.98 2018/08/15 00:36:08 tom Exp $ +-- $Id: CHANGES,v 1.101 2019/11/29 20:59:03 tom Exp $ + +2019/11/29 (diffstat 1.63) + + eliminate fixed buffer when decoding range. + + + use locale in computing filename column-width. + + + improve parsing for git diffs. + + + use terminal-width as default for -w to tty. + + + minor fix in do_merging (Miloslaw Smyk). + + + improve relative-pathname matching in count_lines() + + + add a parsing-case for svn diff. + + + quote filenames in -t/-T output. + + + fix cppcheck warnings about sscanf. + + + update configure macros + + + update config.guess, config.sub 2018/08/15 (diffstat 1.62) + improve checks for unmodified files when -S and -D options are diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/COPYING new/diffstat-1.63/COPYING --- old/diffstat-1.62/COPYING 2018-08-15 01:02:14.000000000 +0200 +++ new/diffstat-1.63/COPYING 2019-11-25 01:11:49.000000000 +0100 @@ -1,4 +1,4 @@ -Copyright 1994-2016,2018 by Thomas E. Dickey +Copyright 1994-2018,2019 by Thomas E. Dickey All Rights Reserved. Permission to use, copy, modify, and distribute this software and its diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/COPYING.asc new/diffstat-1.63/COPYING.asc --- old/diffstat-1.62/COPYING.asc 2018-08-15 01:02:33.000000000 +0200 +++ new/diffstat-1.63/COPYING.asc 2019-11-25 01:12:11.000000000 +0100 @@ -1,8 +1,7 @@ -----BEGIN PGP SIGNATURE----- -Version: GnuPG v1 Comment: See https://invisible-island.net/public/public.html for info -iEYEABECAAYFAltzX4UACgkQcCNT4PfkjtvJuwCgnlebYQ1+3nQsUbwf0x+V/lO8 -+JUAoNC1Li12OE3RmMMmjSBjknaGx2zL -=WmrG +iF0EABECAB0WIQTFIEjAwHSP7iJ9R6JwI1Pg9+SO2wUCXdscWAAKCRBwI1Pg9+SO +24dNAJ4hDPY290kWxNaNZr0kpa28rcjcPACfRPhb5QwpTXimfJCSDCVSPy/gq94= +=Xglp -----END PGP SIGNATURE----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/configure.in new/diffstat-1.63/configure.in --- old/diffstat-1.62/configure.in 2016-01-03 18:44:31.000000000 +0100 +++ new/diffstat-1.63/configure.in 2019-11-29 02:32:17.000000000 +0100 @@ -1,7 +1,10 @@ dnl Process this file with 'autoconf' to produce a 'configure' script -dnl $Id: configure.in,v 1.29 2016/01/03 17:44:31 tom Exp $ -AC_PREREQ(2.52.20011201) -AC_REVISION($Revision: 1.29 $) +dnl $Id: configure.in,v 1.33 2019/11/29 01:32:17 tom Exp $ +dnl +dnl Copyright 1994-2016,2019 Thomas E. Dickey +dnl +AC_PREREQ(2.52.20190901) +AC_REVISION($Revision: 1.33 $) AC_INIT(diffstat.c) AC_CONFIG_HEADER(config.h:config_h.in) @@ -38,18 +41,25 @@ AC_TYPE_SIZE_T +CF_LOCALE + AC_CHECK_FUNCS(\ mkdtemp \ opendir \ +strdup \ tsearch \ ) CF_FUNC_LSTAT CF_FUNC_GETOPT(getopt,\$(srcdir)/porting) CF_FUNC_POPEN(popen,\$(srcdir)/porting) +CF_FUNC_MBSTOWCWIDTH CF_STDIO_UNLOCKED(getc_unlocked) +AC_HAVE_HEADERS(ioctl.h sys/ioctl.h) +CF_TERMIOS + CF_WITH_MAN2HTML CF_DISABLE_LEAKS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/diffstat.1 new/diffstat-1.63/diffstat.1 --- old/diffstat-1.62/diffstat.1 2018-08-15 02:29:55.000000000 +0200 +++ new/diffstat-1.63/diffstat.1 2019-11-29 02:34:39.000000000 +0100 @@ -1,5 +1,5 @@ .\"***************************************************************************** -.\" Copyright 1994-2016,2018 by Thomas E. Dickey * +.\" Copyright 1994-2018,2019 by Thomas E. Dickey * .\" All Rights Reserved. * .\" * .\" Permission to use, copy, modify, and distribute this software and its * @@ -18,7 +18,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR * .\" IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * .\"***************************************************************************** -.\" $Id: diffstat.1,v 1.39 2018/08/15 00:29:55 tom Exp $ +.\" $Id: diffstat.1,v 1.40 2019/11/29 01:34:39 tom Exp $ .ie \n(.g .ds `` \(lq .el .ds `` `` .ie \n(.g .ds '' \(rq @@ -233,6 +233,10 @@ specify the maximum width of the histogram. The histogram will never be shorter than 10 columns, just in case the filenames get too large. +.IP +The default is 80 columns, +unless the output is to a terminal. +In that case, the default width is the terminal's width. .SH ENVIRONMENT .PP \fBDiffstat\fP runs in a POSIX environment. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/diffstat.c new/diffstat-1.63/diffstat.c --- old/diffstat-1.62/diffstat.c 2018-08-15 03:26:54.000000000 +0200 +++ new/diffstat-1.63/diffstat.c 2019-11-29 21:39:01.000000000 +0100 @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 1994-2016,2018 by Thomas E. Dickey * + * Copyright 1994-2018,2019 by Thomas E. Dickey * * All Rights Reserved. * * * * Permission to use, copy, modify, and distribute this software and its * @@ -20,7 +20,7 @@ ******************************************************************************/ #ifndef NO_IDENT -static const char *Id = "$Id: diffstat.c,v 1.62 2018/08/15 01:26:54 tom Exp $"; +static const char *Id = "$Id: diffstat.c,v 1.63 2019/11/29 20:39:01 tom Exp $"; #endif /* @@ -28,6 +28,15 @@ * Author: T.E.Dickey * Created: 02 Feb 1992 * Modified: + * 29 Nov 2019, eliminate fixed buffer when decoding range. + * 28 Nov 2019, use locale in computing filename column-width. + * improve parsing for git diffs. + * use terminal-width as default for -w to tty. + * minor fix in do_merging (Miloslaw Smyk). + * 27 Nov 2019, improve relative-pathname matching in count_lines() + * add a parsing-case for svn diff. + * quote filenames in -t/-T output. + * 24 Nov 2019, fix cppcheck-warnings about sscanf. * 14 Aug 2018, revise -S/-D option to improve count of unmodified * files. * 14 Jan 2016, extend -S option to count unmodified files. @@ -237,6 +246,11 @@ #undef HAVE_TSEARCH #endif +#ifdef HAVE_MBSTOWCWIDTH +#include <locale.h> +#include <wchar.h> +#endif + #ifdef HAVE_GETC_UNLOCKED #define MY_GETC getc_unlocked #else @@ -254,6 +268,19 @@ #include <sys/types.h> #include <sys/stat.h> +#if defined(HAVE_TERMIOS_H) && defined(HAVE_TCGETATTR) +#ifdef HAVE_IOCTL_H +#include <ioctl.h> +#else +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif +#endif +#if !defined(sun) || !defined(NL0) +#include <termios.h> +#endif +#endif /* HAVE_TERMIOS_H */ + #if defined(HAVE_POPEN) && !defined(HAVE_POPEN_PROTOTYPE) extern FILE *popen(const char *, const char *); extern int pclose(FILE *); @@ -314,13 +341,21 @@ #define PATHSEP '/' #endif +#define BACKSL '\\' +#define LPAREN '(' +#define RPAREN ')' #define DQUOTE '"' #define SQUOTE '\'' +#define ESCAPE '\033' #define EOS '\0' +#define TAB '\t' #define BLANK ' ' +#define DEL '\177' #define UC(c) ((unsigned char)(c)) +#define isoctal(c) (((c) >= '0') && ((c) <= '7')) + #ifndef OPT_TRACE #define OPT_TRACE 1 #endif @@ -400,7 +435,7 @@ static int count_files; /* true if we count added/deleted files */ static int format_opt = FMT_NORMAL; static int max_name_wide; /* maximum amount reserved for filenames */ -static int max_width; /* the specified width-limit */ +static int max_width = 80; /* the specified width-limit */ static int merge_names = 1; /* true if we merge similar filenames */ static int merge_opt = 0; /* true if we merge ins/del as modified */ static int min_name_wide; /* minimum amount reserved for filenames */ @@ -540,18 +575,26 @@ } } +#ifdef HAVE_STRDUP +#define new_string(s) strdup(s) +#else static char * new_string(const char *s) { return strcpy((char *) xmalloc((size_t) (strlen(s) + 1)), s); } +#endif static int compare_data(const void *a, const void *b) { const DATA *p = (const DATA *) a; const DATA *q = (const DATA *) b; - return strcmp(p->name + p->base, q->name + q->base); + return ((p != NULL) + ? ((q != NULL) + ? strcmp(p->name + p->base, q->name + q->base) + : 1) + : -1); } static void @@ -631,8 +674,7 @@ static DATA * find_data(const char *name) { - DATA *p, *r; - DATA find; + DATA *r; int base = 0; TRACE(("** find_data(%s)\n", name)); @@ -656,6 +698,8 @@ } else #endif { + DATA *p; + DATA find; DATA *q; init_data(&find, name, 1, base); @@ -803,23 +847,41 @@ * claim that both numbers are line-numbers. However, inspection of the output * shows that the numbers are a line-number followed by a count. */ -static int -decode_range(const char *s, int *first, int *second) +static char * +decode_range(char *s, int *first, int *second) { - int rc = 0; - char check; - if (isdigit(UC(*s))) { - if (sscanf(s, "%d,%d%c", first, second, &check) == 2) { - TRACE(("** decode_range #1 first=%d, second=%d\n", *first, *second)); - rc = 1; - } else if (sscanf(s, "%d%c", first, &check) == 1) { - *second = *first; /* diffutils 2.7 does this */ - TRACE(("** decode_range #2 first=%d, second=%d\n", *first, *second)); - rc = 1; + int count = 0; + int value[2]; + + value[count] = 0; + while (*s != EOS) { + int ch = UC(*s); + if (isdigit(ch)) { + value[count] = (10 * value[count]) + (ch - '0'); + } else if (ch == ',') { + if (++count > 1) { + s = NULL; + break; + } + value[count] = 0; + } else { + break; + } + ++s; + } + if (s != NULL) { + *first = value[0]; + if (count == 0) { + *second = *first; /* diffutils 2.7 does this */ + } else { + *second = value[1]; + } + TRACE(("** decode_range #%d first=%d, second=%d\n", + count + 1, *first, *second)); } } - return rc; + return s; } static int @@ -1031,10 +1093,10 @@ if (can_be_merged(source)) { TRACE(("** merge @%d\n", __LINE__)); if (merge_names - && *target != '\0' + && *target != EOS && prefix_opt < 0) { size_t matched = compare_tails(target, source, &diff); - if (matched) + if (matched && !diff) result = target + (int) (strlen(target) - matched); } } else { @@ -1210,12 +1272,28 @@ if ((filename = malloc(want)) != 0) { int merge = 0; - if (path_dest) { + if (path_dest && *path_opt != EOS && *filetail != PATHSEP) { size_t path_len = strlen(path_opt); + size_t tail_len = strlen(filetail); char *tail_sep = strchr(filetail, PATHSEP); + size_t n; + + for (n = path_len - 1; (int) n >= 0; --n) { + if ((path_len - n) > tail_len) + break; + if ((n == 0 || path_opt[n - 1] == PATHSEP) + && filetail[path_len - n] == PATHSEP) { + if (!strncmp(path_opt + n, filetail, path_len - n)) { + merge = 1; + strcpy(filename, path_opt); + strcpy(filename + n, filetail); + break; + } + } + } - if (tail_sep != 0) { - size_t tail_len = (size_t) (tail_sep - filetail); + if (merge == 0 && tail_sep != 0) { + tail_len = (size_t) (tail_sep - filetail); if (tail_len != 0 && tail_len <= path_len) { if (tail_len < path_len && path_opt[path_len - tail_len - 1] != PATHSEP) { @@ -1297,6 +1375,254 @@ } } +static char * +copy_notabs(char *target, char *source, size_t limit) +{ + char *result = 0; + if (limit-- != 0) { /* count trailing null */ + char ch; + int found = 0; + while ((ch = *source) != EOS) { + if (ch == TAB) { + if (found) + result = source; + break; + } else if (limit-- == 0) { + break; + } + *target++ = ch; + *target = EOS; + ++source; + found = 1; + } + } + return result; +} + +static char * +copy_graphs(char *target, char *source, size_t limit) +{ + int found = 0; + if (limit-- != 0) { /* count trailing null */ + char ch; + while ((ch = *source) != EOS) { + if (ch == TAB || ch == BLANK) { + break; + } else if (limit-- == 0) { + found = 0; + break; + } + *target++ = ch; + *target = EOS; + ++source; + found = 1; + } + } + return found ? source : NULL; +} + +/* + * Tested with git 2.11: + * git uses dummy directory-names "a" and "b" rather than the actual working + * directory. Also, it allows non-printable characters, encoded in C-style + * backslash sequences. When those are used, it double-quotes the string. + */ +static char * +copy_git_name(char *target, char *source, size_t limit) +{ + int found = 0; + int quoted = 0; + + /* + * Account for double-quote. + */ + if (*source == DQUOTE) { + quoted = 1; + ++source; + limit--; + } + + /* + * Check for the dummy directory paths, and quit if not used. + */ + if (limit <= 2 || (strncmp(source, "a/", 2) && strncmp(source, "b/", 2))) { + limit = 0; + } else { + if (path_dest && !strncmp(source, "b/", 2)) { + source += 2; /* tweak to help with counting lines */ + } + } + + if (limit-- != 0) { /* count trailing null */ + char ch; + while ((ch = *source) != EOS) { + if (quoted) { + if (ch == DQUOTE) { + if (*++source != EOS) + found = 0; + break; + } else if (ch == BACKSL) { + int fail = 0; + if ((ch = *++source) == EOS) { + fail = 1; + } else if (isoctal(UC(ch))) { + int need = 3; + int value = 0; + /* decode octal escapes into UTF-8 bytes */ + while (need-- > 0) { + if (isoctal(*source)) { + value <<= 3; + value |= (UC(*source) - '0'); + if (need) { + ++source; + } + } else { + fail = 1; + break; + } + } + ch = (char) value; + } else { + --limit; + switch (ch) { + case BACKSL: + /* FALLTHRU */ + case DQUOTE: + break; + case 'b': + ch = '\b'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + default: + fail = 1; + break; + } + } + if (fail) { + found = 0; + break; + } + } + } else if (!isprint(UC(ch))) { + break; + } + if (limit-- == 0) { + found = 0; + break; + } + *target++ = ch; + *target = EOS; + ++source; + found = 1; + } + } + return found ? source : NULL; +} + +/* perforce */ +static char * +copy_p4_name(char *target, char *source, size_t limit) +{ + int found = 0; + if (limit-- != 0) { /* count trailing null */ + char ch; + while ((ch = *source) != EOS) { + if (ch == TAB || ch == BLANK || ch == '#') { + break; + } else if (limit-- == 0) { + found = 0; + break; + } + *target++ = ch; + *target = EOS; + ++source; + found = 1; + } + } + return found ? source : NULL; +} + +static char * +copy_integer(int *target, char *source) +{ + char *next = NULL; + long value = strtol(source, &next, 10); + *target = (int) value; + return next; +} + +static char * +need_blanks(char *source) +{ + int found = 0; + while (*source != EOS) { + char ch = *source++; + if (ch == BLANK || ch == TAB) + found = 1; + } + return found ? source : NULL; +} + +static char * +need_graphs(char *source) +{ + char *result = NULL; + int found = 0; + while (*source != EOS) { + char ch = *source; + if (ch == BLANK || ch == TAB || ch == EOS) { + if (found) + result = source; + break; + } + ++source; + found = 1; + } + return result; +} + +static char * +need_nospcs(char *source) +{ + char *result = NULL; + int found = 0; + while (*source != EOS) { + char ch = *source; + if (ch == BLANK || ch == EOS) { + if (found) + result = source; + break; + } + ++source; + found = 1; + } + return result; +} + +/* this is used with SVN */ +static char * +need_parens(char *source) +{ + char *result = NULL; + if (*source++ == LPAREN) { + while (*source != EOS) { + if (*source++ == RPAREN) { + result = source; + break; + } + } + } + return result; +} + #define date_delims(a,b) (((a)=='/' && (b)=='/') || ((a) == '-' && (b) == '-')) #define CASE_TRACE() TRACE(("** handle case for '%c' %d:%s\n", *buffer, ok, that ? that->name : "")) @@ -1310,9 +1636,6 @@ DATA *prev = 0; char *buffer = 0; char *b_fname = 0; - char *b_temp1 = 0; - char *b_temp2 = 0; - char *b_temp3 = 0; size_t length = 0; size_t fixed = 0; int ok = HAVE_NOTHING; @@ -1339,9 +1662,6 @@ fixed_buffer(&buffer, fixed = length = BUFSIZ); fixed_buffer(&b_fname, length); - fixed_buffer(&b_temp1, length); - fixed_buffer(&b_temp2, length); - fixed_buffer(&b_temp3, length); while (get_line(&buffer, &length, fp)) { /* @@ -1350,15 +1670,12 @@ if (length > fixed) { fixed = length; adjust_buffer(&b_fname, length); - adjust_buffer(&b_temp1, length); - adjust_buffer(&b_temp2, length); - adjust_buffer(&b_temp3, length); } /* * Trim trailing newline. */ - for (s = buffer + strlen(buffer); s > buffer; s--) { + for (s = buffer + strlen(buffer); s != buffer; s--) { if ((UC(s[-1]) == '\n') || (UC(s[-1]) == '\r')) s[-1] = EOS; else @@ -1372,12 +1689,12 @@ if (trim_escapes && (strchr(buffer, '\033') != 0)) { char *d = buffer; s = d; - while (*s != '\0') { + while (*s != EOS) { if (*s == '\033') { - while (*s != '\0' && !isFINAL(*s)) { + while (*s != EOS && !isFINAL(*s)) { ++s; } - if (*s != '\0') { + if (*s != EOS) { ++s; continue; } else { @@ -1386,7 +1703,7 @@ } *d++ = *s++; } - *d = '\0'; + *d = EOS; } ++line_no; TRACE(("[%05d] %s\n", line_no, buffer)); @@ -1444,16 +1761,14 @@ unified = 0; if (*buffer == '@') { int old_base, new_base, old_size, new_size; - char test_at; + char *sp; old_unify = new_unify = 0; - if (sscanf(buffer, "@@ -%80[0-9,] +%80[0-9,] @%c", - b_temp1, - b_temp2, - &test_at) == 3 - && test_at == '@' - && decode_range(b_temp1, &old_base, &old_size) - && decode_range(b_temp2, &new_base, &new_size)) { + if ((sp = match(buffer, "@@ -")) != NULL + && (sp = decode_range(sp, &old_base, &old_size)) != NULL + && (sp = match(sp, " +")) != NULL + && (sp = decode_range(sp, &new_base, &new_size)) != NULL + && (sp = match(sp, " @")) != NULL) { old_unify = old_size; new_unify = new_size; unified = -1; @@ -1501,7 +1816,7 @@ if (new_unify) --new_unify; break; - case '\\': + case BACKSL: if (strstr(buffer, "newline") != 0) { break; } @@ -1628,44 +1943,61 @@ int ddd, hour, minute, second; int day, month, year; char yrmon, monday; + char *stars = match(buffer, "*** "); + char *sp; + + if (stars == NULL) + break; /* ignore */ /* check for tab-delimited first, so we can * accept filenames containing spaces. */ - if (sscanf(buffer, - "*** %[^\t]\t%[^ ] %[^ ] %d %d:%d:%d %d", - b_fname, - b_temp2, b_temp3, &ddd, - &hour, &minute, &second, &year) == 8 - || (sscanf(buffer, - "*** %[^\t]\t%d%c%d%c%d %d:%d:%d", - b_fname, - &year, &yrmon, &month, &monday, &day, - &hour, &minute, &second) == 9 + if (((sp = copy_notabs(b_fname, stars, length)) != NULL + && (sp = match(sp, "\t")) != NULL + && (sp = need_nospcs(sp)) != NULL + && (sp = match(sp, " ")) != NULL + && (sp = need_nospcs(sp)) != NULL + && sscanf(sp, + " %d %d:%d:%d %d", + &ddd, + &hour, &minute, &second, &year) == 5) + || ((sp = copy_notabs(b_fname, stars, length)) != NULL + && sscanf(sp, + "\t%d%c%d%c%d %d:%d:%d", + &year, &yrmon, &month, &monday, &day, + &hour, &minute, &second) == 8 && date_delims(yrmon, monday) && !version_num(b_fname)) - || (sscanf(buffer, - "*** %[^\t]\t(%[^)])\t(%[^)])", - b_fname, b_temp1, b_temp2) == 3 + || ((sp = copy_notabs(b_fname, stars, length)) != NULL + && (sp = match(sp, "\t")) != NULL + && (sp = need_parens(sp)) != NULL + && (sp = match(sp, "\t")) != NULL + && (sp = need_parens(sp)) != NULL && !version_num(b_fname)) - || sscanf(buffer, - "*** %[^\t ]%[\t ]%[^ ] %[^ ] %d %d:%d:%d %d", - b_fname, - b_temp1, - b_temp2, b_temp3, &ddd, - &hour, &minute, &second, &year) == 9 - || (sscanf(buffer, - "*** %[^\t ]%[\t ]%d%c%d%c%d %d:%d:%d", - b_fname, - b_temp1, - &year, &yrmon, &month, &monday, &day, - &hour, &minute, &second) == 10 + || ((sp = copy_notabs(b_fname, stars, length)) != NULL + && (sp = match(sp, "\t")) != NULL + && (sp = need_parens(sp)) != NULL + && (*skip_blanks(sp) == EOS)) + || ((sp = copy_graphs(b_fname, stars, length)) != NULL + && (sp = need_blanks(sp)) != NULL + && (sp = need_nospcs(sp)) != NULL + && (sp = match(sp, " ")) != NULL + && (sp = need_nospcs(sp)) != NULL + && sscanf(sp, + " %d %d:%d:%d %d", + &ddd, &hour, &minute, &second, &year) == 5) + || ((sp = copy_graphs(b_fname, stars, length)) != NULL + && (sp = need_blanks(sp)) != NULL + && sscanf(sp, + "%d%c%d%c%d %d:%d:%d", + &year, &yrmon, &month, &monday, &day, + &hour, &minute, &second) == 8 && date_delims(yrmon, monday) && !version_num(b_fname)) - || (sscanf(buffer, - "*** %[^\t ]%[\t ]", - b_fname, - b_temp1) >= 1 + || ((sp = copy_git_name(b_fname, stars, length)) != NULL + && *skip_blanks(sp) == EOS) + || ((sp = copy_graphs(b_fname, stars, length)) != NULL + && (*sp == EOS || *sp == BLANK || *sp == TAB) && !version_num(b_fname) && !contain_any(b_fname, "*") && !edit_range(b_fname)) @@ -1687,18 +2019,18 @@ CASE_TRACE(); if (!(ok & HAVE_PATH)) { int rev; + char *bars, *sp; - if (((sscanf(buffer, - "==== %[^\t #]#%d - %[^\t ]", - b_fname, - &rev, - b_temp1) == 3) - || ((sscanf(buffer, - "==== %[^\t #]#%d (%[^)]) - %[^\t ]", - b_fname, - &rev, - b_temp1, - b_temp2) == 4))) + if ((bars = match(buffer, "==== ")) != NULL + && (bars = copy_p4_name(b_fname, bars, length)) != NULL + && (bars = match(bars, "#")) != NULL + && (bars = copy_integer(&rev, bars)) != NULL + && (((sp = match(bars, " - ")) != NULL + && (sp = need_graphs(sp)) != NULL) + || (((sp = match(bars, " ")) != NULL + && (sp = need_parens(sp)) != NULL + && (sp = match(sp, " - ")) != NULL + && (sp = need_graphs(sp)) != NULL))) && !version_num(b_fname) && !contain_any(b_fname, "*") && !edit_range(b_fname)) { @@ -1840,9 +2172,6 @@ free(buffer); free(b_fname); - free(b_temp1); - free(b_temp2); - free(b_temp3); } static void @@ -2056,6 +2385,126 @@ } } +static int +columns_of(const char *value) +{ + int result; + int n; + int ch; +#ifdef HAVE_MBSTOWCWIDTH + int fixup = 0; + for (n = 0; (ch = UC(value[n])) != EOS; ++n) { + if (ch >= DEL || ch < BLANK) { + fixup = 1; + break; + } + } + result = (int) strlen(value); + if (fixup) { + size_t needed; + mbstate_t state; + const char *source; + size_t length = strlen(value); + + memset(&state, 0, sizeof(state)); + source = value; + needed = mbsrtowcs(NULL, &source, length, &state); + if (needed != (size_t) (-1)) { + wchar_t *target = calloc(1 + needed, sizeof(wchar_t)); + memset(&state, 0, sizeof(state)); + source = value; + if (mbsrtowcs(target, &source, length, &state) == needed) { + size_t n2; + result = 0; + for (n2 = 0; n2 < needed; ++n2) { + int nw = wcwidth(target[n2]); + if (nw > 0) + result += nw; + else if (target[n2] < BLANK || target[n2] == DEL) + result += 2; + else + result += 4; /* show as octal */ + } + } + free(target); + } + } +#else + result = (int) strlen(value); + for (n = 0; (ch = UC(value[n])) != EOS; ++n) { + if (ch == DEL || ch < BLANK) { + result += 1; + } else if (ch > DEL) { + result += 3; /* show as octal */ + } + } +#endif + return result; +} + +#define adjustwide(width,name) width += (int) strlen(name) - columns_of(name) + +static void +show_quoted(const char *value) +{ + int ch; + + putchar(DQUOTE); + while ((ch = UC(*value++)) != EOS) { + if (ch == DQUOTE) + putchar(DQUOTE); + putchar(ch); + } + putchar(DQUOTE); +} + +static void +show_unquoted(const char *value, int limit) +{ + int ch; + while ((ch = UC(*value++)) != EOS) { + if (ch < BLANK) { + if (strchr("\b\n\r\t\\\"", ch) != NULL) { + putchar(BACKSL); + switch (ch) { + case '\b': + ch = 'b'; + break; + case '\n': + ch = 'n'; + break; + case '\r': + ch = 'r'; + break; + case '\t': + ch = 't'; + break; + } + } else { + putchar('^'); + ch |= '@'; + } + } else if (ch == DEL) { + putchar('^'); + ch = '?'; + } +#ifndef HAVE_MBSTOWCWIDTH + else if (ch > DEL) { + char temp[5]; + sprintf(temp, "\\%03o", ch & 0xff); + ch = temp[3]; + temp[3] = EOS; + fputs(temp, stdout); + } +#endif + putchar(ch); + --limit; + } + while (limit-- > 0) { + putchar(BLANK); + } +} + #define changed(p) (!merge_names \ || (p)->cmt != Normal \ || (TotalOf(p)) != 0) @@ -2074,7 +2523,7 @@ ; } else if (table_opt == 1) { if (names_only) { - printf("%s\n", name); + show_quoted(name); } else { printf("%ld,%ld,%ld,", InsOf(p), @@ -2087,21 +2536,23 @@ (p->cmt == OnlyRight), (p->cmt == OnlyLeft), (p->cmt == Binary)); - printf("%s\n", name); + show_quoted(name); } + printf("\n"); } else if (names_only) { printf("%s\n", name); } else { printf("%s ", comment_opt); if (max_name_wide > 0 && max_name_wide < min_name_wide - && max_name_wide < ((width = (int) strlen(name)))) { + && max_name_wide < ((width = (int) columns_of(name)))) { printf("%.*s", max_name_wide, name + (width - max_name_wide)); } else { width = ((max_name_wide > 0 && max_name_wide < min_name_wide) ? max_name_wide : min_name_wide); - printf("%-*.*s", width, width, name); + adjustwide(width, name); + show_unquoted(name, width); } if (table_opt == 2) { putchar('|'); @@ -2282,7 +2733,7 @@ *lines += EqlOf(p); if (unchanged) { - int len = (int) strlen(p->name); + int len = columns_of(p->name); if (min_name_wide < (len - p->base)) min_name_wide = (len - p->base); } @@ -2326,7 +2777,7 @@ plot_scale = 0; for (p = all_data; p; p = p->link) { - int len = (int) strlen(p->name); + int len = columns_of(p->name); if (ignore_data(p)) continue; @@ -2440,7 +2891,7 @@ count_unmodified_files(D_option, &files_equal, &total_eql); if (unchanged) { for (p = all_data; p; p = p->link) { - int len = (int) strlen(p->name); + int len = columns_of(p->name); if (longest_name < len) longest_name = len; temp = TotalOf(p); @@ -2541,17 +2992,17 @@ switch (which) { case dcBzip: verb = GET_PROGRAM(BZCAT_PATH); - if (*verb == '\0') { + if (*verb == EOS) { verb = GET_PROGRAM(BZIP2_PATH); opts = "-dc"; } break; case dcCompress: verb = GET_PROGRAM(ZCAT_PATH); - if (*verb == '\0') { + if (*verb == EOS) { verb = GET_PROGRAM(UNCOMPRESS_PATH); opts = "-c"; - if (*verb == '\0') { + if (*verb == EOS) { /* not all compress's recognize the options, test this last */ verb = GET_PROGRAM(COMPRESS_PATH); opts = "-dc"; @@ -2578,10 +3029,10 @@ case dcNone: break; } - if (verb != 0 && *verb != '\0') { + if (verb != 0 && *verb != EOS) { result = (char *) xmalloc(strlen(verb) + 10 + len); sprintf(result, "%s %s", verb, opts); - if (*name != '\0') { + if (*name != EOS) { sprintf(result + strlen(result), " \"%s\"", name); } } @@ -2762,7 +3213,7 @@ { char *next = 0; long value = strtol(optarg, &next, 0); - if (next == 0 || *next != '\0') { + if (next == 0 || *next != EOS) { (void) fflush(stdout); fprintf(stderr, "expected a number, have '%s'\n", optarg); exit(EXIT_FAILURE); @@ -2776,7 +3227,18 @@ int j; char version[80]; - max_width = 80; +#if defined(HAVE_TCGETATTR) && defined(TIOCGWINSZ) + if (isatty(fileno(stdout))) { + struct winsize data; + if (ioctl(fileno(stdout), TIOCGWINSZ, &data) == 0) { + max_width = data.ws_col; + } + } +#endif + +#ifdef HAVE_MBSTOWCWIDTH + setlocale(LC_CTYPE, ""); +#endif while ((j = getopt_helper(argc, argv, "bcCdD:e:Ef:hkKlmn:N:o:p:qr:RsS:tTuvVw:", 'h', 'V')) @@ -2863,7 +3325,7 @@ break; case 'V': #ifndef NO_IDENT - if (!sscanf(Id, "%*s %*s %s", version)) + if (!sscanf(Id, "%*s %*s %30s", version)) #endif (void) strcpy(version, "?"); printf("diffstat version %s\n", version); @@ -2949,8 +3411,8 @@ } if (got == 5 && !strncmp(sniff, "BZh", (size_t) 3) - && isdigit((unsigned char) sniff[3]) - && isdigit((unsigned char) sniff[4])) { + && isdigit(UC(sniff[3])) + && isdigit(UC(sniff[4]))) { which = dcBzip; } } else if (ch == ']') { /* perhaps lzma */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/package/debian/changelog new/diffstat-1.63/package/debian/changelog --- old/diffstat-1.62/package/debian/changelog 2018-08-15 02:41:39.000000000 +0200 +++ new/diffstat-1.63/package/debian/changelog 2019-11-24 19:02:47.000000000 +0100 @@ -1,3 +1,9 @@ +diffstat (1.63) unstable; urgency=low + + * maintenance updates + + -- Thomas E. Dickey <[email protected]> Sun, 24 Nov 2019 13:02:47 -0500 + diffstat (1.62) unstable; urgency=low * maintenance updates diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/package/debian/compat new/diffstat-1.63/package/debian/compat --- old/diffstat-1.62/package/debian/compat 2010-04-20 21:47:10.000000000 +0200 +++ new/diffstat-1.63/package/debian/compat 2019-11-29 21:08:39.000000000 +0100 @@ -1 +1 @@ -5 +9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/package/debian/copyright new/diffstat-1.63/package/debian/copyright --- old/diffstat-1.62/package/debian/copyright 2018-08-15 02:37:15.000000000 +0200 +++ new/diffstat-1.63/package/debian/copyright 2019-11-25 01:13:42.000000000 +0100 @@ -1,7 +1,7 @@ Upstream source http://invisible-island.net/diffstat/diffstat.html /****************************************************************************** - * Copyright 1994-2016,2018 by Thomas E. Dickey * + * Copyright 1994-2018,2019 by Thomas E. Dickey * * All Rights Reserved. * * * * Permission to use, copy, modify, and distribute this software and its * @@ -25,7 +25,7 @@ Files: aclocal.m4 Licence: other-BSD -Copyright: 2003-2016,2018 by Thomas E. Dickey +Copyright: 2003-2018,2019 by Thomas E. Dickey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including @@ -86,7 +86,7 @@ shared with many OS's install programs. Files: debian/* -Copyright: 2010-2016,2018 Thomas E. Dickey +Copyright: 2010-2018,2019 Thomas E. Dickey Licence: other-BSD Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/diffstat-1.62/package/diffstat.spec new/diffstat-1.63/package/diffstat.spec --- old/diffstat-1.62/package/diffstat.spec 2018-08-15 02:35:51.000000000 +0200 +++ new/diffstat-1.63/package/diffstat.spec 2019-11-24 19:02:47.000000000 +0100 @@ -1,7 +1,7 @@ Summary: diffstat - make histogram from diff-output %define AppProgram diffstat -%define AppVersion 1.62 -# $XTermId: diffstat.spec,v 1.13 2018/08/15 00:35:51 tom Exp $ +%define AppVersion 1.63 +# $XTermId: diffstat.spec,v 1.14 2019/11/24 18:02:47 tom Exp $ Name: %{AppProgram} Version: %{AppVersion} Release: 1
