Hello community,

here is the log from the commit of package logwarn for openSUSE:Factory checked 
in at 2016-06-20 11:07:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/logwarn (Old)
 and      /work/SRC/openSUSE:Factory/.logwarn.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "logwarn"

Changes:
--------
--- /work/SRC/openSUSE:Factory/logwarn/logwarn.changes  2016-05-29 
03:14:32.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.logwarn.new/logwarn.changes     2016-06-20 
11:07:44.000000000 +0200
@@ -1,0 +2,6 @@
+Sun Jun 19 22:36:00 UTC 2016 - [email protected]
+
+- Upgrade to release 1.0.13
+  + Added `-T' flag for frequency filtering
+
+-------------------------------------------------------------------

Old:
----
  logwarn-1.0.12.tar.gz

New:
----
  logwarn-1.0.13.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ logwarn.spec ++++++
--- /var/tmp/diff_new_pack.dMrbQ0/_old  2016-06-20 11:07:46.000000000 +0200
+++ /var/tmp/diff_new_pack.dMrbQ0/_new  2016-06-20 11:07:46.000000000 +0200
@@ -18,7 +18,7 @@
 
 
 Name:           logwarn
-Version:        1.0.12
+Version:        1.0.13
 Release:        0
 Summary:        Utility for finding interesting messages in log files
 License:        Apache-2.0

++++++ logwarn-1.0.12.tar.gz -> logwarn-1.0.13.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/CHANGES new/logwarn-1.0.13/CHANGES
--- old/logwarn-1.0.12/CHANGES  2016-05-25 04:04:38.000000000 +0200
+++ new/logwarn-1.0.13/CHANGES  2016-06-19 23:16:59.000000000 +0200
@@ -1,4 +1,8 @@
 
+Version 1.0.13 Released June 19, 2016
+
+    - Added `-T num/secs' for frequency filtering
+
 Version 1.0.12 Released May 24, 2016
 
     - Added note to man page that the default behavior is to match
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/README.md new/logwarn-1.0.13/README.md
--- old/logwarn-1.0.12/README.md        2015-05-04 20:21:56.000000000 +0200
+++ new/logwarn-1.0.13/README.md        2016-06-19 01:01:27.000000000 +0200
@@ -11,3 +11,5 @@
 A [Nagios](http://www.nagios.org/) plugin is also included: see the 
[NagiosPlugin](https://github.com/archiecobbs/logwarn/wiki/NagiosPlugin) wiki 
page for more info.
 
 You can view the 
[ManPage](https://github.com/archiecobbs/logwarn/wiki/ManPage) online.
+
+Downloads available 
[here](https://github.com/archiecobbs/logwarn/wiki/Downloads).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/configure new/logwarn-1.0.13/configure
--- old/logwarn-1.0.12/configure        2016-05-25 04:15:47.000000000 +0200
+++ new/logwarn-1.0.13/configure        2016-06-19 23:20:32.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for logwarn Utility for finding interesting 
messages in log files 1.0.12.
+# Generated by GNU Autoconf 2.69 for logwarn Utility for finding interesting 
messages in log files 1.0.13.
 #
 # Report bugs to <https://github.com/archiecobbs/logwarn/>.
 #
@@ -580,8 +580,8 @@
 # Identity of this package.
 PACKAGE_NAME='logwarn Utility for finding interesting messages in log files'
 PACKAGE_TARNAME='logwarn'
-PACKAGE_VERSION='1.0.12'
-PACKAGE_STRING='logwarn Utility for finding interesting messages in log files 
1.0.12'
+PACKAGE_VERSION='1.0.13'
+PACKAGE_STRING='logwarn Utility for finding interesting messages in log files 
1.0.13'
 PACKAGE_BUGREPORT='https://github.com/archiecobbs/logwarn/'
 PACKAGE_URL=''
 
@@ -1274,7 +1274,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures logwarn Utility for finding interesting messages in 
log files 1.0.12 to adapt to many kinds of systems.
+\`configure' configures logwarn Utility for finding interesting messages in 
log files 1.0.13 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1340,7 +1340,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of logwarn Utility for finding 
interesting messages in log files 1.0.12:";;
+     short | recursive ) echo "Configuration of logwarn Utility for finding 
interesting messages in log files 1.0.13:";;
    esac
   cat <<\_ACEOF
 
@@ -1437,7 +1437,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-logwarn Utility for finding interesting messages in log files configure 1.0.12
+logwarn Utility for finding interesting messages in log files configure 1.0.13
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1693,7 +1693,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by logwarn Utility for finding interesting messages in log 
files $as_me 1.0.12, which was
+It was created by logwarn Utility for finding interesting messages in log 
files $as_me 1.0.13, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2556,7 +2556,7 @@
 
 # Define the identity of the package.
  PACKAGE='logwarn'
- VERSION='1.0.12'
+ VERSION='1.0.13'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -4838,7 +4838,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by logwarn Utility for finding interesting messages in 
log files $as_me 1.0.12, which was
+This file was extended by logwarn Utility for finding interesting messages in 
log files $as_me 1.0.13, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -4904,7 +4904,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-logwarn Utility for finding interesting messages in log files config.status 
1.0.12
+logwarn Utility for finding interesting messages in log files config.status 
1.0.13
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/configure.ac 
new/logwarn-1.0.13/configure.ac
--- old/logwarn-1.0.12/configure.ac     2015-08-25 21:47:56.000000000 +0200
+++ new/logwarn-1.0.13/configure.ac     2016-06-19 23:19:48.000000000 +0200
@@ -16,7 +16,7 @@
 # limitations under the License.
 #
 
-AC_INIT([logwarn Utility for finding interesting messages in log files], 
[1.0.12], [https://github.com/archiecobbs/logwarn/], [logwarn])
+AC_INIT([logwarn Utility for finding interesting messages in log files], 
[1.0.13], [https://github.com/archiecobbs/logwarn/], [logwarn])
 AC_CONFIG_AUX_DIR(scripts)
 AM_INIT_AUTOMAKE
 dnl AM_MAINTAINER_MODE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/gitrev.c new/logwarn-1.0.13/gitrev.c
--- old/logwarn-1.0.12/gitrev.c 2016-05-25 04:15:51.000000000 +0200
+++ new/logwarn-1.0.13/gitrev.c 2016-06-19 23:20:36.000000000 +0200
@@ -1 +1 @@
-const char *const logwarn_version = "1.0.12";
+const char *const logwarn_version = "1.0.13";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/logwarn.1.in 
new/logwarn-1.0.13/logwarn.1.in
--- old/logwarn-1.0.12/logwarn.1.in     2015-08-25 21:48:15.000000000 +0200
+++ new/logwarn-1.0.13/logwarn.1.in     2016-06-19 22:52:49.000000000 +0200
@@ -33,6 +33,7 @@
 .Op Fl M Ar maxprint
 .Op Fl N Ar maxerrors
 .Ar logfile
+.Op Fl T Ar num/secs
 .Ar [!]pattern ...
 .Ek
 .Pp
@@ -268,6 +269,38 @@
 When this flag is given, the last one is chosen instead.
 .Pp
 This option is appropriate when the suffix is formatted as a timestamp.
+.It Fl T
+Suppress output until
+.Ar num
+matching lines appear within a
+.Ar secs
+second interval.
+.Pp
+This flag comes after the
+.Ar logfile .
+Each time it occurs, it applies to all subsequent patterns, or up until the 
next occurrence.
+Use
+.Fl T Ar 1/0
+to revert to normal behavior, in which every matching occurrence is reported.
+.Pp
+The affected patterns are treated as a single group for counting purposes, 
i.e.,
+a single counter tracks lines matching any of the patterns.
+When the last of
+.Ar num
+matching lines is seen in a
+.Ar secs
+second window, it is printed, and the associated tracking is reset, so at 
least another
+.Ar num
+lines must be seen before another match is printed.
+.Pp
+Note that the calculated timing of occurrences is whenever
+.Nm
+reads the file.
+Therefore
+.Nm
+should be invoked more frequently than your smallest
+.Ar secs
+time interval, to provide the required time resolution.
 .It Fl v
 Output version information and exit.
 .It Fl z
@@ -345,6 +378,17 @@
 .Pp
 Show lines not containing `retrying' but containing `ERROR', as well as any 
subsequent lines in a multi-line log message,
 assuming the `myprog: ' prefix marks the start of each new log message.
+For example:
+.It logwarn /var/log/warn -T 3/60 pat1 -T 10/300 pat2 pat3
+.Pp
+Match three or more occurrences of
+.Ar pat1
+within a one minute interval,
+or ten or more occurrences of either
+.Ar pat2
+or
+.Ar pat3
+within a five minute interval.
 .El
 .Sh RETURN VALUES
 .Nm
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/logwarn.h new/logwarn-1.0.13/logwarn.h
--- old/logwarn-1.0.12/logwarn.h        2015-08-25 21:47:43.000000000 +0200
+++ new/logwarn-1.0.13/logwarn.h        2016-06-19 22:29:56.000000000 +0200
@@ -20,12 +20,22 @@
 // Maximum line length
 #define MAX_LINE_LENGTH     100000
 
+// Pattern repeat state
+struct repeat {
+    unsigned int    hash;           // xor of hashes of pattern string(s)
+    unsigned int    num;            // number required in interval
+    unsigned int    secs;           // interval duration in seconds
+    unsigned long   *occurrences;   // timestamps of up to `num' occurrences, 
most recent first
+};
+
 // Log scan state
 struct scan_state {
     ino_t           inode;          // file inode number
     unsigned long   line;           // # lines read + 1
     long            pos;            // seek position in file
     unsigned char   matching;       // within matching entry
+    unsigned int    num_repeats;    // number of repeats
+    struct repeat   *repeats;       // repeat state
 };
 
 // Exit values
@@ -37,9 +47,11 @@
 extern const char *const logwarn_version;
 
 // Global functions
+extern void reset_state(struct scan_state *state);
 extern int  load_state(const char *state_file, struct scan_state *state);
 extern void save_state(const char *state_file, const char *logfile, const 
struct scan_state *state);
 extern void dump_state(FILE *fp, const char *logfile, const struct scan_state 
*state);
 extern void init_state_from_logfile(const char *logfile, struct scan_state 
*state);
 extern void state_file_name(const char *state_dir, const char *logfile, char 
*buf, size_t max);
+extern struct repeat *find_repeat(struct scan_state *state, unsigned int hash);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/main.c new/logwarn-1.0.13/main.c
--- old/logwarn-1.0.12/main.c   2015-08-25 21:48:08.000000000 +0200
+++ new/logwarn-1.0.13/main.c   2016-06-19 22:37:01.000000000 +0200
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 
 #include "logwarn.h"
@@ -48,6 +49,7 @@
     const char      *string;
     regex_t         regex;
     unsigned char   negate;
+    struct repeat   *repeat;
 };
 
 // Global variables
@@ -88,8 +90,17 @@
     int ignore_nonexistent = 0;
     int eflags = 0;
     int initialize = 0;
+    int envset;
     int i;
 
+    // Initialize state
+    memset(&state, 0, sizeof(state));
+    state.line = 1;
+
+    // Make getopt() stop at the first non-flag argument
+    if ((envset = (getenv("POSIXLY_CORRECT") == NULL)))
+        setenv("POSIXLY_CORRECT", "", 1);
+
     // Parse command line
     while ((i = getopt(argc, argv, "acd:f:hilL:m:M:N:npqRr:tvz")) != -1) {
         switch (i) {
@@ -165,6 +176,8 @@
             exit(EXIT_ERROR);
         }
     }
+    if (envset)
+        unsetenv("POSIXLY_CORRECT");
     if (mpat != NULL)
         parse_pattern(&log_pattern, mpat, eflags);
     argv += optind;
@@ -185,19 +198,56 @@
             exit(EXIT_ERROR);
         }
         if (num_match_patterns > 0) {
-            if ((match_patterns = malloc(num_match_patterns * 
sizeof(*match_patterns))) == NULL) {
+            if ((match_patterns = malloc(num_match_patterns * 
sizeof(*match_patterns))) == NULL
+              || (state.repeats = malloc(num_match_patterns * 
sizeof(*state.repeats))) == NULL) {
                 fprintf(stderr, "%s: %s: %s\n", PACKAGE, "malloc", 
strerror(errno));
                 exit(EXIT_ERROR);
             }
             memset(match_patterns, 0, num_match_patterns * 
sizeof(*match_patterns));
+            memset(state.repeats, 0, num_match_patterns * 
sizeof(*state.repeats));
             for (i = 0; i < num_match_patterns; i++) {
                 struct repat *const pat = &match_patterns[i];
-                const char *patstr = argv[i];
+                char *patstr = argv[i];
+
+                // Add new repeat?
+                if (strcmp(patstr, "-T") == 0) {
+                    struct repeat *const repeat = 
&state.repeats[state.num_repeats++];
 
+                    if (i > num_match_patterns - 3 || sscanf(argv[++i], 
"%u/%u", &repeat->num, &repeat->secs) != 2) {
+                        usage();
+                        exit(EXIT_ERROR);
+                    }
+                    if (repeat->num == 0) {
+                        fprintf(stderr, "%s: invalid zero repeat count in \"-T 
%s\"", PACKAGE, argv[i]);
+                        exit(EXIT_ERROR);
+                    }
+                    if ((repeat->occurrences = malloc(repeat->num * 
sizeof(repeat->occurrences))) == NULL) {
+                        fprintf(stderr, "%s: %s: %s\n", PACKAGE, "malloc", 
strerror(errno));
+                        exit(EXIT_ERROR);
+                    }
+                    memset(repeat->occurrences, 0, repeat->num * 
sizeof(*repeat->occurrences));
+                    patstr = argv[++i];
+                }
+
+                // Check for negation
                 if (*patstr == '!') {
                     patstr++;
                     pat->negate = 1;
                 }
+
+                // Add (positive) pattern to the current repeat, if any
+                if (*patstr != '!' && state.num_repeats > 0) {
+                    struct repeat *const current_repeat = 
&state.repeats[state.num_repeats - 1];
+                    unsigned int hash = 0;
+                    const char *s;
+
+                    for (s = patstr; *s != '\0'; s++)
+                        hash = hash * 37 + (unsigned char)*s;
+                    current_repeat->hash ^= hash;
+                    pat->repeat = current_repeat;
+                }
+
+                // Parse pattern
                 parse_pattern(pat, patstr, eflags);
             }
         }
@@ -222,10 +272,6 @@
     // Parse rotated file pattern
     parse_pattern(&rot_pattern, rotpat, 0);
 
-    // Initialize state
-    memset(&state, 0, sizeof(state));
-    state.line = 1;
-
     // Check if logfile exists
     if (logfile != NULL && stat(logfile, &sb) == -1) {
         switch (errno) {
@@ -350,9 +396,6 @@
     // Now scan the logfile itself
     scan_file(logfile, &state);
 
-    // Save state
-    save_state(state_file, logfile, &state);
-
     // Done
     exit(any_matches ? EXIT_MATCHES : EXIT_OK);
 }
@@ -448,19 +491,15 @@
         }
 
         // End of file?
-        if (len == 0 || (len < MAX_LINE_LENGTH - 1 && !newline)) {
-            save_state(state_file, logfile, state);
+        if (len == 0 || (len < MAX_LINE_LENGTH - 1 && !newline))
             break;
-        }
 
         // Is this a new log entry or a continuation line?
         continuation = log_pattern.string != NULL && 
regexec(&log_pattern.regex, line, 0, NULL, 0) != 0;
 
         // If this is not a continuation, check if we have reached our limit 
on the number of errors processed
-        if (!continuation && error_count >= max_errors_processed) {
-            save_state(state_file, logfile, state);
+        if (!continuation && error_count >= max_errors_processed)
             break;
-        }
 
         // Bump position and number of lines read
         state->pos += len;
@@ -473,8 +512,40 @@
             // Determine if this line matches
             for (i = 0; i < num_match_patterns; i++) {
                 const struct repat *const pat = &match_patterns[i];
+                struct repeat *const repeat = pat->repeat;
 
                 if (regexec(&pat->regex, line, 0, NULL, 0) == 0) {
+
+                    // Check for repeat suppression
+                    if (repeat != NULL) {
+                        time_t now;
+                        int count;
+
+                        // Update timestamps by adding the current timestamp 
to the front of the array
+                        time(&now);
+                        memmove(repeat->occurrences + 1, repeat->occurrences, 
(repeat->num - 1) * sizeof(*repeat->occurrences));
+                        repeat->occurrences[0] = (unsigned long)now;
+
+                        // Check whether the repeat threshold has been exceeded
+                        for (count = 0; count < repeat->num && 
repeat->occurrences[count] != 0; count++) {
+                            const unsigned int age = repeat->occurrences[0] - 
repeat->occurrences[count];
+
+                            if (age > repeat->secs)
+                                break;
+                        }
+
+                        // If not, treat like a non-matching line
+                        if (count < repeat->num) {
+                            matches = 0;
+                            break;
+                        }
+
+                        // If so, reset occurrence history for this pattern 
group
+                        memset(repeat->occurrences, 0, repeat->num * 
sizeof(*repeat->occurrences));
+                        break;
+                    }
+
+                    // No repeat suppression
                     matches = pat->negate ? 0 : 1;
                     break;
                 }
@@ -512,6 +583,9 @@
         }
     }
 
+    // Save updated state
+    save_state(state_file, logfile, state);
+
     // Free buffer
     free(line);
 
@@ -547,7 +621,7 @@
 usage(void)
 {
     fprintf(stderr, "Usage:\n");
-    fprintf(stderr, "  logwarn [-d dir | -f file] [-m firstpat] [-r sufpat] 
[-L maxlines] [-M maxprint] [-N maxerrors] [-achlnqpvz] logfile [!]pattern 
...\n");
+    fprintf(stderr, "  logwarn [-d dir | -f file] [-m firstpat] [-r sufpat] 
[-L maxlines] [-M maxprint] [-N maxerrors] [-achlnqpvz] logfile [-T num/secs] 
[!]pattern ...\n");
     fprintf(stderr, "  logwarn [-d dir | -f file] -i logfile\n");
     fprintf(stderr, "Options:\n");
     fprintf(stderr, "  -a    Auto-init: force `-i' if no state file exists\n");
@@ -564,6 +638,7 @@
     fprintf(stderr, "  -n    A nonexistent log file is not an error; treat as 
empty\n");
     fprintf(stderr, "  -q    Don't output the matched log messages\n");
     fprintf(stderr, "  -r    Specify rotated file suffix pattern; default 
\"%s\"\n", DEFAULT_ROTPAT);
+    fprintf(stderr, "  -T    Suppress until `num' occurrences within `secs' 
seconds");
     fprintf(stderr, "  -v    Output version information and exit\n");
     fprintf(stderr, "  -z    Always read from the beginning of the input\n");
     fprintf(stderr, "A logfile of `-' means read from standard input 
(typically used with `-z')\n");
@@ -573,7 +648,7 @@
 version(void)
 {
     fprintf(stderr, "%s version %s (%s)\n", PACKAGE, VERSION, logwarn_version);
-    fprintf(stderr, "Copyright (C) 2010-2013 Archie L. Cobbs\n");
+    fprintf(stderr, "Copyright (C) 2010-2016 Archie L. Cobbs\n");
     fprintf(stderr, "This is free software; see the source for copying 
conditions.  There is NO\n");
     fprintf(stderr, "warranty; not even for MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE.\n");
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logwarn-1.0.12/state.c new/logwarn-1.0.13/state.c
--- old/logwarn-1.0.12/state.c  2015-08-25 21:48:06.000000000 +0200
+++ new/logwarn-1.0.13/state.c  2016-06-19 22:30:30.000000000 +0200
@@ -37,6 +37,8 @@
 #define LINENUM_NAME        "LINENUM"
 #define POSITION_NAME       "POSITION"
 #define MATCHING_NAME       "MATCHING"
+#define REPEAT_PREFIX       "REPEAT_OCCURRENCES_"
+#define REPEAT_PREFIX_LEN   (sizeof(REPEAT_PREFIX) - 1)
 #define STDIN_LOGFILE_NAME  "_stdin"
 
 int
@@ -46,7 +48,7 @@
     struct stat sb;
     FILE *fp;
 
-    memset(state, 0, sizeof(*state));
+    reset_state(state);
     state->line = 1;
     if (stat(state_file, &sb) == -1 || S_ISDIR(sb.st_mode))
         return -1;
@@ -56,7 +58,7 @@
         const char *s = buf;
         unsigned long value;
         const char *fname;
-        const char *fvalue;
+        char *fvalue;
         char *eptr;
         char *t;
 
@@ -78,11 +80,30 @@
             continue;
         *t = '\0';
 
+        // Handle repeat lines
+        if (strncmp(fname, REPEAT_PREFIX, REPEAT_PREFIX_LEN) == 0) {
+            struct repeat *repeat;
+            unsigned int hash;
+            char *saveptr;
+            char *token;
+            int i = 0;
+
+            if (sscanf(fname + REPEAT_PREFIX_LEN, "%x", &hash) != 1)
+                continue;
+            if ((repeat = find_repeat(state, hash)) == NULL)
+                continue;
+            for (token = strtok_r(fvalue, " ", &saveptr); token != NULL && i < 
repeat->num; token = strtok_r(NULL, " ", &saveptr)) {
+                if (sscanf(token, "%lu", &repeat->occurrences[i++]) != 1)
+                    break;
+            }
+            continue;
+        }
+
         // Handle "false" and "true"
         if (strcmp(fvalue, "false") == 0)
-            fvalue = "0";
+            strcpy(fvalue, "0");
         else if (strcmp(fvalue, "true") == 0)
-            fvalue = "1";
+            strcpy(fvalue, "1");
 
         // Decode numerical value
         if (((value = strtoul(fvalue, &eptr, 10)) == ULONG_MAX && errno == 
ERANGE) || *eptr != '\0') {
@@ -104,6 +125,33 @@
     return 0;
 }
 
+struct repeat *
+find_repeat(struct scan_state *state, unsigned int hash) {
+    int i;
+
+    for (i = 0; i < state->num_repeats; i++) {
+        struct repeat *const repeat = &state->repeats[i];
+
+        if (hash == repeat->hash)
+            return repeat;
+    }
+    return NULL;
+}
+
+void
+reset_state(struct scan_state *state)
+{
+    unsigned int num_repeats_save;
+    struct repeat *repeats_save;
+
+    // Reset state
+    num_repeats_save = state->num_repeats;
+    repeats_save = state->repeats;
+    memset(state, 0, sizeof(*state));
+    state->num_repeats = num_repeats_save;
+    state->repeats = repeats_save;
+}
+
 void
 save_state(const char *state_file, const char *logfile, const struct 
scan_state *state)
 {
@@ -124,6 +172,7 @@
 dump_state(FILE *fp, const char *logfile, const struct scan_state *state)
 {
     struct scan_state stdin_state;
+    int i;
 
     if (logfile == NULL) {
         logfile = STDIN_LOGFILE_NAME;
@@ -136,6 +185,20 @@
     fprintf(fp, "%s=\"%lu\"\n", LINENUM_NAME, state->line);
     fprintf(fp, "%s=\"%lu\"\n", POSITION_NAME, state->pos);
     fprintf(fp, "%s=\"%s\"\n", MATCHING_NAME, state->matching ? "true" : 
"false");
+    for (i = 0; i < state->num_repeats; i++) {
+        const struct repeat *repeat = &state->repeats[i];
+        int j;
+
+        if (repeat->occurrences[0] == 0)
+            continue;
+        fprintf(fp, "%s%08x=\"", REPEAT_PREFIX, repeat->hash);
+        for (j = 0; j < repeat->num && repeat->occurrences[j] != 0; j++) {
+            if (j > 0)
+                fputc(' ', fp);
+            fprintf(fp, "%lu", (unsigned long)repeat->occurrences[j]);
+        }
+        fprintf(fp, "\"\n");
+    }
 }
 
 void
@@ -145,7 +208,8 @@
     FILE *fp;
     int ch;
 
-    memset(state, 0, sizeof(*state));
+    // Read state file
+    reset_state(state);
     state->line = 1;
     if (logfile == NULL)
         return;


Reply via email to