1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-09-20 04:24:48 +00:00

move hex/oct/bin functions to separate file

This commit is contained in:
Matthew Kilgore 2024-02-13 01:39:33 -05:00
parent 231b2cbce5
commit 416c81bb8a
5 changed files with 299 additions and 281 deletions

View file

@ -17632,281 +17632,6 @@ wait:
return;
}
qbs *func__bin(int64 value, int32 neg_bits) {
static int32 i, i2, i3, neg;
static int64 value2;
static qbs *str;
str = qbs_new(64, 1);
// negative?
if ((value >> 63) & 1)
neg = 1;
else
neg = 0;
// calc. most significant bit
i2 = 0;
value2 = value;
if (neg) {
for (i = 1; i <= 64; i++) {
if (!(value2 & 1))
i2 = i;
value2 >>= 1;
}
if (i2 >= neg_bits) {
// doesn't fit in neg_bits, so expand to next 16/32/64 boundary
i3 = 64;
if (i2 < 32)
i3 = 32;
if (i2 < 16)
i3 = 16;
i2 = i3;
} else
i2 = neg_bits;
} else {
for (i = 1; i <= 64; i++) {
if (value2 & 1)
i2 = i;
value2 >>= 1;
}
}
if (!i2) {
str->chr[0] = 48;
str->len = 1;
return str;
} //"0"
// calc. number of characters required in i3
i3 = i2; // equal for BIN$ because one bit = one char
// build string
str->len = i3;
i3--;
for (i = 1; i <= i2; i++) {
str->chr[i3--] = (value & 1) + 48;
value >>= 1;
}
return str;
}
// note: QBASIC doesn't have a BIN$ function
// QB64 uses 32 bin digits for SINGLE/DOUBLE/FLOAT but if this range is exceeded
// it uses up to 64 bin digits before generating an "OVERFLOW" error
// performs overflow check before calling func__bin
qbs *func__bin_float(long double value) {
static qbs *str;
static int64 ivalue;
static int64 uivalue;
// ref: uint64 0-18446744073709551615
// int64 \969223372036854775808 to 9223372036854775807
if ((value >= 9.223372036854776E18) || (value <= -9.223372036854776E18)) {
// note: ideally, the following line would be used, however, qbr_longdouble_to_uint64 just does the same as qbr
// if ((value>=1.844674407370956E19)||(value<=-9.223372036854776E18)){
str = qbs_new(0, 1);
error(6); // Overflow
return str;
}
if (value >= 0) {
uivalue = qbr_longdouble_to_uint64(value);
ivalue = uivalue;
} else {
ivalue = qbr(value);
}
return func__bin(ivalue, 32);
}
qbs *func_oct(int64 value, int32 neg_bits) {
static int32 i, i2, i3, x, x2, neg;
static int64 value2;
static qbs *str;
str = qbs_new(22, 1);
// negative?
if ((value >> 63) & 1)
neg = 1;
else
neg = 0;
// calc. most significant bit
i2 = 0;
value2 = value;
if (neg) {
for (i = 1; i <= 64; i++) {
if (!(value2 & 1))
i2 = i;
value2 >>= 1;
}
if (i2 >= neg_bits) {
// doesn't fit in neg_bits, so expand to next 16/32/64 boundary
i3 = 64;
if (i2 < 32)
i3 = 32;
if (i2 < 16)
i3 = 16;
i2 = i3;
} else
i2 = neg_bits;
} else {
for (i = 1; i <= 64; i++) {
if (value2 & 1)
i2 = i;
value2 >>= 1;
}
}
if (!i2) {
str->chr[0] = 48;
str->len = 1;
return str;
} //"0"
// calc. number of characters required in i3
i3 = i2 / 3;
if ((i3 * 3) != i2)
i3++;
// build string
str->len = i3;
i3--;
x = 0;
x2 = 0;
for (i = 1; i <= i2; i++) {
if (value & 1)
x2 |= (1 << x);
value >>= 1;
x++;
if (x == 3) {
str->chr[i3--] = x2 + 48;
x2 = 0;
x = 0;
}
}
if (x)
str->chr[i3] = x2 + 48;
return str;
}
// note: QBASIC uses 11 oct digits for SINGLE/DOUBLE or generates "OVERFLOW" if this range is exceeded
// QB64 uses 11 oct digits for SINGLE/DOUBLE/FLOAT but if this range is exceeded
// it uses up to 22 oct digits before generating an "OVERFLOW" error
// performs overflow check before calling func_oct
qbs *func_oct_float(long double value) {
static qbs *str;
static int64 ivalue;
static int64 uivalue;
// ref: uint64 0-18446744073709551615
// int64 \969223372036854775808 to 9223372036854775807
if ((value >= 9.223372036854776E18) || (value <= -9.223372036854776E18)) {
// note: ideally, the following line would be used, however, qbr_longdouble_to_uint64 just does the same as qbr
// if ((value>=1.844674407370956E19)||(value<=-9.223372036854776E18)){
str = qbs_new(0, 1);
error(6); // Overflow
return str;
}
if (value >= 0) {
uivalue = qbr_longdouble_to_uint64(value);
ivalue = uivalue;
} else {
ivalue = qbr(value);
}
return func_oct(ivalue, 32);
}
qbs *func_hex(int64 value, int32 neg_size) {
// note: negative int64 values can be treated as positive uint64 values (and vise versa)
static int32 i, i2, i3, x, neg;
static int64 value2;
static qbs *str;
str = qbs_new(16, 1);
value2 = value;
i2 = 0;
i3 = 0;
for (i = 1; i <= 16; i++) {
if (value2 & 15)
i2 = i; // most significant digit of positive value
if ((value2 & 15) != 15) {
i3 = i; // most significant digit of negative value
if ((((value2 & 8) == 0) && (i != 16)))
i3++; // for a negative number to fit into 4/8 characters, its top bit must be on
}
x = value2 & 15;
if (x > 9)
x += 55;
else
x += 48;
str->chr[16 - i] = x;
value2 >>= 4;
}
if (!i2) {
str->chr[0] = 48;
str->len = 1;
return str;
} //"0"
// negative?
if ((value >> 63) & 1)
neg = 1;
else
neg = 0;
// change i2 from sig-digits to string-output-digits
if (neg) {
if (i3 <= neg_size) {
i2 = neg_size; // extend to minimum character size
} else {
// didn't fit in recommended size, expand to either 4, 8 or 16 appropriately
i2 = 16;
if (i3 <= 8)
i2 = 8;
if (i3 <= 4)
i2 = 4;
}
} // neg
// adjust string to the left to remove unnecessary characters
if (i2 != 16) {
memmove(str->chr, str->chr + (16 - i2), i2);
str->len = i2;
}
return str;
}
// note: QBASIC uses 8 hex digits for SINGLE/DOUBLE or generates "OVERFLOW" if this range is exceeded
// QB64 uses 8 hex digits for SINGLE/DOUBLE/FLOAT but if this range is exceeded
// it uses up to 16 hex digits before generating an "OVERFLOW" error
// performs overflow check before calling func_hex
qbs *func_hex_float(long double value) {
static qbs *str;
static int64 ivalue;
static int64 uivalue;
// ref: uint64 0-18446744073709551615
// int64 \969223372036854775808 to 9223372036854775807
if ((value >= 9.223372036854776E18) || (value <= -9.223372036854776E18)) {
// note: ideally, the following line would be used, however, qbr_longdouble_to_uint64 just does the same as qbr
// if ((value>=1.844674407370956E19)||(value<=-9.223372036854776E18)){
str = qbs_new(0, 1);
error(6); // Overflow
return str;
}
if (value >= 0) {
uivalue = qbr_longdouble_to_uint64(value);
ivalue = uivalue;
} else {
ivalue = qbr(value);
}
return func_hex(ivalue, 8);
}
ptrszint func_lbound(ptrszint *array, int32 index, int32 num_indexes) {
if ((index < 1) || (index > num_indexes) || ((array[2] & 1) == 0)) {

View file

@ -11,6 +11,7 @@ libqb-objs-y += $(PATH_LIBQB)/src/datetime.o
libqb-objs-y += $(PATH_LIBQB)/src/error_handle.o
libqb-objs-y += $(PATH_LIBQB)/src/gfs.o
libqb-objs-y += $(PATH_LIBQB)/src/qblist.o
libqb-objs-y += $(PATH_LIBQB)/src/hexoctbin.o
libqb-objs-y += $(PATH_LIBQB)/src/mem.o
libqb-objs-y += $(PATH_LIBQB)/src/math.o
libqb-objs-y += $(PATH_LIBQB)/src/rounding.o

View file

@ -0,0 +1,12 @@
#pragma once
#include <stdint.h>
#include "qbs.h"
qbs *func__bin(int64_t value, int32_t neg_bits);
qbs *func__bin_float(long double value);
qbs *func_oct(int64_t value, int32_t neg_bits);
qbs *func_oct_float(long double value);
qbs *func_hex(int64_t value, int32_t neg_size);
qbs *func_hex_float(long double value);

View file

@ -0,0 +1,285 @@
#include "libqb-common.h"
#include <math.h>
#include <stdint.h>
#include <string.h>
#include "rounding.h"
#include "qbs.h"
#include "hexoctbin.h"
qbs *func__bin(int64_t value, int32_t neg_bits) {
static int32_t i, i2, i3, neg;
static int64_t value2;
static qbs *str;
str = qbs_new(64, 1);
// negative?
if ((value >> 63) & 1)
neg = 1;
else
neg = 0;
// calc. most significant bit
i2 = 0;
value2 = value;
if (neg) {
for (i = 1; i <= 64; i++) {
if (!(value2 & 1))
i2 = i;
value2 >>= 1;
}
if (i2 >= neg_bits) {
// doesn't fit in neg_bits, so expand to next 16/32/64 boundary
i3 = 64;
if (i2 < 32)
i3 = 32;
if (i2 < 16)
i3 = 16;
i2 = i3;
} else
i2 = neg_bits;
} else {
for (i = 1; i <= 64; i++) {
if (value2 & 1)
i2 = i;
value2 >>= 1;
}
}
if (!i2) {
str->chr[0] = 48;
str->len = 1;
return str;
} //"0"
// calc. number of characters required in i3
i3 = i2; // equal for BIN$ because one bit = one char
// build string
str->len = i3;
i3--;
for (i = 1; i <= i2; i++) {
str->chr[i3--] = (value & 1) + 48;
value >>= 1;
}
return str;
}
// note: QBASIC doesn't have a BIN$ function
// QB64 uses 32 bin digits for SINGLE/DOUBLE/FLOAT but if this range is exceeded
// it uses up to 64 bin digits before generating an "OVERFLOW" error
// performs overflow check before calling func__bin
qbs *func__bin_float(long double value) {
static qbs *str;
static int64_t ivalue;
static int64_t uivalue;
// ref: uint64 0-18446744073709551615
// int64 \969223372036854775808 to 9223372036854775807
if ((value >= 9.223372036854776E18) || (value <= -9.223372036854776E18)) {
// note: ideally, the following line would be used, however, qbr_longdouble_to_uint64 just does the same as qbr
// if ((value>=1.844674407370956E19)||(value<=-9.223372036854776E18)){
str = qbs_new(0, 1);
error(6); // Overflow
return str;
}
if (value >= 0) {
uivalue = qbr_longdouble_to_uint64(value);
ivalue = uivalue;
} else {
ivalue = qbr(value);
}
return func__bin(ivalue, 32);
}
qbs *func_oct(int64_t value, int32_t neg_bits) {
static int32_t i, i2, i3, x, x2, neg;
static int64_t value2;
static qbs *str;
str = qbs_new(22, 1);
// negative?
if ((value >> 63) & 1)
neg = 1;
else
neg = 0;
// calc. most significant bit
i2 = 0;
value2 = value;
if (neg) {
for (i = 1; i <= 64; i++) {
if (!(value2 & 1))
i2 = i;
value2 >>= 1;
}
if (i2 >= neg_bits) {
// doesn't fit in neg_bits, so expand to next 16/32/64 boundary
i3 = 64;
if (i2 < 32)
i3 = 32;
if (i2 < 16)
i3 = 16;
i2 = i3;
} else
i2 = neg_bits;
} else {
for (i = 1; i <= 64; i++) {
if (value2 & 1)
i2 = i;
value2 >>= 1;
}
}
if (!i2) {
str->chr[0] = 48;
str->len = 1;
return str;
} //"0"
// calc. number of characters required in i3
i3 = i2 / 3;
if ((i3 * 3) != i2)
i3++;
// build string
str->len = i3;
i3--;
x = 0;
x2 = 0;
for (i = 1; i <= i2; i++) {
if (value & 1)
x2 |= (1 << x);
value >>= 1;
x++;
if (x == 3) {
str->chr[i3--] = x2 + 48;
x2 = 0;
x = 0;
}
}
if (x)
str->chr[i3] = x2 + 48;
return str;
}
// note: QBASIC uses 11 oct digits for SINGLE/DOUBLE or generates "OVERFLOW" if this range is exceeded
// QB64 uses 11 oct digits for SINGLE/DOUBLE/FLOAT but if this range is exceeded
// it uses up to 22 oct digits before generating an "OVERFLOW" error
// performs overflow check before calling func_oct
qbs *func_oct_float(long double value) {
static qbs *str;
static int64_t ivalue;
static int64_t uivalue;
// ref: uint64 0-18446744073709551615
// int64 \969223372036854775808 to 9223372036854775807
if ((value >= 9.223372036854776E18) || (value <= -9.223372036854776E18)) {
// note: ideally, the following line would be used, however, qbr_longdouble_to_uint64 just does the same as qbr
// if ((value>=1.844674407370956E19)||(value<=-9.223372036854776E18)){
str = qbs_new(0, 1);
error(6); // Overflow
return str;
}
if (value >= 0) {
uivalue = qbr_longdouble_to_uint64(value);
ivalue = uivalue;
} else {
ivalue = qbr(value);
}
return func_oct(ivalue, 32);
}
qbs *func_hex(int64_t value, int32_t neg_size) {
// note: negative int64 values can be treated as positive uint64 values (and vise versa)
static int32_t i, i2, i3, x, neg;
static int64_t value2;
static qbs *str;
str = qbs_new(16, 1);
value2 = value;
i2 = 0;
i3 = 0;
for (i = 1; i <= 16; i++) {
if (value2 & 15)
i2 = i; // most significant digit of positive value
if ((value2 & 15) != 15) {
i3 = i; // most significant digit of negative value
if ((((value2 & 8) == 0) && (i != 16)))
i3++; // for a negative number to fit into 4/8 characters, its top bit must be on
}
x = value2 & 15;
if (x > 9)
x += 55;
else
x += 48;
str->chr[16 - i] = x;
value2 >>= 4;
}
if (!i2) {
str->chr[0] = 48;
str->len = 1;
return str;
} //"0"
// negative?
if ((value >> 63) & 1)
neg = 1;
else
neg = 0;
// change i2 from sig-digits to string-output-digits
if (neg) {
if (i3 <= neg_size) {
i2 = neg_size; // extend to minimum character size
} else {
// didn't fit in recommended size, expand to either 4, 8 or 16 appropriately
i2 = 16;
if (i3 <= 8)
i2 = 8;
if (i3 <= 4)
i2 = 4;
}
} // neg
// adjust string to the left to remove unnecessary characters
if (i2 != 16) {
memmove(str->chr, str->chr + (16 - i2), i2);
str->len = i2;
}
return str;
}
// note: QBASIC uses 8 hex digits for SINGLE/DOUBLE or generates "OVERFLOW" if this range is exceeded
// QB64 uses 8 hex digits for SINGLE/DOUBLE/FLOAT but if this range is exceeded
// it uses up to 16 hex digits before generating an "OVERFLOW" error
// performs overflow check before calling func_hex
qbs *func_hex_float(long double value) {
static qbs *str;
static int64_t ivalue;
static int64_t uivalue;
// ref: uint64 0-18446744073709551615
// int64 \969223372036854775808 to 9223372036854775807
if ((value >= 9.223372036854776E18) || (value <= -9.223372036854776E18)) {
// note: ideally, the following line would be used, however, qbr_longdouble_to_uint64 just does the same as qbr
// if ((value>=1.844674407370956E19)||(value<=-9.223372036854776E18)){
str = qbs_new(0, 1);
error(6); // Overflow
return str;
}
if (value >= 0) {
uivalue = qbr_longdouble_to_uint64(value);
ivalue = uivalue;
} else {
ivalue = qbr(value);
}
return func_hex(ivalue, 8);
}

View file

@ -12,6 +12,7 @@
#include "filesystem.h"
#include "font.h"
#include "gui.h"
#include "hexoctbin.h"
#include "image.h"
#include "qbmath.h"
#include "qbs.h"
@ -352,12 +353,6 @@ extern void sub_graphics_put(float x1f, float y1f, void *element, int32 option,
extern int32 func_csrlin();
extern int32 func_pos(int32 ignore);
extern void sub_sleep(int32 seconds, int32 passed);
extern qbs *func__bin(int64 value, int32 neg_bits);
extern qbs *func__bin_float(long double value);
extern qbs *func_oct(int64 value, int32 neg_bits);
extern qbs *func_oct_float(long double value);
extern qbs *func_hex(int64 value, int32 neg_size);
extern qbs *func_hex_float(long double value);
extern ptrszint func_lbound(ptrszint *array, int32 index, int32 num_indexes);
extern ptrszint func_ubound(ptrszint *array, int32 index, int32 num_indexes);