removed all string related builtin functions and moved them to separate routines in new 'string' library module

This commit is contained in:
Irmen de Jong 2021-01-07 20:01:11 +01:00
parent ee7f9d457d
commit 58f37513e7
27 changed files with 375 additions and 447 deletions

View File

@ -7,16 +7,14 @@ indent_size = 4
indent_style = space
insert_final_newline = true
max_line_length = 120
tab_width = 4
tab_width = 8
trim_trailing_whitespace = true
ij_smart_tabs = true
[*.p8]
tab_width = 4
indent_size = 4
indent_style = space
[*.asm]
tab_width = 8
indent_size = 8
indent_style = tab

View File

@ -3,6 +3,7 @@
; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
%import textio
%import string
%import syslib
diskio {
@ -84,7 +85,7 @@ io_error:
name_ptrs++
@(name_ptrs) = msb(names_buffer)
name_ptrs++
names_buffer += strcopy(diskio.list_filename, names_buffer) + 1
names_buffer += string.copy(diskio.list_filename, names_buffer) + 1
files_found++
if names_buffer - buffer_start > 512-18
break
@ -204,7 +205,7 @@ close_end:
; note: only a single iteration loop can be active at a time!
f_close()
c64.SETNAM(strlen(filenameptr), filenameptr)
c64.SETNAM(string.length(filenameptr), filenameptr)
c64.SETLFS(11, drivenumber, 3)
void c64.OPEN() ; open 11,8,0,"filename"
if_cc {
@ -373,7 +374,7 @@ io_error:
sub save(ubyte drivenumber, uword filenameptr, uword address, uword size) -> ubyte {
c64.SETNAM(strlen(filenameptr), filenameptr)
c64.SETNAM(string.length(filenameptr), filenameptr)
c64.SETLFS(1, drivenumber, 0)
uword end_address = address + size
@ -403,7 +404,7 @@ io_error:
}
sub load(ubyte drivenumber, uword filenameptr, uword address_override) -> uword {
c64.SETNAM(strlen(filenameptr), filenameptr)
c64.SETNAM(string.length(filenameptr), filenameptr)
ubyte secondary = 1
uword end_of_load = 0
if address_override
@ -435,7 +436,7 @@ io_error:
sub delete(ubyte drivenumber, uword filenameptr) {
; -- delete a file on the drive
ubyte flen = strlen(filenameptr)
ubyte flen = string.length(filenameptr)
filename[0] = 's'
filename[1] = ':'
memcopy(filenameptr, &filename+2, flen+1)
@ -448,8 +449,8 @@ io_error:
sub rename(ubyte drivenumber, uword oldfileptr, uword newfileptr) {
; -- rename a file on the drive
ubyte flen_old = strlen(oldfileptr)
ubyte flen_new = strlen(newfileptr)
ubyte flen_old = string.length(oldfileptr)
ubyte flen_new = string.length(newfileptr)
filename[0] = 'r'
filename[1] = ':'
memcopy(newfileptr, &filename+2, flen_new)

View File

@ -1204,205 +1204,3 @@ func_memcopy255 .proc
ldx P8ZP_SCRATCH_REG
rts
.pend
func_leftstr .proc
; leftstr(source, target, length)
lda _arg_source
ldy _arg_source+1
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda _arg_target
ldy _arg_target+1
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1
ldy _arg_length
lda #0
sta (P8ZP_SCRATCH_W2),y
cpy #0
bne _loop
rts
_loop dey
lda (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W2),y
cpy #0
bne _loop
+ rts
_arg_source .word 0
_arg_target .word 0
_arg_length .byte 0
.pend
func_rightstr .proc
; rightstr(source, target, length)
lda _arg_source
ldy _arg_source+1
jsr func_strlen_into_A
sec
sbc _arg_length
sta P8ZP_SCRATCH_B1
lda _arg_source
ldy _arg_source+1
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda _arg_target
ldy _arg_target+1
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1
ldy #0
sty P8ZP_SCRATCH_REG
- ldy P8ZP_SCRATCH_B1
lda (P8ZP_SCRATCH_W1),y
inc P8ZP_SCRATCH_B1
ldy P8ZP_SCRATCH_REG
sta (P8ZP_SCRATCH_W2),y
inc P8ZP_SCRATCH_REG
cmp #0
bne -
rts
_arg_source .word 0
_arg_target .word 0
_arg_length .byte 0
.pend
func_strlen_into_A .proc
; -- put length of 0-terminated string in A/Y into A
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy #0
- lda (P8ZP_SCRATCH_W1),y
beq +
iny
bne -
+ tya
rts
.pend
func_strlen_stack .proc
jsr func_strlen_into_A
sta P8ESTACK_LO,x
dex
rts
.pend
func_substr .proc
; substr(source, target, start, length)
lda _arg_source
ldy _arg_source+1
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda _arg_target
ldy _arg_target+1
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1
ldy _arg_length
lda _arg_start
sta P8ZP_SCRATCH_B1
; adjust src location
clc
lda P8ZP_SCRATCH_W1
adc P8ZP_SCRATCH_B1
sta P8ZP_SCRATCH_W1
bcc +
inc P8ZP_SCRATCH_W1+1
+ lda #0
sta (P8ZP_SCRATCH_W2),y
jmp _startloop
- lda (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W2),y
_startloop dey
cpy #$ff
bne -
rts
_arg_source .word 0
_arg_target .word 0
_arg_start .byte 0
_arg_length .byte 0
.pend
func_strcmp .proc
; -- compare 2 strings -> A
lda _arg_s2
ldy _arg_s2+1
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1
lda _arg_s1
ldy _arg_s1+1
jmp strcmp_mem
_arg_s1 .word 0
_arg_s2 .word 0
.pend
func_strcmp_stack .proc
jsr func_strcmp
sta P8ESTACK_LO,x
dex
rts
.pend
func_strcopy .proc
lda _arg_to
ldy _arg_to+1
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda _arg_from
ldy _arg_from+1
jsr strcpy
tya
rts
_arg_from .word 0
_arg_to .word 0
.pend
func_strcopy_to_stack .proc
jsr func_strcopy
sta P8ESTACK_LO,x
dex
rts
.pend
func_strfind .proc
lda _arg_string
ldy _arg_string+1
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy #0
- lda (P8ZP_SCRATCH_W1),y
beq _notfound
cmp _arg_char
beq _found
iny
bne -
_notfound lda #0
ldy #0
rts
_found sty P8ZP_SCRATCH_B1
lda P8ZP_SCRATCH_W1
clc
adc P8ZP_SCRATCH_B1
sta P8ZP_SCRATCH_W1
bcc +
inc P8ZP_SCRATCH_W1+1
+ ldy P8ZP_SCRATCH_W1+1
rts
_arg_string .word 0
_arg_char .byte 0
.pend
func_strfind_stack .proc
jsr func_strfind
sta P8ESTACK_LO,x
sty P8ESTACK_HI,x
dex
rts
.pend

View File

@ -5,5 +5,189 @@
string {
asmsub length(uword string @AY) clobbers(A) -> ubyte @Y {
; Returns the number of bytes in the string.
; This value is determined during runtime and counts upto the first terminating 0 byte in the string,
; regardless of the size of the string during compilation time. Dont confuse this with len and sizeof!
%asm {{
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy #0
- lda (P8ZP_SCRATCH_W1),y
beq +
iny
bne -
+ rts
}}
}
asmsub left(uword source @R0, ubyte length @A, uword target @R1) clobbers(A, Y) {
; Copies the left side of the source string of the given length to target string.
; It is assumed the target string buffer is large enough to contain the result.
; Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
; Modifies in-place, doesnt return a value (so cant be used in an expression).
%asm {{
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
ldy cx16.r0
sty P8ZP_SCRATCH_W1
ldy cx16.r0+1
sty P8ZP_SCRATCH_W1+1
ldy cx16.r1
sty P8ZP_SCRATCH_W2
ldy cx16.r1+1
sty P8ZP_SCRATCH_W2+1
tay
lda #0
sta (P8ZP_SCRATCH_W2),y
cpy #0
bne _loop
rts
_loop dey
lda (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W2),y
cpy #0
bne _loop
+ rts
}}
; asmgen.out(" jsr prog8_lib.func_leftstr")
}
asmsub right(uword source @R0, ubyte length @A, uword target @R1) clobbers(A,Y) {
; Copies the right side of the source string of the given length to target string.
; It is assumed the target string buffer is large enough to contain the result.
; Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
; Modifies in-place, doesnt return a value (so cant be used in an expression).
%asm {{
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
sta P8ZP_SCRATCH_B1
lda cx16.r0
ldy cx16.r0+1
jsr string.length
tya
sec
sbc P8ZP_SCRATCH_B1
clc
adc cx16.r0
sta P8ZP_SCRATCH_W1
lda cx16.r0+1
adc #0
sta P8ZP_SCRATCH_W1+1
ldy cx16.r1
sty P8ZP_SCRATCH_W2
ldy cx16.r1+1
sty P8ZP_SCRATCH_W2+1
ldy P8ZP_SCRATCH_B1
lda #0
sta (P8ZP_SCRATCH_W2),y
cpy #0
bne _loop
rts
_loop dey
lda (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W2),y
cpy #0
bne _loop
+ rts
}}
}
asmsub slice(uword source @R0, ubyte start @A, ubyte length @Y, uword target @R1) clobbers(A, Y) {
; Copies a segment from the source string, starting at the given index,
; and of the given length to target string.
; It is assumed the target string buffer is large enough to contain the result.
; Also, you have to make sure yourself that start and length are within bounds of the strings.
; Modifies in-place, doesnt return a value (so cant be used in an expression).
%asm {{
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
; substr(source, target, start, length)
sta P8ZP_SCRATCH_B1
lda cx16.r0
sta P8ZP_SCRATCH_W1
lda cx16.r0+1
sta P8ZP_SCRATCH_W1+1
lda cx16.r1
sta P8ZP_SCRATCH_W2
lda cx16.r1+1
sta P8ZP_SCRATCH_W2+1
; adjust src location
clc
lda P8ZP_SCRATCH_W1
adc P8ZP_SCRATCH_B1
sta P8ZP_SCRATCH_W1
bcc +
inc P8ZP_SCRATCH_W1+1
+ lda #0
sta (P8ZP_SCRATCH_W2),y
beq _startloop
- lda (P8ZP_SCRATCH_W1),y
sta (P8ZP_SCRATCH_W2),y
_startloop dey
cpy #$ff
bne -
rts
}}
}
asmsub find(uword string @R0, ubyte character @A) -> uword @AY {
; Locates the first position of the given character in the string,
; returns the string starting with this character or $0000 if the character is not found.
%asm {{
; need to copy the the cx16 virtual registers to zeropage to be compatible with C64...
sta P8ZP_SCRATCH_B1
lda cx16.r0
ldy cx16.r0+1
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy #0
- lda (P8ZP_SCRATCH_W1),y
beq _notfound
cmp P8ZP_SCRATCH_B1
beq _found
iny
bne -
_notfound lda #0
ldy #0
rts
_found sty P8ZP_SCRATCH_B1
ldy P8ZP_SCRATCH_W1+1
lda P8ZP_SCRATCH_W1
clc
adc P8ZP_SCRATCH_B1
bcc +
iny
+ rts
}}
}
asmsub copy(uword source @R0, uword target @AY) clobbers(A) -> ubyte @Y {
; Copy a string to another, overwriting that one.
; Returns the length of the string that was copied.
; Often you dont have to call this explicitly and can just write string1 = string2
; but this function is useful if youre dealing with addresses for instance.
%asm {{
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda cx16.r0
ldy cx16.r0+1
jmp prog8_lib.strcpy
}}
}
asmsub compare(uword string1 @R0, uword string2 @AY) clobbers(Y) -> ubyte @A {
; Compares two strings for sorting.
; Returns -1 (255), 0 or 1 depeding on wether string1 sorts before, equal or after string2.
; Note that you can also directly compare strings and string values with eachother using
; comparison operators ==, < etcetera (it will use strcmp for you under water automatically).
%asm {{
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1
lda cx16.r0
ldy cx16.r0+1
jmp prog8_lib.strcmp_mem
}}
}
}

View File

@ -79,21 +79,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
"set_carry" -> asmgen.out(" sec")
"clear_irqd" -> asmgen.out(" cli")
"set_irqd" -> asmgen.out(" sei")
"strlen" -> funcStrlen(fcall, resultToStack)
"strfind" -> funcStrfind(fcall, func, resultToStack, sscope)
"strcmp" -> funcStrcmp(fcall, func, resultToStack, sscope)
"strcopy" -> {
translateArguments(fcall.args, func, sscope)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_strcopy_to_stack")
else
asmgen.out(" jsr prog8_lib.func_strcopy")
}
"memcopy", "memset", "memsetw" -> funcMemSetCopy(fcall, func, sscope)
"substr", "leftstr", "rightstr" -> {
translateArguments(fcall.args, func, sscope)
asmgen.out(" jsr prog8_lib.func_${func.name}")
}
"exit" -> {
translateArguments(fcall.args, func, sscope)
asmgen.out(" jmp prog8_lib.func_exit")
@ -198,22 +184,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
}
private fun funcStrfind(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_strfind_stack")
else
asmgen.out(" jsr prog8_lib.func_strfind")
}
private fun funcStrcmp(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_strcmp_stack")
else
asmgen.out(" jsr prog8_lib.func_strcmp")
}
private fun funcSqrt16(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, scope: Subroutine?) {
translateArguments(fcall.args, func, scope)
if(resultToStack)
@ -588,27 +558,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
}
private fun funcStrlen(fcall: IFunctionCall, resultToStack: Boolean) {
if (fcall.args[0] is IdentifierReference) {
// use the address of the variable
val name = asmgen.asmVariableName(fcall.args[0] as IdentifierReference)
val type = fcall.args[0].inferType(program)
when {
type.istype(DataType.STR) -> asmgen.out(" lda #<$name | ldy #>$name")
type.istype(DataType.UWORD) -> asmgen.out(" lda $name | ldy $name+1")
else -> throw AssemblyError("strlen requires str or uword arg")
}
}
else {
// use the expression value as address of the string
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
}
if (resultToStack)
asmgen.out(" jsr prog8_lib.func_strlen_stack")
else
asmgen.out(" jsr prog8_lib.func_strlen_into_A")
}
private fun funcSwap(fcall: IFunctionCall) {
val first = fcall.args[0]
val second = fcall.args[1]

View File

@ -159,24 +159,7 @@ private val functionSignatures: List<FSignature> = listOf(
FSignature("memsetw" , false, listOf(
FParam("address", IterableDatatypes + DataType.UWORD),
FParam("numwords", setOf(DataType.UWORD)),
FParam("wordvalue", setOf(DataType.UWORD, DataType.WORD))), null),
FSignature("strlen" , true, listOf(FParam("string", StringlyDatatypes)), DataType.UBYTE, ::builtinStrlen),
FSignature("strcopy" , false, listOf(FParam("from", StringlyDatatypes), FParam("to", StringlyDatatypes)), DataType.UBYTE),
FSignature("substr" , false, listOf(
FParam("source", StringlyDatatypes),
FParam("target", StringlyDatatypes),
FParam("start", setOf(DataType.UBYTE)),
FParam("length", setOf(DataType.UBYTE))), null),
FSignature("leftstr" , false, listOf(
FParam("source", StringlyDatatypes),
FParam("target", StringlyDatatypes),
FParam("length", setOf(DataType.UBYTE))), null),
FSignature("rightstr" , false, listOf(
FParam("source", StringlyDatatypes),
FParam("target", StringlyDatatypes),
FParam("length", setOf(DataType.UBYTE))), null),
FSignature("strcmp" , true, listOf(FParam("s1", StringlyDatatypes), FParam("s2", StringlyDatatypes)), DataType.BYTE, null),
FSignature("strfind" , true, listOf(FParam("string", StringlyDatatypes), FParam("char", setOf(DataType.UBYTE))), DataType.STR, null)
FParam("wordvalue", setOf(DataType.UWORD, DataType.WORD))), null)
)
val BuiltinFunctions = functionSignatures.associateBy { it.name }
@ -355,23 +338,6 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
}
}
private fun builtinStrlen(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("strlen requires one argument", position)
val argument=args[0]
if(argument is StringLiteralValue)
return NumericLiteralValue.optimalInteger(argument.value.length, argument.position)
val vardecl = (argument as? IdentifierReference)?.targetVarDecl(program.namespace)
if(vardecl!=null) {
if(vardecl.datatype!=DataType.STR && vardecl.datatype!=DataType.UWORD)
throw SyntaxError("strlen must have string argument", position)
if(vardecl.autogeneratedDontRemove && vardecl.value!=null) {
return NumericLiteralValue.optimalInteger((vardecl.value as StringLiteralValue).value.length, argument.position)
}
}
throw NotConstArgumentException()
}
private fun builtinLen(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
// note: in some cases the length is > 255 and then we have to return a UWORD type instead of a UBYTE.
if(args.size!=1)

View File

@ -65,6 +65,49 @@ Provides several routines that deal with disk drive I/O, such as:
- delete and rename files on the disk
string
------
Provides string manipulation routines.
length(str) -> ubyte length
Number of bytes in the string. This value is determined during runtime and counts upto
the first terminating 0 byte in the string, regardless of the size of the string during compilation time.
Don't confuse this with ``len`` and ``sizeof``
left(source, length, target)
Copies the left side of the source string of the given length to target string.
It is assumed the target string buffer is large enough to contain the result.
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
Modifies in-place, doesn't return a value (so can't be used in an expression).
right(source, length, target)
Copies the right side of the source string of the given length to target string.
It is assumed the target string buffer is large enough to contain the result.
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
Modifies in-place, doesn't return a value (so can't be used in an expression).
slice(source, start, length, target)
Copies a segment from the source string, starting at the given index,
and of the given length to target string.
It is assumed the target string buffer is large enough to contain the result.
Also, you have to make sure yourself that start and length are within bounds of the strings.
Modifies in-place, doesn't return a value (so can't be used in an expression).
find(string, char) -> uword address
Locates the first position of the given character in the string, returns the string starting
with this character or $0000 if the character is not found.
compare(string1, string2) -> ubyte result
Returns -1, 0 or 1 depeding on wether string1 sorts before, equal or after string2.
Note that you can also directly compare strings and string values with eachother
using ``==``, ``<`` etcetera (it will use string.compare for you under water automatically).
copy(from, to) -> ubyte length
Copy a string to another, overwriting that one. Returns the length of the string that was copied.
Often you don't have to call this explicitly and can just write ``string1 = string2``
but this function is useful if you're dealing with addresses for instance.
floats
------
Provides definitions for the ROM/kernel subroutines and utility routines dealing with floating

