1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-25 19:29:49 +00:00

Standard library improvements

This commit is contained in:
Karol Stasiak 2018-12-19 19:01:53 +01:00
parent 30d18fba01
commit 05884f2c7b
17 changed files with 236 additions and 68 deletions

View File

@ -39,9 +39,11 @@
* [`stdlib` module](stdlib/stdlib.md)
* [`string` module](stdlib/string.md)
* [Modules for reading input devices](stdlib/input.md)
* [Other cross-platform modules](stdlib/other.md)
* [Other cross-platform modules (`err`, `stdio`)](stdlib/other.md)
* [Definitions available on only some platforms](stdlib/frequent.md)

View File

@ -84,6 +84,10 @@ The following features are defined based on the chosen CPU and compilation optio
* `CPM` 1 if the target is CP/M, 0 otherwise
* `NTSC` 1 if the target is NTSC, 0 otherwise
* `PAL` 1 if the target is PAL, 0 otherwise
### Built-in preprocessor functions and operators
The `defined` function returns 1 if the feature is defined, 0 otherwise.

View File

@ -16,6 +16,19 @@ Moves the cursor to the next line.
Available for: all computer targets.
#### `pointer readline()`
Reads a line from the console and returns a pointer to a null-terminated string.
The string is valid only until next read from the console.
Available for: Commodore 64 with `c64_basic` module.
#### `word readword()`
Reads a 16-bit unsigned integer from the console.
Available for: Commodore 64 with `c64_basic` module.
#### `void bell()`
Beeps.

View File

@ -2,7 +2,7 @@
## stdio
The `stdio` module automatically imports the `string` module.
The `stdio` module automatically imports the `string` and `err` modules.
It requires an implementation of `void putchar(byte a)` and therefore works only on targets with console output.
#### `void putstr(pointer str, byte len)`
@ -14,9 +14,13 @@ Prints a string of length `len` located at address `str`.
Prints a null-terminated string located at address `str`.
If the string is longer than 255 bytes, then the behaviour is undefined (might even crash).
## string
#### `byte strzlen(pointer str)`
## err
Calculates the length of a null-terminated string.
If the string is longer than 255 bytes, then the behaviour is undefined (might even crash).
#### `enum error_number`
Standard error codes. All codes other than `err_ok` suggest that the last operation failed.
#### `error_number errno`
The result of the last operation.

View File

@ -0,0 +1,25 @@
[< back to index](../index.md)
## string
The `string` module automatically imports the `err` module.
#### `byte strzlen(pointer str)`
Calculates the length of a null-terminated string.
If the string is longer than 255 bytes, then the behaviour is undefined (might even crash).
#### `sbyte strzcmp(pointer str1, pointer str2)`
Compares two strings. Returns 0 if equal, non-0 if not equal.
If any of the strings is longer than 255 bytes, then the behaviour is undefined (might even crash).
#### `void strzcopy(pointer dest, pointer src)`
Copies the source null-terminated string into the destination buffer.
If the source string is longer than 255 bytes, then the behaviour is undefined (might even crash).
#### `word strz2word(pointer str)`
Converts a null-terminated string to a number.
Sets `errno`.

View File

