--- /dev/null
+/*****************************************************************************/
+/* */
+/* unittest.h */
+/* */
+/* Unit test helper macros */
+/* */
+/* */
+/* */
+/* (C) 2017 Christian Krueger */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+#ifndef _UNITTEST_H
+#define _UNITTEST_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef COMMA
+#define COMMA ,
+#endif
+
+#define TEST int main(void) \
+ {\
+ printf("%s: ",__FILE__);
+
+#define ENDTEST printf("Passed\n"); \
+ return EXIT_SUCCESS; \
+ }
+
+#define ASSERT_IsTrue(a,b) if (!(a)) \
+ {\
+ printf("Fail at line %d:\n",__LINE__);\
+ printf(b);\
+ printf("\n");\
+ printf("Expected status should be true but wasn't!\n");\
+ exit(EXIT_FAILURE);\
+ }
+
+#define ASSERT_IsFalse(a,b) if ((a)) \
+ {\
+ printf("Fail at line %d:\n",__LINE__);\
+ printf(b);\
+ printf("\n");\
+ printf("Expected status should be false but wasn't!\n");\
+ exit(EXIT_FAILURE);\
+ }
+
+#define ASSERT_AreEqual(a,b,c,d) if ((a) != (b)) \
+ {\
+ printf("Fail at line %d:\n",__LINE__);\
+ printf(d);\
+ printf("\n");\
+ printf("Expected value: "c", but is "c"!\n", (a), (b));\
+ exit(EXIT_FAILURE);\
+ }
+
+#define ASSERT_AreNotEqual(a,b,c,d) if ((a) == (b)) \
+ {\
+ printf("Fail at line %d:\n",__LINE__);\
+ printf(d);\
+ printf("\n");\
+ printf("Expected value not: "c", but is "c"!\n", (a), (b));\
+ exit(EXIT_FAILURE);\
+ }
+
+/* End of unittest.h */
+#endif
+
+
+
+
;
; Ullrich von Bassewitz, 31.05.1998
+; Christian Krueger: 2013-Aug-01, optimization
;
; char* strrchr (const char* s, int c);
;
.export _strrchr
.import popax
- .importzp ptr1, ptr2, tmp1
+ .importzp ptr1, tmp1, tmp2
_strrchr:
- sta tmp1 ; Save c
- jsr popax ; get s
- sta ptr1
- stx ptr1+1
- lda #0 ; function result = NULL
- sta ptr2
- sta ptr2+1
- tay
-
-L1: lda (ptr1),y ; get next char
- beq L3 ; jump if end of string
- cmp tmp1 ; found?
- bne L2 ; jump if no
-
-; Remember a pointer to the character
-
- tya
- clc
- adc ptr1
- sta ptr2
- lda ptr1+1
- adc #$00
- sta ptr2+1
-
-; Next char
-
-L2: iny
- bne L1
- inc ptr1+1
- bne L1 ; jump always
-
-; Return the pointer to the last occurrence
-
-L3: lda ptr2
- ldx ptr2+1
+ sta tmp1 ; Save c
+ jsr popax ; get s
+ tay ; low byte to y
+ stx ptr1+1
+ ldx #0 ; default function result is NULL, X is high byte...
+ stx tmp2 ; tmp2 is low-byte
+ stx ptr1 ; low-byte of source string is in Y, so clear real one...
+
+testChar:
+ lda (ptr1),y ; get char
+ beq finished ; jump if end of string
+ cmp tmp1 ; found?
+ bne nextChar ; jump if no
+
+charFound:
+ sty tmp2 ; y has low byte of location, save it
+ ldx ptr1+1 ; x holds high-byte of result
+
+nextChar:
+ iny
+ bne testChar
+ inc ptr1+1
+ bne testChar ; here like bra...
+
+; return the pointer to the last occurrence
+
+finished:
+ lda tmp2 ; high byte in X is already correct...
rts
-#include <stdio.h>
-#include <stdlib.h>
+#include <unittest.h>
#include <string.h>
#define SourceStringSize 257 // test correct page passing (>256)
static char DestinationString[2*SourceStringSize+1]; // will contain two times the source buffer
-int main (void)
+TEST
{
unsigned i,j;
char* p;
-
- /* Print a header */
- printf ("strcat(): ");
-
+
for (i=0; i < SourceStringSize; ++i)
SourceString[i] = (i%128)+1;
SourceString[i] = 0;
- if (strlen(SourceString) != SourceStringSize)
- {
- printf ("Fail: Source string initialization or 'strlen()' problem!\n");
- printf ("Expected length: %u but is %u!\n", SourceStringSize, strlen(SourceString));
- exit (EXIT_FAILURE);
- }
+ ASSERT_AreEqual(SourceStringSize, strlen(SourceString), "%u", "Source string initialization or 'strlen()' problem!");
/* Ensure empty destination string */
DestinationString[0] = 0;
- if (strlen(DestinationString) != 0)
- {
- printf ("Fail: Destination string initialization or 'strlen()' problem!\n");
- printf ("Expected length: %u but is %u!\n", 0, strlen(DestinationString));
- exit (EXIT_FAILURE);
- }
-
+ ASSERT_AreEqual(0, strlen(DestinationString), "%u", "Destination string initialization or 'strlen()' problem!");
+
/* Test concatenation to empty buffer */
- p = strcat(DestinationString, SourceString);
-
- if (strlen(DestinationString) != SourceStringSize)
- {
- printf ("Fail: String concatenation to empty buffer!\n");
- printf ("Expected length: %u but is %u!\n", SourceStringSize, strlen(DestinationString));
- exit (EXIT_FAILURE);
- }
-
+ strcat(DestinationString, SourceString);
+
+ ASSERT_AreEqual(SourceStringSize, strlen(DestinationString), "%u", "Unexpected string length while string concatenation to empty buffer!");
+
/* Test concatenation to non empty buffer */
p = strcat(DestinationString, SourceString);
- if (strlen(DestinationString) != 2*SourceStringSize)
- {
- printf ("Fail: String concatenation to non-empty buffer!\n");
- printf ("Expected length: %u but is %u!\n", 2*SourceStringSize, strlen(DestinationString));
- exit (EXIT_FAILURE);
- }
+ ASSERT_AreEqual(2*SourceStringSize, strlen(DestinationString), "%u", "Unexpected string length while string concatenation to non-empty buffer!");
/* Test return value */
- if (p != DestinationString)
- {
- printf ("Invalid return value!\n");
- exit (EXIT_FAILURE);
- }
+ ASSERT_IsTrue(p == DestinationString,"Invalid return value!");
/* Test contents */
unsigned position = j*SourceStringSize+i;
unsigned current = DestinationString[position];
unsigned expected = (i%128)+1;
- if (current != expected)
- {
- printf ("Fail: Unexpected destination buffer contents at position %u!\n", position);
- printf ("Expected %u, but is %u!\n", expected, current);
- exit (EXIT_FAILURE);
- }
+ ASSERT_AreEqual(expected, current, "%u", "Unexpected destination buffer contents at position %u!\n" COMMA position);
}
-
- /* Test passed */
- printf ("Passed\n");
- return EXIT_SUCCESS;
}
-
+ENDTEST
--- /dev/null
+#include <unittest.h>
+#include <string.h>
+
+static char TestString[] = "01234567890123456789"; // two times the same string
+static char Found[256];
+
+TEST
+{
+ unsigned len;
+ unsigned i;
+ char* p;
+
+ len = strlen(TestString)/2; // test only one half of the string, to find last appearance
+
+ /* Search for all characters in the string, including the terminator */
+ for (i = 0; i < len; ++i)
+ {
+ /* Search for this char */
+ p = strrchr (TestString, TestString[i]);
+ ASSERT_AreEqual(i+len, p-TestString, "%u", "Unexpected location of character '%c' found!" COMMA TestString[i]);
+
+ /* Mark the char as checked */
+ Found[TestString[i]] = 1;
+ }
+
+ /* Search for all other characters and make sure they aren't found */
+ for (i = 0; i < 256; ++i)
+ {
+ if (!Found[i])
+ {
+ p = strrchr (TestString, i);
+ ASSERT_IsFalse(p, "Unexpected location of character '%c' found!" COMMA TestString[i]);
+ }
+ }
+}
+ENDTEST
+
+