@ 260915.5

220401.1 · 25fabf519fb8cadff46a63303bb98fa69e13a171

released 3.7.7

New complementary options --min-depth, --max-depth, --min-line and --max-line which are added for consistency with the updated options --min-count and max-count. Updated the --min-count option, which can now be combined with any other option except with -v (--invert-match). Updated option -K (--range) to take a MAX argument instead of a FIRST argument for consistency with other min/max options. Recursive searching sysfd, such as /proc and /sys, no longer blocks on special files/devices. Fixed colorization of option -v when used with context options -A, -B and -C. Fixed option -r when combined with argument - (read standard input), which does both, like GNU grep. Updated --stats reporting and other minor improvements.

reading declarations

README.md

@@ -1306,10 +1306,10 @@ using ugrep query selection mode (press Enter to select lines):             Recursively read all files under each directory, following symbolic             links only if they are specified on the command line.  See also             option --sort.-    --depth=[MIN,][MAX], -1, -2 ... -9, --10, --11 ...+    --depth=[MIN,][MAX], -1, -2, -3, ... -9, --10, --11, --12, ...             Restrict recursive searches from MIN to MAX directory levels deep,             where -1 (--depth=1) searches the specified path without recursing-            into subdirectories.  Note that -3 -5, -3-5, or -35 searches 3 to 5+            into subdirectories.  Note that -3 -5, -3-5, and -35 search 3 to 5             levels deep.  Enables -R if -R or -r is not specified.     -g GLOBS, --glob=GLOBS             Search only files whose name matches the specified comma-separated@@ -3509,17 +3509,17 @@ Same, but in this case select `<script>` `src` URLs when referencing `http` and  ### Limiting the number of matches with -1,-2...-9, -K, -m, and --max-files -    --depth=[MIN,][MAX], -1, -2 ... -9, --10, --11 ...+    --depth=[MIN,][MAX], -1, -2, -3, ... -9, --10, --11, --12, ...             Restrict recursive searches from MIN to MAX directory levels deep,             where -1 (--depth=1) searches the specified path without recursing-            into subdirectories.  Note that -3 -5, -3-5, or -35 searches 3 to 5+            into subdirectories.  Note that -3 -5, -3-5, and -35 search 3 to 5             levels deep.  Enables -R if -R or -r is not specified.-    -K FIRST[,LAST], --range=FIRST[,LAST]-            Start searching at line FIRST, stop at line LAST when specified.+    -K [MIN,][MAX], --range=[MIN,][MAX], --min-line=MIN, --max-line=MAX+            Start searching at line MIN, stop at line MAX when specified.     -m [MIN,][MAX], --min-count=MIN, --max-count=MAX-            Stop reading the input after MAX matches in each input file when-            specified.  Require at least MIN matches when specified, for-            options -c, -l, -L and -q.+            Require MIN matches, stop after MAX matches when specified.  Output+            MIN to MAX matches.  For example, -m1 outputs the first match and+            -cm1, (with comma) counts non-zero matches.  See also option -K.     --max-files=NUM             Restrict the number of files matched to NUM.  Note that --sort or             -J1 may be specified to produce replicable results.  If --sort is@@ -3927,12 +3927,12 @@ in markdown:                   ence-recurse', read all files under each directory, recursively,                   following symbolic links.  This is equivalent to the -R  option. -           --depth=[MIN,][MAX], -1, -2 ... -9, --10, --11 ...+           --depth=[MIN,][MAX], -1, -2, -3, ... -9, --10, --11, --12, ...                   Restrict  recursive  searches  from  MIN to MAX directory levels                   deep, where -1 (--depth=1) searches the specified  path  without-                  recursing  into  subdirectories.   Note that -3 -5, -3-5, or -35-                  searches 3 to 5 levels deep.  Enables -R if  -R  or  -r  is  not-                  specified.+                  recursing  into  subdirectories.  Note that -3 -5, -3-5, and -35+                  search 3 to 5 levels deep.  Enables -R if -R or -r is not speci-+                  fied.             --dotall                   Dot  `.' in regular expressions matches anything, including new-@@ -4191,30 +4191,30 @@ in markdown:            --json Output file matches in JSON.  If -H, -n, -k, or -b is specified,                   additional values are output.  See also options --format and -u. -           -K FIRST[,LAST], --range=FIRST[,LAST]-                  Start searching at line FIRST, stop at line LAST when specified.+           -K [MIN,][MAX], --range=[MIN,][MAX], --min-line=MIN, --max-line=MAX+                  Start searching at line MIN, stop at line MAX when specified.             -k, --column-number-                  The  column number of a matched pattern is displayed in front of-                  the respective matched line, starting at  column  1.   Tabs  are+                  The column number of a matched pattern is displayed in front  of+                  the  respective  matched  line,  starting at column 1.  Tabs are                   expanded when columns are counted, see also option --tabs.             -L, --files-without-match-                  Only  the names of files not containing selected lines are writ--                  ten to standard output.  Pathnames  are  listed  once  per  file+                  Only the names of files not containing selected lines are  writ-+                  ten  to  standard  output.   Pathnames  are listed once per file                   searched.   If  the  standard  input  is  searched,  the  string                   ``(standard input)'' is written.             -l, --files-with-matches                   Only the names of files containing selected lines are written to-                  standard  output.   ugrep  will only search a file until a match-                  has been found,  making  searches  potentially  less  expensive.-                  Pathnames  are  listed  once per file searched.  If the standard+                  standard output.  ugrep will only search a file  until  a  match+                  has  been  found,  making  searches  potentially less expensive.+                  Pathnames are listed once per file searched.   If  the  standard                   input is searched, the string ``(standard input)'' is written.             --label=LABEL-                  Displays the LABEL value when input is read from standard  input-                  where  a file name would normally be printed in the output.  As-+                  Displays  the LABEL value when input is read from standard input+                  where a file name would normally be printed in the output.   As-                   sociates a filename extension with standard input when LABEL has                   a suffix.  The default value is `(standard input)'. @@ -4222,23 +4222,24 @@ in markdown:                   Force output to be line buffered instead of block buffered.             --lines-                  Apply  Boolean  queries to match lines, the opposite of --files.-                  This is the default Boolean query mode to match specific  lines.+                  Apply Boolean queries to match lines, the opposite  of  --files.+                  This  is the default Boolean query mode to match specific lines.             -M MAGIC, --file-magic=MAGIC-                  Only  files  matching  the signature pattern MAGIC are searched.-                  The signature "magic bytes" at the start of a file are  compared-                  to  the  MAGIC  regex  pattern.  When matching, the file will be-                  searched.  When MAGIC is preceded by a `!' or a `^', skip  files+                  Only files matching the signature pattern  MAGIC  are  searched.+                  The  signature "magic bytes" at the start of a file are compared+                  to the MAGIC regex pattern.  When matching,  the  file  will  be+                  searched.   When MAGIC is preceded by a `!' or a `^', skip files                   with matching MAGIC signatures.  This option may be repeated and-                  may be combined with options -O and -t  to  expand  the  search.-                  Every  file  on  the search path is read, making searches poten-+                  may  be  combined  with  options -O and -t to expand the search.+                  Every file on the search path is read,  making  searches  poten-                   tially more expensive.             -m [MIN,][MAX], --min-count=MIN, --max-count=MAX-                  Stop reading the input after MAX matches in each input file when-                  specified.   Require  at  least  MIN matches when specified, for-                  options -c, -l, -L and -q.+                  Require  MIN  matches,  stop  after  MAX matches when specified.+                  Output MIN to MAX matches.  For example, -m1 outputs  the  first+                  match  and  -cm1,  (with  a comma) counts non-zero matches.  See+                  also option -K.             --match                   Match all input.  Same as specifying an empty pattern to search.@@ -4377,7 +4378,7 @@ in markdown:             -s, --no-messages                   Silent  mode: nonexistent and unreadable files are ignored, i.e.-                  their error messages are suppressed.+                  their error messages and warnings are suppressed.             --save-config[=FILE]                   Save configuration FILE.  By default `.ugrep' is saved.  If FILE@@ -5098,7 +5099,7 @@ in markdown:   -    ugrep 3.7.6                     March 15, 2022                        UGREP(1)+    ugrep 3.7.7                     April 01, 2022                        UGREP(1)  🔝 [Back to table of contents](#toc) 

bin/win32/ugrep.exe

Binary file changed

bin/win64/ugrep.exe

Binary file changed

include/reflex/absmatcher.h

@@ -156,11 +156,21 @@ class AbstractMatcher {   };   /// AbstractMatcher::Iterator class for scanning, searching, and splitting input character sequences.   template<typename T> /// @tparam <T> AbstractMatcher or const AbstractMatcher-  class Iterator : public std::iterator<std::input_iterator_tag,T> {+  class Iterator {     friend class AbstractMatcher;     friend class Iterator<typename reflex::TypeOp<T>::ConstType>;     friend class Iterator<typename reflex::TypeOp<T>::NonConstType>;    public:+    /// Iterator iterator_category trait.+    typedef std::output_iterator_tag iterator_category;+    /// Iterator value_type trait.+    typedef T value_type;+    /// Iterator difference_type trait.+    typedef std::ptrdiff_t difference_type;+    /// Iterator pointer trait.+    typedef T* pointer;+    /// Iterator reference trait.+    typedef T& reference;     /// Construct an AbstractMatcher::Iterator such that Iterator() == AbstractMatcher::Operation(*this, method).end().     Iterator()       :

include/reflex/input.h

@@ -317,7 +317,7 @@ class Input {   };   /// FILE* handler functor base class to handle FILE* errors and non-blocking FILE* reads   struct Handler {-    virtual int operator()() = 0;+    virtual int operator()(FILE*) = 0;     virtual ~Handler() { };   };   /// Stream buffer for reflex::Input, derived from std::streambuf.@@ -709,7 +709,7 @@ class Input {       while (true)       {         size_t k = file_get(s, n);-        if (k > 0 || feof(file_) || handler_ == NULL || (*handler_)() == 0)+        if (k > 0 || feof(file_) || handler_ == NULL || (*handler_)(file_) == 0)           return k;       }     }

lib/convert.cpp

@@ -931,6 +931,17 @@ static void insert_list(const char *pattern, size_t len, size_t& pos, convert_fl       insert_posix_class(pattern, len, pos, ranges);       pc = -1;     }+    else if (c == '[' && (pattern[pos + 1] == '.' || pattern[pos + 1] == '='))+    {+      // POSIX collating+      if (range)+        throw regex_error(regex_error::invalid_class_range, pattern, pos);+      if (pos + 4 >= len || pattern[pos + 3] != pattern[pos + 1] || pattern[pos + 4] != ']')+        throw regex_error(regex_error::invalid_collating, pattern, pos);+      ranges.insert(pattern[pos + 2]);+      pos += 4;+      pc = -1;+    }     else if (c == '|' && pattern[pos + 1] == '|' && pos + 3 < len && (pattern[pos + 2] == '[' || (pattern[pos + 2] == '{' && macros != NULL)))     {       // character class union [abc||[def]]

lib/input.cpp

@@ -742,7 +742,7 @@ void Input::file_init()       }       break;     }-    if (handler_ == NULL || feof(file_) || (*handler_)() == 0)+    if (handler_ == NULL || feof(file_) || (*handler_)(file_) == 0)       break;   } }

lib/pattern.cpp

