Module Name:    othersrc
Committed By:   dyoung
Date:           Thu Oct  8 22:00:56 UTC 2015

Modified Files:
        othersrc/external/bsd/arfe/dt: Makefile core.c core.h macaddr.c
            portability.h
        othersrc/external/bsd/arfe/dt/rr: daily-output-2-daily-output-5
            daily-output-5-daily-output-2 daily-output-5-daily-output-6
            daily-output-6-daily-output-5 daily-output-6-daily-output-7
            daily-output-7-daily-output-6
        othersrc/external/bsd/arfe/it: Makefile
        othersrc/external/bsd/arfe/tt: Makefile
Added Files:
        othersrc/external/bsd/arfe/dt: dec.c dec.h

Log Message:
Make ARFE understand numbers with decimal points.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 othersrc/external/bsd/arfe/dt/Makefile
cvs rdiff -u -r1.2 -r1.3 othersrc/external/bsd/arfe/dt/core.c \
    othersrc/external/bsd/arfe/dt/core.h
cvs rdiff -u -r0 -r1.1 othersrc/external/bsd/arfe/dt/dec.c \
    othersrc/external/bsd/arfe/dt/dec.h
cvs rdiff -u -r1.3 -r1.4 othersrc/external/bsd/arfe/dt/macaddr.c
cvs rdiff -u -r1.1 -r1.2 othersrc/external/bsd/arfe/dt/portability.h
cvs rdiff -u -r1.1 -r1.2 \
    othersrc/external/bsd/arfe/dt/rr/daily-output-2-daily-output-5 \
    othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-2 \
    othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-6 \
    othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-5 \
    othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-7 \
    othersrc/external/bsd/arfe/dt/rr/daily-output-7-daily-output-6
cvs rdiff -u -r1.4 -r1.5 othersrc/external/bsd/arfe/it/Makefile
cvs rdiff -u -r1.2 -r1.3 othersrc/external/bsd/arfe/tt/Makefile

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/dt/Makefile
diff -u othersrc/external/bsd/arfe/dt/Makefile:1.5 othersrc/external/bsd/arfe/dt/Makefile:1.6
--- othersrc/external/bsd/arfe/dt/Makefile:1.5	Tue Sep 22 01:12:09 2015
+++ othersrc/external/bsd/arfe/dt/Makefile	Thu Oct  8 22:00:56 2015
@@ -1,9 +1,10 @@
-# $ARFE: Makefile 250 2015-09-22 01:04:13Z dyoung $
+# $ARFE: Makefile 262 2015-10-08 21:47:24Z dyoung $
 NOMAN=
 .include <bsd.own.mk>
 
+DPINCS+=core.h dec.h hex.h ipv4.h macaddr.h
 PROG=dt
-SRCS+=core.c dt.c hex.c ipv4.c macaddr.c
+SRCS+=core.c dec.c dt.c hex.c ipv4.c macaddr.c
 #CPPFLAGS+=-DHB_DEBUG
 CPPFLAGS+=-DHB_ASSERT
 DBG+=-g -O3
@@ -13,7 +14,7 @@ DBG+=-g -O3
 CFLAGS+=-std=c99
 WARNS=5
 
-tags: $(SRCS) $(INCS)
+tags: $(SRCS) $(DPINCS) $(INCS)
 	@rm -f $(.OBJDIR)/tags
 	@ctags -atwd $(.ALLSRC)
 	@sort -o $(.OBJDIR)/tags $(.OBJDIR)/tags

Index: othersrc/external/bsd/arfe/dt/core.c
diff -u othersrc/external/bsd/arfe/dt/core.c:1.2 othersrc/external/bsd/arfe/dt/core.c:1.3
--- othersrc/external/bsd/arfe/dt/core.c:1.2	Wed Sep 23 19:32:34 2015
+++ othersrc/external/bsd/arfe/dt/core.c	Thu Oct  8 22:00:56 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: core.c,v 1.2 2015/09/23 19:32:34 dyoung Exp $ */
+/* $NetBSD: core.c,v 1.3 2015/10/08 22:00:56 dyoung Exp $ */
 /* $ARFE$ */
 
 /*-
@@ -25,6 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+#include <ctype.h>	/* for isdigit() */
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -41,6 +42,7 @@
 #include <arpa/inet.h>	/* for inet_net_pton */
 
 #include "core.h"
