mirror of
https://github.com/irmen/prog8.git
synced 2024-11-24 13:32:28 +00:00
268 lines
7.2 KiB
Lua
268 lines
7.2 KiB
Lua
; Number conversions routines.
|
|
|
|
conv {
|
|
|
|
; ----- number conversions to decimal strings ----
|
|
|
|
str string_out = "????????????????" ; result buffer for the string conversion routines
|
|
|
|
sub str_ub0(ubyte value) {
|
|
; ---- convert the ubyte in A in decimal string form, with left padding 0s (3 positions total)
|
|
ubyte hundreds = value / 100
|
|
value -= hundreds*100
|
|
ubyte tens = value / 10
|
|
value -= tens*10
|
|
string_out[0] = hundreds+'0'
|
|
string_out[1] = tens+'0'
|
|
string_out[2] = value+'0'
|
|
string_out[3] = 0
|
|
}
|
|
|
|
sub str_ub(ubyte value) {
|
|
; ---- convert the ubyte in A in decimal string form, without left padding 0s
|
|
internal_str_ub(value, string_out)
|
|
}
|
|
|
|
sub str_b(byte value) {
|
|
; ---- convert the byte in A in decimal string form, without left padding 0s
|
|
uword out_ptr = &string_out
|
|
if value<0 {
|
|
@(out_ptr) = '-'
|
|
out_ptr++
|
|
value = -value
|
|
}
|
|
internal_str_ub(value as ubyte, out_ptr)
|
|
}
|
|
|
|
sub internal_str_ub(ubyte value, uword out_ptr) {
|
|
ubyte hundreds = value / 100
|
|
value -= hundreds*100
|
|
ubyte tens = value / 10
|
|
value -= tens*10
|
|
if hundreds
|
|
goto output_hundreds
|
|
if tens
|
|
goto output_tens
|
|
goto output_ones
|
|
output_hundreds:
|
|
@(out_ptr) = hundreds+'0'
|
|
out_ptr++
|
|
output_tens:
|
|
@(out_ptr) = tens+'0'
|
|
out_ptr++
|
|
output_ones:
|
|
@(out_ptr) = value+'0'
|
|
out_ptr++
|
|
@(out_ptr) = 0
|
|
}
|
|
|
|
str hex_digits = "0123456789abcdef"
|
|
|
|
sub str_ubhex (ubyte value) {
|
|
; ---- convert the ubyte in A in hex string form
|
|
string_out[0] = hex_digits[value>>4]
|
|
string_out[1] = hex_digits[value&15]
|
|
string_out[2] = 0
|
|
}
|
|
|
|
sub str_ubbin (ubyte value) {
|
|
; ---- convert the ubyte in A in binary string form
|
|
uword out_ptr = &string_out
|
|
repeat 8 {
|
|
rol(value)
|
|
if_cc
|
|
@(out_ptr) = '0'
|
|
else
|
|
@(out_ptr) = '1'
|
|
out_ptr++
|
|
}
|
|
@(out_ptr) = 0
|
|
}
|
|
|
|
sub str_uwbin (uword value) {
|
|
; ---- convert the uword in A/Y in binary string form
|
|
uword out_ptr = &string_out
|
|
repeat 16 {
|
|
rol(value)
|
|
if_cc
|
|
@(out_ptr) = '0'
|
|
else
|
|
@(out_ptr) = '1'
|
|
out_ptr++
|
|
}
|
|
@(out_ptr) = 0
|
|
}
|
|
|
|
sub str_uwhex (uword value) {
|
|
; ---- convert the uword in A/Y in hexadecimal string form (4 digits)
|
|
ubyte bits = msb(value)
|
|
string_out[0] = hex_digits[bits>>4]
|
|
string_out[1] = hex_digits[bits&15]
|
|
bits = lsb(value)
|
|
string_out[2] = hex_digits[bits>>4]
|
|
string_out[3] = hex_digits[bits&15]
|
|
string_out[4] = 0
|
|
}
|
|
|
|
sub str_uw0 (uword value) {
|
|
; ---- convert the uword in A/Y in decimal string form, with left padding 0s (5 positions total)
|
|
uword value2 = value/10
|
|
ubyte digits = value-value2*10 as ubyte
|
|
uword value3 = value2/10
|
|
ubyte tens = value2-value3*10 as ubyte
|
|
uword value4 = value3/10
|
|
ubyte hundreds = value3-value4*10 as ubyte
|
|
uword value5 = value4/10
|
|
ubyte thousands = value4-value5*10 as ubyte
|
|
uword value6 = value5/10
|
|
ubyte tenthousands = value5-value6*10 as ubyte
|
|
string_out[0] = tenthousands+'0'
|
|
string_out[1] = thousands+'0'
|
|
string_out[2] = hundreds+'0'
|
|
string_out[3] = tens+'0'
|
|
string_out[4] = digits+'0'
|
|
string_out[5] = 0
|
|
}
|
|
|
|
sub str_uw (uword value) {
|
|
; ---- convert the uword in A/Y in decimal string form, without left padding 0s
|
|
internal_str_uw(value, string_out)
|
|
}
|
|
|
|
sub str_w (word value) {
|
|
; ---- convert the (signed) word in A/Y in decimal string form, without left padding 0's
|
|
uword out_ptr = &string_out
|
|
if value<0 {
|
|
@(out_ptr) = '-'
|
|
out_ptr++
|
|
value = -value
|
|
}
|
|
internal_str_uw(value as uword, out_ptr)
|
|
}
|
|
|
|
sub internal_str_uw(uword value, uword out_ptr) {
|
|
uword value2 = value/10
|
|
ubyte digits = value-value2*10 as ubyte
|
|
uword value3 = value2/10
|
|
ubyte tens = value2-value3*10 as ubyte
|
|
uword value4 = value3/10
|
|
ubyte hundreds = value3-value4*10 as ubyte
|
|
uword value5 = value4/10
|
|
ubyte thousands = value4-value5*10 as ubyte
|
|
uword value6 = value5/10
|
|
ubyte tenthousands = value5-value6*10 as ubyte
|
|
if tenthousands
|
|
goto output_tenthousands
|
|
if thousands
|
|
goto output_thousands
|
|
if hundreds
|
|
goto output_hundreds
|
|
if tens
|
|
goto output_tens
|
|
goto output_ones
|
|
output_tenthousands:
|
|
@(out_ptr) = tenthousands+'0'
|
|
out_ptr++
|
|
output_thousands:
|
|
@(out_ptr) = thousands+'0'
|
|
out_ptr++
|
|
output_hundreds:
|
|
@(out_ptr) = hundreds+'0'
|
|
out_ptr++
|
|
output_tens:
|
|
@(out_ptr) = tens+'0'
|
|
out_ptr++
|
|
output_ones:
|
|
@(out_ptr) = digits+'0'
|
|
out_ptr++
|
|
@(out_ptr) = 0
|
|
}
|
|
|
|
|
|
; ---- string conversion to numbers -----
|
|
|
|
sub str2ubyte(str string) -> ubyte {
|
|
; -- returns in A the unsigned byte value of the string number argument in AY
|
|
; the number may NOT be preceded by a + sign and may NOT contain spaces
|
|
; (any non-digit character will terminate the number string that is parsed)
|
|
return str2uword(string) as ubyte
|
|
}
|
|
|
|
sub str2byte(str string) -> byte {
|
|
; -- returns in A the signed byte value of the string number argument in AY
|
|
; the number may be preceded by a + or - sign but may NOT contain spaces
|
|
; (any non-digit character will terminate the number string that is parsed)
|
|
return str2word(string) as byte
|
|
}
|
|
|
|
sub str2uword(str string) -> uword {
|
|
; -- returns the unsigned word value of the string number argument in AY
|
|
; the number may NOT be preceded by a + sign and may NOT contain spaces
|
|
; (any non-digit character will terminate the number string that is parsed)
|
|
%ir {{
|
|
loadm.w r65535,conv.str2uword.string
|
|
syscall 11 (r65535.w) : r0.w
|
|
returnr.w r0
|
|
}}
|
|
}
|
|
|
|
sub str2word(str string) -> word {
|
|
; -- returns the signed word value of the string number argument in AY
|
|
; the number may be preceded by a + or - sign but may NOT contain spaces
|
|
; (any non-digit character will terminate the number string that is parsed)
|
|
%ir {{
|
|
loadm.w r65535,conv.str2word.string
|
|
syscall 12 (r65535.w) : r0.w
|
|
returnr.w r0
|
|
}}
|
|
}
|
|
|
|
sub hex2uword(str string) -> uword {
|
|
; -- hexadecimal string (with or without '$') to uword.
|
|
; stops parsing at the first character that's not a hex digit (except leading $)
|
|
uword result
|
|
ubyte char
|
|
if @(string)=='$'
|
|
string++
|
|
repeat {
|
|
char = @(string)
|
|
if char==0
|
|
return result
|
|
result <<= 4
|
|
if char>='0' and char<='9'
|
|
result |= char-'0'
|
|
else
|
|
result |= char-'a'+10
|
|
string++
|
|
}
|
|
}
|
|
|
|
sub bin2uword(str string) -> uword {
|
|
; -- binary string (with or without '%') to uword.
|
|
; stops parsing at the first character that's not a 0 or 1. (except leading %)
|
|
uword result
|
|
ubyte char
|
|
if @(string)=='%'
|
|
string++
|
|
repeat {
|
|
char = @(string)
|
|
if char==0
|
|
return result
|
|
result <<= 1
|
|
if char=='1'
|
|
result |= 1
|
|
string++
|
|
}
|
|
}
|
|
|
|
sub any2uword(str string) -> uword {
|
|
; -- convert any number string (any prefix allowed) to uword.
|
|
when string[0] {
|
|
'$' -> return hex2uword(string)
|
|
'%' -> return bin2uword(string)
|
|
else -> return str2uword(string)
|
|
}
|
|
}
|
|
|
|
}
|