@@ -1126,9 +1126,9 @@ void Pattern::parse4(       c = at(++loc);     while (c != '\0')     {-      if (c == '[' && at(loc + 1) == ':')+      if (c == '[' && (at(loc + 1) == ':' || at(loc + 1) == '.' || at(loc + 1) == '='))       {-        size_t c_loc = find_at(loc + 2, ':');+        size_t c_loc = find_at(loc + 2, at(loc + 1));         if (c_loc != std::string::npos && at(static_cast<Location>(c_loc + 1)) == ']')           loc = static_cast<Location>(c_loc + 1);       }@@ -1483,7 +1483,7 @@ void Pattern::compile(         if (opt_.i)         {           // normalize by removing upper case if option i (case insensitivem matching) is enabled-          static const uint64_t upper[5] = { 0x0000000000000000, 0x0000000007FFFFFE, 0, 0, 0 };+          static const uint64_t upper[5] = { 0x0000000000000000ULL, 0x0000000007FFFFFEULL, 0ULL, 0ULL, 0ULL };           chars -= Chars(upper);         }         if (chars.any())@@ -1609,8 +1609,8 @@ void Pattern::compile(         }         if (opt_.i)         {-          // normalize by removing upper case if option i (case insensitivem matching) is enabled-          static const uint64_t upper[5] = { 0x0000000000000000, 0x0000000007FFFFFE, 0, 0, 0 };+          // normalize by removing upper case if option i (case insensitive matching) is enabled+          static const uint64_t upper[5] = { 0x0000000000000000ULL, 0x0000000007FFFFFEULL, 0ULL, 0ULL, 0ULL };           chars -= Chars(upper);         }         if (chars.any())@@ -1756,8 +1756,8 @@ void Pattern::compile(         }         if (opt_.i)         {-          // normalize by removing upper case if option i (case insensitivem matching) is enabled-          static const uint64_t upper[5] = { 0x0000000000000000, 0x0000000007FFFFFE, 0, 0, 0 };+          // normalize by removing upper case if option i (case insensitive matching) is enabled+          static const uint64_t upper[5] = { 0x0000000000000000ULL, 0x0000000007FFFFFEULL, 0ULL, 0ULL, 0ULL };           chars -= Chars(upper);         }         if (chars.any())@@ -2182,12 +2182,12 @@ void Pattern::compile_transition(               case '.':                 if (is_modified(ModConst::s, modifiers, loc))                 {-                  static const uint64_t dot[5] = { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0 };+                  static const uint64_t dot[5] = { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0ULL };                   chars |= Chars(dot);                 }                 else                 {-                  static const uint64_t dot[5] = { 0xFFFFFFFFFFFFFBFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0 };+                  static const uint64_t dot[5] = { 0xFFFFFFFFFFFFFBFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0ULL };                   chars |= Chars(dot);                 }                 break;@@ -2397,6 +2397,13 @@ void Pattern::compile_list(Location loc, Chars& chars, const Mods modifiers) con         }         loc = static_cast<Location>(c_loc + 1);       }+      else if (c == '[' && (at(loc + 1) == '.' || at(loc + 1) == '='))+      {+        c = at(loc + 2);+        if (c == '\0' || at(loc + 3) != at(loc + 1) || at(loc + 4) != ']')+          error(regex_error::invalid_collating, loc);+        loc += 4;+      }       else if (c == opt_.e && !opt_.b)       {         c = parse_esc(loc, &chars);

man/ugrep.1

@@ -1,4 +1,4 @@-.TH UGREP "1" "March 15, 2022" "ugrep 3.7.6" "User Commands"+.TH UGREP "1" "April 01, 2022" "ugrep 3.7.7" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS@@ -189,10 +189,10 @@ option.  If ACTION is `dereference\-recurse', read all files under each directory, recursively, following symbolic links.  This is equivalent to the \fB\-R\fR option. .TP-\fB\-\-depth\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-1\fR, \fB\-2\fR ... \fB\-9\fR, \fB\-\-10\fR, \fB\-\-11\fR ...+\fB\-\-depth\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-1\fR, \fB\-2\fR, \fB\-3\fR, ... \fB\-9\fR, \fB\-\-10\fR, \fB\-\-11\fR, \fB\-\-12\fR, ... Restrict recursive searches from MIN to MAX directory levels deep, where \fB\-1\fR (\fB\-\-depth\fR=1) searches the specified path without recursing-into subdirectories.  Note that \fB\-3\fR \fB\-5\fR, \fB\-3\fR\-5, or \fB\-3\fR5 searches 3 to 5+into subdirectories.  Note that \fB\-3\fR \fB\-5\fR, \fB\-3\fR\-5, and \fB\-3\fR5 search 3 to 5 levels deep.  Enables \fB\-R\fR if \fB\-R\fR or \fB\-r\fR is not specified. .TP \fB\-\-dotall\fR@@ -442,8 +442,8 @@ is specified with a literal ASCII upper case letter. Output file matches in JSON.  If \fB\-H\fR, \fB\-n\fR, \fB\-k\fR, or \fB\-b\fR is specified, additional values are output.  See also options \fB\-\-format\fR and \fB\-u\fR. .TP-\fB\-K\fR \fIFIRST\fR[,\fILAST\fR], \fB\-\-range\fR=\fIFIRST\fR[,\fILAST\fR]-Start searching at line FIRST, stop at line LAST when specified.+\fB\-K\fR [\fIMIN\fR,][\fIMAX\fR], \fB\-\-range\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-\-min\-line\fR=\fIMIN\fR, \fB\-\-max\-line\fR=\fIMAX\fR+Start searching at line MIN, stop at line MAX when specified. .TP \fB\-k\fR, \fB\-\-column\-number\fR The column number of a matched pattern is displayed in front of the@@ -486,9 +486,9 @@ with options \fB\-O\fR and \fB\-t\fR to expand the search.  Every file on the search path is read, making searches potentially more expensive. .TP \fB\-m\fR [\fIMIN\fR,][\fIMAX\fR], \fB\-\-min\-count\fR=\fIMIN\fR, \fB\-\-max\-count\fR=\fIMAX\fR-Stop reading the input after MAX matches in each input file when-specified.  Require at least MIN matches when specified, for-options \fB\-c\fR, \fB\-l\fR, \fB\-L\fR and \fB\-q\fR.+Require MIN matches, stop after MAX matches when specified.  Output+MIN to MAX matches.  For example, \fB\-m\fR1 outputs the first match and+\fB\-c\fRm1, (with a comma) counts non\-zero matches.  See also option \fB\-K\fR. .TP \fB\-\-match\fR Match all input.  Same as specifying an empty pattern to search.@@ -621,7 +621,7 @@ default is not to follow symbolic links. .TP \fB\-s\fR, \fB\-\-no\-messages\fR Silent mode: nonexistent and unreadable files are ignored, i.e.-their error messages are suppressed.+their error messages and warnings are suppressed. .TP \fB\-\-save\-config\fR[=\fIFILE\fR] Save configuration FILE.  By default `.ugrep' is saved.  If FILE is

src/flag.hpp

@@ -66,7 +66,7 @@ class Flag { enum class Sort { NA, NAME, BEST, SIZE, USED, CHANGED, CREATED, LIST };  // -D, --devices and -d, --directories-enum class Action { SKIP, READ, RECURSE };+enum class Action { UNSP, SKIP, READ, RECURSE };  // ugrep command-line options extern bool flag_all_threads;

src/query.cpp

@@ -3347,7 +3347,7 @@ void Query::set_flags()   else if (flags_[19].flag)     flag_directories_action = Action::RECURSE, flag_dereference = false;   else-    flag_directories_action = Action::SKIP;+    flag_directories_action = Action::UNSP;   flag_initial_tab = flags_[20].flag;   flag_binary = flags_[21].flag;   flag_ungroup = flags_[22].flag;

src/stats.cpp

@@ -60,7 +60,7 @@ void Stats::report(FILE *output)   if (warnings > 0)     fprintf(output, "Received %zu warning%s" NEWLINESTR, ws, ws == 1 ? "" : "s"); -  fprintf(output, "The following pathname selections and restrictions were applied:" NEWLINESTR);+  fprintf(output, "The following pathname selections and search restrictions were applied:" NEWLINESTR);   if (flag_config != NULL)     fprintf(output, "  --config=%s" NEWLINESTR, flag_config_file.c_str());   if (flag_min_depth > 0 && flag_max_depth > 0)@@ -69,6 +69,35 @@ void Stats::report(FILE *output)     fprintf(output, "  --depth=%zu," NEWLINESTR, flag_min_depth);   else if (flag_max_depth > 0)     fprintf(output, "  --depth=%zu" NEWLINESTR, flag_max_depth);+  if (flag_dereference)+    fprintf(output, "  --dereference" NEWLINESTR);+  else if (flag_no_dereference)+    fprintf(output, "  --no-dereference" NEWLINESTR);+  switch (flag_devices_action)+  {+    case Action::SKIP:+      fprintf(output, "  --devices=skip" NEWLINESTR);+      break;+    case Action::READ:+      fprintf(output, "  --devices=read" NEWLINESTR);+      break;+    default:+      break;+  }+  switch (flag_directories_action)+  {+    case Action::SKIP:+      fprintf(output, "  --directories=skip" NEWLINESTR);+      break;+    case Action::READ:+      fprintf(output, "  --directories=read" NEWLINESTR);+      break;+    case Action::RECURSE:+      fprintf(output, "  --directories=recurse" NEWLINESTR);+      break;+    default:+      break;+  }   if (flag_files)     fprintf(output, "  --files" NEWLINESTR); #ifdef WITH_HIDDEN@@ -84,6 +113,10 @@ void Stats::report(FILE *output) #endif   for (auto& i : flag_ignore_files)     fprintf(output, "  --ignore-files='%s'" NEWLINESTR, i.c_str());+  if (flag_min_count > 0)+    fprintf(output, "  --min-count=%zu" NEWLINESTR, flag_min_count);+  if (flag_max_count > 0)+    fprintf(output, "  --max-count=%zu" NEWLINESTR, flag_max_count);   if (flag_sort != NULL)     fprintf(output, "  --sort=%s" NEWLINESTR, flag_sort);   for (auto& i : ignore)

src/ugrep.cpp

@@ -366,8 +366,8 @@ Flag flag_smart_case; Flag flag_text; Flag flag_ungroup; Sort flag_sort_key                 = Sort::NA;-Action flag_devices_action         = Action::SKIP;-Action flag_directories_action     = Action::SKIP;+Action flag_devices_action         = Action::UNSP;+Action flag_directories_action     = Action::UNSP; size_t flag_after_context          = 0; size_t flag_before_context         = 0; size_t flag_fuzzy                  = 0;@@ -394,8 +394,8 @@ const char *flag_binary_files      = "binary"; const char *flag_color             = DEFAULT_COLOR; const char *flag_colors            = NULL; const char *flag_config            = NULL;-const char *flag_devices           = "skip";-const char *flag_directories       = "skip";+const char *flag_devices           = NULL;+const char *flag_directories       = NULL; const char *flag_encoding          = NULL; const char *flag_filter            = NULL; const char *flag_format            = NULL;@@ -466,7 +466,7 @@ void trim_pathname_arg(const char *arg); bool is_output(ino_t inode); size_t strtonum(const char *string, const char *message); size_t strtopos(const char *string, const char *message);-void strtopos2(const char *string, size_t& pos1, size_t& pos2, const char *message, bool optional_first = false);+void strtopos2(const char *string, size_t& pos1, size_t& pos2, const char *message); size_t strtofuzzy(const char *string, const char *message); void import_globs(FILE *file, std::vector<std::string>& files, std::vector<std::string>& dirs); void format(const char *format, size_t matches);@@ -1769,7 +1769,7 @@ struct Grep {   };  #ifndef OS_WIN-  // extend the reflex::Input::Handler to handle stdin from a TTY or a slow pipe+  // extend the reflex::Input::Handler to handle stdin from a TTY or from a slow pipe   struct StdInHandler : public reflex::Input::Handler {      StdInHandler(Grep *grep)@@ -1779,10 +1779,10 @@ struct Grep {      Grep *grep; -    int operator()()+    int operator()(FILE *file)     {       grep->out.flush();-+             while (true)       {         struct timeval tv;@@ -1793,14 +1793,20 @@ struct Grep {         FD_SET(0, &efds);         tv.tv_sec = 1;         tv.tv_usec = 0;-        int r = ::select(1, &rfds, NULL, &efds, &tv);+        int r = ::select(fileno(file) + 1, &rfds, NULL, &efds, &tv);         if (r < 0 && errno != EINTR)           return 0;-        if (r > 0 && FD_ISSET(0, &efds))+        if (r > 0 && FD_ISSET(fileno(file), &efds))           return 0;         if (r > 0)-          return 1;+          break;       }++      // clear EAGAIN and EINTR error on the nonblocking stdin+      clearerr(file);++      // no error+      return 1;     }   }; #endif@@ -1929,7 +1935,7 @@ struct Grep {           break;         } -        // -m: max number of matches reached?+        // --max-count: max number of matches reached?         if (flag_max_count > 0 && matches >= flag_max_count)           break; @@ -2022,7 +2028,7 @@ struct Grep {             grep.out.format(flag_format_open, pathname, grep.partname, Stats::found_parts(), &matcher, false, Stats::found_parts() > 1);         } -        // -m: max number of matches reached?+        // --max-count: max number of matches reached?         if (flag_max_count > 0 && matches >= flag_max_count)           break; @@ -2109,7 +2115,7 @@ struct Grep {           }         } -        // -m: max number of matches reached?+        // --max-count: max number of matches reached?         if (flag_invert_match && flag_max_count > 0 && matches >= flag_max_count)         {           stop = true;@@ -2330,7 +2336,7 @@ struct Grep {           }         } -        // -m: max number of matches reached?+        // --max-count: max number of matches reached?         if (flag_invert_match && flag_max_count > 0 && matches >= flag_max_count)         {           stop = true;@@ -2646,7 +2652,7 @@ struct Grep {           }         } -        // -m: max number of matches reached?+        // --max-count: max number of matches reached?         if (flag_invert_match && flag_max_count > 0 && matches >= flag_max_count)         {           stop = true;@@ -2931,7 +2937,7 @@ struct Grep {   // open a file for (binary) reading and assign input, decompress the file when -z, --decompress specified, may throw bad_alloc   bool open_file(const char *pathname)   {-    if (pathname == NULL)+    if (pathname == NULL || *pathname == '\0')     {       if (source == NULL)         return false;@@ -2951,14 +2957,18 @@ struct Grep {     }  #ifndef OS_WIN-    // skip empty regular files that are not readable; this skips sysfd files e.g. in /proc and /sys+    // check if a regular file is special and recursive searching files should not block     struct stat buf;-    if (fstat(fileno(file_in), &buf) == 0 && S_ISREG(buf.st_mode) && buf.st_size == 0)+    if (file_in != stdin && file_in != source && fstat(fileno(file_in), &buf) == 0 && S_ISREG(buf.st_mode))     {+      // recursive searches should not block on special regular files like in /proc and /sys+      if (flag_directories_action == Action::RECURSE)+        fcntl(fileno(file_in), F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);++      // check if an empty file is readable e.g. not a special sysfd file like in /proc and /sys       char data[1];-      if (read(fileno(file_in), data, 1) < 0 || fseek(file_in, 0, SEEK_SET) != 0)+      if (buf.st_size == 0 && (read(fileno(file_in), data, 1) < 0 || fseek(file_in, 0, SEEK_SET) != 0))       {-        errno = EAGAIN; // override the confusing "Invalid argument" (22) and "Input/output error" (5) ...         warning("cannot read", pathname);         fclose(file_in);         file_in = NULL;@@ -3223,7 +3233,35 @@ struct Grep {   // close the file and clear input, return true if next file is extracted from an archive to search   bool close_file(const char *pathname)   {-    (void)pathname; // appease -Wunused-parameter+    // check if the input has no error conditions, but do not check stdin which is nonblocking and handled differently+    if (file_in != NULL && file_in != stdin && file_in != source && ferror(file_in))+    {+      warning("cannot read", pathname);++#ifdef HAVE_LIBZ+#ifdef WITH_DECOMPRESSION_THREAD+      if (flag_decompress)+        zthread.cancel();+#else+      if (stream != NULL)+      {+        delete stream;+        stream = NULL;+      }+#endif+#endif++      // close the current input file+      if (file_in != NULL && file_in != stdin && file_in != source)+      {+        fclose(file_in);+        file_in = NULL;+      }++      input.clear();++      return false;+    }  #ifdef HAVE_LIBZ #ifdef WITH_DECOMPRESSION_THREAD@@ -3387,7 +3425,7 @@ struct Grep {   reflex::Input                  input;         // input to the matcher   FILE                          *file_in;       // the current input file #ifndef OS_WIN-  StdInHandler                   stdin_handler; // a handler to handle non-blocking stdin from a TTY or a slow pipe+  StdInHandler                   stdin_handler; // a handler to handle nonblocking stdin from a TTY or a slow pipe #endif #ifdef HAVE_LIBZ #ifdef WITH_DECOMPRESSION_THREAD@@ -3414,7 +3452,7 @@ struct Job {    Job(const char *pathname, size_t slot)     :-      pathname(pathname),+      pathname(pathname != NULL ? pathname : ""),       slot(slot)   { } @@ -4014,7 +4052,7 @@ static void set_depth(const char *arg)   }   else   {-    strtopos2(arg, flag_min_depth, flag_max_depth, "invalid argument --", true);+    strtopos2(arg, flag_min_depth, flag_max_depth, "invalid argument --");   } } @@ -4364,7 +4402,7 @@ void options(std::list<std::pair<CNF::PATTERN,const char*>>& pattern_args, int a                 if (strcmp(arg, "decompress") == 0)                   flag_decompress = true;                 else if (strncmp(arg, "depth=", 6) == 0)-                  strtopos2(arg + 6, flag_min_depth, flag_max_depth, "invalid argument --depth=", true);+                  strtopos2(arg + 6, flag_min_depth, flag_max_depth, "invalid argument --depth=");                 else if (strcmp(arg, "dereference") == 0)                   flag_dereference = true;                 else if (strcmp(arg, "dereference-recursive") == 0)@@ -4554,10 +4592,18 @@ void options(std::list<std::pair<CNF::PATTERN,const char*>>& pattern_args, int a                   flag_match = true;                 else if (strncmp(arg, "max-count=", 10) == 0)                   flag_max_count = strtopos(arg + 10, "invalid argument --max-count=");+                else if (strncmp(arg, "max-depth=", 10) == 0)+                  flag_max_depth = strtopos(arg + 10, "invalid argument --max-depth=");                 else if (strncmp(arg, "max-files=", 10) == 0)                   flag_max_files = strtopos(arg + 10, "invalid argument --max-files=");+                else if (strncmp(arg, "max-line=", 9) == 0)+                  flag_max_line = strtopos(arg + 9, "invalid argument --max-line=");                 else if (strncmp(arg, "min-count=", 10) == 0)                   flag_min_count = strtopos(arg + 10, "invalid argument --min-count=");+                else if (strncmp(arg, "min-depth=", 10) == 0)+                  flag_min_depth = strtopos(arg + 10, "invalid argument --min-depth=");+                else if (strncmp(arg, "min-line=", 9) == 0)+                  flag_min_line = strtopos(arg + 9, "invalid argument --min-line=");                 else if (strncmp(arg, "min-steal=", 10) == 0)                   flag_min_steal = strtopos(arg + 10, "invalid argument --min-steal=");                 else if (strcmp(arg, "mmap") == 0)@@ -4566,10 +4612,10 @@ void options(std::list<std::pair<CNF::PATTERN,const char*>>& pattern_args, int a                   flag_max_mmap = strtopos(arg + 5, "invalid argument --mmap=");                 else if (strcmp(arg, "messages") == 0)                   flag_no_messages = false;-                else if (strcmp(arg, "max-count") == 0 || strcmp(arg, "max-files") == 0)+                else if (strcmp(arg, "max-count") == 0 || strcmp(arg, "max-depth") == 0 || strcmp(arg, "max-files") == 0 || strcmp(arg, "max-line") == 0 || strcmp(arg, "min-count") == 0 || strcmp(arg, "min-depth") == 0 || strcmp(arg, "min-line") == 0)                   usage("missing argument for --", arg);                 else-                  usage("invalid option --", arg, "--match, --max-count, --max-files, --min-count, --mmap or --messages");+                  usage("invalid option --", arg, "--match, --max-count, --max-depth, --max-files, --max-line, --min-count, --min-depth, --min-line, --mmap or --messages");                 break;                case 'n':@@ -4976,11 +5022,11 @@ void options(std::list<std::pair<CNF::PATTERN,const char*>>& pattern_args, int a           case 'm':             ++arg;             if (*arg)-              strtopos2(&arg[*arg == '='], flag_min_count, flag_max_count, "invalid argument -m=", true);+              strtopos2(&arg[*arg == '='], flag_min_count, flag_max_count, "invalid argument -m=");             else if (++i < argc)-              strtopos2(argv[i], flag_min_count, flag_max_count, "invalid argument -m=", true);+              strtopos2(argv[i], flag_min_count, flag_max_count, "invalid argument -m=");             else-              usage("missing NUM argument for option -m");+              usage("missing MAX argument for option -m");             is_grouped = false;             break; @@ -5721,41 +5767,56 @@ void init(int argc, const char **argv)  #endif -  // -D: check ACTION value-  if (strcmp(flag_devices, "skip") == 0)-    flag_devices_action = Action::SKIP;-  else if (strcmp(flag_devices, "read") == 0)-    flag_devices_action = Action::READ;-  else-    usage("invalid argument -D ACTION, valid arguments are 'skip' and 'read'");--  // normalize -R (--dereference-recurse) option-  if (strcmp(flag_directories, "dereference-recurse") == 0)+  if (flag_devices != NULL)   {-    flag_directories = "recurse";-    flag_dereference = true;+    // -D: check ACTION value+    if (strcmp(flag_devices, "skip") == 0)+      flag_devices_action = Action::SKIP;+    else if (strcmp(flag_devices, "read") == 0)+      flag_devices_action = Action::READ;+    else+      usage("invalid argument -D ACTION, valid arguments are 'skip' and 'read'");   } -  // -d: check ACTION value and set flags-  if (strcmp(flag_directories, "skip") == 0)-    flag_directories_action = Action::SKIP;-  else if (strcmp(flag_directories, "read") == 0)-    flag_directories_action = Action::READ;-  else if (strcmp(flag_directories, "recurse") == 0)-    flag_directories_action = Action::RECURSE;-  else-    usage("invalid argument -d ACTION, valid arguments are 'skip', 'read', 'recurse' and 'dereference-recurse'");--  // if no FILE specified and no -r or -R specified, when reading standard input from a TTY then enable -R-  if (!flag_stdin && arg_files.empty() && flag_directories_action != Action::RECURSE && isatty(STDIN_FILENO))+  if (flag_directories != NULL)   {-    flag_directories_action = Action::RECURSE;-    flag_dereference = true;+    // normalize -R (--dereference-recurse) option+    if (strcmp(flag_directories, "dereference-recurse") == 0)+    {+      flag_directories = "recurse";+      flag_dereference = true;+    }++    // -d: check ACTION value and set flags+    if (strcmp(flag_directories, "skip") == 0)+      flag_directories_action = Action::SKIP;+    else if (strcmp(flag_directories, "read") == 0)+      flag_directories_action = Action::READ;+    else if (strcmp(flag_directories, "recurse") == 0)+      flag_directories_action = Action::RECURSE;+    else+      usage("invalid argument -d ACTION, valid arguments are 'skip', 'read', 'recurse' and 'dereference-recurse'");   } -  // if no FILE specified then read standard input, unless recursive searches are specified-  if (arg_files.empty() && flag_min_depth == 0 && flag_max_depth == 0 && flag_directories_action != Action::RECURSE)-    flag_stdin = true;+  if (!flag_stdin && arg_files.empty())+  {+    // if no FILE specified when reading standard input from a TTY then enable -R if not already -r or -R+    if (isatty(STDIN_FILENO) && (flag_directories_action == Action::UNSP || flag_directories_action == Action::RECURSE))+    {+      if (flag_directories_action == Action::UNSP)+      {+        flag_directories_action = Action::RECURSE;+        flag_dereference = true;+      }++      flag_all_threads = true;+    }+    else+    {+      // if no FILE specified then read standard input+      flag_stdin = true;+    }+  }    // check FILE arguments, warn about non-existing and non-readable files and directories   auto file = arg_files.begin();@@ -5780,7 +5841,8 @@ void init(int argc, const char **argv)       // use threads to recurse into a directory       if ((attr & FILE_ATTRIBUTE_DIRECTORY))       {-        flag_all_threads = true;+        if (flag_directories_action == Action::UNSP)+          flag_all_threads = true;          // remove trailing path separators, if any (*file points to argv[])         trim_pathname_arg(*file);@@ -5832,7 +5894,8 @@ void init(int argc, const char **argv)         // use threads to recurse into a directory         if (S_ISDIR(buf.st_mode))         {-          flag_all_threads = true;+          if (flag_directories_action == Action::UNSP)+            flag_all_threads = true;            // remove trailing path separators, if any (*file points to argv[])           trim_pathname_arg(*file);@@ -5879,13 +5942,21 @@ void init(int argc, const char **argv)   if (flag_replace != NULL && flag_format != NULL)     abort("--format is not permitted with --replace"); +  // -v with --only-line-number is not permitted+  if (flag_invert_match && flag_only_line_number)+    abort("--invert-match is not permitted with --only-line-number");+   // -v with --files is not permitted-  if (flag_files && flag_invert_match)-    abort("-v is not permitted with --files, invert the Boolean query instead");+  if (flag_invert_match && flag_files)+    abort("--invert-match is not permitted with --files, invert the Boolean query instead");++  // --min-count is not permitted with --files+  if (flag_min_count > 0 && flag_files)+    abort("--min-count is not permitted with --files"); -  // --min-count is not permitted with options other than -q, -l, -L and -c-  if (flag_min_count > 0 && !flag_quiet && !flag_files_with_matches && !flag_files_without_match && !flag_count)-    abort("--min-count is not permitted without -c, -l, -L or -q");+  // --min-count is not permitted with -v when not combined with -q, -l, -L or -c+  if (flag_min_count > 0 && flag_invert_match && !flag_quiet && !flag_files_with_matches && !flag_files_without_match && !flag_count)+    abort("--min-count is not permitted with --invert-match");  #ifdef HAVE_STATVFS @@ -6933,7 +7004,7 @@ void ugrep()     flag_only_matching = flag_ungroup = false;    // --depth: if -R or -r is not specified then enable -R-  if ((flag_min_depth > 0 || flag_max_depth > 0) && flag_directories_action != Action::RECURSE)+  if ((flag_min_depth > 0 || flag_max_depth > 0) && flag_directories_action == Action::UNSP)   {     flag_directories_action = Action::RECURSE;     flag_dereference = true;@@ -7361,21 +7432,22 @@ void clear_grep_handle() // search the specified files or standard input for pattern matches void Grep::ugrep() {-  if (!flag_stdin && arg_files.empty())+  // read each input file to find pattern matches+  if (flag_stdin)   {-    recurse(1, ".");+    Stats::score_file();++    // search standard input+    search(NULL);+  }++  if (arg_files.empty())+  {+    if (flag_directories_action == Action::RECURSE)+      recurse(1, ".");   }   else   {-    // read each input file to find pattern matches-    if (flag_stdin)-    {-      Stats::score_file();--      // search standard input-      search(NULL);-    }- #ifndef OS_WIN     std::pair<std::set<ino_t>::iterator,bool> vino; #endif@@ -7404,17 +7476,20 @@ void Grep::ugrep()       switch (select(1, pathname, basename, DIRENT_TYPE_UNKNOWN, inode, info, true))       {         case Type::DIRECTORY:+          if (flag_directories_action != Action::SKIP)+          { #ifndef OS_WIN-          if (flag_dereference)-            vino = visited.insert(inode);+            if (flag_dereference)+              vino = visited.insert(inode); #endif -          recurse(1, pathname);+            recurse(1, pathname);  #ifndef OS_WIN-          if (flag_dereference)-            visited.erase(vino.first);+            if (flag_dereference)+              visited.erase(vino.first); #endif+          }           break;          case Type::OTHER:@@ -8202,7 +8277,7 @@ uint16_t Grep::cost(const char *pathname)     return cost;   } -  // -Z: matcher is a FuzzyMatcher+  // -Z: matcher is a FuzzyMatcher for sure   reflex::FuzzyMatcher *fuzzy_matcher = dynamic_cast<reflex::FuzzyMatcher*>(matcher);    // search file to compute minimum cost@@ -8260,13 +8335,13 @@ void Grep::search(const char *pathname)   catch (...)   {     // this should never happen-    warning("exception while opening", pathname);+    warning("exception while opening", pathname != NULL && *pathname != '\0' ? pathname : flag_label);      return;   }    // pathname is NULL when stdin is searched-  if (pathname == NULL)+  if (pathname == NULL || *pathname == '\0')     pathname = flag_label;    bool colorize = flag_apply_color || flag_tag != NULL;@@ -8669,8 +8744,14 @@ void Grep::search(const char *pathname)                 continue;             } -            // --format-open-            if (matches == 0)+            ++matches;++            // --min-count: require at least min-count matches+            if (flag_min_count > 0 && matches < flag_min_count)+              continue;++            // output --format-open=FORMAT for the first (or --min-count) match found+            if (matches == flag_min_count + (flag_min_count == 0))             {               if (flag_files && matchers != NULL)               {@@ -8706,12 +8787,10 @@ void Grep::search(const char *pathname)               }             } -            ++matches;-             // output --format=FORMAT             out.format(flag_format, pathname, partname, matches, matcher, matches > 1, matches > 1); -            // -m: max number of matches reached?+            // --max-count: max number of matches reached?             if (flag_max_count > 0 && matches >= flag_max_count)               break; @@ -8719,6 +8798,10 @@ void Grep::search(const char *pathname)           }         } +        // --min-count: require at least min-count matches+        if (flag_min_count > 0 && matches < flag_min_count)+          goto exit_search;+         // --files: if we are still holding the output and CNF is not satisfyable then no global matches were made         if (flag_files && matchers != NULL)           if (!cnf_satisfied(true))@@ -8757,18 +8840,25 @@ void Grep::search(const char *pathname)                 continue;             } -            if (matches == 0 && (!flag_files || matchers == NULL))+            ++matches;++            // --min-count: require at least min-count matches+            if (flag_min_count > 0 && matches < flag_min_count)+            {+              lineno = current_lineno;+              continue;+            }++            if (matches == flag_min_count + (flag_min_count == 0) && (!flag_files || matchers == NULL))             {               // --max-files: max reached?               if (!Stats::found_part())                 goto exit_search;             } -            ++matches;-             out.header(pathname, partname, current_lineno, matcher, matcher->first(), separator, true); -            // -m: max number of matches reached?+            // --max-count: max number of matches reached?             if (flag_max_count > 0 && matches >= flag_max_count)               break; @@ -8779,6 +8869,10 @@ void Grep::search(const char *pathname)             lineno = current_lineno;           }         }++        // --min-count: require at least min-count matches+        if (flag_min_count > 0 && matches < flag_min_count)+          goto exit_search;       }       else if (flag_only_matching)       {@@ -8819,7 +8913,7 @@ void Grep::search(const char *pathname)             if (flag_max_line > 0 && current_lineno > flag_max_line)               break; -            // -m: max number of matches reached?+            // --max-count: max number of matches reached?             if (flag_max_count > 0 && matches >= flag_max_count)               break; @@ -8837,7 +8931,16 @@ void Grep::search(const char *pathname)                 continue;             } -            if (matches == 0 && (!flag_files || matchers == NULL))+            ++matches;++            // --min-count: require at least min-count matches+            if (flag_min_count > 0 && matches < flag_min_count)+            {+              lineno = current_lineno;+              continue;+            }++            if (matches == flag_min_count + (flag_min_count == 0) && (!flag_files || matchers == NULL))             {               // --max-files: max reached?               if (!Stats::found_part())@@ -8862,8 +8965,6 @@ void Grep::search(const char *pathname)               goto done_search;             } -            ++matches;-             if (!flag_no_header)             {               const char *separator = lineno != current_lineno ? flag_separator : "+";@@ -8873,6 +8974,10 @@ void Grep::search(const char *pathname)             lineno = current_lineno;           } +          // --min-count: require at least min-count matches+          if (flag_min_count > 0 && matches < flag_min_count)+            continue;+           hex = binary;            if (binary)@@ -8949,6 +9054,10 @@ void Grep::search(const char *pathname)           }         } +        // --min-count: require at least min-count matches+        if (flag_min_count > 0 && matches < flag_min_count)+          goto exit_search;+         if (nl)           out.nl(); @@ -9013,7 +9122,7 @@ void Grep::search(const char *pathname)             if (flag_max_line > 0 && current_lineno > flag_max_line)               break; -            // -m: max number of matches reached?+            // --max-count: max number of matches reached?             if (flag_max_count > 0 && matches >= flag_max_count)               break; @@ -9028,7 +9137,16 @@ void Grep::search(const char *pathname)             if (matchers != NULL && !cnf_matching(bol, eol))               continue; -            if (matches == 0 && (!flag_files || matchers == NULL))+            ++matches;++            // --min-count: require at least min-count matches+            if (flag_min_count > 0 && matches < flag_min_count)+            {+              lineno = current_lineno;+              continue;+            }++            if (matches == flag_min_count + (flag_min_count == 0) && (!flag_files || matchers == NULL))             {               // --max-files: max reached?               if (!Stats::found_part())@@ -9055,8 +9173,6 @@ void Grep::search(const char *pathname)               goto done_search;             } -            ++matches;-             size_t border = matcher->border();             size_t first = matcher->first();             const char *begin = matcher->begin();@@ -9187,6 +9303,10 @@ void Grep::search(const char *pathname)           }           else           {+            // --min-count: require at least min-count matches+            if (flag_min_count > 0 && matches < flag_min_count)+              continue;+             size_t size = matcher->size();              if (size > 0)@@ -9353,6 +9473,10 @@ void Grep::search(const char *pathname)           }         } +        // --min-count: require at least min-count matches+        if (flag_min_count > 0 && matches < flag_min_count)+          goto exit_search;+         if (restline_data != NULL)         {           if (binary)@@ -9446,7 +9570,7 @@ void Grep::search(const char *pathname)             if (stop)               goto exit_search; -            // -m: max number of matches reached?+            // --max-count: max number of matches reached?             if (flag_max_count > 0 && matches >= flag_max_count)               goto done_search; @@ -9545,6 +9669,33 @@ void Grep::search(const char *pathname)             if (matchers != NULL && !cnf_matching(bol, eol))               continue; +            if (!flag_invert_match)+            {+              ++matches;++              // --min-count: require at least min-count matches+              if (flag_min_count > 0 && matches < flag_min_count)+              {+                lineno = current_lineno;+                continue;+              }++              if (matches == flag_min_count + (flag_min_count == 0) && (!flag_files || matchers == NULL))+              {+                // --max-files: max reached?+                if (!Stats::found_part())+                  goto exit_search;+              }+            }++            // --range: max line exceeded?+            if (flag_max_line > 0 && current_lineno > flag_max_line)+              break;++            // --max-files: max reached?+            if (stop)+              goto exit_search;+             // get the lines before the matched line             context = matcher->before(); @@ -9571,28 +9722,8 @@ void Grep::search(const char *pathname)               }             } -            // --range: max line exceeded?-            if (flag_max_line > 0 && current_lineno > flag_max_line)-              break;--            // --max-files: max reached?-            if (stop)-              goto exit_search;--            if (!flag_invert_match)-            {-              if (matches == 0 && (!flag_files || matchers == NULL))-              {-                // --max-files: max reached?-                if (!Stats::found_part())-                  goto exit_search;-              }--              ++matches;-            }--            // -m: max number of matches reached?-            if (flag_max_count > 0 && matches >= flag_max_count)+            // --max-count: max number of matches reached?+            if (flag_max_count > 0 && matches > flag_max_count)               break;              // output blocked?@@ -9737,6 +9868,10 @@ void Grep::search(const char *pathname)           }           else if (!binfile && (!binary || flag_hex || flag_with_hex))           {+            // --min-count: require at least min-count matches+            if (flag_min_count > 0 && matches < flag_min_count)+              continue;+             size_t size = matcher->size();              if (size > 0)@@ -9869,6 +10004,10 @@ void Grep::search(const char *pathname)           }         } +        // --min-count: require at least min-count matches+        if (flag_min_count > 0 && matches < flag_min_count)+          matches = 0;+         if (restline_data != NULL)         {           if (binary)@@ -9983,6 +10122,15 @@ void Grep::search(const char *pathname)             if (matchers != NULL && !cnf_matching(bol, eol))               continue; +            ++matches;++            // --min-count: require at least min-count matches+            if (flag_min_count > 0 && matches < flag_min_count)+            {+              lineno = current_lineno;+              continue;+            }+             // get the lines before the matched line             context = matcher->before(); @@ -10017,17 +10165,15 @@ void Grep::search(const char *pathname)             if (stop)               goto exit_search; -            if (matches == 0 && (!flag_files || matchers == NULL))+            if (matches == 1 && (!flag_files || matchers == NULL))             {               // --max-files: max reached?               if (!Stats::found_part())                 goto exit_search;             } -            ++matches;--            // -m: max number of matches reached?-            if (flag_max_count > 0 && matches >= flag_max_count)+            // --max-count: max number of matches reached?+            if (flag_max_count > 0 && matches > flag_max_count)               break;              // output blocked?@@ -10177,6 +10323,10 @@ void Grep::search(const char *pathname)           }           else           {+            // --min-count: require at least min-count matches+            if (flag_min_count > 0 && matches < flag_min_count)+              continue;+             size_t size = matcher->size();              if (size > 0)@@ -10367,7 +10517,7 @@ void Grep::search(const char *pathname)          // InvertContextGrepHandler requires lineno to be set precisely, i.e. after skipping --range lines         size_t lineno = flag_min_line > 0 ? flag_min_line - 1 : 0;-        size_t last_lineno = 0;+        size_t last_lineno = lineno;         size_t after = flag_after_context;         bool binfile = !flag_text && !flag_hex && !flag_with_hex && !flag_binary_without_match && init_is_binary();         bool hex = false;@@ -10385,7 +10535,7 @@ void Grep::search(const char *pathname)         // register an event handler functor to display non-matching lines         matcher->set_handler(&invert_context_handler); -        // to get the context from the any_line handler explicitly+        // to get the context from the handler explicitly         reflex::AbstractMatcher::Context context;          while (matcher->find())@@ -10393,12 +10543,15 @@ void Grep::search(const char *pathname)           size_t current_lineno = matcher->lineno();           size_t lines = matcher->lines(); -          if (last_lineno + 1 >= current_lineno)-            after += lines;-          else if (last_lineno != current_lineno)-            after = 0;-           if (last_lineno != current_lineno)+          {+            if (lineno + 1 >= current_lineno)+              after += lines;+            else+              after = 0;+          }++          if (lineno != current_lineno)           {             if (restline_data != NULL)             {@@ -10475,7 +10628,7 @@ void Grep::search(const char *pathname)             }             */ -            // -m: max number of matches reached?+            // --max-count: max number of matches reached?             if (flag_max_count > 0 && matches >= flag_max_count)               break; @@ -10844,7 +10997,8 @@ void Grep::search(const char *pathname)             }           } -          lineno = last_lineno = current_lineno + lines - 1;+          last_lineno = current_lineno;+          lineno = current_lineno + lines - 1;         }          if (restline_data != NULL)@@ -11284,7 +11438,7 @@ size_t strtopos(const char *string, const char *message) }  // convert one or two comma-separated unsigned decimals specifying a range to positive size_t, produce error when conversion fails or when the range is invalid-void strtopos2(const char *string, size_t& min, size_t& max, const char *message, bool optional_first)+void strtopos2(const char *string, size_t& min, size_t& max, const char *message) {   char *rest = const_cast<char*>(string);   if (*string != ',')@@ -11293,10 +11447,8 @@ void strtopos2(const char *string, size_t& min, size_t& max, const char *message     min = 0;   if (*rest == ',')     max = static_cast<size_t>(strtoull(rest + 1, &rest, 10));-  else if (optional_first)-    max = min, min = 0;   else-    max = 0;+    max = min, min = 0;   if (rest == NULL || *rest != '\0' || (max > 0 && min > max))     usage(message, string); }@@ -11338,14 +11490,41 @@ void usage(const char *message, const char *arg, const char *valid) {   std::cerr << "ugrep: " << message << (arg != NULL ? arg : "");   if (valid != NULL)+  {     std::cerr << ", did you mean " << valid << "?" << std::endl;+    std::cerr << "For more help on options, try `ugrep --help' or `ugrep --help WHAT'" << std::endl;+  }   else+  {+    const char *s = message;+    while (*s != '\0' && *s != '-')+      ++s;     std::cerr << std::endl;-  std::cerr << "For more help on options, try `ugrep --help'";-  if (arg != NULL)-    std::cerr << " or `ugrep --help " << arg << "'" << std::endl;-  else-    std::cerr << std::endl;+    std::cerr << "For more help on options, try `ugrep --help' or `ugrep --help ";+    if (*s == '\0')+    {+      std::cerr << "WHAT'" << std::endl;+    }+    else+    {+      const char *e = s;+      while (*e == '-')+        ++e;+      if (*e == '\0')+      {+        if (arg != NULL)+          std::cerr << std::string(s, e - s) << arg << "'" << std::endl;+        else+          std::cerr << "WHAT'" << std::endl;+      }+      else+      {+        while (*e != '\0' && (*e == '-' || isalpha(*e)))+          ++e;+        std::cerr << std::string(s, e - s) << "'" << std::endl;+      }+    }+  }    // do not exit when reading a config file   if (!flag_usage_warnings)@@ -11478,10 +11657,10 @@ void help(std::ostream& out)             option.  If ACTION is `dereference-recurse', read all files under\n\             each directory, recursively, following symbolic links.  This is\n\             equivalent to the -R option.\n\-    --depth=[MIN,][MAX], -1, -2 ... -9, --10, --11 ...\n\+    --depth=[MIN,][MAX], -1, -2, -3, ... -9, --10, --11, --12, ...\n\             Restrict recursive searches from MIN to MAX directory levels deep,\n\             where -1 (--depth=1) searches the specified path without recursing\n\-            into subdirectories.  Note that -3 -5, -3-5, or -35 searches 3 to 5\n\+            into subdirectories.  Note that -3 -5, -3-5, and -35 search 3 to 5\n\             levels deep.  Enables -R if -R or -r is not specified.\n\     --dotall\n\             Dot `.' in regular expressions matches anything, including newline.\n\@@ -11710,8 +11889,8 @@ void help(std::ostream& out)     --json\n\             Output file matches in JSON.  If -H, -n, -k, or -b is specified,\n\             additional values are output.  See also options --format and -u.\n\-    -K FIRST[,LAST], --range=FIRST[,LAST]\n\-            Start searching at line FIRST, stop at line LAST when specified.\n\+    -K [MIN,][MAX], --range=[MIN,][MAX], --min-line=MIN, --max-line=MAX\n\+            Start searching at line MIN, stop at line MAX when specified.\n\     -k, --column-number\n\             The column number of a matched pattern is displayed in front of the\n\             respective matched line, starting at column 1.  Tabs are expanded\n\@@ -11746,9 +11925,9 @@ void help(std::ostream& out)             with options -O and -t to expand the search.  Every file on the\n\             search path is read, making searches potentially more expensive.\n\     -m [MIN,][MAX], --min-count=MIN, --max-count=MAX\n\-            Stop reading the input after MAX matches in each input file when\n\-            specified.  Require at least MIN matches when specified, for\n\-            options -c, -l, -L and -q.\n\+            Require MIN matches, stop after MAX matches when specified.  Output\n\+            MIN to MAX matches.  For example, -m1 outputs the first match and\n\+            -cm1, (with a comma) counts non-zero matches.  See also option -K.\n\     --match\n\             Match all input.  Same as specifying an empty pattern to search.\n\     --max-files=NUM\n\@@ -11868,7 +12047,7 @@ void help(std::ostream& out)             default is not to follow symbolic links.\n\     -s, --no-messages\n\             Silent mode: nonexistent and unreadable files are ignored, i.e.\n\-            their error messages are suppressed.\n\+            their error messages and warnings are suppressed.\n\     --save-config[=FILE]\n\             Save configuration FILE.  By default `.ugrep' is saved.  If FILE is\n\             a `-', write the configuration to standard output.\n\

src/ugrep.hpp

@@ -38,7 +38,7 @@ #define UGREP_HPP  // ugrep version-#define UGREP_VERSION "3.7.6"+#define UGREP_VERSION "3.7.7"  // disable mmap because mmap is almost always slower than the file reading speed improvements since 3.0.0 #define WITH_NO_MMAP@@ -46,7 +46,7 @@ // use a task-parallel thread to decompress the stream into a pipe to search, handles archives and increases decompression speed for larger files #define WITH_DECOMPRESSION_THREAD -// drain stdin until eof - this is disabled for speed, almost all utilities handle SIGPIPE these days anyway+// drain stdin until eof to prevent broken pipe signal // #define WITH_STDIN_DRAIN  // enable easy-to-use abbreviated ANSI SGR color codes with WITH_EASY_GREP_COLORS@@ -245,7 +245,12 @@ inline int fopenw_s(FILE **file, const char *filename, const char *mode) #if defined(HAVE_F_RDAHEAD)   if (strchr(mode, 'a') == NULL && strchr(mode, 'w') == NULL)   {-    int fd = open(filename, O_RDONLY); // removed O_NOATIME which may fail+    // removed O_NOATIME which may fail+#if defined(O_NOCTTY)+    int fd = open(filename, O_RDONLY | O_NOCTTY);+#else+    int fd = open(filename, O_RDONLY);+#endif     if (fd < 0)       return errno;     fcntl(fd, F_RDAHEAD, 1);

tests/archive.gz

Binary file changed

tests/archive.tar.zip

Binary file changed

tests/archive.tgz

Binary file changed

tests/archive2.tgz

Binary file changed

tests/archive3.tgz

Binary file changed

tests/out/Hello_Hello-W-nvC2.out

@@ -19,7 +19,7 @@ 00000070  -- -- -- -- -- -- -- --  -- -- 48 65 6c 6c 6f 2e  |----------Hello.| 00000080  6a 61 76 61 0c 00 07 00  08 07 00 17 0c 00 18 00  |javaL@G@HG@WL@X@| 00000090  19 01 00 0c 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |YA@LHello World!|-000000a0  07 00 1a 0c 00 1b 00 1c  01 00 05 48 65 6c 6c 6f  |G@ZL@[@\A@EHello|+000000a0  07 00 1a 0c 00 1b 00 1c  01 00 05 48 65 6c 6c 6f  |G@ZL@[@\A@EHello| 000000b0  01 00 10 6a 61 76 61 2f  6c 61 6e 67 2f 4f 62 6a  |A@Pjava/lang/Obj| 000000c0  65 63 74 01 00 10 6a 61  76 61 2f 6c 61 6e 67 2f  |ectA@Pjava/lang/| 000000d0  53 79 73 74 65 6d 01 00  03 6f 75 74 01 00 15 4c  |SystemA@CoutA@UL|

tests/out/Hello_Hello-W-vC2.out

@@ -19,7 +19,7 @@ 00000070  -- -- -- -- -- -- -- --  -- -- 48 65 6c 6c 6f 2e  |----------Hello.| 00000080  6a 61 76 61 0c 00 07 00  08 07 00 17 0c 00 18 00  |javaL@G@HG@WL@X@| 00000090  19 01 00 0c 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |YA@LHello World!|-000000a0  07 00 1a 0c 00 1b 00 1c  01 00 05 48 65 6c 6c 6f  |G@ZL@[@\A@EHello|+000000a0  07 00 1a 0c 00 1b 00 1c  01 00 05 48 65 6c 6c 6f  |G@ZL@[@\A@EHello| 000000b0  01 00 10 6a 61 76 61 2f  6c 61 6e 67 2f 4f 62 6a  |A@Pjava/lang/Obj| 000000c0  65 63 74 01 00 10 6a 61  76 61 2f 6c 61 6e 67 2f  |ectA@Pjava/lang/| 000000d0  53 79 73 74 65 6d 01 00  03 6f 75 74 01 00 15 4c  |SystemA@CoutA@UL|

tests/out/Hello_Hello-X-nvC2.out

@@ -22,7 +22,7 @@ 00000070  -- -- -- -- -- -- -- --  -- -- 48 65 6c 6c 6f 2e  |----------Hello.| 00000080  6a 61 76 61 0c 00 07 00  08 07 00 17 0c 00 18 00  |javaL@G@HG@WL@X@| 00000090  19 01 00 0c 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |YA@LHello World!|-000000a0  07 00 1a 0c 00 1b 00 1c  01 00 05 48 65 6c 6c 6f  |G@ZL@[@\A@EHello|+000000a0  07 00 1a 0c 00 1b 00 1c  01 00 05 48 65 6c 6c 6f  |G@ZL@[@\A@EHello| 000000b0  01 00 10 6a 61 76 61 2f  6c 61 6e 67 2f 4f 62 6a  |A@Pjava/lang/Obj| 000000c0  65 63 74 01 00 10 6a 61  76 61 2f 6c 61 6e 67 2f  |ectA@Pjava/lang/| 000000d0  53 79 73 74 65 6d 01 00  03 6f 75 74 01 00 15 4c  |SystemA@CoutA@UL|

tests/out/Hello_Hello-X-vC2.out

@@ -22,7 +22,7 @@ 00000070  -- -- -- -- -- -- -- --  -- -- 48 65 6c 6c 6f 2e  |----------Hello.| 00000080  6a 61 76 61 0c 00 07 00  08 07 00 17 0c 00 18 00  |javaL@G@HG@WL@X@| 00000090  19 01 00 0c 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |YA@LHello World!|-000000a0  07 00 1a 0c 00 1b 00 1c  01 00 05 48 65 6c 6c 6f  |G@ZL@[@\A@EHello|+000000a0  07 00 1a 0c 00 1b 00 1c  01 00 05 48 65 6c 6c 6f  |G@ZL@[@\A@EHello| 000000b0  01 00 10 6a 61 76 61 2f  6c 61 6e 67 2f 4f 62 6a  |A@Pjava/lang/Obj| 000000c0  65 63 74 01 00 10 6a 61  76 61 2f 6c 61 6e 67 2f  |ectA@Pjava/lang/| 000000d0  53 79 73 74 65 6d 01 00  03 6f 75 74 01 00 15 4c  |SystemA@CoutA@UL|

tests/out/Hello_wsS-I-nvC2.out

@@ -2,7 +2,7 @@ Hello.bat-2-echo "Hello World!" Hello.java-1-import java.lang.*; Hello.java:2:-Hello.java-3-public class Hello // prints a Hello World! greeting+Hello.java-3-public class Hello // prints a Hello World! greeting Hello.java-4-{ public static void main(String[] arg) Hello.java-5-  { System.out.println("Hello World!"); Hello.java:6:  }

tests/out/Hello_wsS-I-vC2.out

@@ -2,7 +2,7 @@ Hello.bat-echo "Hello World!" Hello.java-import java.lang.*; Hello.java:-Hello.java-public class Hello // prints a Hello World! greeting+Hello.java-public class Hello // prints a Hello World! greeting Hello.java-{ public static void main(String[] arg) Hello.java-  { System.out.println("Hello World!"); Hello.java:  }

tests/out/Hello_wsS-W-nvC2.out

@@ -43,7 +43,7 @@ 00000190  00 05 00 08 00 06 00 01  00 0d 00 00 00 02 00 0e  |@E@H@F@A@M@@@B@N| Hello.java-1-import java.lang.*; Hello.java:2:-Hello.java-3-public class Hello // prints a Hello World! greeting+Hello.java-3-public class Hello // prints a Hello World! greeting Hello.java-4-{ public static void main(String[] arg) Hello.java-5-  { System.out.println("Hello World!"); Hello.java:6:  }@@ -53,7 +53,7 @@ 00000000  -- -- -- -- -- -- -- --  -- 25 c4 e5 f2 e5 eb a7  |---------%......| 00000010  f3 a0 d0 c4 c6 0a -- --  -- -- -- -- -- -- -- --  |.....J----------| Hello.pdf-3-4 0 obj-Hello.pdf-4-<< /Length 5 0 R /Filter /FlateDecode >>+Hello.pdf-4-<< /Length 5 0 R /Filter /FlateDecode >> Hello.pdf:5:stream Hello.pdf:6: 00000040  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 78 01  |--------------xA|@@ -75,15 +75,15 @@ Hello.pdf:12:123 Hello.pdf:13:endobj Hello.pdf-14-2 0 obj-Hello.pdf-15-<< /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R /MediaBox [0 0 612 792]+Hello.pdf-15-<< /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R /MediaBox [0 0 612 792] Hello.pdf:16:>> Hello.pdf:17:endobj Hello.pdf-18-6 0 obj-Hello.pdf-19-<< /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 7 0 R >> /Font << /TT1 8 0 R+Hello.pdf-19-<< /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 7 0 R >> /Font << /TT1 8 0 R Hello.pdf:20:>> >> Hello.pdf:21:endobj Hello.pdf-22-9 0 obj-Hello.pdf-23-<< /Length 10 0 R /N 1 /Alternate /DeviceGray /Filter /FlateDecode >>+Hello.pdf-23-<< /Length 10 0 R /N 1 /Alternate /DeviceGray /Filter /FlateDecode >> Hello.pdf:24:stream Hello.pdf-25- 00000200  -- -- -- -- -- -- -- --  -- -- -- -- 78 01 85 55  |------------xA.U|@@ -173,28 +173,28 @@ Hello.pdf:34:1116 Hello.pdf:35:endobj Hello.pdf-36-7 0 obj-Hello.pdf-37-[ /ICCBased 9 0 R ]+Hello.pdf-37-[ /ICCBased 9 0 R ] Hello.pdf:38:endobj Hello.pdf-39-3 0 obj-Hello.pdf-40-<< /Type /Pages /MediaBox [0 0 612 792] /Count 1 /Kids [ 2 0 R ] >>+Hello.pdf-40-<< /Type /Pages /MediaBox [0 0 612 792] /Count 1 /Kids [ 2 0 R ] >> Hello.pdf:41:endobj Hello.pdf-42-11 0 obj-Hello.pdf-43-<< /Type /Catalog /Pages 3 0 R >>+Hello.pdf-43-<< /Type /Catalog /Pages 3 0 R >> Hello.pdf:44:endobj Hello.pdf-45-8 0 obj-Hello.pdf-46-<< /Type /Font /Subtype /TrueType /BaseFont /GQTMZF+Menlo-Regular /FontDescriptor+Hello.pdf-46-<< /Type /Font /Subtype /TrueType /BaseFont /GQTMZF+Menlo-Regular /FontDescriptor -- Hello.pdf-48-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 602 0 0 0 0 0 0 602 Hello.pdf-49-0 0 602 ] >> Hello.pdf:50:endobj Hello.pdf-51-12 0 obj-Hello.pdf-52-<< /Type /FontDescriptor /FontName /GQTMZF+Menlo-Regular /Flags 33 /FontBBox+Hello.pdf-52-<< /Type /FontDescriptor /FontName /GQTMZF+Menlo-Regular /Flags 33 /FontBBox Hello.pdf-53-[-558 -375 718 1041] /ItalicAngle 0 /Ascent 928 /Descent -236 /CapHeight 729 Hello.pdf-54-/StemV 99 /XHeight 547 /StemH 83 /AvgWidth 602 /MaxWidth 602 /FontFile2 13 0 R Hello.pdf:55:>> Hello.pdf:56:endobj Hello.pdf-57-13 0 obj-Hello.pdf-58-<< /Length 14 0 R /Length1 4064 /Filter /FlateDecode >>+Hello.pdf-58-<< /Length 14 0 R /Length1 4064 /Filter /FlateDecode >> Hello.pdf:59:stream Hello.pdf-60- 00000980  -- -- 78 01 dd 57 7b 78  54 c5 15 3f 73 7f 77 36  |--xA.W{xT.U?s~w6|@@ -226,11 +226,11 @@ 00000b00  a6 09 94 cb 34 de b4 17  67 6a c5 92 8d 91 18 93  |.I..4..Wgj....X.| 00000b10  b7 98 3a d2 e4 75 13 87  89 68 26 22 02 21 05 a5  |..:..uS..h&"B!E.| 00000b20  70 b5 02 57 14 2e 2b b4  e6 e2 9f 75 f8 ae 02 97  |p.BWT.+....u..B.|-00000b30  5a aa e5 25 85 4b 0d 7a  cb c5 90 6c a9 46 4b a5  |Z..%.KMz...l.FK.|-00000b40  7e f1 42 17 79 31 84 8b  01 fd 42 17 7c 7b 3e 47  |~.BWy1..A.BW|{>G|-00000b50  7e db 8a f3 39 f8 87 c2  39 85 6f 72 71 d6 85 bf  |~...9...9.orq...|-00000b60  d7 a2 99 43 6c 56 68 8e  5c 3b 18 b8 a6 7f 3d 12  |...ClVh.\;X..~=R|-00000b70  5f 9d 29 94 5f d5 e2 4c  21 fe a6 70 fa cb 0c 79  |_.)._..L!..p..Ly|+00000b30  5a aa e5 25 85 4b 0d 7a  cb c5 90 6c a9 46 4b a5  |Z..%.KMz...l.FK.|+00000b40  7e f1 42 17 79 31 84 8b  01 fd 42 17 7c 7b 3e 47  |~.BWy1..A.BW|{>G|+00000b50  7e db 8a f3 39 f8 87 c2  39 85 6f 72 71 d6 85 bf  |~...9...9.orq...|+00000b60  d7 a2 99 43 6c 56 68 8e  5c 3b 18 b8 a6 7f 3d 12  |...ClVh.\;X..~=R|+00000b70  5f 9d 29 94 5f d5 e2 4c  21 fe a6 70 fa cb 0c 79  |_.)._..L!..p..Ly| 00000b80  5a e1 cb 0c 7c a1 f0 f9  5d f8 4c e1 d3 3a 9c 3a  |Z..L|...].L..:.:| 00000b90  99 2e 4f b5 e2 64 3a 4e  d4 e2 13 85 8f 15 8e 1f  |..O..d:N..S..U._| 00000ba0  4b 91 c7 15 8e a5 e0 68  2d 3e fa 30 45 7e a4 f0  |K..U...h->.0E~..|@@ -414,7 +414,7 @@ Hello.pdf:85:(Hello) Hello.pdf:86:endobj Hello.pdf-87-16 0 obj-Hello.pdf-88-(Mac OS X 10.12.6 Quartz PDFContext)+Hello.pdf-88-(Mac OS X 10.12.6 Quartz PDFContext) Hello.pdf:89:endobj Hello.pdf-90-17 0 obj Hello.pdf:91:(TextEdit)@@ -429,7 +429,7 @@ Hello.pdf:100:[ ] Hello.pdf:101:endobj Hello.pdf-102-1 0 obj-Hello.pdf-103-<< /Title 15 0 R /Producer 16 0 R /Creator 17 0 R /CreationDate 18 0 R /ModDate+Hello.pdf-103-<< /Title 15 0 R /Producer 16 0 R /Creator 17 0 R /CreationDate 18 0 R /ModDate Hello.pdf-104-18 0 R /Keywords 19 0 R /AAPL:Keywords 20 0 R >> Hello.pdf:105:endobj Hello.pdf:106:xref@@ -439,7 +439,7 @@ Hello.pdf-127-0000005353 00000 n  Hello.pdf-128-0000005372 00000 n  Hello.pdf:129:trailer-Hello.pdf-130-<< /Size 21 /Root 11 0 R /Info 1 0 R /ID [ <8db88d3335070bd9583341583cf769a3>+Hello.pdf-130-<< /Size 21 /Root 11 0 R /Info 1 0 R /ID [ <8db88d3335070bd9583341583cf769a3> Hello.pdf:131:<8db88d3335070bd9583341583cf769a3> ] >> Hello.pdf:132:startxref Hello.pdf:133:5536

tests/out/Hello_wsS-W-vC2.out

@@ -43,7 +43,7 @@ 00000190  00 05 00 08 00 06 00 01  00 0d 00 00 00 02 00 0e  |@E@H@F@A@M@@@B@N| Hello.java-import java.lang.*; Hello.java:-Hello.java-public class Hello // prints a Hello World! greeting+Hello.java-public class Hello // prints a Hello World! greeting Hello.java-{ public static void main(String[] arg) Hello.java-  { System.out.println("Hello World!"); Hello.java:  }@@ -53,7 +53,7 @@ 00000000  -- -- -- -- -- -- -- --  -- 25 c4 e5 f2 e5 eb a7  |---------%......| 00000010  f3 a0 d0 c4 c6 0a -- --  -- -- -- -- -- -- -- --  |.....J----------| Hello.pdf-4 0 obj-Hello.pdf-<< /Length 5 0 R /Filter /FlateDecode >>+Hello.pdf-<< /Length 5 0 R /Filter /FlateDecode >> Hello.pdf:stream Hello.pdf: 00000040  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 78 01  |--------------xA|@@ -75,15 +75,15 @@ Hello.pdf:123 Hello.pdf:endobj Hello.pdf-2 0 obj-Hello.pdf-<< /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R /MediaBox [0 0 612 792]+Hello.pdf-<< /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R /MediaBox [0 0 612 792] Hello.pdf:>> Hello.pdf:endobj Hello.pdf-6 0 obj-Hello.pdf-<< /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 7 0 R >> /Font << /TT1 8 0 R+Hello.pdf-<< /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 7 0 R >> /Font << /TT1 8 0 R Hello.pdf:>> >> Hello.pdf:endobj Hello.pdf-9 0 obj-Hello.pdf-<< /Length 10 0 R /N 1 /Alternate /DeviceGray /Filter /FlateDecode >>+Hello.pdf-<< /Length 10 0 R /N 1 /Alternate /DeviceGray /Filter /FlateDecode >> Hello.pdf:stream Hello.pdf- 00000200  -- -- -- -- -- -- -- --  -- -- -- -- 78 01 85 55  |------------xA.U|@@ -173,28 +173,28 @@ Hello.pdf:1116 Hello.pdf:endobj Hello.pdf-7 0 obj-Hello.pdf-[ /ICCBased 9 0 R ]+Hello.pdf-[ /ICCBased 9 0 R ] Hello.pdf:endobj Hello.pdf-3 0 obj-Hello.pdf-<< /Type /Pages /MediaBox [0 0 612 792] /Count 1 /Kids [ 2 0 R ] >>+Hello.pdf-<< /Type /Pages /MediaBox [0 0 612 792] /Count 1 /Kids [ 2 0 R ] >> Hello.pdf:endobj Hello.pdf-11 0 obj-Hello.pdf-<< /Type /Catalog /Pages 3 0 R >>+Hello.pdf-<< /Type /Catalog /Pages 3 0 R >> Hello.pdf:endobj Hello.pdf-8 0 obj-Hello.pdf-<< /Type /Font /Subtype /TrueType /BaseFont /GQTMZF+Menlo-Regular /FontDescriptor+Hello.pdf-<< /Type /Font /Subtype /TrueType /BaseFont /GQTMZF+Menlo-Regular /FontDescriptor -- Hello.pdf-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 602 0 0 0 0 0 0 602 Hello.pdf-0 0 602 ] >> Hello.pdf:endobj Hello.pdf-12 0 obj-Hello.pdf-<< /Type /FontDescriptor /FontName /GQTMZF+Menlo-Regular /Flags 33 /FontBBox+Hello.pdf-<< /Type /FontDescriptor /FontName /GQTMZF+Menlo-Regular /Flags 33 /FontBBox Hello.pdf-[-558 -375 718 1041] /ItalicAngle 0 /Ascent 928 /Descent -236 /CapHeight 729 Hello.pdf-/StemV 99 /XHeight 547 /StemH 83 /AvgWidth 602 /MaxWidth 602 /FontFile2 13 0 R Hello.pdf:>> Hello.pdf:endobj Hello.pdf-13 0 obj-Hello.pdf-<< /Length 14 0 R /Length1 4064 /Filter /FlateDecode >>+Hello.pdf-<< /Length 14 0 R /Length1 4064 /Filter /FlateDecode >> Hello.pdf:stream Hello.pdf- 00000980  -- -- 78 01 dd 57 7b 78  54 c5 15 3f 73 7f 77 36  |--xA.W{xT.U?s~w6|@@ -226,11 +226,11 @@ 00000b00  a6 09 94 cb 34 de b4 17  67 6a c5 92 8d 91 18 93  |.I..4..Wgj....X.| 00000b10  b7 98 3a d2 e4 75 13 87  89 68 26 22 02 21 05 a5  |..:..uS..h&"B!E.| 00000b20  70 b5 02 57 14 2e 2b b4  e6 e2 9f 75 f8 ae 02 97  |p.BWT.+....u..B.|-00000b30  5a aa e5 25 85 4b 0d 7a  cb c5 90 6c a9 46 4b a5  |Z..%.KMz...l.FK.|-00000b40  7e f1 42 17 79 31 84 8b  01 fd 42 17 7c 7b 3e 47  |~.BWy1..A.BW|{>G|-00000b50  7e db 8a f3 39 f8 87 c2  39 85 6f 72 71 d6 85 bf  |~...9...9.orq...|-00000b60  d7 a2 99 43 6c 56 68 8e  5c 3b 18 b8 a6 7f 3d 12  |...ClVh.\;X..~=R|-00000b70  5f 9d 29 94 5f d5 e2 4c  21 fe a6 70 fa cb 0c 79  |_.)._..L!..p..Ly|+00000b30  5a aa e5 25 85 4b 0d 7a  cb c5 90 6c a9 46 4b a5  |Z..%.KMz...l.FK.|+00000b40  7e f1 42 17 79 31 84 8b  01 fd 42 17 7c 7b 3e 47  |~.BWy1..A.BW|{>G|+00000b50  7e db 8a f3 39 f8 87 c2  39 85 6f 72 71 d6 85 bf  |~...9...9.orq...|+00000b60  d7 a2 99 43 6c 56 68 8e  5c 3b 18 b8 a6 7f 3d 12  |...ClVh.\;X..~=R|+00000b70  5f 9d 29 94 5f d5 e2 4c  21 fe a6 70 fa cb 0c 79  |_.)._..L!..p..Ly| 00000b80  5a e1 cb 0c 7c a1 f0 f9  5d f8 4c e1 d3 3a 9c 3a  |Z..L|...].L..:.:| 00000b90  99 2e 4f b5 e2 64 3a 4e  d4 e2 13 85 8f 15 8e 1f  |..O..d:N..S..U._| 00000ba0  4b 91 c7 15 8e a5 e0 68  2d 3e fa 30 45 7e a4 f0  |K..U...h->.0E~..|@@ -414,7 +414,7 @@ Hello.pdf:(Hello) Hello.pdf:endobj Hello.pdf-16 0 obj-Hello.pdf-(Mac OS X 10.12.6 Quartz PDFContext)+Hello.pdf-(Mac OS X 10.12.6 Quartz PDFContext) Hello.pdf:endobj Hello.pdf-17 0 obj Hello.pdf:(TextEdit)@@ -429,7 +429,7 @@ Hello.pdf:[ ] Hello.pdf:endobj Hello.pdf-1 0 obj-Hello.pdf-<< /Title 15 0 R /Producer 16 0 R /Creator 17 0 R /CreationDate 18 0 R /ModDate+Hello.pdf-<< /Title 15 0 R /Producer 16 0 R /Creator 17 0 R /CreationDate 18 0 R /ModDate Hello.pdf-18 0 R /Keywords 19 0 R /AAPL:Keywords 20 0 R >> Hello.pdf:endobj Hello.pdf:xref@@ -439,7 +439,7 @@ Hello.pdf-0000005353 00000 n  Hello.pdf-0000005372 00000 n  Hello.pdf:trailer-Hello.pdf-<< /Size 21 /Root 11 0 R /Info 1 0 R /ID [ <8db88d3335070bd9583341583cf769a3>+Hello.pdf-<< /Size 21 /Root 11 0 R /Info 1 0 R /ID [ <8db88d3335070bd9583341583cf769a3> Hello.pdf:<8db88d3335070bd9583341583cf769a3> ] >> Hello.pdf:startxref Hello.pdf:5536

tests/out/Hello_wsS-X-nvC2.out

@@ -51,8 +51,8 @@ 00000010  -- -- -- -- 0a -- -- --  -- -- -- -- -- -- -- --  |----J-----------| Hello.java-3- 00000010  -- -- -- -- -- 70 75 62  6c 69 63 20 63 6c 61 73  |-----public clas|-00000020  73 20 48 65 6c 6c 6f 20  2f 2f 20 70 72 69 6e 74  |s Hello // print|-00000030  73 20 61 20 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |s a Hello World!|+00000020  73 20 48 65 6c 6c 6f 20  2f 2f 20 70 72 69 6e 74  |s Hello // print|+00000030  73 20 61 20 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |s a Hello World!| 00000040  20 67 72 65 65 74 69 6e  67 0a -- -- -- -- -- --  | greetingJ------| Hello.java-4- 00000040  -- -- -- -- -- -- -- --  -- -- 7b 20 70 75 62 6c  |----------{ publ|@@ -76,9 +76,9 @@ 00000010  -- -- -- -- -- -- 34 20  30 20 6f 62 6a 0a -- --  |------4 0 objJ--| Hello.pdf-4- 00000010  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 3c 3c  |--------------<<|-00000020  20 2f 4c 65 6e 67 74 68  20 35 20 30 20 52 20 2f  | /Length 5 0 R /|-00000030  46 69 6c 74 65 72 20 2f  46 6c 61 74 65 44 65 63  |Filter /FlateDec|-00000040  6f 64 65 20 3e 3e 0a --  -- -- -- -- -- -- -- --  |ode >>J---------|+00000020  20 2f 4c 65 6e 67 74 68  20 35 20 30 20 52 20 2f  | /Length 5 0 R /|+00000030  46 69 6c 74 65 72 20 2f  46 6c 61 74 65 44 65 63  |Filter /FlateDec|+00000040  6f 64 65 20 3e 3e 0a --  -- -- -- -- -- -- -- --  |ode >>J---------| Hello.pdf:5: 00000040  -- -- -- -- -- -- -- 73  74 72 65 61 6d 0a -- --  |-------streamJ--| Hello.pdf:6:@@ -112,11 +112,11 @@ 000000f0  30 20 6f 62 6a 0a -- --  -- -- -- -- -- -- -- --  |0 objJ----------| Hello.pdf-15- 000000f0  -- -- -- -- -- -- 3c 3c  20 2f 54 79 70 65 20 2f  |------<< /Type /|-00000100  50 61 67 65 20 2f 50 61  72 65 6e 74 20 33 20 30  |Page /Parent 3 0|-00000110  20 52 20 2f 52 65 73 6f  75 72 63 65 73 20 36 20  | R /Resources 6 |-00000120  30 20 52 20 2f 43 6f 6e  74 65 6e 74 73 20 34 20  |0 R /Contents 4 |-00000130  30 20 52 20 2f 4d 65 64  69 61 42 6f 78 20 5b 30  |0 R /MediaBox [0|-00000140  20 30 20 36 31 32 20 37  39 32 5d 0a -- -- -- --  | 0 612 792]J----|+00000100  50 61 67 65 20 2f 50 61  72 65 6e 74 20 33 20 30  |Page /Parent 3 0|+00000110  20 52 20 2f 52 65 73 6f  75 72 63 65 73 20 36 20  | R /Resources 6 |+00000120  30 20 52 20 2f 43 6f 6e  74 65 6e 74 73 20 34 20  |0 R /Contents 4 |+00000130  30 20 52 20 2f 4d 65 64  69 61 42 6f 78 20 5b 30  |0 R /MediaBox [0|+00000140  20 30 20 36 31 32 20 37  39 32 5d 0a -- -- -- --  | 0 612 792]J----| Hello.pdf:16: 00000140  -- -- -- -- -- -- -- --  -- -- -- -- 3e 3e 0a --  |------------>>J-| Hello.pdf:17:@@ -126,11 +126,11 @@ 00000150  -- -- -- -- -- -- 36 20  30 20 6f 62 6a 0a -- --  |------6 0 objJ--| Hello.pdf-19- 00000150  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 3c 3c  |--------------<<|-00000160  20 2f 50 72 6f 63 53 65  74 20 5b 20 2f 50 44 46  | /ProcSet [ /PDF|-00000170  20 2f 54 65 78 74 20 5d  20 2f 43 6f 6c 6f 72 53  | /Text ] /ColorS|-00000180  70 61 63 65 20 3c 3c 20  2f 43 73 31 20 37 20 30  |pace << /Cs1 7 0|-00000190  20 52 20 3e 3e 20 2f 46  6f 6e 74 20 3c 3c 20 2f  | R >> /Font << /|-000001a0  54 54 31 20 38 20 30 20  52 0a -- -- -- -- -- --  |TT1 8 0 RJ------|+00000160  20 2f 50 72 6f 63 53 65  74 20 5b 20 2f 50 44 46  | /ProcSet [ /PDF|+00000170  20 2f 54 65 78 74 20 5d  20 2f 43 6f 6c 6f 72 53  | /Text ] /ColorS|+00000180  70 61 63 65 20 3c 3c 20  2f 43 73 31 20 37 20 30  |pace << /Cs1 7 0|+00000190  20 52 20 3e 3e 20 2f 46  6f 6e 74 20 3c 3c 20 2f  | R >> /Font << /|+000001a0  54 54 31 20 38 20 30 20  52 0a -- -- -- -- -- --  |TT1 8 0 RJ------| Hello.pdf:20: 000001a0  -- -- -- -- -- -- -- --  -- -- 3e 3e 20 3e 3e 0a  |---------->> >>J| Hello.pdf:21:@@ -139,11 +139,11 @@ 000001b0  -- -- -- -- -- -- -- 39  20 30 20 6f 62 6a 0a --  |-------9 0 objJ-| Hello.pdf-23- 000001b0  -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- 3c  |---------------<|-000001c0  3c 20 2f 4c 65 6e 67 74  68 20 31 30 20 30 20 52  |< /Length 10 0 R|-000001d0  20 2f 4e 20 31 20 2f 41  6c 74 65 72 6e 61 74 65  | /N 1 /Alternate|-000001e0  20 2f 44 65 76 69 63 65  47 72 61 79 20 2f 46 69  | /DeviceGray /Fi|-000001f0  6c 74 65 72 20 2f 46 6c  61 74 65 44 65 63 6f 64  |lter /FlateDecod|-00000200  65 20 3e 3e 0a -- -- --  -- -- -- -- -- -- -- --  |e >>J-----------|+000001c0  3c 20 2f 4c 65 6e 67 74  68 20 31 30 20 30 20 52  |< /Length 10 0 R|+000001d0  20 2f 4e 20 31 20 2f 41  6c 74 65 72 6e 61 74 65  | /N 1 /Alternate|+000001e0  20 2f 44 65 76 69 63 65  47 72 61 79 20 2f 46 69  | /DeviceGray /Fi|+000001f0  6c 74 65 72 20 2f 46 6c  61 74 65 44 65 63 6f 64  |lter /FlateDecod|+00000200  65 20 3e 3e 0a -- -- --  -- -- -- -- -- -- -- --  |e >>J-----------| Hello.pdf:24: 00000200  -- -- -- -- -- 73 74 72  65 61 6d 0a -- -- -- --  |-----streamJ----| Hello.pdf-25-@@ -245,7 +245,7 @@ 00000690  20 30 20 6f 62 6a 0a --  -- -- -- -- -- -- -- --  | 0 objJ---------| Hello.pdf-37- 00000690  -- -- -- -- -- -- -- 5b  20 2f 49 43 43 42 61 73  |-------[ /ICCBas|-000006a0  65 64 20 39 20 30 20 52  20 5d 0a -- -- -- -- --  |ed 9 0 R ]J-----|+000006a0  65 64 20 39 20 30 20 52  20 5d 0a -- -- -- -- --  |ed 9 0 R ]J-----| Hello.pdf:38: 000006a0  -- -- -- -- -- -- -- --  -- -- -- 65 6e 64 6f 62  |-----------endob| 000006b0  6a 0a -- -- -- -- -- --  -- -- -- -- -- -- -- --  |jJ--------------|@@ -253,10 +253,10 @@ 000006b0  -- -- 33 20 30 20 6f 62  6a 0a -- -- -- -- -- --  |--3 0 objJ------| Hello.pdf-40- 000006b0  -- -- -- -- -- -- -- --  -- -- 3c 3c 20 2f 54 79  |----------<< /Ty|-000006c0  70 65 20 2f 50 61 67 65  73 20 2f 4d 65 64 69 61  |pe /Pages /Media|-000006d0  42 6f 78 20 5b 30 20 30  20 36 31 32 20 37 39 32  |Box [0 0 612 792|-000006e0  5d 20 2f 43 6f 75 6e 74  20 31 20 2f 4b 69 64 73  |] /Count 1 /Kids|-000006f0  20 5b 20 32 20 30 20 52  20 5d 20 3e 3e 0a -- --  | [ 2 0 R ] >>J--|+000006c0  70 65 20 2f 50 61 67 65  73 20 2f 4d 65 64 69 61  |pe /Pages /Media|+000006d0  42 6f 78 20 5b 30 20 30  20 36 31 32 20 37 39 32  |Box [0 0 612 792|+000006e0  5d 20 2f 43 6f 75 6e 74  20 31 20 2f 4b 69 64 73  |] /Count 1 /Kids|+000006f0  20 5b 20 32 20 30 20 52  20 5d 20 3e 3e 0a -- --  | [ 2 0 R ] >>J--| Hello.pdf:41: 000006f0  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 65 6e  |--------------en| 00000700  64 6f 62 6a 0a -- -- --  -- -- -- -- -- -- -- --  |dobjJ-----------|@@ -265,17 +265,17 @@ Hello.pdf-43- 00000700  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 3c 3c  |--------------<<| 00000710  20 2f 54 79 70 65 20 2f  43 61 74 61 6c 6f 67 20  | /Type /Catalog |-00000720  2f 50 61 67 65 73 20 33  20 30 20 52 20 3e 3e 0a  |/Pages 3 0 R >>J|+00000720  2f 50 61 67 65 73 20 33  20 30 20 52 20 3e 3e 0a  |/Pages 3 0 R >>J| Hello.pdf:44: 00000730  65 6e 64 6f 62 6a 0a --  -- -- -- -- -- -- -- --  |endobjJ---------| Hello.pdf-45- 00000730  -- -- -- -- -- -- -- 38  20 30 20 6f 62 6a 0a --  |-------8 0 objJ-| Hello.pdf-46- 00000730  -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- 3c  |---------------<|-00000740  3c 20 2f 54 79 70 65 20  2f 46 6f 6e 74 20 2f 53  |< /Type /Font /S|-00000750  75 62 74 79 70 65 20 2f  54 72 75 65 54 79 70 65  |ubtype /TrueType|-00000760  20 2f 42 61 73 65 46 6f  6e 74 20 2f 47 51 54 4d  | /BaseFont /GQTM|-00000770  5a 46 2b 4d 65 6e 6c 6f  2d 52 65 67 75 6c 61 72  |ZF+Menlo-Regular|+00000740  3c 20 2f 54 79 70 65 20  2f 46 6f 6e 74 20 2f 53  |< /Type /Font /S|+00000750  75 62 74 79 70 65 20 2f  54 72 75 65 54 79 70 65  |ubtype /TrueType|+00000760  20 2f 42 61 73 65 46 6f  6e 74 20 2f 47 51 54 4d  | /BaseFont /GQTM|+00000770  5a 46 2b 4d 65 6e 6c 6f  2d 52 65 67 75 6c 61 72  |ZF+Menlo-Regular| 00000780  20 2f 46 6f 6e 74 44 65  73 63 72 69 70 74 6f 72  | /FontDescriptor| 00000790  0a -- -- -- -- -- -- --  -- -- -- -- -- -- -- --  |J---------------| --@@ -297,9 +297,9 @@ Hello.pdf-52- 00000840  -- -- -- -- -- -- -- 3c  3c 20 2f 54 79 70 65 20  |-------<< /Type | 00000850  2f 46 6f 6e 74 44 65 73  63 72 69 70 74 6f 72 20  |/FontDescriptor |-00000860  2f 46 6f 6e 74 4e 61 6d  65 20 2f 47 51 54 4d 5a  |/FontName /GQTMZ|-00000870  46 2b 4d 65 6e 6c 6f 2d  52 65 67 75 6c 61 72 20  |F+Menlo-Regular |-00000880  2f 46 6c 61 67 73 20 33  33 20 2f 46 6f 6e 74 42  |/Flags 33 /FontB|+00000860  2f 46 6f 6e 74 4e 61 6d  65 20 2f 47 51 54 4d 5a  |/FontName /GQTMZ|+00000870  46 2b 4d 65 6e 6c 6f 2d  52 65 67 75 6c 61 72 20  |F+Menlo-Regular |+00000880  2f 46 6c 61 67 73 20 33  33 20 2f 46 6f 6e 74 42  |/Flags 33 /FontB| 00000890  42 6f 78 0a -- -- -- --  -- -- -- -- -- -- -- --  |BoxJ------------| Hello.pdf-53- 00000890  -- -- -- -- 5b 2d 35 35  38 20 2d 33 37 35 20 37  |----[-558 -375 7|@@ -323,9 +323,9 @@ 00000940  62 6a 0a -- -- -- -- --  -- -- -- -- -- -- -- --  |bjJ-------------| Hello.pdf-58- 00000940  -- -- -- 3c 3c 20 2f 4c  65 6e 67 74 68 20 31 34  |---<< /Length 14|-00000950  20 30 20 52 20 2f 4c 65  6e 67 74 68 31 20 34 30  | 0 R /Length1 40|-00000960  36 34 20 2f 46 69 6c 74  65 72 20 2f 46 6c 61 74  |64 /Filter /Flat|-00000970  65 44 65 63 6f 64 65 20  3e 3e 0a -- -- -- -- --  |eDecode >>J-----|+00000950  20 30 20 52 20 2f 4c 65  6e 67 74 68 31 20 34 30  | 0 R /Length1 40|+00000960  36 34 20 2f 46 69 6c 74  65 72 20 2f 46 6c 61 74  |64 /Filter /Flat|+00000970  65 44 65 63 6f 64 65 20  3e 3e 0a -- -- -- -- --  |eDecode >>J-----| Hello.pdf:59: 00000970  -- -- -- -- -- -- -- --  -- -- -- 73 74 72 65 61  |-----------strea| 00000980  6d 0a -- -- -- -- -- --  -- -- -- -- -- -- -- --  |mJ--------------|@@ -359,11 +359,11 @@ 00000b00  a6 09 94 cb 34 de b4 17  67 6a c5 92 8d 91 18 93  |.I..4..Wgj....X.| 00000b10  b7 98 3a d2 e4 75 13 87  89 68 26 22 02 21 05 a5  |..:..uS..h&"B!E.| 00000b20  70 b5 02 57 14 2e 2b b4  e6 e2 9f 75 f8 ae 02 97  |p.BWT.+....u..B.|-00000b30  5a aa e5 25 85 4b 0d 7a  cb c5 90 6c a9 46 4b a5  |Z..%.KMz...l.FK.|-00000b40  7e f1 42 17 79 31 84 8b  01 fd 42 17 7c 7b 3e 47  |~.BWy1..A.BW|{>G|-00000b50  7e db 8a f3 39 f8 87 c2  39 85 6f 72 71 d6 85 bf  |~...9...9.orq...|-00000b60  d7 a2 99 43 6c 56 68 8e  5c 3b 18 b8 a6 7f 3d 12  |...ClVh.\;X..~=R|-00000b70  5f 9d 29 94 5f d5 e2 4c  21 fe a6 70 fa cb 0c 79  |_.)._..L!..p..Ly|+00000b30  5a aa e5 25 85 4b 0d 7a  cb c5 90 6c a9 46 4b a5  |Z..%.KMz...l.FK.|+00000b40  7e f1 42 17 79 31 84 8b  01 fd 42 17 7c 7b 3e 47  |~.BWy1..A.BW|{>G|+00000b50  7e db 8a f3 39 f8 87 c2  39 85 6f 72 71 d6 85 bf  |~...9...9.orq...|+00000b60  d7 a2 99 43 6c 56 68 8e  5c 3b 18 b8 a6 7f 3d 12  |...ClVh.\;X..~=R|+00000b70  5f 9d 29 94 5f d5 e2 4c  21 fe a6 70 fa cb 0c 79  |_.)._..L!..p..Ly| 00000b80  5a e1 cb 0c 7c a1 f0 f9  5d f8 4c e1 d3 3a 9c 3a  |Z..L|...].L..:.:| 00000b90  99 2e 4f b5 e2 64 3a 4e  d4 e2 13 85 8f 15 8e 1f  |..O..d:N..S..U._| 00000ba0  4b 91 c7 15 8e a5 e0 68  2d 3e fa 30 45 7e a4 f0  |K..U...h->.0E~..|@@ -560,8 +560,8 @@ 00001470  36 20 30 20 6f 62 6a 0a  -- -- -- -- -- -- -- --  |6 0 objJ--------| Hello.pdf-88- 00001470  -- -- -- -- -- -- -- --  28 4d 61 63 20 4f 53 20  |--------(Mac OS |-00001480  58 20 31 30 2e 31 32 2e  36 20 51 75 61 72 74 7a  |X 10.12.6 Quartz|-00001490  20 50 44 46 43 6f 6e 74  65 78 74 29 0a -- -- --  | PDFContext)J---|+00001480  58 20 31 30 2e 31 32 2e  36 20 51 75 61 72 74 7a  |X 10.12.6 Quartz|+00001490  20 50 44 46 43 6f 6e 74  65 78 74 29 0a -- -- --  | PDFContext)J---| Hello.pdf:89: 00001490  -- -- -- -- -- -- -- --  -- -- -- -- -- 65 6e 64  |-------------end| 000014a0  6f 62 6a 0a -- -- -- --  -- -- -- -- -- -- -- --  |objJ------------|@@ -599,10 +599,10 @@ 00001510  31 20 30 20 6f 62 6a 0a  -- -- -- -- -- -- -- --  |1 0 objJ--------| Hello.pdf-103- 00001510  -- -- -- -- -- -- -- --  3c 3c 20 2f 54 69 74 6c  |--------<< /Titl|-00001520  65 20 31 35 20 30 20 52  20 2f 50 72 6f 64 75 63  |e 15 0 R /Produc|-00001530  65 72 20 31 36 20 30 20  52 20 2f 43 72 65 61 74  |er 16 0 R /Creat|-00001540  6f 72 20 31 37 20 30 20  52 20 2f 43 72 65 61 74  |or 17 0 R /Creat|-00001550  69 6f 6e 44 61 74 65 20  31 38 20 30 20 52 20 2f  |ionDate 18 0 R /|+00001520  65 20 31 35 20 30 20 52  20 2f 50 72 6f 64 75 63  |e 15 0 R /Produc|+00001530  65 72 20 31 36 20 30 20  52 20 2f 43 72 65 61 74  |er 16 0 R /Creat|+00001540  6f 72 20 31 37 20 30 20  52 20 2f 43 72 65 61 74  |or 17 0 R /Creat|+00001550  69 6f 6e 44 61 74 65 20  31 38 20 30 20 52 20 2f  |ionDate 18 0 R /| 00001560  4d 6f 64 44 61 74 65 0a  -- -- -- -- -- -- -- --  |ModDateJ--------| Hello.pdf-104- 00001560  -- -- -- -- -- -- -- --  31 38 20 30 20 52 20 2f  |--------18 0 R /|@@ -630,8 +630,8 @@ 00001750  61 69 6c 65 72 0a -- --  -- -- -- -- -- -- -- --  |ailerJ----------| Hello.pdf-130- 00001750  -- -- -- -- -- -- 3c 3c  20 2f 53 69 7a 65 20 32  |------<< /Size 2|-00001760  31 20 2f 52 6f 6f 74 20  31 31 20 30 20 52 20 2f  |1 /Root 11 0 R /|-00001770  49 6e 66 6f 20 31 20 30  20 52 20 2f 49 44 20 5b  |Info 1 0 R /ID [|+00001760  31 20 2f 52 6f 6f 74 20  31 31 20 30 20 52 20 2f  |1 /Root 11 0 R /|+00001770  49 6e 66 6f 20 31 20 30  20 52 20 2f 49 44 20 5b  |Info 1 0 R /ID [| 00001780  20 3c 38 64 62 38 38 64  33 33 33 35 30 37 30 62  | <8db88d3335070b| 00001790  64 39 35 38 33 33 34 31  35 38 33 63 66 37 36 39  |d9583341583cf769| 000017a0  61 33 3e 0a -- -- -- --  -- -- -- -- -- -- -- --  |a3>J------------|

tests/out/Hello_wsS-X-vC2.out

@@ -51,8 +51,8 @@ 00000010  -- -- -- -- 0a -- -- --  -- -- -- -- -- -- -- --  |----J-----------| Hello.java- 00000010  -- -- -- -- -- 70 75 62  6c 69 63 20 63 6c 61 73  |-----public clas|-00000020  73 20 48 65 6c 6c 6f 20  2f 2f 20 70 72 69 6e 74  |s Hello // print|-00000030  73 20 61 20 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |s a Hello World!|+00000020  73 20 48 65 6c 6c 6f 20  2f 2f 20 70 72 69 6e 74  |s Hello // print|+00000030  73 20 61 20 48 65 6c 6c  6f 20 57 6f 72 6c 64 21  |s a Hello World!| 00000040  20 67 72 65 65 74 69 6e  67 0a -- -- -- -- -- --  | greetingJ------| Hello.java- 00000040  -- -- -- -- -- -- -- --  -- -- 7b 20 70 75 62 6c  |----------{ publ|@@ -76,9 +76,9 @@ 00000010  -- -- -- -- -- -- 34 20  30 20 6f 62 6a 0a -- --  |------4 0 objJ--| Hello.pdf- 00000010  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 3c 3c  |--------------<<|-00000020  20 2f 4c 65 6e 67 74 68  20 35 20 30 20 52 20 2f  | /Length 5 0 R /|-00000030  46 69 6c 74 65 72 20 2f  46 6c 61 74 65 44 65 63  |Filter /FlateDec|-00000040  6f 64 65 20 3e 3e 0a --  -- -- -- -- -- -- -- --  |ode >>J---------|+00000020  20 2f 4c 65 6e 67 74 68  20 35 20 30 20 52 20 2f  | /Length 5 0 R /|+00000030  46 69 6c 74 65 72 20 2f  46 6c 61 74 65 44 65 63  |Filter /FlateDec|+00000040  6f 64 65 20 3e 3e 0a --  -- -- -- -- -- -- -- --  |ode >>J---------| Hello.pdf: 00000040  -- -- -- -- -- -- -- 73  74 72 65 61 6d 0a -- --  |-------streamJ--| Hello.pdf:@@ -112,11 +112,11 @@ 000000f0  30 20 6f 62 6a 0a -- --  -- -- -- -- -- -- -- --  |0 objJ----------| Hello.pdf- 000000f0  -- -- -- -- -- -- 3c 3c  20 2f 54 79 70 65 20 2f  |------<< /Type /|-00000100  50 61 67 65 20 2f 50 61  72 65 6e 74 20 33 20 30  |Page /Parent 3 0|-00000110  20 52 20 2f 52 65 73 6f  75 72 63 65 73 20 36 20  | R /Resources 6 |-00000120  30 20 52 20 2f 43 6f 6e  74 65 6e 74 73 20 34 20  |0 R /Contents 4 |-00000130  30 20 52 20 2f 4d 65 64  69 61 42 6f 78 20 5b 30  |0 R /MediaBox [0|-00000140  20 30 20 36 31 32 20 37  39 32 5d 0a -- -- -- --  | 0 612 792]J----|+00000100  50 61 67 65 20 2f 50 61  72 65 6e 74 20 33 20 30  |Page /Parent 3 0|+00000110  20 52 20 2f 52 65 73 6f  75 72 63 65 73 20 36 20  | R /Resources 6 |+00000120  30 20 52 20 2f 43 6f 6e  74 65 6e 74 73 20 34 20  |0 R /Contents 4 |+00000130  30 20 52 20 2f 4d 65 64  69 61 42 6f 78 20 5b 30  |0 R /MediaBox [0|+00000140  20 30 20 36 31 32 20 37  39 32 5d 0a -- -- -- --  | 0 612 792]J----| Hello.pdf: 00000140  -- -- -- -- -- -- -- --  -- -- -- -- 3e 3e 0a --  |------------>>J-| Hello.pdf:@@ -126,11 +126,11 @@ 00000150  -- -- -- -- -- -- 36 20  30 20 6f 62 6a 0a -- --  |------6 0 objJ--| Hello.pdf- 00000150  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 3c 3c  |--------------<<|-00000160  20 2f 50 72 6f 63 53 65  74 20 5b 20 2f 50 44 46  | /ProcSet [ /PDF|-00000170  20 2f 54 65 78 74 20 5d  20 2f 43 6f 6c 6f 72 53  | /Text ] /ColorS|-00000180  70 61 63 65 20 3c 3c 20  2f 43 73 31 20 37 20 30  |pace << /Cs1 7 0|-00000190  20 52 20 3e 3e 20 2f 46  6f 6e 74 20 3c 3c 20 2f  | R >> /Font << /|-000001a0  54 54 31 20 38 20 30 20  52 0a -- -- -- -- -- --  |TT1 8 0 RJ------|+00000160  20 2f 50 72 6f 63 53 65  74 20 5b 20 2f 50 44 46  | /ProcSet [ /PDF|+00000170  20 2f 54 65 78 74 20 5d  20 2f 43 6f 6c 6f 72 53  | /Text ] /ColorS|+00000180  70 61 63 65 20 3c 3c 20  2f 43 73 31 20 37 20 30  |pace << /Cs1 7 0|+00000190  20 52 20 3e 3e 20 2f 46  6f 6e 74 20 3c 3c 20 2f  | R >> /Font << /|+000001a0  54 54 31 20 38 20 30 20  52 0a -- -- -- -- -- --  |TT1 8 0 RJ------| Hello.pdf: 000001a0  -- -- -- -- -- -- -- --  -- -- 3e 3e 20 3e 3e 0a  |---------->> >>J| Hello.pdf:@@ -139,11 +139,11 @@ 000001b0  -- -- -- -- -- -- -- 39  20 30 20 6f 62 6a 0a --  |-------9 0 objJ-| Hello.pdf- 000001b0  -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- 3c  |---------------<|-000001c0  3c 20 2f 4c 65 6e 67 74  68 20 31 30 20 30 20 52  |< /Length 10 0 R|-000001d0  20 2f 4e 20 31 20 2f 41  6c 74 65 72 6e 61 74 65  | /N 1 /Alternate|-000001e0  20 2f 44 65 76 69 63 65  47 72 61 79 20 2f 46 69  | /DeviceGray /Fi|-000001f0  6c 74 65 72 20 2f 46 6c  61 74 65 44 65 63 6f 64  |lter /FlateDecod|-00000200  65 20 3e 3e 0a -- -- --  -- -- -- -- -- -- -- --  |e >>J-----------|+000001c0  3c 20 2f 4c 65 6e 67 74  68 20 31 30 20 30 20 52  |< /Length 10 0 R|+000001d0  20 2f 4e 20 31 20 2f 41  6c 74 65 72 6e 61 74 65  | /N 1 /Alternate|+000001e0  20 2f 44 65 76 69 63 65  47 72 61 79 20 2f 46 69  | /DeviceGray /Fi|+000001f0  6c 74 65 72 20 2f 46 6c  61 74 65 44 65 63 6f 64  |lter /FlateDecod|+00000200  65 20 3e 3e 0a -- -- --  -- -- -- -- -- -- -- --  |e >>J-----------| Hello.pdf: 00000200  -- -- -- -- -- 73 74 72  65 61 6d 0a -- -- -- --  |-----streamJ----| Hello.pdf-@@ -245,7 +245,7 @@ 00000690  20 30 20 6f 62 6a 0a --  -- -- -- -- -- -- -- --  | 0 objJ---------| Hello.pdf- 00000690  -- -- -- -- -- -- -- 5b  20 2f 49 43 43 42 61 73  |-------[ /ICCBas|-000006a0  65 64 20 39 20 30 20 52  20 5d 0a -- -- -- -- --  |ed 9 0 R ]J-----|+000006a0  65 64 20 39 20 30 20 52  20 5d 0a -- -- -- -- --  |ed 9 0 R ]J-----| Hello.pdf: 000006a0  -- -- -- -- -- -- -- --  -- -- -- 65 6e 64 6f 62  |-----------endob| 000006b0  6a 0a -- -- -- -- -- --  -- -- -- -- -- -- -- --  |jJ--------------|@@ -253,10 +253,10 @@ 000006b0  -- -- 33 20 30 20 6f 62  6a 0a -- -- -- -- -- --  |--3 0 objJ------| Hello.pdf- 000006b0  -- -- -- -- -- -- -- --  -- -- 3c 3c 20 2f 54 79  |----------<< /Ty|-000006c0  70 65 20 2f 50 61 67 65  73 20 2f 4d 65 64 69 61  |pe /Pages /Media|-000006d0  42 6f 78 20 5b 30 20 30  20 36 31 32 20 37 39 32  |Box [0 0 612 792|-000006e0  5d 20 2f 43 6f 75 6e 74  20 31 20 2f 4b 69 64 73  |] /Count 1 /Kids|-000006f0  20 5b 20 32 20 30 20 52  20 5d 20 3e 3e 0a -- --  | [ 2 0 R ] >>J--|+000006c0  70 65 20 2f 50 61 67 65  73 20 2f 4d 65 64 69 61  |pe /Pages /Media|+000006d0  42 6f 78 20 5b 30 20 30  20 36 31 32 20 37 39 32  |Box [0 0 612 792|+000006e0  5d 20 2f 43 6f 75 6e 74  20 31 20 2f 4b 69 64 73  |] /Count 1 /Kids|+000006f0  20 5b 20 32 20 30 20 52  20 5d 20 3e 3e 0a -- --  | [ 2 0 R ] >>J--| Hello.pdf: 000006f0  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 65 6e  |--------------en| 00000700  64 6f 62 6a 0a -- -- --  -- -- -- -- -- -- -- --  |dobjJ-----------|@@ -265,17 +265,17 @@ Hello.pdf- 00000700  -- -- -- -- -- -- -- --  -- -- -- -- -- -- 3c 3c  |--------------<<| 00000710  20 2f 54 79 70 65 20 2f  43 61 74 61 6c 6f 67 20  | /Type /Catalog |-00000720  2f 50 61 67 65 73 20 33  20 30 20 52 20 3e 3e 0a  |/Pages 3 0 R >>J|+00000720  2f 50 61 67 65 73 20 33  20 30 20 52 20 3e 3e 0a  |/Pages 3 0 R >>J| Hello.pdf: 00000730  65 6e 64 6f 62 6a 0a --  -- -- -- -- -- -- -- --  |endobjJ---------| Hello.pdf- 00000730  -- -- -- -- -- -- -- 38  20 30 20 6f 62 6a 0a --  |-------8 0 objJ-| Hello.pdf- 00000730  -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- 3c  |---------------<|-00000740  3c 20 2f 54 79 70 65 20  2f 46 6f 6e 74 20 2f 53  |< /Type /Font /S|-00000750  75 62 74 79 70 65 20 2f  54 72 75 65 54 79 70 65  |ubtype /TrueType|-00000760  20 2f 42 61 73 65 46 6f  6e 74 20 2f 47 51 54 4d  | /BaseFont /GQTM|-00000770  5a 46 2b 4d 65 6e 6c 6f  2d 52 65 67 75 6c 61 72  |ZF+Menlo-Regular|+00000740  3c 20 2f 54 79 70 65 20  2f 46 6f 6e 74 20 2f 53  |< /Type /Font /S|+00000750  75 62 74 79 70 65 20 2f  54 72 75 65 54 79 70 65  |ubtype /TrueType|+00000760  20 2f 42 61 73 65 46 6f  6e 74 20 2f 47 51 54 4d  | /BaseFont /GQTM|+00000770  5a 46 2b 4d 65 6e 6c 6f  2d 52 65 67 75 6c 61 72  |ZF+Menlo-Regular| 00000780  20 2f 46 6f 6e 74 44 65  73 63 72 69 70 74 6f 72  | /FontDescriptor| 00000790  0a -- -- -- -- -- -- --  -- -- -- -- -- -- -- --  |J---------------| --@@ -297,9 +297,9 @@ Hello.pdf- 00000840  -- -- -- -- -- -- -- 3c  3c 20 2f 54 79 70 65 20  |-------<< /Type | 00000850  2f 46 6f 6e 74 44 65 73  63 72 69 70 74 6f 72 20  |/FontDescriptor |-00000860  2f 46 6f 6e 74 4e 61 6d  65 20 2f 47 51 54 4d 5a  |/FontName /GQTMZ|-00000870  46 2b 4d 65 6e 6c 6f 2d  52 65 67 75 6c 61 72 20  |F+Menlo-Regular |-00000880  2f 46 6c 61 67 73 20 33  33 20 2f 46 6f 6e 74 42  |/Flags 33 /FontB|+00000860  2f 46 6f 6e 74 4e 61 6d  65 20 2f 47 51 54 4d 5a  |/FontName /GQTMZ|+00000870  46 2b 4d 65 6e 6c 6f 2d  52 65 67 75 6c 61 72 20  |F+Menlo-Regular |+00000880  2f 46 6c 61 67 73 20 33  33 20 2f 46 6f 6e 74 42  |/Flags 33 /FontB| 00000890  42 6f 78 0a -- -- -- --  -- -- -- -- -- -- -- --  |BoxJ------------| Hello.pdf- 00000890  -- -- -- -- 5b 2d 35 35  38 20 2d 33 37 35 20 37  |----[-558 -375 7|@@ -323,9 +323,9 @@ 00000940  62 6a 0a -- -- -- -- --  -- -- -- -- -- -- -- --  |bjJ-------------| Hello.pdf- 00000940  -- -- -- 3c 3c 20 2f 4c  65 6e 67 74 68 20 31 34  |---<< /Length 14|-00000950  20 30 20 52 20 2f 4c 65  6e 67 74 68 31 20 34 30  | 0 R /Length1 40|-00000960  36 34 20 2f 46 69 6c 74  65 72 20 2f 46 6c 61 74  |64 /Filter /Flat|-00000970  65 44 65 63 6f 64 65 20  3e 3e 0a -- -- -- -- --  |eDecode >>J-----|+00000950  20 30 20 52 20 2f 4c 65  6e 67 74 68 31 20 34 30  | 0 R /Length1 40|+00000960  36 34 20 2f 46 69 6c 74  65 72 20 2f 46 6c 61 74  |64 /Filter /Flat|+00000970  65 44 65 63 6f 64 65 20  3e 3e 0a -- -- -- -- --  |eDecode >>J-----| Hello.pdf: 00000970  -- -- -- -- -- -- -- --  -- -- -- 73 74 72 65 61  |-----------strea| 00000980  6d 0a -- -- -- -- -- --  -- -- -- -- -- -- -- --  |mJ--------------|@@ -359,11 +359,11 @@ 00000b00  a6 09 94 cb 34 de b4 17  67 6a c5 92 8d 91 18 93  |.I..4..Wgj....X.| 00000b10  b7 98 3a d2 e4 75 13 87  89 68 26 22 02 21 05 a5  |..:..uS..h&"B!E.| 00000b20  70 b5 02 57 14 2e 2b b4  e6 e2 9f 75 f8 ae 02 97  |p.BWT.+....u..B.|-00000b30  5a aa e5 25 85 4b 0d 7a  cb c5 90 6c a9 46 4b a5  |Z..%.KMz...l.FK.|-00000b40  7e f1 42 17 79 31 84 8b  01 fd 42 17 7c 7b 3e 47  |~.BWy1..A.BW|{>G|-00000b50  7e db 8a f3 39 f8 87 c2  39 85 6f 72 71 d6 85 bf  |~...9...9.orq...|-00000b60  d7 a2 99 43 6c 56 68 8e  5c 3b 18 b8 a6 7f 3d 12  |...ClVh.\;X..~=R|-00000b70  5f 9d 29 94 5f d5 e2 4c  21 fe a6 70 fa cb 0c 79  |_.)._..L!..p..Ly|+00000b30  5a aa e5 25 85 4b 0d 7a  cb c5 90 6c a9 46 4b a5  |Z..%.KMz...l.FK.|+00000b40  7e f1 42 17 79 31 84 8b  01 fd 42 17 7c 7b 3e 47  |~.BWy1..A.BW|{>G|+00000b50  7e db 8a f3 39 f8 87 c2  39 85 6f 72 71 d6 85 bf  |~...9...9.orq...|+00000b60  d7 a2 99 43 6c 56 68 8e  5c 3b 18 b8 a6 7f 3d 12  |...ClVh.\;X..~=R|+00000b70  5f 9d 29 94 5f d5 e2 4c  21 fe a6 70 fa cb 0c 79  |_.)._..L!..p..Ly| 00000b80  5a e1 cb 0c 7c a1 f0 f9  5d f8 4c e1 d3 3a 9c 3a  |Z..L|...].L..:.:| 00000b90  99 2e 4f b5 e2 64 3a 4e  d4 e2 13 85 8f 15 8e 1f  |..O..d:N..S..U._| 00000ba0  4b 91 c7 15 8e a5 e0 68  2d 3e fa 30 45 7e a4 f0  |K..U...h->.0E~..|@@ -560,8 +560,8 @@ 00001470  36 20 30 20 6f 62 6a 0a  -- -- -- -- -- -- -- --  |6 0 objJ--------| Hello.pdf- 00001470  -- -- -- -- -- -- -- --  28 4d 61 63 20 4f 53 20  |--------(Mac OS |-00001480  58 20 31 30 2e 31 32 2e  36 20 51 75 61 72 74 7a  |X 10.12.6 Quartz|-00001490  20 50 44 46 43 6f 6e 74  65 78 74 29 0a -- -- --  | PDFContext)J---|+00001480  58 20 31 30 2e 31 32 2e  36 20 51 75 61 72 74 7a  |X 10.12.6 Quartz|+00001490  20 50 44 46 43 6f 6e 74  65 78 74 29 0a -- -- --  | PDFContext)J---| Hello.pdf: 00001490  -- -- -- -- -- -- -- --  -- -- -- -- -- 65 6e 64  |-------------end| 000014a0  6f 62 6a 0a -- -- -- --  -- -- -- -- -- -- -- --  |objJ------------|@@ -599,10 +599,10 @@ 00001510  31 20 30 20 6f 62 6a 0a  -- -- -- -- -- -- -- --  |1 0 objJ--------| Hello.pdf- 00001510  -- -- -- -- -- -- -- --  3c 3c 20 2f 54 69 74 6c  |--------<< /Titl|-00001520  65 20 31 35 20 30 20 52  20 2f 50 72 6f 64 75 63  |e 15 0 R /Produc|-00001530  65 72 20 31 36 20 30 20  52 20 2f 43 72 65 61 74  |er 16 0 R /Creat|-00001540  6f 72 20 31 37 20 30 20  52 20 2f 43 72 65 61 74  |or 17 0 R /Creat|-00001550  69 6f 6e 44 61 74 65 20  31 38 20 30 20 52 20 2f  |ionDate 18 0 R /|+00001520  65 20 31 35 20 30 20 52  20 2f 50 72 6f 64 75 63  |e 15 0 R /Produc|+00001530  65 72 20 31 36 20 30 20  52 20 2f 43 72 65 61 74  |er 16 0 R /Creat|+00001540  6f 72 20 31 37 20 30 20  52 20 2f 43 72 65 61 74  |or 17 0 R /Creat|+00001550  69 6f 6e 44 61 74 65 20  31 38 20 30 20 52 20 2f  |ionDate 18 0 R /| 00001560  4d 6f 64 44 61 74 65 0a  -- -- -- -- -- -- -- --  |ModDateJ--------| Hello.pdf- 00001560  -- -- -- -- -- -- -- --  31 38 20 30 20 52 20 2f  |--------18 0 R /|@@ -630,8 +630,8 @@ 00001750  61 69 6c 65 72 0a -- --  -- -- -- -- -- -- -- --  |ailerJ----------| Hello.pdf- 00001750  -- -- -- -- -- -- 3c 3c  20 2f 53 69 7a 65 20 32  |------<< /Size 2|-00001760  31 20 2f 52 6f 6f 74 20  31 31 20 30 20 52 20 2f  |1 /Root 11 0 R /|-00001770  49 6e 66 6f 20 31 20 30  20 52 20 2f 49 44 20 5b  |Info 1 0 R /ID [|+00001760  31 20 2f 52 6f 6f 74 20  31 31 20 30 20 52 20 2f  |1 /Root 11 0 R /|+00001770  49 6e 66 6f 20 31 20 30  20 52 20 2f 49 44 20 5b  |Info 1 0 R /ID [| 00001780  20 3c 38 64 62 38 38 64  33 33 33 35 30 37 30 62  | <8db88d3335070b| 00001790  64 39 35 38 33 33 34 31  35 38 33 63 66 37 36 39  |d9583341583cf769| 000017a0  61 33 3e 0a -- -- -- --  -- -- -- -- -- -- -- --  |a3>J------------|

tests/out/Hello_wsS-nvC2.out

@@ -3,7 +3,7 @@ Binary file Hello.class matches Hello.java-1-import java.lang.*; Hello.java:2:-Hello.java-3-public class Hello // prints a Hello World! greeting+Hello.java-3-public class Hello // prints a Hello World! greeting Hello.java-4-{ public static void main(String[] arg) Hello.java-5-  { System.out.println("Hello World!"); Hello.java:6:  }

tests/out/Hello_wsS-vC2.out

@@ -3,7 +3,7 @@ Binary file Hello.class matches Hello.java-import java.lang.*; Hello.java:-Hello.java-public class Hello // prints a Hello World! greeting+Hello.java-public class Hello // prints a Hello World! greeting Hello.java-{ public static void main(String[] arg) Hello.java-  { System.out.println("Hello World!"); Hello.java:  }