aboutsummaryrefslogtreecommitdiff
path: root/bcdfp.c
diff options
context:
space:
mode:
Diffstat (limited to 'bcdfp.c')
-rw-r--r--bcdfp.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/bcdfp.c b/bcdfp.c
index 76157c1..a80e55d 100644
--- a/bcdfp.c
+++ b/bcdfp.c
@@ -1,8 +1,18 @@
#include <string.h>
+#include <stdio.h>
#include "bcdfp.h"
+/* very dumb and limited BCD floating point conversions.
+ they're written this way because they're only required to
+ support line numbers, and I don't want to have to link with
+ the math library (-lm). */
+
extern void die(const char *msg);
+void die_range(void) {
+ die("Line number out of range (>65535)");
+}
+
unsigned char bcd2int(unsigned char bcd) {
return (bcd >> 4) * 10 + (bcd & 0x0f);
}
@@ -12,24 +22,32 @@ unsigned char int2bcd(unsigned char i) {
}
unsigned short fp2int(const unsigned char *fp) {
- unsigned short result = 0;
+ unsigned int result = 0;
/* examine the exponent/sign byte */
if(fp[0] == 0) return 0; /* special case */
- if(fp[0] & 0x80) die("negative numbers not supported");
+ if(fp[0] & 0x80) die("Negative line numbers not supported");
switch(fp[0]) {
case 0x40:
- result = bcd2int(fp[1]); break;
+ result = bcd2int(fp[1]);
+ if(fp[2] >= 0x50) result++;
+ break;
case 0x41:
- result = bcd2int(fp[1]) * 100 + bcd2int(fp[2]); break;
+ result = bcd2int(fp[1]) * 100 + bcd2int(fp[2]);
+ if(fp[3] >= 0x50) result++;
+ break;
case 0x42:
- result = bcd2int(fp[1]) * 10000 + bcd2int(fp[2]) * 100 + bcd2int(fp[3]); break;
+ result = bcd2int(fp[1]) * 10000 + bcd2int(fp[2]) * 100 + bcd2int(fp[3]);
+ if(fp[4] >= 0x50) result++;
+ break;
default:
- die("number out of range"); break;
+ die_range(); break;
}
- return result;
+ if(result > 0xffff) die_range();
+
+ return (unsigned short)result;
}
void int2fp(unsigned short num, unsigned char *fp) {