View File

@ -799,44 +799,6 @@ memsetw(address, numwords, wordvalue)
Efficiently set a part of memory to the given (u)word value.
But the most efficient will always be to write a specialized fill routine in assembly yourself!
leftstr(source, target, length)
Copies the left side of the source string of the given length to target string.
It is assumed the target string buffer is large enough to contain the result.
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
Modifies in-place, doesn't return a value (so can't be used in an expression).
rightstr(source, target, length)
Copies the right side of the source string of the given length to target string.
It is assumed the target string buffer is large enough to contain the result.
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
Modifies in-place, doesn't return a value (so can't be used in an expression).
strlen(str)
Number of bytes in the string. This value is determined during runtime and counts upto
the first terminating 0 byte in the string, regardless of the size of the string during compilation time.
Don't confuse this with ``len`` and ``sizeof``
strcmp(string1, string2)
Returns -1, 0 or 1 depeding on wether string1 sorts before, equal or after string2.
Note that you can also directly compare strings and string values with eachother
using ``==``, ``<`` etcetera (it will use strcmp for you under water automatically).
substr(source, target, start, length)
Copies a segment from the source string, starting at the given index,
and of the given length to target string.
It is assumed the target string buffer is large enough to contain the result.
Also, you have to make sure yourself that start and length are within bounds of the strings.
Modifies in-place, doesn't return a value (so can't be used in an expression).
strcopy(from, to)
Copy a string to another, overwriting that one. Returns the length of the string that was copied.
Often you don't have to call this explicitly and can just write ``string1 = string2``
but this function is useful if you're dealing with addresses for instance.
strfind(string, char)
Locates the first position of the given character in the string, returns the string starting
with this character or $0000 if the character is not found.
Miscellaneous
^^^^^^^^^^^^^

