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

Merge pull request #458 from mkilgore/libqb-refactor

Libqb refactor - Part 5
This commit is contained in:
Matt Kilgore 2024-02-19 16:40:14 -05:00 committed by GitHub
commit 2693733b37
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 303 additions and 281 deletions

View file

@ -12776,6 +12776,8 @@ int32 hexoct2uint64(qbs *h) {
hexoct2uint64_value = result; hexoct2uint64_value = result;
return 3; return 3;
} // type == 3 } // type == 3
return 0;
} }
// input method (complex, calls other qbs functions) // input method (complex, calls other qbs functions)
@ -17632,281 +17634,6 @@ wait:
return; 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) { ptrszint func_lbound(ptrszint *array, int32 index, int32 num_indexes) {
if ((index < 1) || (index > num_indexes) || ((array[2] & 1) == 0)) { if ((index < 1) || (index > num_indexes) || ((array[2] & 1) == 0)) {
@ -18810,6 +18537,7 @@ qbs *func_input(int32 n, int32 i, int32 passed) {
// RANDOM (todo) // RANDOM (todo)
return str;
} else { } else {
// keyboard/piped // keyboard/piped
// For extended-two-byte character codes, only the first, CHR$(0), is returned and counts a 1 byte // For extended-two-byte character codes, only the first, CHR$(0), is returned and counts a 1 byte
@ -23984,6 +23712,7 @@ int32 connection_new(int32 method, qbs *info_in, int32 value) {
} //_OPENCONNECTION } //_OPENCONNECTION
return -1;
} // connection_new } // connection_new
// network prototype: // network prototype:

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/error_handle.o
libqb-objs-y += $(PATH_LIBQB)/src/gfs.o libqb-objs-y += $(PATH_LIBQB)/src/gfs.o
libqb-objs-y += $(PATH_LIBQB)/src/qblist.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/mem.o
libqb-objs-y += $(PATH_LIBQB)/src/math.o libqb-objs-y += $(PATH_LIBQB)/src/math.o
libqb-objs-y += $(PATH_LIBQB)/src/rounding.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 "filesystem.h"
#include "font.h" #include "font.h"
#include "gui.h" #include "gui.h"
#include "hexoctbin.h"
#include "image.h" #include "image.h"
#include "qbmath.h" #include "qbmath.h"
#include "qbs.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_csrlin();
extern int32 func_pos(int32 ignore); extern int32 func_pos(int32 ignore);
extern void sub_sleep(int32 seconds, int32 passed); 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_lbound(ptrszint *array, int32 index, int32 num_indexes);
extern ptrszint func_ubound(ptrszint *array, int32 index, int32 num_indexes); extern ptrszint func_ubound(ptrszint *array, int32 index, int32 num_indexes);