+#include "dec.h"
 #include "hex.h"
 #include "ipv4.h"
 #include "macaddr.h"
@@ -521,35 +523,78 @@ hex_clocc(const scratch_t *scratch, int 
 	return newchain_with_match_idx(strdup("<hexmax>"), column, idx_b);
 }
 
+static void
+align_decimal_points(const decimal_t *ina, const decimal_t *inb,
+    decimal_t *outa, decimal_t *outb)
+{
+	*outa = *ina;
+	*outb = *inb;
+	while (outa->log10denom > outb->log10denom) {
+		outa->num *= 10;
+		outa->log10denom--;
+	}
+	while (outb->log10denom > outa->log10denom) {
+		outb->num *= 10;
+		outb->log10denom--;
+	}
+}
+
+static intmax_t
+power10(unsigned int x)
+{
+	if (x == 0)
+		return 1;
+
+	if (x % 2 == 0) {
+		intmax_t root = power10(x / 2);
+		return root * root;
+	}
+	return power10(x - 1) * 10;
+}
+
 static chain_t *
-int_clocc(const scratch_t *scratch, int idx_a, int idx_b)
+dec_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];
+	struct {
+		decimal_t a, b;
+	} val;
 
 	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);
+	align_decimal_points(&a->val_u.u_dec, &b->val_u.u_dec, &val.a, &val.b);
+
+	dbg2_printf("%jd / 10^%d @ %d ; %jd / 10^%d @ %d -> column %d\n",
+	    val.a.num, val.a.log10denom, a->column,
+	    val.b.num, val.b.log10denom, b->column, column);
 
 	switch (scratch->dec_op) {
 	case '-':
-		result = b->val_u.u_intmax - a->val_u.u_intmax;
+		result = val.b.num - val.a.num;
 		break;
 	case '+':
-		result = b->val_u.u_intmax + a->val_u.u_intmax;
+		result = val.b.num + val.a.num;
 		break;
 	case 'l':
 	default:
-		result = a->val_u.u_intmax;
+		result = val.a.num;
 		break;
 	}
 
-	if (asprintf(&ret, "%jd", result) != -1)
+	intmax_t lop = result / power10(val.a.log10denom),
+	         rop = imaxabs(result) % power10(val.a.log10denom);
+ 
+#if 0
+	assert(result >= 0);
+#endif
+
+	if (val.a.log10denom != 0 && asprintf(&ret, "%s%jd.%0*jd", (result < 0 && lop == 0) ? "-" : "", lop, (int)val.a.log10denom, rop) != -1)
+		return newchain_with_match_idx(ret, column, idx_b);
+	if (val.a.log10denom == 0 && asprintf(&ret, "%jd", result) != -1)
 		return newchain_with_match_idx(ret, column, idx_b);
 
 	return newchain_with_match_idx(strdup("<intmax>"), column, idx_b);
@@ -570,7 +615,7 @@ clocc(const scratch_t *scratch, int idx_
 	}
 
 	if (b->kind == KIND_INTMAX_DEC)
-		return int_clocc(scratch, idx_a, idx_b);
+		return dec_clocc(scratch, idx_a, idx_b);
 
 	if (b->kind == KIND_IPv4)
 		return ipv4_clocc(scratch, idx_a, idx_b);
@@ -1107,6 +1152,66 @@ emit_ipv4_clocc(ipv4_detection_t *d, voi
 }
 
 static void
