Module Name:    othersrc
Committed By:   dyoung
Date:           Sat Aug 22 05:08:48 UTC 2015

Modified Files:
        othersrc/external/bsd/arfe: README
        othersrc/external/bsd/arfe/dt: Makefile README dt.c testit
        othersrc/external/bsd/arfe/dt/rr: ifconfig.0-ifconfig.1
            ifconfig.0-logger-ifconfig.0 ifconfig.1-ifconfig.0
            logger-ifconfig.0-ifconfig.0 wm0-a-wm0-b wm0-b-wm0-a

Log Message:
Locate in both inputs hexadecimal numbers starting 0x and make them
"wild" in the alignments dt computes.  In dt, bitwise-AND the 0x-hex
numbers.  In it, bitwise-OR them.  Take care not to match a hexadecimal
with a decimal or vice versa!

TBD: identify hexadecimals that don't start 0x.

Remove a little dead code.

Split HB_DEBUG into HB_DEBUG and HB_ASSERT.  The latter just enables the
assertions.

Update old test results for the new treatment of 0x-hexadecimal.  Add
some new tests.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 othersrc/external/bsd/arfe/README
cvs rdiff -u -r1.1 -r1.2 othersrc/external/bsd/arfe/dt/Makefile \
    othersrc/external/bsd/arfe/dt/README othersrc/external/bsd/arfe/dt/testit
cvs rdiff -u -r1.2 -r1.3 othersrc/external/bsd/arfe/dt/dt.c
cvs rdiff -u -r1.1 -r1.2 \
    othersrc/external/bsd/arfe/dt/rr/ifconfig.0-ifconfig.1 \
    othersrc/external/bsd/arfe/dt/rr/ifconfig.0-logger-ifconfig.0 \
    othersrc/external/bsd/arfe/dt/rr/ifconfig.1-ifconfig.0 \
    othersrc/external/bsd/arfe/dt/rr/logger-ifconfig.0-ifconfig.0 \
    othersrc/external/bsd/arfe/dt/rr/wm0-a-wm0-b \
    othersrc/external/bsd/arfe/dt/rr/wm0-b-wm0-a

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: othersrc/external/bsd/arfe/README
diff -u othersrc/external/bsd/arfe/README:1.1 othersrc/external/bsd/arfe/README:1.2
--- othersrc/external/bsd/arfe/README:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/README	Sat Aug 22 05:08:48 2015
@@ -1,3 +1,5 @@
+$ARFE: README 216 2015-08-22 05:04:28Z dyoung $
+
 ARFE is a suite of tools for processing record- and field-oriented
 digital texts.  ARFE strives to make a useful set of automatic
 text-processing functions available at a level of abstraction that both

Index: othersrc/external/bsd/arfe/dt/Makefile
diff -u othersrc/external/bsd/arfe/dt/Makefile:1.1 othersrc/external/bsd/arfe/dt/Makefile:1.2
--- othersrc/external/bsd/arfe/dt/Makefile:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/Makefile	Sat Aug 22 05:08:48 2015
@@ -1,9 +1,11 @@
+# $ARFE: Makefile 216 2015-08-22 05:04:28Z dyoung $
 NOMAN=
 .include <bsd.own.mk>
 
 PROG=dt
 SRCS+=dt.c
 #CPPFLAGS+=-DHB_DEBUG
+CPPFLAGS+=-DHB_ASSERT
 DBG+=-g -O3
 #DBG+=-g -O0
 #COPTS+=-pg
Index: othersrc/external/bsd/arfe/dt/README
diff -u othersrc/external/bsd/arfe/dt/README:1.1 othersrc/external/bsd/arfe/dt/README:1.2
--- othersrc/external/bsd/arfe/dt/README:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/README	Sat Aug 22 05:08:48 2015
@@ -1,3 +1,5 @@
+$ARFE: README 216 2015-08-22 05:04:28Z dyoung $
+
 DT---(d)ifferentiate (t)ext---finds a longest common subsequence (LCS)
 of two texts where decimal numbers are "wild": a span of decimal digits
 in the first text will match a digits span in the second text.  Then it
Index: othersrc/external/bsd/arfe/dt/testit
diff -u othersrc/external/bsd/arfe/dt/testit:1.1 othersrc/external/bsd/arfe/dt/testit:1.2
--- othersrc/external/bsd/arfe/dt/testit:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/testit	Sat Aug 22 05:08:48 2015
@@ -1,4 +1,5 @@
 #!/bin/sh
+# $ARFE: testit 216 2015-08-22 05:04:28Z dyoung $
 
 results=rr
 
