diff --git a/compiler/res/prog8lib/diskio.p8 b/compiler/res/prog8lib/diskio.p8 index b125916b2..4092b9d21 100644 --- a/compiler/res/prog8lib/diskio.p8 +++ b/compiler/res/prog8lib/diskio.p8 @@ -83,9 +83,7 @@ io_error: name_ptrs++ @(name_ptrs) = msb(buf_ptr) name_ptrs++ - ; ubyte length = strcpy(diskio.list_filename, buf_ptr) - memcopy(diskio.list_filename, buf_ptr, strlen(list_filename)+1) ; todo replace with strcpy() - buf_ptr += strlen(list_filename)+1 + buf_ptr += strcopy(diskio.list_filename, buf_ptr) + 1 files_found++ if buf_ptr - &names_buffer > (len(names_buffer) + len(names_buffer1) - 18) break diff --git a/compiler/res/prog8lib/prog8_funcs.asm b/compiler/res/prog8lib/prog8_funcs.asm index 2fd348992..71bda5377 100644 --- a/compiler/res/prog8lib/prog8_funcs.asm +++ b/compiler/res/prog8lib/prog8_funcs.asm @@ -1346,3 +1346,24 @@ func_strcmp_stack .proc 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 diff --git a/compiler/res/prog8lib/prog8_lib.asm b/compiler/res/prog8lib/prog8_lib.asm index 47b410a27..da1a6f038 100644 --- a/compiler/res/prog8lib/prog8_lib.asm +++ b/compiler/res/prog8lib/prog8_lib.asm @@ -993,6 +993,7 @@ _arg_index .byte 0 strcpy .proc ; copy a string (must be 0-terminated) from A/Y to (P8ZP_SCRATCH_W1) ; it is assumed the target string is large enough. + ; returns the length of the string that was copied in Y. sta P8ZP_SCRATCH_W2 sty P8ZP_SCRATCH_W2+1 ldy #$ff diff --git a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt index 638a79e0e..5a1e8c08f 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt @@ -81,6 +81,13 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val "set_irqd" -> asmgen.out(" sei") "strlen" -> funcStrlen(fcall, resultToStack) "strcmp" -> funcStrcmp(fcall, func, resultToStack, scope) + "strcopy" -> { + translateArguments(fcall.args, func, scope) + 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, scope) "substr", "leftstr", "rightstr" -> { translateArguments(fcall.args, func, scope) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt index a7e2cb8c3..7a8eef332 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt @@ -1947,24 +1947,29 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } } - private fun translateBinaryOperatorWords(operator: String, types: DataType) { + private fun translateBinaryOperatorWords(operator: String, dt: DataType) { when(operator) { "**" -> throw AssemblyError("** operator requires floats") "*" -> asmgen.out(" jsr prog8_lib.mul_word") - "/" -> asmgen.out(if(types==DataType.UWORD) " jsr prog8_lib.idiv_uw" else " jsr prog8_lib.idiv_w") + "/" -> asmgen.out(if(dt==DataType.UWORD) " jsr prog8_lib.idiv_uw" else " jsr prog8_lib.idiv_w") "%" -> { - if(types==DataType.WORD) + if(dt==DataType.WORD) throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead") asmgen.out(" jsr prog8_lib.remainder_uw") } "+" -> asmgen.out(" jsr prog8_lib.add_w") "-" -> asmgen.out(" jsr prog8_lib.sub_w") - "<<" -> throw AssemblyError("<< should not operate via stack") - ">>" -> throw AssemblyError(">> should not operate via stack") - "<" -> asmgen.out(if(types==DataType.UWORD) " jsr prog8_lib.less_uw" else " jsr prog8_lib.less_w") - ">" -> asmgen.out(if(types==DataType.UWORD) " jsr prog8_lib.greater_uw" else " jsr prog8_lib.greater_w") - "<=" -> asmgen.out(if(types==DataType.UWORD) " jsr prog8_lib.lesseq_uw" else " jsr prog8_lib.lesseq_w") - ">=" -> asmgen.out(if(types==DataType.UWORD) " jsr prog8_lib.greatereq_uw" else " jsr prog8_lib.greatereq_w") + "<<" -> asmgen.out(" jsr math.shift_left_w") + ">>" -> { + if(dt==DataType.UWORD) + asmgen.out(" jsr math.shift_right_uw") + else + asmgen.out(" jsr math.shift_right_w") + } + "<" -> asmgen.out(if(dt==DataType.UWORD) " jsr prog8_lib.less_uw" else " jsr prog8_lib.less_w") + ">" -> asmgen.out(if(dt==DataType.UWORD) " jsr prog8_lib.greater_uw" else " jsr prog8_lib.greater_w") + "<=" -> asmgen.out(if(dt==DataType.UWORD) " jsr prog8_lib.lesseq_uw" else " jsr prog8_lib.lesseq_w") + ">=" -> asmgen.out(if(dt==DataType.UWORD) " jsr prog8_lib.greatereq_uw" else " jsr prog8_lib.greatereq_w") "==" -> asmgen.out(" jsr prog8_lib.equal_w") "!=" -> asmgen.out(" jsr prog8_lib.notequal_w") "&" -> asmgen.out(" jsr prog8_lib.bitand_w") "^" -> asmgen.out(" jsr prog8_lib.bitxor_w") diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 43b2580ae..8a7d0622f 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -156,6 +156,7 @@ private val functionSignatures: List = listOf( FParam("numwords", setOf(DataType.UWORD)), FParam("wordvalue", setOf(DataType.UWORD, DataType.WORD))), null), FSignature("strlen" , true, listOf(FParam("string", setOf(DataType.STR))), DataType.UBYTE, ::builtinStrlen), + FSignature("strcopy" , false, listOf(FParam("from", IterableDatatypes + DataType.UWORD), FParam("to", IterableDatatypes + DataType.UWORD)), DataType.UBYTE), FSignature("substr" , false, listOf( FParam("source", IterableDatatypes + DataType.UWORD), FParam("target", IterableDatatypes + DataType.UWORD), diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 370e93086..4ba8a5e52 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -814,6 +814,12 @@ substr(source, target, start, length) 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. + + Miscellaneous ^^^^^^^^^^^^^ exit(returncode) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 2f4c36fdf..5a6f7ee67 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,8 +2,6 @@ TODO ==== -- txt.clear_screen() must also position text cursor at 0,0 on both machines -- add strcpy() - reverse mkword() again because of consistency with the platform and AY register pairs... - see if we can group some errors together for instance the (now single) errors about unidentified symbols - Cx16 target: support full-screen 640x480 and 320x240 graphics? That requires our own custom graphics routines though to draw lines. diff --git a/examples/arithmetic/builtins.p8 b/examples/arithmetic/builtins.p8 index 8c28294e8..c3198c941 100644 --- a/examples/arithmetic/builtins.p8 +++ b/examples/arithmetic/builtins.p8 @@ -324,6 +324,10 @@ main { txt.print(result) txt.chrout('\n') + void strcopy(s2, s1) + txt.print_ub(99+strcopy(s2,s1)) + txt.chrout('\n') + test_stack.test() } diff --git a/examples/test.p8 b/examples/test.p8 index 39e725bd4..aa48e7890 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,22 +9,39 @@ main { sub start () { - uword bitmap_load_address = progend() - uword max_bitmap_size = $9eff - bitmap_load_address ; TODO why is this not optimized away? + str s1 = "1234567890" + str s2 = "aapje" - ; foo(2**x) ; TODO arg is zero if x=8, in the function. Param type uword. fix that . also check bit shift - ; foo($0001<>xx) ; TODO fix crash +; +; +; xx = $0001<>xx ; TODO make math.shift_right_(u)w +; uword scanline_data_ptr= $6000 +; uword pixptr = xx/8 + scanline_data_ptr ; TODO why is this code so much larger than the following line: +; uword pixptr2 = scanline_data_ptr + xx/8 test_stack.test() } + sub foo(uword argje) { + txt.print_uwhex(argje, 1) + txt.chrout('\n') + } + }