View File

@ -3,8 +3,10 @@ TODO
====
- move all str* builtin functions to a strings library module, mem* to the sys module. update docs.
- move target() builtin to sys.target constant
- use (zp) addressing mode on 65c02 specific code rather than ldy#0 / lda (zp),y
- optimize pointer access code @(pointer)? use a subroutine? macro? 65c02 vs 6502?
- allow byte return type with single register for asmsubs, for instance string.compare
- can we get rid of the --longOptionName command line options and only keep the short versions? https://github.com/Kotlin/kotlinx-cli/issues/50
- optimizer: detect variables that are written but never read - mark those as unused too and remove them, such as uword unused = memory("unused222", 20) - also remove the memory slab allocation
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)

View File

@ -7,16 +7,14 @@ indent_size = 4
indent_style = space
insert_final_newline = true
max_line_length = 120
tab_width = 4
tab_width = 8
trim_trailing_whitespace = true
ij_smart_tabs = true
[*.p8]
tab_width = 4
indent_size = 4
indent_style = space
[*.asm]
tab_width = 8
indent_size = 8
indent_style = tab

View File

@ -1,5 +1,6 @@
%import floats
%import textio
%import string
%zeropage basicsafe
main {
@ -22,10 +23,10 @@ main {
if length!=5 txt.print("error len1\n")
length = len(uwarr)
if length!=5 txt.print("error len2\n")
length=strlen(name)
length=string.length(name)
if length!=5 txt.print("error strlen1\n")
name[3] = 0
length=strlen(name)
length=string.length(name)
if length!=3 txt.print("error strlen2\n")
; MAX

View File

@ -477,6 +477,7 @@ main {
; @TODO fix type errors
sub shiftrsw0() -> word {
word q = -12345

View File

@ -1,5 +1,6 @@
%import textio
%import floats
%import string
%import syslib
%import test_stack
%zeropage basicsafe
@ -8,7 +9,6 @@ main {
sub start() {
rotations()
strings()
integers()
floatingpoint()
@ -256,82 +256,6 @@ main {
}
sub strings() {
const uword ADDR = $8400
const uword ADDR2 = $8000
memset(ADDR2, 40*25, '*')
memset(ADDR2, 40, '1')
memset(ADDR2+24*40, 39, '2')
memsetw(ADDR2, 40*25/2, $3132)
memsetw(ADDR2, 20, $4142)
memsetw(ADDR2+24*40, 19, $4241)
memcopy(ADDR2, ADDR, 200)
str result = "?" *10
str s1 = "irmen"
str s2 = "hello"
str dots = "....."
ubyte ub
byte bb
ubyte zero=0
bb = strcmp(s1, s2)
txt.print_b(bb)
txt.chrout('\n')
bb = strcmp(s2, s1)
txt.print_b(bb)
txt.chrout('\n')
txt.print_ub(s1==s2)
txt.chrout('\n')
txt.print_ub(s1<s2)
txt.chrout('\n')
txt.print_ub(s1>s2)
txt.chrout('\n')
bb = zero+strcmp(s1,s2)*1+zero
txt.print_b(bb)
txt.chrout('\n')
bb = zero+strcmp(s2,s1)*1+zero
txt.print_b(bb)
txt.chrout('\n')
ub = strlen(s1)
txt.print_ub(ub)
txt.chrout('\n')
ub = zero+strlen(s1)*1+zero
txt.print_ub(ub)
txt.chrout('\n')
leftstr(s1, result, 3)
txt.print(result)
txt.chrout('\n')
leftstr(s1, result, len(s1))
txt.print(result)
txt.chrout('\n')
txt.chrout('\n')
result = "x"*8
rightstr(s2, result, 3)
txt.print(result)
txt.chrout('\n')
rightstr(s2, result, len(s1))
txt.print(result)
txt.chrout('\n')
result = "y"*10
substr(s2, result, 1, 3)
txt.print(result)
txt.chrout('\n')
void strcopy(s2, s1)
txt.print_ub(99+strcopy(s2,s1))
txt.chrout('\n')
test_stack.test()
}
sub integers() {
ubyte[] ubarr = [1,2,3,4,5,0,4,3,2,1, 255, 255, 255]
byte[] barr = [1,2,3,4,5,-4,0,-3,2,1, -128, -128, -127]

View File

@ -6,6 +6,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%import perf2
%import perf3
@ -954,7 +955,7 @@ util {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util10 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util2 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util3 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util4 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util5 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util6 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util7 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util8 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -944,7 +945,7 @@ util9 {
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
repeat width - string.length(string) {
txt.chrout(' ')
}
txt.print(string)

View File

@ -1,6 +1,7 @@
%target cx16
%import test_stack
%import textio
%import string
%zeropage basicsafe
%option no_sysinit
@ -61,7 +62,7 @@ textparse {
}
uword value = conv.any2uword(word_addrs[2])
if strcmp("*", word_addrs[0])==0 {
if word_addrs[0] == "*" { ; TODO does this string compare work?
program_counter = value
} else {
set_symbol(word_addrs[0], value)
@ -96,7 +97,7 @@ textparse {
}
if label_ptr {
uword lastlabelchar = label_ptr + strlen(label_ptr)-1
uword lastlabelchar = label_ptr + string.length(label_ptr)-1
if @(lastlabelchar) == ':'
@(lastlabelchar) = 0
if instructions.match(label_ptr) {
@ -346,7 +347,7 @@ textparse {
}
if changed {
@(dest)=0
void strcopy(input_line2, src)
string.copy(input_line2, src)
}
}
}

View File

@ -2,6 +2,7 @@
%import gfx2
%import textio
%import diskio
%import string
%import koala_module
%import iff_module
%import pcx_module
@ -14,7 +15,7 @@ main {
sub start() {
; trick to check if we're running on sdcard or host system shared folder
txt.print("\nimage viewer for commander x16\nformats supported: .iff, .pcx, .bmp, .koa (c64 koala)\n\n")
if strlen(diskio.status(8)) {
if string.length(diskio.status(8)) {
txt.print("enter image file name or just enter for all on disk: ")
ubyte i = txt.input_chars(diskio.filename)
gfx2.screen_mode(1) ; 320*240, 256c
@ -54,7 +55,7 @@ main {
;txt.print(filenameptr)
;txt.chrout('\n')
uword extension = filenameptr + rfind(filenameptr, '.')
if strcmp(extension, ".iff")==0 {
if extension == ".iff" { ; TODO does this compare work?
;txt.print("loading ")
;txt.print("iff\n")
if iff_module.show_image(filenameptr) {
@ -70,7 +71,7 @@ main {
load_error(filenameptr)
}
}
else if strcmp(extension, ".pcx")==0 {
else if extension == ".pcx" { ; TODO works?
;txt.print("loading ")
;txt.print("pcx\n")
if pcx_module.show_image(filenameptr) {
@ -79,7 +80,7 @@ main {
load_error(filenameptr)
}
}
else if strcmp(extension, ".koa")==0 {
else if extension == ".koa" { ; TODO works?
;txt.print("loading ")
;txt.print("koala\n")
if koala_module.show_image(filenameptr) {
@ -88,7 +89,7 @@ main {
load_error(filenameptr)
}
}
else if strcmp(extension, ".bmp")==0 {
else if extension == ".bmp" { ; TODO works?
;txt.print("loading ")
;txt.print("bmp\n")
if bmp_module.show_image(filenameptr) {
@ -97,7 +98,7 @@ main {
load_error(filenameptr)
}
}
; else if strcmp(extension, ".ci")==0 {
; else if extension == ".ci" {
;; txt.print("loading ")
;; txt.print("ci\n")
; if ci_module.show_image(filenameptr) {
@ -117,12 +118,12 @@ main {
sub extension_equals(uword stringptr, uword extensionptr) -> ubyte {
ubyte ix = rfind(stringptr, '.')
return ix<255 and strcmp(stringptr+ix, extensionptr)==0
return ix<255 and string.compare(stringptr+ix, extensionptr)==0
}
sub rfind(uword stringptr, ubyte char) -> ubyte {
ubyte i
for i in strlen(stringptr)-1 downto 0 {
for i in string.length(stringptr)-1 downto 0 {
if @(stringptr+i)==char
return i
}

View File

@ -1,11 +1,99 @@
%import test_stack
%import textio
%import string
%zeropage basicsafe
%option no_sysinit
main {
sub start () {
; TODO: error when a parameter has the same name as an existing module/block/subroutine: sub print_right(ubyte width, uword string) {
sub start() {
str s1 = "irmen"
str s2 = "what"
str s3 = "irmen2"
s3[5] = 0
txt.print("length:\n")
txt.print_ub(len(s1))
txt.chrout('\n')
txt.print_ub(string.length(s1))
txt.print("\n\ncopy:\n")
txt.print(s3)
txt.chrout('\n')
s3 = s2
txt.print(s3)
txt.chrout('\n')
txt.print_ub(string.copy("new", s3))
txt.print(s3)
txt.print("\n\ncompare:\n")
txt.chrout('\n')
txt.print_ub(string.compare(s1, s2))
txt.chrout('\n')
txt.print_ub(string.compare(s2, s1))
txt.chrout('\n')
txt.print_ub(string.compare(s1, s3))
txt.chrout('\n')
txt.chrout('\n')
txt.print_ub(s1==s2)
txt.chrout('\n')
txt.print_ub(s1<s2)
txt.chrout('\n')
txt.print_ub(s1>s2)
txt.chrout('\n')
txt.print("\n\nleft:")
string.left(s2,2,s3)
txt.print(s3)
txt.chrout('\n')
txt.print("\n\nright:\n")
txt.print(s2)
txt.chrout('\n')
string.right(s2,2,s3)
txt.print(s3)
txt.chrout('\n')
txt.print("\n\nfind:\n")
txt.print(s1)
txt.chrout('\n')
uword found = string.find(s1, 'e')
txt.print_uwhex(found, 1)
if found
txt.print(found)
txt.chrout('\n')
found = string.find(s1, 'i')
txt.print_uwhex(found, 1)
if found
txt.print(found)
txt.chrout('\n')
found = string.find(s1, 'x')
txt.print_uwhex(found, 1)
if found
txt.print(found)
txt.chrout('\n')
txt.print("\n\nslice:\n")
string.slice(s1, 0, 5, s2)
txt.print(s2)
txt.chrout('\n')
string.slice(s1, 1, 4, s2)
txt.print(s2)
txt.chrout('\n')
string.slice(s1, 2, 2, s2)
txt.print(s2)
txt.chrout('\n')
string.slice(s1, 3, 2, s2)
txt.print(s2)
txt.chrout('\n')
test_stack.test()
}
sub start2 () {
str[] binstrings = [
"",
"%",
@ -151,16 +239,16 @@ main {
}
; found = strfind("irmen de jong", ' ')
; found = string.find("irmen de jong", ' ')
; txt.print_uwhex(found, 1)
; txt.chrout('\n')
; found = strfind(" irmen-de-jong", ' ')
; found = string.find(" irmen-de-jong", ' ')
; txt.print_uwhex(found, 1)
; txt.chrout('\n')
; found = strfind("irmen-de-jong ", ' ')
; found = string.find("irmen-de-jong ", ' ')
; txt.print_uwhex(found, 1)
; txt.chrout('\n')
; found = strfind("irmen-de-jong", ' ')
; found = string.find("irmen-de-jong", ' ')
; txt.print_uwhex(found, 1)
; txt.chrout('\n')

View File

@ -1,6 +1,7 @@
%import textio
%import conv
%import diskio
%import string
%import test_stack
%option no_sysinit
%zeropage basicsafe
@ -943,11 +944,11 @@ util {
return false
}
sub print_right(ubyte width, uword string) {
repeat width - strlen(string) {
sub print_right(ubyte width, uword s) {
repeat width - string.length(s) {
txt.chrout(' ')
}
txt.print(string)
txt.print(s)
}
asmsub print_10s(uword value @AY) clobbers(A, X, Y) {