summary refs log tree commit diff
path: root/parse.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2017-02-27 11:14:32 -0500
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2017-02-27 11:14:32 -0500
commit7432b0a64761aa07f95ad19761c61bf11db428e9 (patch)
treed5ab002a15bab9b985c7f070e2c2a91a1491d66b /parse.c
parente80252a52bf25f762bc986ce6e4e0d17fbb130d0 (diff)
downloadroux-7432b0a64761aa07f95ad19761c61bf11db428e9.tar.gz
fix int parsing
The spec says that numbers can be arbitrarily
big, and only the last 64 bits will be taken
into consideration.  Calling sscanf does not
implement this, so I wrote an ad-hoc function.
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/parse.c b/parse.c
index 38481aa..edb6c29 100644
--- a/parse.c
+++ b/parse.c
@@ -254,6 +254,29 @@ lexinit()
 	done = 1;
 }
 
+static int64_t
+getint()
+{
+	uint64_t n;
+	int c, m;
+
+	n = 0;
+	c = fgetc(inf);
+	m = 0;
+	switch (c) {
+	case '-': m = 1;
+	case '+': c = fgetc(inf);
+	}
+	do {
+		n = 10*n + (c - '0');
+		c = fgetc(inf);
+	} while ('0' <= c && c <= '9');
+	ungetc(c, inf);
+	if (m)
+		n = 1 + ~n;
+	return *(int64_t *)&n;
+}
+
 static int
 lex()
 {
@@ -312,8 +335,7 @@ lex()
 	}
 	if (isdigit(c) || c == '-' || c == '+') {
 		ungetc(c, inf);
-		if (fscanf(inf, "%"SCNd64, &tokval.num) != 1)
-			err("invalid integer literal");
+		tokval.num = getint();
 		return Tint;
 	}
 	if (c == '"') {