@ -5,22 +5,25 @@ void main() {
word a
word b
putstrz("enter first number:{n}"z)
putstrz("enter first number:"z)
new_line()
a = readword()
while readword_err != 0 {
putstrz("that wasn't a number, try again:{n}"z)
while errno != err_ok {
putstrz("that wasn't a number, try again:"z)
new_line()
a = readword()
}
putstrz("enter second number:{n}"z)
b = readword()
while readword_err != 0 {
putstrz("that wasn't a number, try again:{n}"z)
while errno != err_ok {
putstrz("that wasn't a number, try again:"z)
new_line()
b = readword()
}
putstrz("the sum is:{n}"z)
a += b
putword(a)
putchar(13)
putstrz("the sum is:"z)
new_line()
putword(a + b)
new_line()
}

View File

@ -20,6 +20,7 @@ KEYBOARD=1
; TODO: ?
JOYSTICKS=1
HAS_BITMAP_MODE=1
PAL=1
[output]
style=single

View File

@ -5,41 +5,26 @@
#endif
import c64_kernal
import err
// print a 16-bit number on the standard output
asm void putword(word xa) @$BDCD extern
asm void readline() @$A560 extern
asm void putword_basic(word xa) @$BDCD extern
//alias putword = putword_basic!
asm void __readline_basic() @$A560 extern
pointer readline_basic() {
__readline_basic()
return readline_out
}
alias readline = readline_basic!
const pointer readline_out = $200
byte readword_err
word readword() {
readline()
readword_err = 0
word result
word four
result = 0
byte char
byte i
i = 0
while true {
char = readline_out[i]
if char == 0 {
if i == 0 {
readword_err = 1
}
return result
}
if 48 <= char <= 48+9 {
four = result
four <<= 2
result += four
result <<= 1
result += char - 48
} else {
readword_err = 1
return result
}
i += 1
}
inline word readword_basic() {
return strz2word(readline_basic())
}
alias readword = readword_basic!

11
include/err.mfk Normal file
View File

@ -0,0 +1,11 @@
enum error_number {
err_ok
err_fail
err_numberformat
err_outofmemory
err_domain
err_range
}
error_number errno

View File

@ -19,6 +19,7 @@ KEYBOARD=1
; TODO:
JOYSTICKS=1
HAS_BITMAP_MODE=1
NTSC=1
[output]
style=single

View File

@ -27,3 +27,28 @@ void putstrz(pointer str) {
#endif
void putword(word w) {
byte digits
byte lastdigit
digits = 0
word mask
for mask:[40000,4000,400,40,4] {
lastdigit = 0
while w >= mask {
w -= mask
lastdigit += 4
}
mask >>= 2
while w >= mask {
w -= mask
lastdigit += 1
}
if digits != 0 || lastdigit != 0 {
putchar('0' + lastdigit)
digits += 1
}
}
if digits == 0 {
putchar('0')
}
}

View File

@ -7,3 +7,7 @@ import stdlib_i80
#else
#warn Unsupported architecture
#endif
#if PAL && NTSC
#warn PAL and NTSC enabled simultaneously
#endif

View File

@ -29,7 +29,7 @@ asm byte hi_nibble_to_hex(byte a) {
LSR
LSR
LSR
JMP lo_nibble_to_hex
? JMP lo_nibble_to_hex
}
asm byte lo_nibble_to_hex(byte a) {
@ -40,7 +40,7 @@ asm byte lo_nibble_to_hex(byte a) {
BCC _lo_nibble_to_hex_lbl
ADC #$6 // carry is set
_lo_nibble_to_hex_lbl:
RTS
? RTS
}
macro asm void panic() {

View File

@ -1,23 +1,39 @@
import err
#if ARCH_I80
byte strzlen(pointer str) {
pointer end
end = str
while end[0] != 0 {
end += 1
}
return lo(end - str)
}
import string_fastpointers
#else
import string_fastindices
#endif
byte strzlen(pointer str) {
byte index
index = 0
while str[index] != 0 {
index += 1
word strz2word(pointer str) {
byte i
byte char
word next
word result
result = 0
i = 0
errno = err_ok
while true {
char = str[i]
if char == 0 {
if i == 0 {
errno = err_numberformat
}
return result
}
if '0' <= char <= '0' + 9 {
next = result * 10
next += char - '0'
if next < result {
errno = err_range
}
result = next
} else {
errno = err_numberformat
return result
}
i += 1
}
return index
}
#endif

View File

@ -0,0 +1,37 @@
byte strzlen(pointer str) {
byte index
index = 0
while str[index] != 0 {
index += 1
}
return index
}
sbyte strzcmp(pointer str1, pointer str2) {
byte i1
byte i2
i1 = 0
i2 = 0
while true {
if str1[i1] != str2[i2] {
if str1[i1] < str2[i2] { return -1 }
return 1
}
if str1[i1] == 0 {
return 0
}
i1 += 1
i2 += 1
}
}
void strzcopy(pointer dest, pointer src) {
byte i
byte c
i = 0
do {
c = src[i]
dest[i] = c
i += 1
} while c != 0
}

View File

@ -0,0 +1,37 @@
#pragma zilog_syntax
byte strzlen(pointer str) {
pointer end
end = str
while end[0] != 0 {
end += 1
}
return lo(end - str)
}
sbyte strzcmp(pointer str1, pointer str2) {
while true {
if str1[0] == 0 {
if str2[0] == 0 {
return 0
} else {
return -1
}
} else if str1[0] != str2[0] {
if str1[0] < str2[0] { return -1 }
return 1
}
str1 += 1
str2 += 1
}
}
void strzcopy(pointer dest, pointer src) {
byte c
do {
c = src[0]
dest[0] = c
src += 1
dest += 1
} while c != 0
}

View File

@ -353,7 +353,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
addThing(ConstantThing("true", NumericConstant(1, 0), trueType), None)
addThing(ConstantThing("false", NumericConstant(0, 0), falseType), None)
addThing(ConstantThing("__zeropage_usage", UnexpandedConstant("__zeropage_usage", 1), b), None)
addThing(ConstantThing("__heap_start", UnexpandedConstant("__heap_start", 1), b), None)
addThing(ConstantThing("__heap_start", UnexpandedConstant("__heap_start", 2), p), None)
addThing(ConstantThing("$0000", NumericConstant(0, 2), p), None)
addThing(FlagBooleanType("set_carry",
BranchingOpcodeMapping(Opcode.BCS, IfFlagSet(ZFlag.C)),