extern char *optarg; /* set by getopt */
extern int optind; /* set by getopt */
- int status, file_only, compile_only, argcount;
+ int status, file_only, compile_only, argcount, mergecount;
struct scf_t *scf;
char *dir, *outfile;
sort_hashes(sort_buffer, sort_count);
report_time("Sort done");
- emit_report1(sort_buffer, sort_count);
+ mergecount = merge_compare(sort_buffer, sort_count);
+ printf("Matches: %d\n", mergecount);
puts("%%");
for (scf = scflist; scf->next; scf = scf->next)
scf->totallines);
puts("%%");
- emit_report2();
+ emit_report();
exit(0);
}
static struct match_t *hitlist;
static int mergecount;
-void emit_report1(struct sorthash_t *obarray, int hashcount)
+int merge_compare(struct sorthash_t *obarray, int hashcount)
/* report our results (header portion) */
{
struct match_t *match, *copy;
if (debug)
dump_array("After removing uniques.\n", obarray, hashcount);
report_time("%d range groups after removing unique hashes", matchcount);
- mergecount = collapse_ranges(hitlist, matchcount);
- if (debug)
- dump_array("After merging ranges.\n", obarray, hashcount);
- report_time("%d range groups after merging", mergecount);
+ mergecount = collapse_ranges(hitlist, matchcount);
/*
- * A little extra effort so we can generate a sorted report.
- * Compact the match list in order to cut the n log n qsort time
+ * Here's where we do significance filtering. As a side effect,
+ * compact the match list in order to cut the n log n qsort time
*/
for (copy = match = hitlist; match < hitlist + matchcount; match++)
if (match->nmatches > 0 && copy < match)
- *copy++ = *match;
+ {
+ int i, flags = 0, maxsize = 0;
+
+ for (i=0; i < match->nmatches; i++)
+ {
+ struct sorthash_t *rp = match->matches+i;
+ int matchsize = rp->hash.end - rp->hash.start + 1;
+
+ if (matchsize >= maxsize)
+ maxsize = matchsize;
+
+ /*
+ * This odd-looking bit of logic, deals with an
+ * annoying edge case. Sometimes we'll get boilerplate C
+ * stuff in both a C and a text file. To cope, propagate
+ * insignificance -- if we know from one context that a
+ * particular span of text is not interesting, declare it
+ * uninteresting everywhere.
+ */
+ flags |= rp->hash.flags;
+ }
+
+ /*
+ * Filter for sigificance right at the last minute. The
+ * point of doing it this way is to allow significance bits to
+ * propagate through range merges.
+ */
+ if (maxsize >= minsize && (nofilter || !(flags & INSIGNIFICANT)))
+ *copy++ = *match;
+ }
+
mergecount = (copy - hitlist);
- printf("Matches: %d\n", mergecount);
+ /* sort everything so the report looks neat */
+ qsort(hitlist, mergecount, sizeof(struct match_t), sortmatch);
+
+ if (debug)
+ dump_array("After merging ranges.\n", obarray, hashcount);
+ report_time("%d range groups after merging", mergecount);
+
+ return(mergecount);
}
-void emit_report2(void)
+void emit_report(void)
/* report our results (matches) */
{
struct match_t *match;
- qsort(hitlist, mergecount, sizeof(struct match_t), sortmatch);
-
for (match = hitlist; match < hitlist + mergecount; match++)
{
- int i, flags = 0, maxsize = 0;
-
- for (i=0; i < match->nmatches; i++)
- {
- struct sorthash_t *rp = match->matches+i;
- int matchsize = rp->hash.end - rp->hash.start + 1;
-
- if (matchsize >= maxsize)
- maxsize = matchsize;
-
- /*
- * This odd-looking bit of logic, deals with an
- * annoying edge case. Sometimes we'll get boilerplate C
- * stuff in both a C and a text file. To cope, propagate
- * insignificance -- if we know from one context that a
- * particular span of text is not interesting, declare it
- * uninteresting everywhere.
- */
- flags |= rp->hash.flags;
- }
-
- /*
- * Filter for sigificance right at the last minute. The
- * point of doing it this way is to allow significance bits to
- * propagate through range merges.
- */
- if (maxsize < minsize || (!nofilter && (flags & INSIGNIFICANT)))
- continue;
+ int i;
for (i=0; i < match->nmatches; i++)
{