@@ -34,4 +35,6 @@ quackabequack quackdariaquack
 quackdariaquack quackabequack 
 wm0-a wm0-b
 wm0-b wm0-a
+if-re0 if-wm0
+if-wm0 if-re0
 EOF

Index: othersrc/external/bsd/arfe/dt/dt.c
diff -u othersrc/external/bsd/arfe/dt/dt.c:1.2 othersrc/external/bsd/arfe/dt/dt.c:1.3
--- othersrc/external/bsd/arfe/dt/dt.c:1.2	Tue Aug 11 21:04:59 2015
+++ othersrc/external/bsd/arfe/dt/dt.c	Sat Aug 22 05:08:48 2015
@@ -1,5 +1,5 @@
-/* $NetBSD: dt.c,v 1.2 2015/08/11 21:04:59 dyoung Exp $ */
-/* $Id: dt.c,v 1.2 2015/08/11 21:04:59 dyoung Exp $ */
+/* $NetBSD: dt.c,v 1.3 2015/08/22 05:08:48 dyoung Exp $ */
+/* $ARFE: dt.c 215 2015-08-22 05:02:46Z dyoung $ */
 
 /*-
  * Copyright (c) 2014,2015 David Young <[email protected]>
@@ -32,6 +32,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <assert.h>
+#include <ctype.h>	/* for ispunct(), isspace(), isxdigit() */
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -44,7 +45,7 @@
 #include <limits.h>
 #include <string.h>
 
-#if defined(HB_DEBUG)
+#if defined(HB_ASSERT)
 #define	dbg_assert	assert
 #else
 #define dbg_assert(__x)	do { } while (false) /* do nothing */
@@ -55,6 +56,90 @@ typedef struct origin {
 	int j;
 } origin_t;
 
