ref: 58739b0bf2e4057783fed0e8acfc3d0a7668b568
parent: 3e4c2fe712c80207f855a46420572fdd9f0d5f84
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Wed Dec 9 15:08:26 EST 2020
Implement `STRRIN`, like `STRIN` but searching from the right
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -195,6 +195,7 @@
{"STRCMP", T_OP_STRCMP},
{"STRIN", T_OP_STRIN},
+ {"STRRIN", T_OP_STRRIN},
{"STRSUB", T_OP_STRSUB},
{"STRLEN", T_OP_STRLEN},
{"STRCAT", T_OP_STRCAT},
@@ -472,7 +473,7 @@
uint16_t children[0x60 - ' '];
struct KeywordMapping const *keyword;
/* Since the keyword structure is invariant, the min number of nodes is known at compile time */
-} keywordDict[338] = {0}; /* Make sure to keep this correct when adding keywords! */
+} keywordDict[341] = {0}; /* Make sure to keep this correct when adding keywords! */
/* Convert a char into its index into the dict */
static inline uint8_t dictIndex(char c)
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -54,6 +54,21 @@
return r;
}
+static char *strrstr(char *s1, char *s2)
+{
+ size_t len1 = strlen(s1);
+ size_t len2 = strlen(s2);
+
+ if (len2 > len1)
+ return NULL;
+
+ for (char *p = s1 + len1 - len2; p >= s1; p--)
+ if (!strncmp(p, s2, len2))
+ return p;
+
+ return NULL;
+}
+
static size_t strlenUTF8(const char *s)
{
size_t len = 0;
@@ -233,6 +248,7 @@
%left T_OP_STRCMP
%left T_OP_STRIN
+%left T_OP_STRRIN
%left T_OP_STRSUB
%left T_OP_STRLEN
%left T_OP_STRCAT
@@ -996,6 +1012,11 @@
}
| T_OP_STRIN T_LPAREN string T_COMMA string T_RPAREN {
char *p = strstr($3, $5);
+
+ rpn_Number(&$$, p ? p - $3 + 1 : 0);
+ }
+ | T_OP_STRRIN T_LPAREN string T_COMMA string T_RPAREN {
+ char *p = strrstr($3, $5);
rpn_Number(&$$, p ? p - $3 + 1 : 0);
}
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -282,7 +282,8 @@
.It Fn STRLEN string Ta Returns the number of characters in Ar string .
.It Fn STRCAT str1 str2 Ta Appends Ar str2 No to Ar str1 .
.It Fn STRCMP str1 str2 Ta Returns -1 if Ar str1 No is alphabetically lower than Ar str2 No , zero if they match, 1 if Ar str1 No is greater than Ar str2 .
-.It Fn STRIN str1 str2 Ta Returns the position of Ar str2 No in Ar str1 No or zero if it's not present Pq first character is position 1 .
+.It Fn STRIN str1 str2 Ta Returns the first position of Ar str2 No in Ar str1 No or zero if it's not present Pq first character is position 1 .
+.It Fn STRRIN str1 str2 Ta Returns the last position of Ar str2 No in Ar str1 No or zero if it's not present Pq first character is position 1 .
.It Fn STRSUB str pos len Ta Returns a substring from Ar str No starting at Ar pos Po first character is position 1 Pc and Ar len No characters long.
.It Fn STRUPR str Ta Converts all characters in Ar str No to capitals and returns the new string.
.It Fn STRLWR str Ta Converts all characters in Ar str No to lower case and returns the new string.
--- /dev/null
+++ b/test/asm/strin-strrin.asm
@@ -1,0 +1,15 @@
+SECTION "Test", ROM0
+
+ assert STRIN("foo bar baz", "bar") == STRRIN("foo bar baz", "bar")
+
+ assert STRIN("foo bar bargain", "bar") == 5
+ assert STRRIN("foo bar bargain", "bar") == 9
+
+ assert STRIN("foo bar", "qux") == 0
+ assert STRRIN("foo bar", "qux") == 0
+
+ assert STRIN("foo", "foobar") == 0
+ assert STRRIN("foo", "foobar") == 0
+
+ assert STRIN("foobar", "") == 1
+ assert STRRIN("foobar", "") == STRLEN("foobar") + 1