diff --git a/man/rgbasm.5 b/man/rgbasm.5 index f7049c71..df22e187 100644 --- a/man/rgbasm.5 +++ b/man/rgbasm.5 @@ -625,18 +625,6 @@ the charmap entries of a string are counted by .Ql CHARLEN ; and the values of a charmap entry are counted by .Ql CHARSIZE . -.Pp -The following legacy functions are similar to other functions that operate on string expressions, but for historical reasons, they count starting from -.Em position 1 , -not from index 0! -(Position -1 still counts from the end.) -.Bl -column "STRSUB(str, pos, len)" -.It Sy Name Ta Sy Operation -.It Fn STRSUB str pos len Ta Returns a substring of Ar str No starting at Ar pos No and Ar len No characters long. If Ar len No is not specified, the substring continues to the end of Ar str No . -.It Fn STRIN str sub Ta Returns the first position of Ar sub No in Ar str Ns , or 0 if it's not present. -.It Fn STRRIN str sub Ta Returns the last position of Ar sub No in Ar str Ns , or 0 if it's not present. -.It Fn CHARSUB str pos Ta Returns the substring of Ar str No for the charmap entry at Ar pos No with the current charmap . Pq Ar pos No counts charmap entries, not characters. -.El .Ss Character maps When writing text strings that are meant to be displayed on the Game Boy, the character encoding in the ROM may need to be different than the source file encoding. For example, the tiles used for uppercase letters may be placed starting at tile index 128, which differs from ASCII starting at 65. diff --git a/src/asm/actions.cpp b/src/asm/actions.cpp index be26050c..08bad262 100644 --- a/src/asm/actions.cpp +++ b/src/asm/actions.cpp @@ -351,6 +351,8 @@ std::string } std::string act_StringSub(std::string const &str, int32_t negPos, std::optional optLen) { + warning(WARNING_OBSOLETE, "`STRSUB` is deprecated; use 0-indexed `STRSLICE` instead"); + size_t adjustLen = act_StringLen(str, false); uint32_t pos = adjustNegativePos(negPos, adjustLen, "STRSUB"); uint32_t len = optLen ? *optLen : pos > adjustLen ? 0 : adjustLen + 1 - pos; @@ -447,6 +449,8 @@ std::string act_StringChar(std::string const &str, int32_t negIdx) { } std::string act_CharSub(std::string const &str, int32_t negPos) { + warning(WARNING_OBSOLETE, "`CHARSUB` is deprecated; use 0-indexed `STRCHAR` instead"); + size_t adjustLen = act_CharLen(str); uint32_t pos = adjustNegativePos(negPos, adjustLen, "CHARSUB"); diff --git a/src/asm/parser.y b/src/asm/parser.y index 8d9b0cb8..09fcedb9 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -1493,10 +1493,12 @@ relocexpr_no_str: $$.makeNumber(pos != std::string::npos ? pos : -1); } | OP_STRIN LPAREN string COMMA string RPAREN { + warning(WARNING_OBSOLETE, "`STRIN` is deprecated; use 0-indexed `STRFIND` instead"); size_t pos = $3.find($5); $$.makeNumber(pos != std::string::npos ? pos + 1 : 0); } | OP_STRRIN LPAREN string COMMA string RPAREN { + warning(WARNING_OBSOLETE, "`STRRIN` is deprecated; use 0-indexed `STRRFIND` instead"); size_t pos = $3.rfind($5); $$.makeNumber(pos != std::string::npos ? pos + 1 : 0); } diff --git a/test/asm/charlen-strchar.asm b/test/asm/charlen-strchar.asm index 94258c64..9bc0ea3e 100644 --- a/test/asm/charlen-strchar.asm +++ b/test/asm/charlen-strchar.asm @@ -18,11 +18,6 @@ DEF S EQUS "XBoldABC" assert STRCHAR("{S}", 0) == $58 ; ASCII "X" db "{S}" - for n, CHARLEN("{S}") - assert STRCHAR("{S}", n) == CHARSUB("{S}", n + 1) - assert STRCHAR("{S}", -n - 1) == CHARSUB("{S}", -n - 1) - endr - newcharmap ascii assert CHARLEN("{S}") == 14 diff --git a/test/asm/invalid-strchar-charsub.asm b/test/asm/invalid-strchar-charsub.asm deleted file mode 100644 index 3acffe9c..00000000 --- a/test/asm/invalid-strchar-charsub.asm +++ /dev/null @@ -1,3 +0,0 @@ -DEF S EQUS STRCHAR("ABC", 3) -DEF T EQUS CHARSUB("ABC", 4) -DEF U EQUS CHARSUB("ABC", 0) diff --git a/test/asm/invalid-strchar-charsub.err b/test/asm/invalid-strchar-charsub.err deleted file mode 100644 index 8ae4381c..00000000 --- a/test/asm/invalid-strchar-charsub.err +++ /dev/null @@ -1,6 +0,0 @@ -warning: invalid-strchar-charsub.asm(1): [-Wbuiltin-args] - STRCHAR: Index 3 is past the end of the string -warning: invalid-strchar-charsub.asm(2): [-Wbuiltin-args] - CHARSUB: Position 4 is past the end of the string -warning: invalid-strchar-charsub.asm(3): [-Wbuiltin-args] - CHARSUB: Position starts at 1 diff --git a/test/asm/invalid-strchar.asm b/test/asm/invalid-strchar.asm new file mode 100644 index 00000000..1386d22c --- /dev/null +++ b/test/asm/invalid-strchar.asm @@ -0,0 +1,2 @@ +DEF S EQUS STRCHAR("ABC", 3) +DEF T EQUS STRCHAR("ABC", -4) diff --git a/test/asm/invalid-strchar.err b/test/asm/invalid-strchar.err new file mode 100644 index 00000000..a1231df0 --- /dev/null +++ b/test/asm/invalid-strchar.err @@ -0,0 +1,4 @@ +warning: invalid-strchar.asm(1): [-Wbuiltin-args] + STRCHAR: Index 3 is past the end of the string +warning: invalid-strchar.asm(2): [-Wbuiltin-args] + STRCHAR: Index starts at 0 diff --git a/test/asm/invalid-utf-8-strings.asm b/test/asm/invalid-utf-8-strings.asm index 7e6bfee3..aa042742 100644 --- a/test/asm/invalid-utf-8-strings.asm +++ b/test/asm/invalid-utf-8-strings.asm @@ -14,11 +14,11 @@ DEF invalid EQUS "aäb漢,ab!" DEF n = STRLEN("{invalid}") -DEF copy EQUS STRSUB("{invalid}", 1) +DEF copy EQUS STRSLICE("{invalid}", 0) println "\"{#s:invalid}\" == \"{#s:copy}\" ({d:n})" -DEF mid1 EQUS STRSUB("{invalid}", 5, 2) +DEF mid1 EQUS STRSLICE("{invalid}", 4, 6) DEF mid2 EQUS STRSLICE("{invalid}", 8, 9) println "\"{#s:mid2}{#s:mid1}\"" @@ -51,8 +51,5 @@ DEF n = STRLEN("{invalid}") DEF r = CHARLEN("{invalid}") println "\"{#s:invalid}\": {d:n} == {d:r}" -DEF final EQUS STRSUB("{invalid}", 4, 1) -println "\"{#s:invalid}\" ends \"{#s:final}\"" - -REDEF final EQUS STRSLICE("{invalid}", 3, 4) +DEF final EQUS STRSLICE("{invalid}", 3, 4) println "\"{#s:invalid}\" ends \"{#s:final}\"" diff --git a/test/asm/invalid-utf-8-strings.err b/test/asm/invalid-utf-8-strings.err index 6a07ff32..693a4d70 100644 --- a/test/asm/invalid-utf-8-strings.err +++ b/test/asm/invalid-utf-8-strings.err @@ -7,13 +7,13 @@ error: invalid-utf-8-strings.asm(16): error: invalid-utf-8-strings.asm(16): STRLEN: Invalid UTF-8 byte 0xA2 error: invalid-utf-8-strings.asm(17): - STRSUB: Invalid UTF-8 byte 0xA3 + STRSLICE: Invalid UTF-8 byte 0xA3 error: invalid-utf-8-strings.asm(17): - STRSUB: Invalid UTF-8 byte 0xA4 + STRSLICE: Invalid UTF-8 byte 0xA4 error: invalid-utf-8-strings.asm(17): - STRSUB: Invalid UTF-8 byte 0xF0 + STRSLICE: Invalid UTF-8 byte 0xF0 error: invalid-utf-8-strings.asm(17): - STRSUB: Invalid UTF-8 byte 0xA2 + STRSLICE: Invalid UTF-8 byte 0xA2 error: invalid-utf-8-strings.asm(22): STRSLICE: Invalid UTF-8 byte 0xA3 error: invalid-utf-8-strings.asm(22): @@ -55,7 +55,5 @@ error: invalid-utf-8-strings.asm(40): error: invalid-utf-8-strings.asm(50): STRLEN: Incomplete UTF-8 character error: invalid-utf-8-strings.asm(54): - STRSUB: Incomplete UTF-8 character -error: invalid-utf-8-strings.asm(57): STRSLICE: Incomplete UTF-8 character -Assembly aborted with 30 errors! +Assembly aborted with 29 errors! diff --git a/test/asm/invalid-utf-8-strings.out b/test/asm/invalid-utf-8-strings.out index c8c5c274..5602df61 100644 --- a/test/asm/invalid-utf-8-strings.out +++ b/test/asm/invalid-utf-8-strings.out @@ -4,4 +4,3 @@ "漢" "abc": 4 == 4 "abc" ends "" -"abc" ends "" diff --git a/test/asm/null-char-functions.asm b/test/asm/null-char-functions.asm index 13777eb3..6bc5438a 100644 --- a/test/asm/null-char-functions.asm +++ b/test/asm/null-char-functions.asm @@ -23,11 +23,3 @@ assert_equal strrpl(#s, "\0", "0"), "hello0world" assert_equal strfmt("%s", #s), #s assert_equal strchar(#s, 5), "\0" assert_equal strchar(#s, -1), "d" - -assert strin(#s, "o\0w") == 5 -assert strin(#s, "orld") == 8 -assert strrin(#s, "o\0w") == 5 -assert strrin(#s, "o") == 8 - -assert_equal strsub(#s, 5, 3), "o\0w" -assert_equal strsub(#s, 7), "world" diff --git a/test/asm/quine.asm b/test/asm/quine.asm index dc0b595b..6f40f414 100644 --- a/test/asm/quine.asm +++ b/test/asm/quine.asm @@ -1,6 +1,6 @@ MACRO N FOR R,1,_NARG+1 -PRINT STRSUB("\n\"\\ PR1NT,ABCDEFGHIMnOSU2_+-()<>",\+1,1) +PRINT STRSLICE("\n\"\\ PR1NT,ABCDEFGHILMnOS2_+-()<>",\,\+1) ENDR REPT R-2 PRINT"\1," @@ -8,4 +8,4 @@ SHIFT ENDR PRINT"\1\n" ENDM - N 19,10,12,5,21,3,7,0,15,21,5,3,5,9,6,9,25,7,10,5,16,26,6,0,4,5,18,7,8,3,22,8,5,22,23,11,28,1,2,20,2,1,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,9,2,30,5,31,26,6,9,6,29,0,14,7,13,5,0,5,14,4,8,3,5,27,24,0,4,5,18,7,8,1,2,6,9,1,0,22,17,18,15,8,0,14,7,13,5,0,4,5,18,7,8,1,2,6,2,20,1,0,14,7,13,19,0,3,7,3 +N 20,10,12,5,22,3,7,0,15,22,5,3,5,9,6,9,25,7,10,5,16,26,6,0,4,5,18,7,8,3,23,8,5,23,19,18,12,14,28,1,2,21,2,1,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,9,2,30,5,31,9,2,30,5,31,26,6,29,0,14,7,13,5,0,5,14,4,8,3,5,27,24,0,4,5,18,7,8,1,2,6,9,1,0,23,17,18,15,8,0,14,7,13,5,0,4,5,18,7,8,1,2,6,2,21,1,0,14,7,13,20,0,7,3 diff --git a/test/asm/quine.out b/test/asm/quine.out index dc0b595b..6f40f414 100644 --- a/test/asm/quine.out +++ b/test/asm/quine.out @@ -1,6 +1,6 @@ MACRO N FOR R,1,_NARG+1 -PRINT STRSUB("\n\"\\ PR1NT,ABCDEFGHIMnOSU2_+-()<>",\+1,1) +PRINT STRSLICE("\n\"\\ PR1NT,ABCDEFGHILMnOS2_+-()<>",\,\+1) ENDR REPT R-2 PRINT"\1," @@ -8,4 +8,4 @@ SHIFT ENDR PRINT"\1\n" ENDM - N 19,10,12,5,21,3,7,0,15,21,5,3,5,9,6,9,25,7,10,5,16,26,6,0,4,5,18,7,8,3,22,8,5,22,23,11,28,1,2,20,2,1,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,9,2,30,5,31,26,6,9,6,29,0,14,7,13,5,0,5,14,4,8,3,5,27,24,0,4,5,18,7,8,1,2,6,9,1,0,22,17,18,15,8,0,14,7,13,5,0,4,5,18,7,8,1,2,6,2,20,1,0,14,7,13,19,0,3,7,3 +N 20,10,12,5,22,3,7,0,15,22,5,3,5,9,6,9,25,7,10,5,16,26,6,0,4,5,18,7,8,3,23,8,5,23,19,18,12,14,28,1,2,21,2,1,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,9,2,30,5,31,9,2,30,5,31,26,6,29,0,14,7,13,5,0,5,14,4,8,3,5,27,24,0,4,5,18,7,8,1,2,6,9,1,0,23,17,18,15,8,0,14,7,13,5,0,4,5,18,7,8,1,2,6,2,21,1,0,14,7,13,20,0,7,3 diff --git a/test/asm/raw-string-symbols.asm b/test/asm/raw-string-symbols.asm index e49bd53d..cba53b5d 100644 --- a/test/asm/raw-string-symbols.asm +++ b/test/asm/raw-string-symbols.asm @@ -4,7 +4,7 @@ def hello equs "world" def name equs "hello" println "{name}" println #name -assert !strcmp(strsub(#name, 1, 4), "hell") +assert !strcmp(strslice(#name, 0, 4), "hell") assert strlen(#hello) == charlen(#hello) assert strlen("{hello}") == 5 diff --git a/test/asm/strfind-strin.asm b/test/asm/strfind-strin.asm deleted file mode 100644 index d229871e..00000000 --- a/test/asm/strfind-strin.asm +++ /dev/null @@ -1,28 +0,0 @@ -SECTION "Test", ROM0 - - assert STRFIND("foo bar baz", "bar") == STRRFIND("foo bar baz", "bar") - assert STRIN("foo bar baz", "bar") == STRRIN("foo bar baz", "bar") - - assert STRFIND("foo bar bargain", "bar") == 4 - assert STRIN("foo bar bargain", "bar") == 5 - - assert STRRFIND("foo bar bargain", "bar") == 8 - assert STRRIN("foo bar bargain", "bar") == 9 - - assert STRFIND("foo bar", "qux") == -1 - assert STRIN("foo bar", "qux") == 0 - - assert STRRFIND("foo bar", "qux") == -1 - assert STRRIN("foo bar", "qux") == 0 - - assert STRFIND("foo", "foobar") == -1 - assert STRIN("foo", "foobar") == 0 - - assert STRRFIND("foo", "foobar") == -1 - assert STRRIN("foo", "foobar") == 0 - - assert STRFIND("foobar", "") == 0 - assert STRIN("foobar", "") == 1 - - assert STRRFIND("foobar", "") == STRLEN("foobar") - assert STRRIN("foobar", "") == STRLEN("foobar") + 1 diff --git a/test/asm/strfind-strrfind.asm b/test/asm/strfind-strrfind.asm new file mode 100644 index 00000000..28612fc2 --- /dev/null +++ b/test/asm/strfind-strrfind.asm @@ -0,0 +1,10 @@ + + assert STRFIND("foo bar baz", "bar") == STRRFIND("foo bar baz", "bar") + assert STRFIND("foo bar bargain", "bar") == 4 + assert STRRFIND("foo bar bargain", "bar") == 8 + assert STRFIND("foo bar", "qux") == -1 + assert STRRFIND("foo bar", "qux") == -1 + assert STRFIND("foo", "foobar") == -1 + assert STRRFIND("foo", "foobar") == -1 + assert STRFIND("foobar", "") == 0 + assert STRRFIND("foobar", "") == STRLEN("foobar") diff --git a/test/asm/strslice-strsub.err b/test/asm/strslice-strsub.err deleted file mode 100644 index 952db44e..00000000 --- a/test/asm/strslice-strsub.err +++ /dev/null @@ -1,40 +0,0 @@ -warning: strslice-strsub.asm(14) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Start index 4 is past the end of the string -warning: strslice-strsub.asm(15) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Index starts at 0 -warning: strslice-strsub.asm(18) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Stop index 31 is past the end of the string -warning: strslice-strsub.asm(19) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Stop index 300 is past the end of the string -warning: strslice-strsub.asm(20) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Index starts at 0 -warning: strslice-strsub.asm(20) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Stop index 300 is past the end of the string -warning: strslice-strsub.asm(22) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Start index 4 is past the end of the string -warning: strslice-strsub.asm(22) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Stop index 4 is past the end of the string -warning: strslice-strsub.asm(23) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Stop index 4 is past the end of the string -warning: strslice-strsub.asm(26) -> strslice-strsub.asm::xstrslice(2): [-Wbuiltin-args] - STRSLICE: Stop index 12 is past the end of the string -warning: strslice-strsub.asm(41) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Position starts at 1 -warning: strslice-strsub.asm(43) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Position 5 is past the end of the string -warning: strslice-strsub.asm(44) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Position starts at 1 -warning: strslice-strsub.asm(47) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Length too big: 32 -warning: strslice-strsub.asm(48) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Length too big: 300 -warning: strslice-strsub.asm(49) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Position starts at 1 -warning: strslice-strsub.asm(49) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Length too big: 300 -warning: strslice-strsub.asm(51) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Position 5 is past the end of the string -warning: strslice-strsub.asm(52) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Length too big: 1 -warning: strslice-strsub.asm(55) -> strslice-strsub.asm::xstrsub(31): [-Wbuiltin-args] - STRSUB: Length too big: 10 diff --git a/test/asm/strslice-strsub.asm b/test/asm/strslice.asm similarity index 52% rename from test/asm/strslice-strsub.asm rename to test/asm/strslice.asm index c8e5341f..bc122595 100644 --- a/test/asm/strslice-strsub.asm +++ b/test/asm/strslice.asm @@ -26,32 +26,3 @@ ENDM xstrslice "カタカナ", 2, 12 xstrslice "g̈", 0, 1 xstrslice "g̈", 0, 2 - -MACRO xstrsub - PRINTLN "STRSUB(\#): ", STRSUB(\#) -ENDM - - xstrsub "ABC", 1, 1 - xstrsub "ABC", 2, 1 - xstrsub "ABC", 3, 1 - xstrsub "ABC", -3, 1 - xstrsub "ABC", -2, 1 - xstrsub "ABC", -1, 1 - xstrsub "ABC", 2 - xstrsub "ABC", 0 - xstrsub "ABC", -2 - xstrsub "ABC", 5 - xstrsub "ABC", -5 - xstrsub "ABC", 1, 2 - xstrsub "ABC", 2, 2 - xstrsub "ABC", 2, 32 - xstrsub "ABC", 2, 300 - xstrsub "ABC", -4, 300 - xstrsub "ABC", 4, 0 - xstrsub "ABC", 5, 0 - xstrsub "ABC", 4, 1 - xstrsub "カタカナ", 1, 2 - xstrsub "カタカナ", 3, 2 - xstrsub "カタカナ", 3, 10 - xstrsub "g̈", 1, 1 - xstrsub "g̈", 1, 2 diff --git a/test/asm/strslice.err b/test/asm/strslice.err new file mode 100644 index 00000000..75360696 --- /dev/null +++ b/test/asm/strslice.err @@ -0,0 +1,20 @@ +warning: strslice.asm(14) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Start index 4 is past the end of the string +warning: strslice.asm(15) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Index starts at 0 +warning: strslice.asm(18) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Stop index 31 is past the end of the string +warning: strslice.asm(19) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Stop index 300 is past the end of the string +warning: strslice.asm(20) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Index starts at 0 +warning: strslice.asm(20) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Stop index 300 is past the end of the string +warning: strslice.asm(22) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Start index 4 is past the end of the string +warning: strslice.asm(22) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Stop index 4 is past the end of the string +warning: strslice.asm(23) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Stop index 4 is past the end of the string +warning: strslice.asm(26) -> strslice.asm::xstrslice(2): [-Wbuiltin-args] + STRSLICE: Stop index 12 is past the end of the string diff --git a/test/asm/strslice-strsub.out b/test/asm/strslice.out similarity index 52% rename from test/asm/strslice-strsub.out rename to test/asm/strslice.out index d0e95f19..6dbc4300 100644 --- a/test/asm/strslice-strsub.out +++ b/test/asm/strslice.out @@ -22,27 +22,3 @@ STRSLICE("カタカナ",2,4): カナ STRSLICE("カタカナ",2,12): カナ STRSLICE("g̈",0,1): g STRSLICE("g̈",0,2): g̈ -STRSUB("ABC",1,1): A -STRSUB("ABC",2,1): B -STRSUB("ABC",3,1): C -STRSUB("ABC",-3,1): A -STRSUB("ABC",-2,1): B -STRSUB("ABC",-1,1): C -STRSUB("ABC",2): BC -STRSUB("ABC",0): ABC -STRSUB("ABC",-2): BC -STRSUB("ABC",5): -STRSUB("ABC",-5): ABC -STRSUB("ABC",1,2): AB -STRSUB("ABC",2,2): BC -STRSUB("ABC",2,32): BC -STRSUB("ABC",2,300): BC -STRSUB("ABC",-4,300): ABC -STRSUB("ABC",4,0): -STRSUB("ABC",5,0): -STRSUB("ABC",4,1): -STRSUB("カタカナ",1,2): カタ -STRSUB("カタカナ",3,2): カナ -STRSUB("カタカナ",3,10): カナ -STRSUB("g̈",1,1): g -STRSUB("g̈",1,2): g̈