+emit_dec_clocc(dec_detection_t *d, void *arg)
+{
+	cloccs_t *o = arg;
+	intmax_t val, ropval = 0;
+	char *end, *ropend;
+	unsigned int log10denom = 0;
+	uintmax_t denom = 1;
+	int sign = 1;
+	char *next;
+
+	dbg_printf("found decimal string %s @ [%d, %d]\n", d->d_digits,
+	    d->d_idx.start, d->d_idx.stop);
+
+	if (o->noccs >= (int)__arraycount(o->occs))
+		return;
+
+	if (d->d_digits[0] == '-') {
+		next = &d->d_digits[1];
+		sign = -1;
+	} else {
+		next = &d->d_digits[0];
+		sign = 1;
+	}
+	if (!isdigit((unsigned char)*next)) {
+		val = 0;
+		end = next;
+	} else {
+		val = strtoimax(next, &end, 10);
+
+		if (*end != '\0' && errno == ERANGE) {
+			warnx("%s: over/underflow at %d", __func__,
+			    d->d_column.start);
+		}
+	}
+
+	if (*end == '.') {
+		++end;
+		ropval = strtoimax(end, &ropend, 10);
+
+		if (*ropend != '\0' && errno == ERANGE) {
+			warnx("%s: over/underflow at %d", __func__,
+			    d->d_column.start + end - d->d_digits);
+		}
+		for (; end < ropend; end++) {
+			log10denom++;
+			denom *= 10;
+		}
+	}
+
+	o->occs[o->noccs].column = d->d_column.start;
+	o->occs[o->noccs].first = d->d_idx.start;
+	o->occs[o->noccs].last = d->d_idx.stop;
+	o->occs[o->noccs].kind = KIND_INTMAX_DEC;
+	o->occs[o->noccs].qual = QUAL_NONE;
+	o->occs[o->noccs].val_u.u_dec.num = sign * (val * denom + ropval);
+	o->occs[o->noccs].val_u.u_dec.log10denom = log10denom;
+	o->noccs++;
+}
+
+static void
 emit_hex_clocc(hex_detection_t *d, void *arg, bool use0x)
 {
 	cloccs_t *o = arg;
@@ -1203,13 +1308,13 @@ cloccs_hash(cloccs_t *o, const slice_t *
 void
 cloccs_init(cloccs_t *o, const slice_t *s)
 {
+	dec_parser_t *dec_parser;
 	hex_parser_t *hex_parser;
 	ipv4_parser_t *ipv4_parser;
 	mac_parser_t *mac_parser;
 	size_t column, i;
 	size_t n = length(s);
-	unsigned int j, k;
-	char digits[64 / 3 + 1]; /* XXX how many digits in an intmax_t? */
+	unsigned int j;
 
 	clocc_htbl_init(&o->htbl);
 
@@ -1286,59 +1391,27 @@ parse_hexadecimal:
 	hex_parser_free(hex_parser);
 
 parse_decimal:
+	dec_parser = dec_parser_alloc(emit_dec_clocc, o);
+	if (dec_parser == NULL)
+		goto out;
 
-	j = 0;
 	column = 0;
-	while (o->noccs < (int)__arraycount(o->occs)) {
-		intmax_t val;
-		char *end;
+	for (j = 0; j < n; j++) {
 		char c;
 
-		++column;
-
-		if (j == n)
-			break;
-
 		c = get(s, j);
-		for (k = j + 1; k < n; k++) {
-			if (strchr("0123456789", get(s, k)) == NULL)
-				break;
-		}
-		if (c == '-') {
-			if (j == k - 1) {
-				j++;
-				continue;
-			}
-		} else if (strchr("0123456789", c) == NULL) {
-			if (c == '\n')
-				column = 0;
-			j++;
-			continue;
-		}
-
-		if (k - j > __arraycount(digits) - 1)
-			goto next;
+		++column;
+		dec_parser_drive(dec_parser, j, column, c);
+		if (c == '\n')
+			column = 0;
+	}
+	dec_parser_drive(dec_parser, n, column + 1, -1);
 
-		extract(s, j, k - 1, digits);
+	dec_parser_free(dec_parser);
 
-		val = strtoimax(digits, &end, 10);
-		if (*end == '\0') {
-			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_DEC;
-			o->occs[o->noccs].val_u.u_intmax = val;
-			dbg_printf("found %jd at %d - %d\n",
-			    val, o->occs[o->noccs].first,
-			    o->occs[o->noccs].last);
-			o->noccs++;
-		} else if (errno == ERANGE)
-			warnx("%s: over/underflow at %d", __func__, j);
-next:
-		column += k - 1 - j;
-		j = k;
-	}
-	mergesort(o->occs, o->noccs, sizeof(*o->occs), clocc_cmp);
+out:
+	if (o->noccs > 0)
+		mergesort(o->occs, o->noccs, sizeof(*o->occs), clocc_cmp);
 	cloccs_dedup(o);
 }
 
Index: othersrc/external/bsd/arfe/dt/core.h
diff -u othersrc/external/bsd/arfe/dt/core.h:1.2 othersrc/external/bsd/arfe/dt/core.h:1.3
--- othersrc/external/bsd/arfe/dt/core.h:1.2	Wed Sep 23 19:32:34 2015
+++ othersrc/external/bsd/arfe/dt/core.h	Thu Oct  8 22:00:56 2015
@@ -1,5 +1,5 @@
-/* $NetBSD: core.h,v 1.2 2015/09/23 19:32:34 dyoung Exp $ */
-/* $ARFE: core.h 258 2015-09-23 19:31:17Z dyoung $ */
+/* $NetBSD: core.h,v 1.3 2015/10/08 22:00:56 dyoung Exp $ */
+/* $ARFE: core.h 262 2015-10-08 21:47:24Z dyoung $ */
 
 /*-
  * Copyright (c) 2014,2015 David Young <[email protected]>
@@ -113,6 +113,13 @@ typedef enum {
 struct chainelt;
 typedef struct chainelt chainelt_t;
 
+struct decimal {
+	intmax_t num;
+	unsigned int log10denom;
+};
+
+typedef struct decimal decimal_t;
+
 typedef struct clocc {
 	int column;
 	int first;
@@ -120,7 +127,7 @@ typedef struct clocc {
 	clocc_kind_t kind;
 	clocc_qual_t qual;
 	union {
-		intmax_t u_intmax;
+		decimal_t u_dec;
 		uintmax_t u_uintmax;
 		uint32_t u_ipv4;
 		uint8_t u_macaddr[6];

Index: othersrc/external/bsd/arfe/dt/macaddr.c
diff -u othersrc/external/bsd/arfe/dt/macaddr.c:1.3 othersrc/external/bsd/arfe/dt/macaddr.c:1.4
--- othersrc/external/bsd/arfe/dt/macaddr.c:1.3	Tue Sep 22 01:12:09 2015
+++ othersrc/external/bsd/arfe/dt/macaddr.c	Thu Oct  8 22:00:56 2015
@@ -1,5 +1,5 @@
-/* $NetBSD: macaddr.c,v 1.3 2015/09/22 01:12:09 dyoung Exp $ */
-/* $ARFE:47:33Z dyoung $ */
+/* $NetBSD: macaddr.c,v 1.4 2015/10/08 22:00:56 dyoung Exp $ */
+/* $ARFE: macaddr.c 260 2015-09-23 19:37:44Z dyoung $ */
 
 /*-
  * Copyright (c) 2014,2015 David Young <[email protected]>

Index: othersrc/external/bsd/arfe/dt/portability.h
diff -u othersrc/external/bsd/arfe/dt/portability.h:1.1 othersrc/external/bsd/arfe/dt/portability.h:1.2
--- othersrc/external/bsd/arfe/dt/portability.h:1.1	Wed Sep 16 21:07:44 2015
+++ othersrc/external/bsd/arfe/dt/portability.h	Thu Oct  8 22:00:56 2015
@@ -1,3 +1,6 @@
+/* $NetBSD: portability.h,v 1.2 2015/10/08 22:00:56 dyoung Exp $ */
+/* $ARFE: portability.h 261 2015-09-23 19:39:10Z dyoung $ */
+
 #ifndef __NetBSD__
 #define __aligned(__x)	/* */
 #define __arraycount(__x) (sizeof(__x) / sizeof(__x[0]))

Index: othersrc/external/bsd/arfe/dt/rr/daily-output-2-daily-output-5
diff -u othersrc/external/bsd/arfe/dt/rr/daily-output-2-daily-output-5:1.1 othersrc/external/bsd/arfe/dt/rr/daily-output-2-daily-output-5:1.2
--- othersrc/external/bsd/arfe/dt/rr/daily-output-2-daily-output-5:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/daily-output-2-daily-output-5	Thu Oct  8 22:00:56 2015
@@ -1,6 +1,6 @@
 
 
-Uptime:  0: 0AM  up 3 day, 0:0,  -10 users, load averages: 0.13, 0. 4, 0. 1
+Uptime:  0: 0AM  up 3 day, 0:0,  -10 users, load averages: 0.13, 0.04, 0.01
 
 Checking subsystem status:
 
Index: othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-2
diff -u othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-2:1.1 othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-2:1.2
--- othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-2:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-2	Thu Oct  8 22:00:56 2015
@@ -1,6 +1,6 @@
 
 
-Uptime:  0: 0AM  up -3 day, 0:0,  10 users, load averages: 0.-13, 0.-4, 0.-1
+Uptime:  0: 0AM  up -3 day, 0:0,  10 users, load averages: -0.13, -0.04, -0.01
 
 Checking subsystem status:
 
Index: othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-6
diff -u othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-6:1.1 othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-6:1.2
--- othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-6:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/daily-output-5-daily-output-6	Thu Oct  8 22:00:56 2015
@@ -1,6 +1,6 @@
 
 
-Uptime:  0: 0AM  up 1 days,  0: 0, 0 users, load averages: 0.-11, 0.-2, 0.-1
+Uptime:  0: 0AM  up 1 days,  0: 0, 0 users, load averages: -0.11, -0.02, -0.01
 
 Checking subsystem status:
 
Index: othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-5
diff -u othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-5:1.1 othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-5:1.2
--- othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-5:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-5	Thu Oct  8 22:00:56 2015
@@ -1,6 +1,6 @@
 
 
-Uptime:  0: 0AM  up -1 days, 0: 0, 0 users, load averages: 0.11, 0. 2, 0. 1
+Uptime:  0: 0AM  up -1 days, 0: 0, 0 users, load averages: 0.11, 0.02, 0.01
 
 Checking subsystem status:
 
Index: othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-7
diff -u othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-7:1.1 othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-7:1.2
--- othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-7:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/daily-output-6-daily-output-7	Thu Oct  8 22:00:56 2015
@@ -1,6 +1,6 @@
 
 
-Uptime:  0: 0AM  up 1 days,  0: 0, 0 users, load averages: 0.-2, 0.-2, 0. 0
+Uptime:  0: 0AM  up 1 days,  0: 0, 0 users, load averages: -0.02, -0.02, 0.00
 
 Checking subsystem status:
 
Index: othersrc/external/bsd/arfe/dt/rr/daily-output-7-daily-output-6
diff -u othersrc/external/bsd/arfe/dt/rr/daily-output-7-daily-output-6:1.1 othersrc/external/bsd/arfe/dt/rr/daily-output-7-daily-output-6:1.2
--- othersrc/external/bsd/arfe/dt/rr/daily-output-7-daily-output-6:1.1	Mon Aug 10 21:10:59 2015
+++ othersrc/external/bsd/arfe/dt/rr/daily-output-7-daily-output-6	Thu Oct  8 22:00:56 2015
@@ -1,6 +1,6 @@
 
 
-Uptime:  0: 0AM  up -1 days, 0: 0, 0 users, load averages: 0. 2, 0. 2, 0. 0
+Uptime:  0: 0AM  up -1 days, 0: 0, 0 users, load averages: 0.02, 0.02, 0.00
 
 Checking subsystem status:
 

Index: othersrc/external/bsd/arfe/it/Makefile
diff -u othersrc/external/bsd/arfe/it/Makefile:1.4 othersrc/external/bsd/arfe/it/Makefile:1.5
--- othersrc/external/bsd/arfe/it/Makefile:1.4	Tue Sep 22 01:12:09 2015
+++ othersrc/external/bsd/arfe/it/Makefile	Thu Oct  8 22:00:56 2015
@@ -2,7 +2,7 @@ NOMAN=
 .include <bsd.own.mk>
 
 PROG=it
-SRCS+=core.c hex.c ipv4.c it.c macaddr.c
+SRCS+=core.c dec.c hex.c ipv4.c it.c macaddr.c
 #CPPFLAGS+=-DHB_DEBUG
 CPPFLAGS+=-I$(.CURDIR)/../dt
 DBG+=-g -O3

Index: othersrc/external/bsd/arfe/tt/Makefile
diff -u othersrc/external/bsd/arfe/tt/Makefile:1.2 othersrc/external/bsd/arfe/tt/Makefile:1.3
--- othersrc/external/bsd/arfe/tt/Makefile:1.2	Tue Sep 22 01:12:09 2015
+++ othersrc/external/bsd/arfe/tt/Makefile	Thu Oct  8 22:00:56 2015
@@ -2,7 +2,7 @@ NOMAN=
 .include <bsd.own.mk>
 
 PROG=tt
-SRCS+=core.c hex.c ipv4.c macaddr.c tt.c
+SRCS+=core.c dec.c hex.c ipv4.c macaddr.c tt.c
 #CPPFLAGS+=-DHB_DEBUG
 CPPFLAGS+=-DHB_ASSERT
 CPPFLAGS+=-I$(.CURDIR)/../dt

Added files:

Index: othersrc/external/bsd/arfe/dt/dec.c
diff -u /dev/null othersrc/external/bsd/arfe/dt/dec.c:1.1
--- /dev/null	Thu Oct  8 22:00:56 2015
+++ othersrc/external/bsd/arfe/dt/dec.c	Thu Oct  8 22:00:56 2015
@@ -0,0 +1,256 @@
+/* $NetBSD: dec.c,v 1.1 2015/10/08 22:00:56 dyoung Exp $ */
+/* $ARFE: dec.c 262 2015-10-08 21:47:24Z dyoung $ */
+
+/*-
+ * Copyright (c) 2014,2015 David Young <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "dec.h"
+
+typedef enum dec_op {
+	  DEC_OP_NONE = 0
+	, DEC_OP_PUSH
+	, DEC_OP_EMIT
+	, DEC_OP_START
+} dec_op_t;
+
+struct dec_state;
+typedef struct dec_state dec_state_t;
+
+typedef struct dec_transition {
+	const dec_state_t	*t_newstate;
+	dec_op_t		t_op;
+} dec_transition_t;
+
+struct dec_state {
+	const char *s_descr;
+	dec_transition_t s_other;
+	dec_transition_t s_minus;
+	dec_transition_t s_point;
+	dec_transition_t s_0_9;
+	dec_transition_t s_delimiter;
+	dec_transition_t s_eof;
+};
+
+enum dec_state_idxs {
+	  READ_SIGN
+	, READ_POINT
+	, READ_POINT_DIGITS
+	, READ_DIGITS
+	, READ_DIGITS_POINT
+	, READ_DIGITS_POINT_DIGITS
+	, READ_EOF
+	, READ_OTHER
+	, READ_DELIMITER
+};
+
+#define	read_sign dec_states[READ_SIGN]
+#define	read_point dec_states[READ_POINT]
+#define	read_point_digits dec_states[READ_POINT_DIGITS]
+#define	read_digits dec_states[READ_DIGITS]
+#define	read_digits_point dec_states[READ_DIGITS_POINT]
+#define	read_digits_point_digits dec_states[READ_DIGITS_POINT_DIGITS]
+#define	read_eof dec_states[READ_EOF]
+#define	read_other dec_states[READ_OTHER]
+#define	read_delimiter dec_states[READ_DELIMITER]
+
+static const dec_state_t dec_states[] = {[READ_SIGN] = {
+	.s_descr = "read sign",
+	.s_other = {&read_other, DEC_OP_NONE},
+	.s_point = {&read_point, DEC_OP_PUSH},
+	.s_0_9 = {&read_digits, DEC_OP_PUSH},
+}, [READ_POINT] = {
+	.s_descr = "read point",
+	.s_other = {&read_other, DEC_OP_NONE},
+	.s_0_9 = {&read_point_digits, DEC_OP_PUSH},
+}, [READ_POINT_DIGITS] = {
+	.s_descr = "read point digits",
+	.s_other = {&read_other, DEC_OP_NONE},
+	.s_minus = {&read_delimiter, DEC_OP_EMIT},
+	.s_delimiter = {&read_delimiter, DEC_OP_EMIT},
+	.s_eof = {&read_eof, DEC_OP_EMIT},
+	.s_0_9 = {&read_point_digits, DEC_OP_PUSH},
+}, [READ_DIGITS] = {
+	.s_descr = "read digits",
+	.s_other = {&read_other, DEC_OP_NONE},
+	.s_delimiter = {&read_delimiter, DEC_OP_EMIT},
+	.s_minus = {&read_delimiter, DEC_OP_EMIT},
+	.s_eof = {&read_eof, DEC_OP_EMIT},
+	.s_0_9 = {&read_digits, DEC_OP_PUSH},
+	.s_point = {&read_digits_point, DEC_OP_PUSH},
+}, [READ_DIGITS_POINT] = {
+	.s_descr = "read digits point",
+	.s_other = {&read_other, DEC_OP_NONE},
+	.s_delimiter = {&read_delimiter, DEC_OP_EMIT},
+	.s_minus = {&read_delimiter, DEC_OP_EMIT},
+	.s_eof = {&read_eof, DEC_OP_EMIT},
+	.s_0_9 = {&read_digits_point_digits, DEC_OP_PUSH},
+}, [READ_DIGITS_POINT_DIGITS] = {
+	.s_descr = "read digits point digits",
+	.s_other = {&read_other, DEC_OP_NONE},
+	.s_delimiter = {&read_delimiter, DEC_OP_EMIT},
+	.s_minus = {&read_delimiter, DEC_OP_EMIT},
+	.s_eof = {&read_eof, DEC_OP_EMIT},
+	.s_0_9 = {&read_digits_point_digits, DEC_OP_PUSH},
+}, [READ_EOF] = {
+	.s_descr = "read eof",
+	.s_other = {&read_eof, DEC_OP_NONE},
+}, [READ_OTHER] = {
+	.s_descr = "read other",
+	.s_other = {&read_other, DEC_OP_NONE},
+	.s_delimiter = {&read_delimiter, DEC_OP_NONE},
+}, [READ_DELIMITER] = {
+	.s_descr = "read delimiter",
+	.s_minus = {&read_sign, DEC_OP_START},
+	.s_point = {&read_point, DEC_OP_START},
+	.s_0_9 = {&read_digits, DEC_OP_START},
+	.s_delimiter = {&read_delimiter, DEC_OP_NONE},
+	.s_other = {&read_other, DEC_OP_NONE},
+}};
+
+struct dec_parser {
+	dec_detection_t p_detection;
+#define	p_column	p_detection.d_column
+#define	p_digits	p_detection.d_digits
+#define	p_idx		p_detection.d_idx
+	char *p_top;
+	const dec_state_t *p_state;
+	dec_emitter_t p_emitter;
+	void *p_arg;
+};
+
+void
+dec_parser_free(dec_parser_t *p)
+{
+	free(p);
+}
+
+static void
+dec_parser_init(dec_parser_t *p, dec_emitter_t emitter, void *arg)
+{
+	memset(p, 0, sizeof(*p));
+	p->p_state = &read_delimiter;
+	p->p_emitter = emitter;
+	p->p_arg = arg;
+}
+
+dec_parser_t *
+dec_parser_alloc(dec_emitter_t emitter, void *arg)
+{
+	dec_parser_t *p;
+
+	p = malloc(sizeof(*p));
+	if (p == NULL)
+		return NULL;
+
+	dec_parser_init(p, emitter, arg);
+	return p;
+}
+
+static const char *
+dec_op_string(dec_op_t op)
+{
+	switch (op) {
+	case DEC_OP_NONE:
+		return "none";
+	case DEC_OP_EMIT:
+		return "emit";
+	case DEC_OP_PUSH:
+		return "push";
+	case DEC_OP_START:
+		return "start";
+	default:
+		return "unknown";
+	}
+}
+
+void
+dec_parser_drive(dec_parser_t *p, int idx, int column, int c)
+{
+	const dec_transition_t *t;
+	const dec_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 == '-' && (ns = s->s_minus.t_newstate) != NULL)
+		t = &s->s_minus;
+	else if (c == '.' && (ns = s->s_point.t_newstate) != NULL)
+		t = &s->s_point;
+	else if ((isalpha(c) || isspace(c) || ispunct(c)) && c != '.' && c != '-' &&
+	         (ns = s->s_delimiter.t_newstate) != NULL)
+		t = &s->s_delimiter;
+	else if (isdigit(c) && (ns = s->s_0_9.t_newstate) != NULL)
+		t = &s->s_0_9;
+	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, dec_op_string(t->t_op));
+	} else {
+		dbg_printf("%s: transition (%s, %c) -> %s (op %s)\n", __func__,
+		    s->s_descr, c, ns->s_descr, dec_op_string(t->t_op));
+	}
+
+	switch (t->t_op) {
+	case DEC_OP_START:
+		p->p_column.start = column;
+		p->p_idx.start = idx;
+		p->p_top = &p->p_digits[0];
+		/*FALLTHROUGH*/
+	case DEC_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_column.stop = column;
+		p->p_idx.stop = idx;
+		break;
+	case DEC_OP_EMIT:
+		if (p->p_top == NULL)
+			dbg_printf("decimal string too long\n");
+		*p->p_top = '\0';
+		(*p->p_emitter)(&p->p_detection, p->p_arg);
+		break;
+	case DEC_OP_NONE:
+		break;
+	}
+
+	p->p_state = ns;
+}
Index: othersrc/external/bsd/arfe/dt/dec.h
diff -u /dev/null othersrc/external/bsd/arfe/dt/dec.h:1.1
--- /dev/null	Thu Oct  8 22:00:56 2015
+++ othersrc/external/bsd/arfe/dt/dec.h	Thu Oct  8 22:00:56 2015
@@ -0,0 +1,49 @@
+/* $NetBSD: dec.h,v 1.1 2015/10/08 22:00:56 dyoung Exp $ */
+/* $ARFE: dec.h 262 2015-10-08 21:47:24Z dyoung $ */
+
+/*-
+ * Copyright (c) 2014,2015 David Young <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _DEC_H
+#define _DEC_H
+
+#include <stdbool.h>
+
+typedef struct dec_detection {
+	struct {
+		int start, stop;
+	} d_column, d_idx;
+	/* XXX how many decimal digits in an intmax_t? */
+	char d_digits[64 / 3 + 1];
+} dec_detection_t;
+
+struct dec_parser;
+typedef struct dec_parser dec_parser_t;
+
+typedef void (*dec_emitter_t)(dec_detection_t *, void *);
+dec_parser_t *dec_parser_alloc(dec_emitter_t, void *);
+void dec_parser_drive(dec_parser_t *, int, int, int);
+void dec_parser_free(dec_parser_t *);
+
+#endif /* _DEC_H */

Reply via email to