+typedef enum hex_op {
+	  HEX_OP_NONE = 0
+	, HEX_OP_PUSH
+	, HEX_OP_EMIT
+	, HEX_OP_START
+} hex_op_t;
+
+struct hex_state;
+typedef struct hex_state hex_state_t;
+
+typedef struct hex_transition {
+	const hex_state_t	*t_newstate;
+	hex_op_t		t_op;
+} hex_transition_t;
+
+struct hex_state {
+	const char *s_descr;
+	hex_transition_t s_other;
+	hex_transition_t s_hexdigit;
+	hex_transition_t s_0;
+	hex_transition_t s_x;
+	hex_transition_t s_delimiter;
+	hex_transition_t s_eof;
+};
+
+enum hex_state_idxs {
+	  READ_0
+	, READ_X
+	, READ_HEXDIGIT
+	, READ_EOF
+	, READ_OTHER
+	, READ_DELIMITER
+};
+
+#define	read_0 hex_states[READ_0]
+#define	read_x hex_states[READ_X]
+#define	read_hexdigit hex_states[READ_HEXDIGIT]
+#define	read_eof hex_states[READ_EOF]
+#define	read_other hex_states[READ_OTHER]
+#define	read_delimiter hex_states[READ_DELIMITER]
+
+static const hex_state_t hex_states[] = {[READ_0] = {
+	.s_descr = "read 0",
+	.s_other = {&read_other, HEX_OP_NONE},
+	.s_x = {&read_x, HEX_OP_NONE},
+}, [READ_X] = {
+	.s_descr = "read x",
+	.s_other = {&read_other, HEX_OP_NONE},
+	.s_hexdigit = {&read_hexdigit, HEX_OP_PUSH},
+}, [READ_HEXDIGIT] = {
+	.s_descr = "read hexdigit",
+	.s_other = {&read_other, HEX_OP_NONE},
+	.s_delimiter = {&read_delimiter, HEX_OP_EMIT},
+	.s_eof = {&read_eof, HEX_OP_EMIT},
+	.s_hexdigit = {&read_hexdigit, HEX_OP_PUSH},
+}, [READ_EOF] = {
+	.s_descr = "read eof",
+	.s_other = {&read_eof, HEX_OP_NONE},
+}, [READ_OTHER] = {
+	.s_descr = "read other",
+	.s_other = {&read_other, HEX_OP_NONE},
+	.s_delimiter = {&read_delimiter, HEX_OP_NONE},
+}, [READ_DELIMITER] = {
+	.s_descr = "read delimiter",
+	.s_0 = {&read_0, HEX_OP_START},
+	.s_other = {&read_other, HEX_OP_NONE},
+}};
+
+struct hex_parser;
+typedef struct hex_parser hex_parser_t;
+
+typedef void (*hex_emitter_t)(hex_parser_t *, void *);
+
+struct hex_parser {
+	struct {
+		int start, stop;
+	} p_column, p_idx;
+	char p_digits[16 + 1];	/* XXX how many hex digits in an intmax_t? */
+	char *p_top;
+	const hex_state_t *p_state;
+	hex_emitter_t p_emitter;
+	void *p_arg;
+};
+
 typedef struct chainelt {
 	TAILQ_ENTRY(chainelt) ce_link;
 	int ce_column;	/*  0: no column alignment,
@@ -74,17 +159,21 @@ typedef struct slice {
 	bool backward;
 } slice_t;
 
+typedef enum {
+	  KIND_NONE = 0
+	, KIND_INTMAX_DEC
+	, KIND_INTMAX_HEX
+	, KIND_STRING
+} clocc_kind_t;
+
 typedef struct clocc {
 	int column;
 	int first;
 	int last;
-	enum {
-		  KIND_NONE = 0
-		, KIND_INTMAX
-		, KIND_STRING
-	} kind;
+	clocc_kind_t kind;
 	union {
 		intmax_t u_intmax;
+		uintmax_t u_uintmax;
 	} val_u;
 } clocc_t;
 
@@ -101,7 +190,8 @@ typedef struct scratch {
 	cloccs_t Aoccs, Boccs;
 	slice_t *Abasis, *Bbasis;
 	size_t expected_lcs;
-	char op;
+	char dec_op;
+	char hex_op;
 } scratch_t;
 
 union freeslice;
@@ -124,8 +214,6 @@ static bool freeslices_initialized __ali
 static freeslice_t *first_freeslice __aligned(COHERENCY_UNIT);
 static freeslice_t freeslices[2048];
 
-static int mainloop __aligned(COHERENCY_UNIT) = 0;
-
 static int dbg_printf(const char *, ...) __printflike(1, 2);
 static int dbg2_printf(const char *, ...) __printflike(1, 2);
 
@@ -166,6 +254,99 @@ dbg2_printf(const char *fmt, ...)
 #endif
 
 static void
+hex_parser_init(hex_parser_t *p, hex_emitter_t emitter, void *arg)
+{
+	memset(p, 0, sizeof(*p));
+	p->p_state = &read_delimiter;
+	p->p_emitter = emitter;
+	p->p_arg = arg;
+}
+
+static const char *
+hex_op_string(hex_op_t op)
+{
+	switch (op) {
+	case HEX_OP_NONE:
+		return "none";
+	case HEX_OP_EMIT:
+		return "emit";
+	case HEX_OP_PUSH:
+		return "push";
+	case HEX_OP_START:
+		return "start";
+	default:
+		return "unknown";
+	}
+}
+
+static void
+hex_parser_drive(hex_parser_t *p, int idx, int column, int c)
+{
+	const hex_transition_t *t;
+	const hex_state_t *ns, *s;
+
+	s = p->p_state;
+
+	if (c == -1 && (ns = s->s_eof.t_newstate) != NULL)
+		t = &s->s_eof;
+	else if (c == '0' && (ns = s->s_0.t_newstate) != NULL)
+		t = &s->s_0;
+	else if (c == 'x' && (ns = s->s_x.t_newstate) != NULL)
+		t = &s->s_x;
+	else if ((isspace(c) || ispunct(c)) &&
+	         (ns = s->s_delimiter.t_newstate) != NULL)
+		t = &s->s_delimiter;
+	else if (isxdigit(c) && (ns = s->s_hexdigit.t_newstate) != NULL)
+		t = &s->s_hexdigit;
+	else if ((ns = s->s_other.t_newstate) != NULL)
+		t = &s->s_other;
+	else
+		ns = NULL;
+
+	assert(ns != NULL);
+	if (c == -1) {
+		dbg_printf("%s: transition (%s, eof) -> %s (op %s)\n", __func__,
+		    s->s_descr, ns->s_descr, hex_op_string(t->t_op));
+	} else {
+		dbg_printf("%s: transition (%s, %c) -> %s (op %s)\n", __func__,
+		    s->s_descr, c, ns->s_descr, hex_op_string(t->t_op));
+	}
+
+	switch (t->t_op) {
+	case HEX_OP_PUSH:
+		if (p->p_top == NULL)
+			;
+		else if (p->p_top - &p->p_digits[0] ==
+		         __arraycount(p->p_digits) - 1)
+			p->p_top = NULL;
+		else {
+			*p->p_top = c;
+			p->p_top++;
+		}
+		p->p_idx.stop = idx;
+		p->p_column.stop = column;
+		break;
+	case HEX_OP_START:
+		p->p_column.start = column;
+		p->p_column.stop = column + 1;
+		p->p_idx.start = idx;
+		p->p_idx.stop = idx + 1;
+		p->p_top = &p->p_digits[0];
+		break;
+	case HEX_OP_EMIT:
+		if (p->p_top == NULL)
+			dbg_printf("hex string too long\n");
+		*p->p_top = '\0';
+		(*p->p_emitter)(p, p->p_arg);
+		break;
+	case HEX_OP_NONE:
+		break;
+	}
+
+	p->p_state = ns;
+}
+
+static void
 init_freeslices(void)
 {
 	unsigned int i;
@@ -323,7 +504,7 @@ subslice(const slice_t *s, unsigned int 
 }
 
 static bool
-clocc_starts_at(const cloccs_t *o, int first, size_t *wlenp)
+clocc_starts_at(const cloccs_t *o, int first, size_t *wlenp, clocc_kind_t *kindp)
 {
 	const clocc_t *occ;
 	int l, m, r;
@@ -344,13 +525,15 @@ clocc_starts_at(const cloccs_t *o, int f
 	return false;
 
 found:
+	if (kindp != NULL)
+		*kindp = occ->kind;
 	if (wlenp != NULL)
 		*wlenp = occ->last - occ->first + 1;
 	return true;
 }
 
 static bool
-clocc_ends_at(const cloccs_t *o, int last, size_t *wlenp)
+clocc_ends_at(const cloccs_t *o, int last, size_t *wlenp, clocc_kind_t *kindp)
 {
 	const clocc_t *occ;
 	int l, m, r;
@@ -371,6 +554,8 @@ clocc_ends_at(const cloccs_t *o, int las
 	return false;
 
 found:
+	if (kindp != NULL)
+		*kindp = occ->kind;
 	if (wlenp != NULL)
 		*wlenp = occ->last - occ->first + 1;
 	return true;
@@ -390,18 +575,18 @@ clocc_starts_in_slice_at(const cloccs_t 
 {
 	const int iprime = index_versus_basis(basis, s, i);
 
-	return (s->backward) ? clocc_ends_at(o, iprime, NULL)
-	                     : clocc_starts_at(o, iprime, NULL);
+	return (s->backward) ? clocc_ends_at(o, iprime, NULL, NULL)
+	                     : clocc_starts_at(o, iprime, NULL, NULL);
 }
 
 static bool
 clocc_ends_in_slice_at(const cloccs_t *o, const slice_t *basis,
-    const slice_t *s, int i, size_t *wlenp)
+    const slice_t *s, int i, size_t *wlenp, size_t *kindp)
 {
 	const int iprime = index_versus_basis(basis, s, i);
 
-	return (s->backward) ? clocc_starts_at(o, iprime, wlenp)
-	                     : clocc_ends_at(o, iprime, wlenp);
+	return (s->backward) ? clocc_starts_at(o, iprime, wlenp, kindp)
+	                     : clocc_ends_at(o, iprime, wlenp, kindp);
 }
 
 static chain_t *
@@ -424,34 +609,66 @@ newchain(char *content, int column)
 	return c;
 }
 
+/* Return 0 if the `a' and `b' are not left- or right-aligned on
+ * the same column, the column they right-align on, or zero minus
+ * the column they left-align on.
+ */
+static int
+cloccs_to_column(const clocc_t * const a, const clocc_t * const b)
+{
+	if (a->column + a->last - a->first ==
+	    b->column + b->last - b->first)
+		return b->column + b->last - b->first;
+	else if (a->column == b->column)
+		return -a->column;
+	else
+		return 0;
+}
+
 static chain_t *
-clocc(const scratch_t *scratch, int idx_a, int idx_b)
+hex_clocc(const scratch_t *scratch, int idx_a, int idx_b)
 {
 	char *ret;
 	int column;
-	intmax_t result;
+	uintmax_t result;
 	const clocc_t * const a = &scratch->Aoccs.occs[idx_a],
 	              * const b = &scratch->Boccs.occs[idx_b];
 
-	if (a->kind != b->kind)
-		return newchain(strdup("<clocc>"), 0);
+	column = cloccs_to_column(a, b);
 
-	if (b->kind != KIND_INTMAX)
-		return newchain(strdup("<word>"), 0);
+	dbg2_printf("%#jx @ %d / %#jx @ %d -> column %d\n",
+	    a->val_u.u_uintmax, a->column,
+	    b->val_u.u_uintmax, b->column, column);
 
-	if (a->column + a->last - a->first ==
-	    b->column + b->last - b->first)
-		column = b->column + b->last - b->first;
-	else if (a->column == b->column)
-		column = -a->column;
+	if (scratch->hex_op == '&')
+		result = b->val_u.u_uintmax & a->val_u.u_uintmax;
 	else
-		column = 0;
+		result = b->val_u.u_uintmax | a->val_u.u_uintmax;
+
+	if (result == 0)
+		return newchain(strdup("0x0"), column);
+	if (asprintf(&ret, "%#jx", result) != -1)
+		return newchain(ret, column);
+
+	return newchain(strdup("<hexmax>"), column);
+}
+
+static chain_t *
+int_clocc(const scratch_t *scratch, int idx_a, int idx_b)
+{
+	char *ret;
+	int column;
+	intmax_t result;
+	const clocc_t * const a = &scratch->Aoccs.occs[idx_a],
+	              * const b = &scratch->Boccs.occs[idx_b];
+
+	column = cloccs_to_column(a, b);
 
 	dbg2_printf("%jd @ %d / %jd @ %d -> column %d\n",
 	    a->val_u.u_intmax, a->column,
 	    b->val_u.u_intmax, b->column, column);
 
-	if (scratch->op == '-')
+	if (scratch->dec_op == '-')
 		result = b->val_u.u_intmax - a->val_u.u_intmax;
 	else
 		result = b->val_u.u_intmax + a->val_u.u_intmax;
@@ -463,6 +680,24 @@ clocc(const scratch_t *scratch, int idx_
 }
 
 static chain_t *
+clocc(const scratch_t *scratch, int idx_a, int idx_b)
+{
+	const clocc_t * const a = &scratch->Aoccs.occs[idx_a],
+	              * const b = &scratch->Boccs.occs[idx_b];
+
+	if (a->kind != b->kind)
+		return newchain(strdup("<clocc>"), 0);
+
+	if (b->kind == KIND_INTMAX_HEX)
+		return hex_clocc(scratch, idx_a, idx_b);
+
+	if (b->kind == KIND_INTMAX_DEC)
+		return int_clocc(scratch, idx_a, idx_b);
+
+	return newchain(strdup("<word>"), 0);
+}
+
+static chain_t *
 empty(void)
 {
 	return newchain(strdup(""), 0);
@@ -477,6 +712,9 @@ algb(const slice_t *A, const slice_t *B,
 	unsigned int i, j;
 	size_t *K[2], *Kclocc, *Kcur, *Kprev, *Ktmp;
 	struct {
+		clocc_kind_t A, B;
+	} kind;
+	struct {
 		size_t A, B;
 	} wlen;
 	bool inside_clocc = false;
@@ -510,7 +748,7 @@ algb(const slice_t *A, const slice_t *B,
 
 		const bool clocc_ends_this_row = inside_clocc &&
 		    clocc_ends_in_slice_at(&scratch->Aoccs, scratch->Abasis,
-		        A, i, &wlen.A);
+		        A, i, &wlen.A, &kind.A);
 
 		for (j = 0; j < n; j++) {
 
@@ -522,7 +760,7 @@ algb(const slice_t *A, const slice_t *B,
 			if (clocc_ends_this_row &&
 			    clocc_ends_in_slice_at(&scratch->Boccs,
 			                          scratch->Bbasis, B, j,
-						  &wlen.B)) {
+						  &wlen.B, &kind.B) && kind.A == kind.B) {
 				const size_t step = wlen.A * wlen.B + 1,
 				             nscore = Kclocc[j - wlen.B] + step;
 				assert(wlen.B <= j + 1);
@@ -633,7 +871,7 @@ split_interval(cloccs_t *o, int origin, 
  */
 static int
 widest_clocc_in_interval(cloccs_t *o, int origin, int first, int last,
-    int *startp, int *endp)
+    int *startp, int *endp, clocc_kind_t kind)
 {
 	int i, widest = -1, maxw = 0;
 
@@ -645,6 +883,9 @@ widest_clocc_in_interval(cloccs_t *o, in
 		if (o->occs[i].last > origin + last)
 			break;
 
+		if (o->occs[i].kind != kind)
+			continue;
+
 		w = o->occs[i].last - o->occs[i].first + 1;
 		if (w > maxw) {
 			maxw = w;
@@ -657,14 +898,17 @@ widest_clocc_in_interval(cloccs_t *o, in
 }
 
 static int
-interval_to_clocc_index(cloccs_t *o, int origin, int first, int last)
+interval_to_clocc_index(cloccs_t *o, int origin, int first, int last, clocc_kind_t *kindp)
 {
 	int i;
 
 	for (i = 0; i < o->noccs; i++) {
 		if (origin + first == o->occs[i].first &&
-		    origin + last == o->occs[i].last)
+		    origin + last == o->occs[i].last) {
+			if (kindp != NULL)
+				*kindp = o->occs[i].kind;
 			return i;
+		}
 	}
 	return -1;
 }
@@ -740,20 +984,22 @@ algc(const slice_t *A, const slice_t *B,
 		return algc_return(m, n, origin, lcsp, 0, empty());
 	}
 
-	ivlidx.A = interval_to_clocc_index(&scratch->Aoccs, origin.i, 0, m - 1);
+	clocc_kind_t kind;
+
+	ivlidx.A = interval_to_clocc_index(&scratch->Aoccs, origin.i, 0, m - 1, &kind);
 
 	/* If A is a clocc occurrence, must try to match A with a clocc in B! */
 	if (ivlidx.A != -1) {
 		int start = 0, end = 0;
 
 		ivlidx.B = widest_clocc_in_interval(&scratch->Boccs, origin.j,
-		    0, n - 1, &start, &end);
+		    0, n - 1, &start, &end, kind);
 
 		if (ivlidx.B != -1) {
 			dbg_assert(expected_lcs == no_expected_lcs ||
-			    (size_t)(end - start + 2) == expected_lcs);
+			    (size_t)(end - start + 1) * m + 1 == expected_lcs);
 			return algc_return(m, n, origin, lcsp,
-			    (size_t)(end - start + 2),
+			    (size_t)(end - start + 1) * m + 1,
 			    clocc(scratch, ivlidx.A, ivlidx.B));
 		}
 	}
@@ -904,11 +1150,75 @@ slicestr(slice_t *s, const char *t)
 }
 
 static void
+emit_hex_clocc(hex_parser_t *p, void *arg)
+{
+	cloccs_t *o = arg;
+	intmax_t val;
+	char *end;
+
+	dbg_printf("found hex string %s\n", p->p_digits);
+
+	if (o->noccs >= (int)__arraycount(o->occs))
+		return;
+
+	val = strtoimax(p->p_digits, &end, 16);
+
+	if (*end != '\0' && errno == ERANGE)
+		warnx("%s: over/underflow at %d", __func__, p->p_column.start);
+
+#if 1
+	o->occs[o->noccs].column = p->p_column.start;
+	o->occs[o->noccs].first = p->p_idx.start;
+	o->occs[o->noccs].last = p->p_idx.stop;
+	o->occs[o->noccs].kind = KIND_INTMAX_HEX;
+	o->occs[o->noccs].val_u.u_uintmax = val;
+	o->noccs++;
+#endif
+}
+
+static int
+clocc_cmp(const void *l0, const void *r0)
+{
+	const clocc_t *l = l0, *r = r0;
+
+	return l->first - r->first;
+}
+
+static int
+clocc_width(const clocc_t *c)
+{
+	assert(c->last >= c->first);
+	return c->last - c->first + 1;
+}
+
+static void
+cloccs_dedup(cloccs_t *o)
+{
+	int i, j;
+
+	for (i = 1; i < o->noccs;) {
+		clocc_t *l, *r;
+		l = &o->occs[i - 1];
+		r = &o->occs[i];
+		if (l->last < r->first) {
+			i++;
+			continue;
+		}
+		if (clocc_width(r) > clocc_width(l))
+			*l = *r;
+		for (j = i + 1; j < o->noccs; j++)
+			o->occs[j - 1] = o->occs[j];
+		o->noccs--;
+	}
+}
+
+static void
 cloccs_init(cloccs_t *o, slice_t *s)
 {
+	hex_parser_t hex_parser;
 	size_t column, i, n;
 	unsigned int j, k;
-	char digits[64 / 3 + 1];
+	char digits[64 / 3 + 1]; /* XXX how many digits in an intmax_t? */
 
 	o->noccs = 0;
 	for (i = 0; i < __arraycount(names); i++) {
@@ -926,9 +1236,23 @@ cloccs_init(cloccs_t *o, slice_t *s)
 		o->noccs++;
 	}
 
-	j = 0;
+	hex_parser_init(&hex_parser, emit_hex_clocc, o);
+
 	column = 0;
 	n = length(s);
+	for (j = 0; j < n; j++) {
+		char c;
+
+		c = get(s, j);
+		++column;
+		hex_parser_drive(&hex_parser, j, column, c);
+		if (c == '\n')
+			column = 0;
+	}
+	hex_parser_drive(&hex_parser, n, column + 1, -1);
+
+	j = 0;
+	column = 0;
 	while (o->noccs < (int)__arraycount(o->occs)) {
 		intmax_t val;
 		char *end;
@@ -966,7 +1290,7 @@ cloccs_init(cloccs_t *o, slice_t *s)
 			o->occs[o->noccs].column = column;
 			o->occs[o->noccs].first = j;
 			o->occs[o->noccs].last = k - 1;
-			o->occs[o->noccs].kind = KIND_INTMAX;
+			o->occs[o->noccs].kind = KIND_INTMAX_DEC;
 			o->occs[o->noccs].val_u.u_intmax = val;
 			dbg_printf("found %jd at %d - %d\n",
 			    val, o->occs[o->noccs].first,
@@ -978,6 +1302,8 @@ next:
 		column += k - 1 - j;
 		j = k;
 	}
+	mergesort(o->occs, o->noccs, sizeof(*o->occs), clocc_cmp);
+	cloccs_dedup(o);
 }
 
 static void
@@ -1026,11 +1352,13 @@ main(int argc, char **argv)
 	B = file_to_slice(argv[2]);
 	n = length(B);
 	scratch_init(&scratch, n, A, B);
-	if (strcmp(getprogname(), "dt") == 0)
-		scratch.op = '-';
-	else if (strcmp(getprogname(), "it") == 0)
-		scratch.op = '+';
-	else
+	if (strcmp(getprogname(), "dt") == 0) {
+		scratch.dec_op = '-';
+		scratch.hex_op = '&';
+	} else if (strcmp(getprogname(), "it") == 0) {
+		scratch.dec_op = '+';
+		scratch.hex_op = '|';
+	} else
 		errx(EXIT_FAILURE, "not implemented");
 
 	cloccs_init(&scratch.Aoccs, A);
@@ -1042,7 +1370,5 @@ main(int argc, char **argv)
 	printchain(C);
 	dbg_printf("\n");
 
-	dbg_printf("\n%d times through main loop\n", mainloop);
-
 	return EXIT_SUCCESS;
 }

Index: othersrc/external/bsd/arfe/dt/rr/ifconfig.0-ifconfig.1
diff -u othersrc/external/bsd/arfe/dt/rr/ifconfig.0-ifconfig.1:1.1 othersrc/external/bsd/arfe/dt/rr/ifconfig.0-ifconfig.1:1.2
--- othersrc/external/bsd/arfe/dt/rr/ifconfig.0-ifconfig.1:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/ifconfig.0-ifconfig.1	Sat Aug 22 05:08:48 2015
@@ -6,5 +6,5 @@ wm0: flags=   0<UP,BROADCAST,RUNNING,SIM
 	status: active
 	input:      61 packets,       5432 bytes,       3 multicasts
 	output:      30 packets,       3436 bytes,    0 multicasts
-	inet  0.0.0. 0 netmask 0xffffff 0 broadcast  0.0.0.  0
-	inet0 fe 0:: 0a:bff:fecd:0ef%wm0 prefixlen  0 scopeid 0x0
+	inet  0.0.0. 0 netmask 0xffffff00 broadcast  0.0.0.  0
+	inet0 fe 0:: 0a:bff:fecd:0ef%wm0 prefixlen  0 scopeid 0x1
Index: othersrc/external/bsd/arfe/dt/rr/ifconfig.0-logger-ifconfig.0
diff -u othersrc/external/bsd/arfe/dt/rr/ifconfig.0-logger-ifconfig.0:1.1 othersrc/external/bsd/arfe/dt/rr/ifconfig.0-logger-ifconfig.0:1.2
--- othersrc/external/bsd/arfe/dt/rr/ifconfig.0-logger-ifconfig.0:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/ifconfig.0-logger-ifconfig.0	Sat Aug 22 05:08:48 2015
@@ -6,5 +6,5 @@ media: Ethernet autoselect (0baseT full-
 status: active
 input: 0 packets, 0 bytes, 0 multicasts
 output: 0 packets, 0 bytes, 0 multicasts
-inet 0.0.0.0 netmask 0xffffff0 broadcast 0.0.0.0
-inet0 fe0::0a:bff:fecd:0ef%wm0 prefixlen 0 scopeid 0x0
+inet 0.0.0.0 netmask 0xffffff00 broadcast 0.0.0.0
+inet0 fe0::0a:bff:fecd:0ef%wm0 prefixlen 0 scopeid 0x1
Index: othersrc/external/bsd/arfe/dt/rr/ifconfig.1-ifconfig.0
diff -u othersrc/external/bsd/arfe/dt/rr/ifconfig.1-ifconfig.0:1.1 othersrc/external/bsd/arfe/dt/rr/ifconfig.1-ifconfig.0:1.2
--- othersrc/external/bsd/arfe/dt/rr/ifconfig.1-ifconfig.0:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/ifconfig.1-ifconfig.0	Sat Aug 22 05:08:48 2015
@@ -6,5 +6,5 @@ wm0: flags=   0<UP,BROADCAST,RUNNING,SIM
 	status: active
 	input:     -61 packets,      -5432 bytes,      -3 multicasts
 	output:     -30 packets,      -3436 bytes,    0 multicasts
-	inet  0.0.0. 0 netmask 0xffffff 0 broadcast  0.0.0.  0
-	inet0 fe 0:: 0a:bff:fecd:0ef%wm0 prefixlen  0 scopeid 0x0
+	inet  0.0.0. 0 netmask 0xffffff00 broadcast  0.0.0.  0
+	inet0 fe 0:: 0a:bff:fecd:0ef%wm0 prefixlen  0 scopeid 0x1
Index: othersrc/external/bsd/arfe/dt/rr/logger-ifconfig.0-ifconfig.0
diff -u othersrc/external/bsd/arfe/dt/rr/logger-ifconfig.0-ifconfig.0:1.1 othersrc/external/bsd/arfe/dt/rr/logger-ifconfig.0-ifconfig.0:1.2
--- othersrc/external/bsd/arfe/dt/rr/logger-ifconfig.0-ifconfig.0:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/logger-ifconfig.0-ifconfig.0	Sat Aug 22 05:08:48 2015
@@ -6,5 +6,5 @@ media: Ethernet autoselect (0baseT full-
 status: active
 input: 0 packets, 0 bytes, 0 multicasts
 output: 0 packets, 0 bytes, 0 multicasts
-inet 0.0.0.0 netmask 0xffffff0 broadcast 0.0.0.0
-inet0 fe0::0a:bff:fecd:0ef%wm0 prefixlen 0 scopeid 0x0
+inet 0.0.0.0 netmask 0xffffff00 broadcast 0.0.0.0
+inet0 fe0::0a:bff:fecd:0ef%wm0 prefixlen 0 scopeid 0x1
Index: othersrc/external/bsd/arfe/dt/rr/wm0-a-wm0-b
diff -u othersrc/external/bsd/arfe/dt/rr/wm0-a-wm0-b:1.1 othersrc/external/bsd/arfe/dt/rr/wm0-a-wm0-b:1.2
--- othersrc/external/bsd/arfe/dt/rr/wm0-a-wm0-b:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/wm0-a-wm0-b	Sat Aug 22 05:08:48 2015
@@ -6,7 +6,7 @@ wm0: flags=   0<UP,BROADCAST,RUNNING,SIM
 	status: active
 	input:     112 packets,      11380 bytes,      11 multicasts
 	output:      60 packets,      11440 bytes,    0 multicasts
-	inet  0.0.0. 0 netmask 0xffffff 0 broadcast  0.0.0.  0
-	inet0 fe 0:: 0a:bff:fecd:0ef%wm0 prefixlen  0 scopeid 0x0
+	inet  0.0.0. 0 netmask 0xffffff00 broadcast  0.0.0.  0
+	inet0 fe 0:: 0a:bff:fecd:0ef%wm0 prefixlen  0 scopeid 0x1
 
 
Index: othersrc/external/bsd/arfe/dt/rr/wm0-b-wm0-a
diff -u othersrc/external/bsd/arfe/dt/rr/wm0-b-wm0-a:1.1 othersrc/external/bsd/arfe/dt/rr/wm0-b-wm0-a:1.2
--- othersrc/external/bsd/arfe/dt/rr/wm0-b-wm0-a:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/wm0-b-wm0-a	Sat Aug 22 05:08:48 2015
@@ -6,7 +6,7 @@ wm0: flags=   0<UP,BROADCAST,RUNNING,SIM
 	status: active
 	input:    -112 packets,     -11380 bytes,     -11 multicasts
 	output:     -60 packets,     -11440 bytes,    0 multicasts
-	inet  0.0.0. 0 netmask 0xffffff 0 broadcast  0.0.0.  0
-	inet0 fe 0:: 0a:bff:fecd:0ef%wm0 prefixlen  0 scopeid 0x0
+	inet  0.0.0. 0 netmask 0xffffff00 broadcast  0.0.0.  0
+	inet0 fe 0:: 0a:bff:fecd:0ef%wm0 prefixlen  0 scopeid 0x1
 
 

Reply via email to