shithub: rgbds

Download patch

ref: a70ecba06f804990400326d0df079cd41e2ef096
parent: 9d2d5cfcfe4d647cb0a8a5363653e05b115f9940
author: Rangi <[email protected]>
date: Fri Jan 1 15:37:32 EST 2021

Implement PRINT and PRINTLN (#672)

Fixes #669
Closes #368
Closes #624

Deprecate PRINTT, PRINTV, PRINTI, and PRINTF

Default STRFMT("%f") to 5 fractional digits like "{f:}"
Any use of string formatting will share this default

--- a/src/asm/format.c
+++ b/src/asm/format.c
@@ -220,12 +220,16 @@
 		}
 	} else if (fmt->type == 'f') {
 		/* Special case for fixed-point */
-		if (fmt->fracWidth) {
+
+		/* Default fractional width (C's is 6 for "%f"; here 5 is enough) */
+		uint8_t fracWidth = fmt->hasFrac ? fmt->fracWidth : 5;
+
+		if (fracWidth) {
 			char spec[16]; /* Max "%" + 5-char PRIu32 + ".%0255.f" + terminator */
 
-			snprintf(spec, sizeof(spec), "%%" PRIu32 ".%%0%d.f", fmt->fracWidth);
+			snprintf(spec, sizeof(spec), "%%" PRIu32 ".%%0%d.f", fracWidth);
 			snprintf(valueBuf, sizeof(valueBuf), spec, value >> 16,
-				 (value % 65536) / 65536.0 * pow(10, fmt->fracWidth) + 0.5);
+				 (value % 65536) / 65536.0 * pow(10, fracWidth) + 0.5);
 		} else {
 			snprintf(valueBuf, sizeof(valueBuf), "%" PRIu32, value >> 16);
 		}
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -207,6 +207,8 @@
 	{"STRFMT", T_OP_STRFMT},
 
 	{"INCLUDE", T_POP_INCLUDE},
+	{"PRINT", T_POP_PRINT},
+	{"PRINTLN", T_POP_PRINTLN},
 	{"PRINTT", T_POP_PRINTT},
 	{"PRINTI", T_POP_PRINTI},
 	{"PRINTV", T_POP_PRINTV},
@@ -491,7 +493,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[356] = {0}; /* Make sure to keep this correct when adding keywords! */
+} keywordDict[353] = {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)
@@ -1315,13 +1317,8 @@
 				fmt_UseCharacter(&fmt, symName[j]);
 			fmt_FinishCharacters(&fmt);
 			symName[i] = '\0';
-			if (!fmt_IsValid(&fmt)) {
+			if (!fmt_IsValid(&fmt))
 				error("Invalid format spec '%s'\n", symName);
-			} else if (!strcmp(symName, "f")) {
-				/* Format 'f' defaults to '.5f' like PRINTF */
-				fmt.hasFrac = true;
-				fmt.fracWidth = 5;
-			}
 			i = 0; /* Now that format has been set, restart at beginning of string */
 		} else {
 			shiftChars(1);
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -317,6 +317,7 @@
 %type	<sVal>		relocexpr
 %type	<sVal>		relocexpr_no_str
 %type	<nConstValue>	const
+%type	<nConstValue>	const_no_str
 %type	<nConstValue>	uconst
 %type	<nConstValue>	rs_uconst
 %type	<nConstValue>	const_3bit
@@ -399,7 +400,7 @@
 %token	T_POP_EQUAL
 %token	T_POP_EQUS
 
-%token	T_POP_INCLUDE T_POP_PRINTF T_POP_PRINTT T_POP_PRINTV T_POP_PRINTI
+%token	T_POP_INCLUDE T_POP_PRINT T_POP_PRINTLN T_POP_PRINTF T_POP_PRINTT T_POP_PRINTV T_POP_PRINTI
 %token	T_POP_IF T_POP_ELIF T_POP_ELSE T_POP_ENDC
 %token	T_POP_EXPORT T_POP_GLOBAL T_POP_XDEF
 %token	T_POP_DB T_POP_DS T_POP_DW T_POP_DL
@@ -617,6 +618,8 @@
 ;
 
 simple_pseudoop : include
+		| print
+		| println
 		| printf
 		| printt
 		| printv
@@ -966,18 +969,45 @@
 popc		: T_POP_POPC	{ charmap_Pop(); }
 ;
 
-printt		: T_POP_PRINTT string	{ printf("%s", $2); }
+print		: T_POP_PRINT print_exprs
 ;
 
-printv		: T_POP_PRINTV const	{ printf("$%" PRIX32, $2); }
+println		: T_POP_PRINTLN { putchar('\n'); }
+		| T_POP_PRINTLN print_exprs { putchar('\n'); }
 ;
 
-printi		: T_POP_PRINTI const	{ printf("%" PRId32, $2); }
+print_exprs	: print_expr
+		| print_exprs T_COMMA print_expr
 ;
 
-printf		: T_POP_PRINTF const	{ math_Print($2); }
+print_expr	: const_no_str { printf("$%" PRIX32, $1); }
+		| string { printf("%s", $1); }
 ;
 
+printt		: T_POP_PRINTT string	{
+			warning(WARNING_OBSOLETE, "`PRINTT` is deprecated; use `PRINT`\n");
+			printf("%s", $2);
+		}
+;
+
+printv		: T_POP_PRINTV const	{
+			warning(WARNING_OBSOLETE, "`PRINTV` is deprecated; use `PRINT`\n");
+			printf("$%" PRIX32, $2);
+		}
+;
+
+printi		: T_POP_PRINTI const	{
+			warning(WARNING_OBSOLETE, "`PRINTI` is deprecated; use `PRINT` with `STRFMT`\n");
+			printf("%" PRId32, $2);
+		}
+;
+
+printf		: T_POP_PRINTF const	{
+			warning(WARNING_OBSOLETE, "`PRINTF` is deprecated; use `PRINT` with `STRFMT`\n");
+			math_Print($2);
+		}
+;
+
 const_3bit	: const {
 			int32_t value = $1;
 
@@ -1240,6 +1270,17 @@
 ;
 
 const		: relocexpr {
+			if (!rpn_isKnown(&$1)) {
+				error("Expected constant expression: %s\n",
+					$1.reason);
+				$$ = 0;
+			} else {
+				$$ = $1.nVal;
+			}
+		}
+;
+
+const_no_str	: relocexpr_no_str {
 			if (!rpn_isKnown(&$1)) {
 				error("Expected constant expression: %s\n",
 					$1.reason);
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -269,7 +269,7 @@
 TOPIC equs "life, the universe, and \[rs]"everything\[rs]""
 ANSWER = 42
 ;\ Prints "The answer to life, the universe, and "everything" is $2A"
-PRINTT "The answer to {TOPIC} is {ANSWER}\[rs]n"
+PRINTLN "The answer to {TOPIC} is {ANSWER}"
 .Ed
 .Pp
 Symbol interpolations can be nested, too!
@@ -313,6 +313,7 @@
 \[en]
 .Ql 9 .
 If specified, prints this many digits of a fixed-point fraction.
+Defaults to 5 digits.
 .It Ql <type> Ta Specifies the type of value.
 .El
 .Pp
@@ -334,11 +335,11 @@
 Examples:
 .Bd -literal -offset indent
 ; Prints "%0010 + $3 == 5"
-PRINTT STRFMT("%#05b + %#x == %d\n", 2, 3, 2+3)
+PRINTLN STRFMT("%#05b + %#x == %d", 2, 3, 2+3)
 ; Prints "32% of 20 = 6.40"
-PRINTT STRFMT("%d%% of %d = %.2f\n", 32, 20, MUL(20.0, 0.32))
+PRINTLN STRFMT("%d%% of %d = %.2f", 32, 20, MUL(20.0, 0.32))
 ; Prints "Hello world!"
-PRINTT STRFMT("Hello %s!\n", STRLWR("WORLD"))
+PRINTLN STRFMT("Hello %s!", STRLWR("WORLD"))
 .Ed
 .Pp
 HINT: The
@@ -355,7 +356,7 @@
 ;\ Defines ITEM_100 as "\[rs]"hundredth\[rs]""
 {NAME}_{d:INDEX} equs "\[rs]"hundredth\[rs]""
 ;\ Prints "ITEM_100 is hundredth"
-PRINTT STRCAT("{NAME}_{d:INDEX} is ", {NAME}_{d:INDEX})
+PRINTLN STRCAT("{NAME}_{d:INDEX} is ", {NAME}_{d:INDEX})
 ;\ Purges ITEM_100
 PURGE {NAME}_{d:INDEX}
 .Ed
@@ -1065,7 +1066,7 @@
 .Bd -literal -offset indent
 outer: MACRO
 inner: MACRO
-    PRINTT "Hello!\[rs]n"
+    PRINTLN "Hello!"
 ENDM
 ENDM
 .Ed
@@ -1073,7 +1074,7 @@
 But this will:
 .Bd -literal -offset indent
 outer: MACRO
-definition equs "inner: MACRO\[rs]nPRINTT \[rs]"Hello!\[rs]\[rs]n\[rs]"\[rs]nENDM"
+definition equs "inner: MACRO\[rs]nPRINTLN \[rs]"Hello!\[rs]"\[rs]nENDM"
 definition
     PURGE definition
 ENDM
@@ -1435,15 +1436,15 @@
 For instance, consider the following:
 .Bd -literal -offset indent
 print_double: MACRO
-    PRINTV \[rs]1 * 2
+    PRINTLN \[rs]1 * 2
 ENDM
     print_double 1 + 2
 .Ed
 .Pp
 The
-.Ic PRINTV
+.Ic PRINTLN
 statement will expand to
-.Ql PRINTV 1 + 2 * 2 ,
+.Ql PRINTLN 1 + 2 * 2 ,
 which will print 5 and not 6 as you might have expected.
 .Pp
 Line continuations work as usual inside macros or lists of macro arguments.
@@ -1450,7 +1451,7 @@
 However, some characters need to be escaped, as in the following example:
 .Bd -literal -offset indent
 PrintMacro: MACRO
-    PRINTT \[rs]1
+    PRINT \[rs]1
 ENDM
 
     PrintMacro STRCAT("Hello "\[rs], \[rs]
@@ -1490,31 +1491,31 @@
 .Ic SHIFT
 can optionally be given an integer parameter, and will apply the above shifting that number of times.
 .Ss Printing things during assembly
-The next four commands print text and values to the standard output.
+The
+.Ic PRINT
+and
+.Ic PRINTLN
+commands print text and values to the standard output.
 Useful for debugging macros, or wherever you may feel the need to tell yourself some important information.
 .Bd -literal -offset indent
-PRINTT "I'm the greatest programmer in the whole wide world\[rs]n"
-PRINTI (2 + 3) / 5
-PRINTV $FF00 + $F0
-PRINTF MUL(3.14, 3987.0)
+PRINT "Hello world!\[rs]n"
+PRINTLN "Hello world!"
+PRINT _NARG, " arguments\[rs]n"
+PRINTLN "sum: ", 2+3, " product: ", 2*3
+PRINTLN "Line #", __LINE__
+PRINTLN STRFMT("E = %f", 2.718)
 .Ed
 .Bl -inset
-.It Ic PRINTT
-prints out a string.
-Be careful to add a line feed
-.Pq Qq \[rs]n
-at the end, as it is not added automatically.
-.It Ic PRINTV
-prints out an integer value in hexadecimal or, as in the example, the result of a calculation.
-Unsurprisingly, you can also print out a constant symbol's value.
-.It Ic PRINTI
-prints out a signed integer value.
-.It Ic PRINTF
-prints out a fixed point value.
+.It Ic PRINT
+prints out each of its comma-separated arguments.
+Numbers are printed as unsigned uppercase hexadecimal with a leading
+.Ic $ .
+For different formats, use
+.Ic STRFMT .
+.It Ic PRINTLN
+prints out each of its comma-separated arguments, if any, followed by a line feed
+.Pq Ql \[rs]n .
 .El
-.Pp
-Be careful that none of those automatically print a line feed; if you need one, use
-.Ic PRINTT "\[rs]n" .
 .Ss Automatically repeating blocks of code
 Suppose you want to unroll a time consuming loop without copy-pasting it.
 .Ic REPT
@@ -1537,14 +1538,12 @@
 .Ic REPT
 to generate tables on the fly:
 .Bd -literal -offset indent
-;\ --
-;\ -- Generate a 256 byte sine table with values between 0 and 128
-;\ --
-ANGLE =   0.0
-      REPT  256
-      db    (MUL(64.0, SIN(ANGLE)) + 64.0) >> 16
-ANGLE = ANGLE+256.0
-      ENDR
+; Generate a 256-byte sine table with values between 0 and 128
+ANGLE = 0.0
+    REPT 256
+        db (MUL(64.0, SIN(ANGLE)) + 64.0) >> 16
+ANGLE = ANGLE + 256.0
+    ENDR
 .Ed
 .Pp
 As in macros, you can also use the escape sequence
@@ -1602,9 +1601,9 @@
 For example:
 .Bd -literal -offset indent
 FOR V, 4, 25, 5
-      PRINTT "{d:V} "
+      PRINT "{d:V} "
 ENDR
-      PRINTT "done {d:V}\n"
+      PRINTLN "done {d:V}"
 .Ed
 This will print:
 .Bd -literal -offset indent
@@ -1714,11 +1713,11 @@
 This is a powerful feature commonly used in macros.
 .Bd -literal -offset indent
 IF NUM < 0
-  PRINTT "NUM < 0\[rs]n"
+  PRINTLN "NUM < 0"
 ELIF NUM == 0
-  PRINTT "NUM == 0\[rs]n"
+  PRINTLN "NUM == 0"
 ELSE
-  PRINTT "NUM > 0\[rs]n"
+  PRINTLN "NUM > 0"
 ENDC
 .Ed
 .Pp
--- a/test/asm/arg-shift.asm
+++ b/test/asm/arg-shift.asm
@@ -1,24 +1,23 @@
 print_all: MACRO
 	REPT _NARG
-		PRINTT " \1"
+		PRINT " \1"
 		SHIFT
 	ENDR
-	PRINTT "\n"
+	PRINTLN
 ENDM
 
 print_some: MACRO
-	PRINTT "\1"
+	PRINT "\1"
 	SHIFT 5
-	PRINTT "\2\6\9"
+	PRINT "\2\6\9"
 	SHIFT 17
 	SHIFT
-	PRINTT "\3\9"
+	PRINT "\3\9"
 ENDM
 
 bad: MACRO
 	shift _NARG - 1
-	PRINTT \1
-	PRINTT "\n"
+	PRINTLN \1
 ENDM
 
 bad_rept: MACRO
@@ -27,8 +26,7 @@
 			shift
 		ENDR
 	ENDR
-	PRINTT \1
-	PRINTT "\n"
+	PRINTLN \1
 ENDM
 
 	print_all This test, probably, passes\,, but who knows, ?
--- a/test/asm/bank.asm
+++ b/test/asm/bank.asm
@@ -5,8 +5,7 @@
 		SECTION "\1", \2, BANK[\3]
 	ENDC
 
-	PRINTV BANK("\1")
-	PRINTT "\n"
+	PRINTLN BANK("\1")
 endm
 
  def_sect ROM0_ok,  ROM0
--- a/test/asm/bank.err
+++ b/test/asm/bank.err
@@ -1,9 +1,9 @@
-ERROR: bank.asm(14) -> bank.asm::def_sect(8):
+ERROR: bank.asm(13) -> bank.asm::def_sect(8):
     Expected constant expression: Section "ROMX_bad"'s bank is not known
-ERROR: bank.asm(16) -> bank.asm::def_sect(8):
+ERROR: bank.asm(15) -> bank.asm::def_sect(8):
     Expected constant expression: Section "VRAM_bad"'s bank is not known
-ERROR: bank.asm(18) -> bank.asm::def_sect(8):
+ERROR: bank.asm(17) -> bank.asm::def_sect(8):
     Expected constant expression: Section "SRAM_bad"'s bank is not known
-ERROR: bank.asm(21) -> bank.asm::def_sect(8):
+ERROR: bank.asm(20) -> bank.asm::def_sect(8):
     Expected constant expression: Section "WRAMX_bad"'s bank is not known
 error: Assembly aborted (4 errors)!
--- a/test/asm/block-comment-contents-error.asm
+++ b/test/asm/block-comment-contents-error.asm
@@ -1,2 +1,2 @@
 /* block comments containing /* throw warnings */
-PRINTT "reachable\n"
+PRINTLN "reachable"
--- a/test/asm/block-comment-termination-error.asm
+++ b/test/asm/block-comment-termination-error.asm
@@ -1,1 +1,1 @@
-PRINTT /* block comments must terminate before EOF
\ No newline at end of file
+PRINT /* block comments must terminate before EOF
\ No newline at end of file
--- a/test/asm/block-comment.asm
+++ b/test/asm/block-comment.asm
@@ -1,5 +1,5 @@
-PRINTT /* block comments are ignored // ** */ "hi\n"
-PRINTT "block (/* ... */) comments at ends of line are fine\n" /* hi */
-PRINTT /* block comments
+PRINTLN /* block comments are ignored // ** */ "hi"
+PRINTLN "block (/* ... */) comments at ends of line are fine" /* hi */
+PRINTLN /* block comments
 can span multiple lines
-*/ "mutliline\n"
+*/ "mutliline"
--- a/test/asm/bracketed-symbols.asm
+++ b/test/asm/bracketed-symbols.asm
@@ -1,21 +1,21 @@
 X = 42
-PRINTT "{X}\n"
-PRINTT "{x:X}\n"
-PRINTT "{X:X}\n"
-PRINTT "{d:X}\n"
-PRINTT "{b:X}\n"
+PRINTLN "{X}"
+PRINTLN "{x:X}"
+PRINTLN "{X:X}"
+PRINTLN "{d:X}"
+PRINTLN "{b:X}"
 
 Y equ 1337
-PRINTT "{b:Y}\n"
+PRINTLN "{b:Y}"
 
 rsreset
 R rb 0
-PRINTT "{d:R}\n"
+PRINTLN "{d:R}"
 
 S equs "You can't format me!"
-PRINTT "{X:S}\n"
+PRINTLN "{X:S}"
 
 SECTION "Test", ROM0
 Label:
-PRINTT "{x:Label}\n"
-PRINTT "{x:@}\n"
+PRINTLN "{x:Label}"
+PRINTLN "{x:@}"
--- a/test/asm/deprecated-pi.asm
+++ b/test/asm/deprecated-pi.asm
@@ -1,4 +1,3 @@
 ; Remove this test case when _PI is removed.
-	PRINTF _PI
-	PRINTT "\n"
+	PRINTLN "{f:_PI}"
 	PURGE _PI
--- a/test/asm/deprecated-pi.err
+++ b/test/asm/deprecated-pi.err
@@ -1,5 +1,5 @@
 warning: deprecated-pi.asm(2): [-Wobsolete]
     `_PI` is deprecated; use 3.14159
-ERROR: deprecated-pi.asm(4):
+ERROR: deprecated-pi.asm(3):
     Built-in symbol '_PI' cannot be purged
 error: Assembly aborted (1 errors)!
--- a/test/asm/equs-macrodef.asm
+++ b/test/asm/equs-macrodef.asm
@@ -1,3 +1,3 @@
-DEFINE equs "mac: MACRO\nPRINTT \"Hello :D\\n\"\nENDM"
+DEFINE equs "mac: MACRO\nPRINTLN \"Hello :D\"\nENDM"
 DEFINE
 	mac
--- a/test/asm/equs-nest.asm
+++ b/test/asm/equs-nest.asm
@@ -1,4 +1,4 @@
 X1 equs "Y1 equs \"\\\"Success!\\\\n\\\"\""
 Y1 equs "Z1"
 X1
-	PRINTT Z1
+	PRINT Z1
--- a/test/asm/file-sym.asm
+++ b/test/asm/file-sym.asm
@@ -1,1 +1,1 @@
-PRINTT "{__FILE__}\n"
+PRINTLN "{__FILE__}"
--- a/test/asm/for.asm
+++ b/test/asm/for.asm
@@ -1,48 +1,48 @@
 for n, 10
-	printt "{d:n} "
+	print "{d:n} "
 endr
-	printt "-> {d:n}\n"
+	println "-> {d:n}"
 
 for v, 0
-	printt "unreached"
+	print "unreached"
 endr
 
 for v, 2, 1
-	printt "unreached"
+	print "unreached"
 endr
 
 for v, 1, 2, 0
-	printt "unreached"
+	print "unreached"
 endr
 
 for x, 1, 5+1
-	printt "{d:x} "
+	print "{d:x} "
 endr
-	printt "-> {d:x}\n"
+	println "-> {d:x}"
 
 for v, 10, -1, -1
-	printt "{d:v} "
+	print "{d:v} "
 v = 42
 endr
-	printt "-> {d:v}\n"
+	println "-> {d:v}"
 
 for q, 5, 21, 5
-	printt "{d:q} "
+	print "{d:q} "
 purge q
 endr
-	printt "-> {d:q}\n"
+	println "-> {d:q}"
 
 s EQUS "x"
 for s, 3, 30, 3
-	printt "{d:x} "
+	print "{d:x} "
 endr
-	printt "-> {d:x}\n"
+	println "-> {d:x}"
 
 for v, 10
-	printt "{d:v}\n"
+	println "{d:v}"
 if v == 3
 purge v
 v equ 42 ; causes a fatal error
 endc
 endr
-	printt "-> {d:v}\n"
+	println "-> {d:v}"
--- a/test/asm/interpolation.asm
+++ b/test/asm/interpolation.asm
@@ -9,7 +9,7 @@
 ; Defines ITEM_100 as "\"hundredth\""
 {NAME}_{d:INDEX} equs "\"hundredth\""
 ; Prints "ITEM_100 is hundredth"
-PRINTT STRCAT("{NAME}_{d:INDEX} is ", {NAME}_{d:INDEX}, "\n")
+PRINTLN STRCAT("{NAME}_{d:INDEX}", " is ", {NAME}_{d:INDEX})
 ; Purges ITEM_100
 PURGE {NAME}_{d:INDEX}
 ASSERT !DEF({NAME}_{d:INDEX})
--- a/test/asm/isconst.asm
+++ b/test/asm/isconst.asm
@@ -5,7 +5,7 @@
 TEST_NUM = TEST_NUM + 1
 
 IS_CONST = ISCONST(\1)
-	PRINTT "Test #{d:TEST_NUM}: ISCONST reports {IS_CONST}\n"
+	PRINTLN "Test #{d:TEST_NUM}: ISCONST reports {IS_CONST}"
 	IF (\1) || 1 ; Only test if the expression can be evaluated
 		WARN "Test #{d:TEST_NUM}: Compile-time constant"
 	ENDC
--- a/test/asm/jr-section.asm
+++ b/test/asm/jr-section.asm
@@ -3,4 +3,4 @@
 Label:
 	jr Label
 DIFF equ Label - @
-	PRINTT "{DIFF}\n"
+	PRINTLN "{DIFF}"
--- a/test/asm/label-diff.asm
+++ b/test/asm/label-diff.asm
@@ -17,10 +17,8 @@
 
 
 print_diff: MACRO
-	PRINTV (\1) - (\2)
-	PRINTT "\n"
-	PRINTV (\2) - (\1)
-	PRINTT "\n"
+	PRINTLN (\1) - (\2)
+	PRINTLN (\2) - (\1)
 ENDM
 
 POPS ; Ensure we are in neither section
--- a/test/asm/label-diff.err
+++ b/test/asm/label-diff.err
@@ -1,37 +1,37 @@
-ERROR: label-diff.asm(34) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(32) -> label-diff.asm::print_diff(20):
     Expected constant expression: 'Known' is not constant at assembly time
-ERROR: label-diff.asm(34) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(32) -> label-diff.asm::print_diff(21):
     Expected constant expression: 'Known' is not constant at assembly time
-ERROR: label-diff.asm(36) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(34) -> label-diff.asm::print_diff(20):
     Expected constant expression: 'Unknown' is not constant at assembly time
-ERROR: label-diff.asm(36) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(34) -> label-diff.asm::print_diff(21):
     Expected constant expression: 'Unknown' is not constant at assembly time
-ERROR: label-diff.asm(38) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(36) -> label-diff.asm::print_diff(20):
     Expected constant expression: 'Known' is not constant at assembly time
-ERROR: label-diff.asm(38) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(36) -> label-diff.asm::print_diff(21):
     Expected constant expression: 'Unknown' is not constant at assembly time
-ERROR: label-diff.asm(40) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(38) -> label-diff.asm::print_diff(20):
     Expected constant expression: 'Unknown' is not constant at assembly time
-ERROR: label-diff.asm(40) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(38) -> label-diff.asm::print_diff(21):
     Expected constant expression: 'Unknown2' is not constant at assembly time
-ERROR: label-diff.asm(47) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(45) -> label-diff.asm::print_diff(20):
     Expected constant expression: 'Known' is not constant at assembly time
-ERROR: label-diff.asm(47) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(45) -> label-diff.asm::print_diff(21):
     Expected constant expression: 'Known' is not constant at assembly time
-ERROR: label-diff.asm(49) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(47) -> label-diff.asm::print_diff(20):
     Expected constant expression: 'Unknown' is not constant at assembly time
-ERROR: label-diff.asm(49) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(47) -> label-diff.asm::print_diff(21):
     Expected constant expression: 'Unknown' is not constant at assembly time
-ERROR: label-diff.asm(60) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(58) -> label-diff.asm::print_diff(20):
     Expected constant expression: PC is not constant at assembly time
-ERROR: label-diff.asm(60) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(58) -> label-diff.asm::print_diff(21):
     Expected constant expression: PC is not constant at assembly time
-ERROR: label-diff.asm(62) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(60) -> label-diff.asm::print_diff(20):
     Expected constant expression: 'Known' is not constant at assembly time
-ERROR: label-diff.asm(62) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(60) -> label-diff.asm::print_diff(21):
     Expected constant expression: PC is not constant at assembly time
-ERROR: label-diff.asm(64) -> label-diff.asm::print_diff(20):
+ERROR: label-diff.asm(62) -> label-diff.asm::print_diff(20):
     Expected constant expression: 'Unknown' is not constant at assembly time
-ERROR: label-diff.asm(64) -> label-diff.asm::print_diff(22):
+ERROR: label-diff.asm(62) -> label-diff.asm::print_diff(21):
     Expected constant expression: PC is not constant at assembly time
 error: Assembly aborted (18 errors)!
--- a/test/asm/label-macro-arg.asm
+++ b/test/asm/label-macro-arg.asm
@@ -1,9 +1,3 @@
-print: MACRO
-	printv \1
-	printt "\n"
-ENDM
-
-
 m1: MACRO
 x\1
 ENDM
@@ -20,10 +14,10 @@
 	m1 x = 7
 	m2 2 = 8
 
-	print x
-	print y
-	print xx
-	print yy
+	println x
+	println y
+	println xx
+	println yy
 
 
 test_char: MACRO
@@ -32,7 +26,7 @@
 sizeof_\1something = 1
 	PURGE VAR_DEF
 
-VAR_PRINT equs "printt \"sizeof_\1something equals {sizeof_\1something}\\n\""
+VAR_PRINT equs "println \"sizeof_\1something equals {sizeof_\1something}\""
 	VAR_PRINT
 	PURGE VAR_PRINT
 ENDM
--- a/test/asm/label-macro-arg.err
+++ b/test/asm/label-macro-arg.err
@@ -1,7 +1,7 @@
-ERROR: label-macro-arg.asm(44) -> label-macro-arg.asm::test_char(31):
+ERROR: label-macro-arg.asm(38) -> label-macro-arg.asm::test_char(25):
     Local label 'sizeof_.something' in main scope
 while expanding symbol "VAR_DEF"
-ERROR: label-macro-arg.asm(44) -> label-macro-arg.asm::test_char(31):
+ERROR: label-macro-arg.asm(38) -> label-macro-arg.asm::test_char(25):
     syntax error
 while expanding symbol "VAR_DEF"
 error: Assembly aborted (2 errors)!
--- a/test/asm/label-outside-section.asm
+++ b/test/asm/label-outside-section.asm
@@ -1,4 +1,4 @@
 bad:
 SECTION "Test", ROM0
 good:
-    PRINTT "OK!\n"
+    PRINTLN "OK!"
--- a/test/asm/local-purge.asm
+++ b/test/asm/local-purge.asm
@@ -5,4 +5,4 @@
 Glob:
 .loc
 	PURGE .loc
-	PRINTT "{.loc}\n" ; This should fail because the label doesn't exist anymore
+	PRINTLN "{.loc}" ; This should fail because the label doesn't exist anymore
--- a/test/asm/long-rpn-expression.asm
+++ b/test/asm/long-rpn-expression.asm
@@ -6,12 +6,9 @@
 \1 EQUS STRCAT("{X\2}", "+1")
 ENDM
 
-n = 0
-
-REPT $7E
+FOR n, $7E
 n1 = n + 1
     m X{X:n1}, {X:n}
-n = n + 1
 ENDR
 
 ; string of 127 zeros separated by plus signs
--- a/test/asm/macro-#.asm
+++ b/test/asm/macro-#.asm
@@ -27,7 +27,7 @@
 	object 12,  6, $66, $77, $88
 
 echo: MACRO
-	printt "\#\n"
+	println "\#"
 ENDM
 
 R EQUS "S"
@@ -36,11 +36,10 @@
 	echo Q,R, {R},  T
 	echo 42,$2a
 
-print: MACRO
-	printt STRCAT(\#)
-	printt "\n"
+printall: MACRO
+	println \#
 ENDM
 
-	print
-	print "A"
-	print "B", "C",  "D"
+	printall
+	printall "A"
+	printall "B", "C",  "D"
--- a/test/asm/macro-arg-in-string.asm
+++ b/test/asm/macro-arg-in-string.asm
@@ -1,18 +1,16 @@
-print: MACRO
-	PRINTT "\1"
-	PRINTT "\n"
+print1: MACRO
+	PRINTLN "\1"
 ENDM
 
-	print John "Danger" Smith
-	print \\A\nB
-	print C\
+	print1 John "Danger" Smith
+	print1 \\A\nB
+	print1 C\
 D
-	print E\!F ; illegal character escape
+	print1 E\!F ; illegal character escape
 
 
 iprint: MACRO
-	PRINTT "{\1}"
-	PRINTT "\n"
+	PRINTLN "{\1}"
 ENDM
 
 s EQUS "hello"
--- a/test/asm/macro-arg-in-string.err
+++ b/test/asm/macro-arg-in-string.err
@@ -1,3 +1,3 @@
-ERROR: macro-arg-in-string.asm(10) -> macro-arg-in-string.asm::print(2):
+ERROR: macro-arg-in-string.asm(9) -> macro-arg-in-string.asm::print1(2):
     Illegal character escape '!'
 error: Assembly aborted (1 errors)!
--- a/test/asm/multi-line-strings.asm
+++ b/test/asm/multi-line-strings.asm
@@ -1,12 +1,12 @@
 S EQUS "Hello"
 
-PRINTT "\"\"\"\n"
+PRINT "\"\"\"\n"
 
-PRINTT """{S}
+PRINT """{S}
 world
 """
 
-PRINTT """The multi-line string \ ; line continuations work
+PRINT """The multi-line string \ ; line continuations work
 can contain:
 - "single quotes"
 - ""double quotes""
@@ -13,11 +13,11 @@
 - even escaped \"""triple"\"" ""\"quotes\"\"\"
 !"""
 
-PRINTT """\n"""
+PRINT """\n"""
 
 printarg: MACRO
-	PRINTT "arg <\1>\n"
-	PRINTT """arg (\1)\n"""
+	PRINTLN "arg <\1>"
+	PRINTLN """arg (\1)"""
 ENDM
 
 	printarg "
@@ -29,4 +29,4 @@
 EMPTY3 EQUS """"""
 EMPTY4 EQUS """\ ; comment
 """
-	PRINTT STRCAT("(", "{EMPTY1}", "{EMPTY2}", "{EMPTY3}", "{EMPTY4}", ")\n")
+	PRINTLN STRCAT("(", "{EMPTY1}", "{EMPTY2}", "{EMPTY3}", "{EMPTY4}", ")")
--- a/test/asm/multiple-charmaps.asm
+++ b/test/asm/multiple-charmaps.asm
@@ -1,56 +1,56 @@
 new_: MACRO
 	IF _NARG > 1
-	printt "newcharmap \1, \2\n"
+	println "newcharmap \1, \2"
 	newcharmap \1, \2
 	ELSE
-	printt "newcharmap \1\n"
+	println "newcharmap \1"
 	newcharmap \1
 	ENDC
 ENDM
 
 set_: MACRO
-	printt "setcharmap \1\n"
+	println "setcharmap \1"
 	setcharmap \1
 ENDM
 
 push_: MACRO
-	printt "pushc\n"
+	println "pushc"
 	pushc
 ENDM
 
 pop_: MACRO
-	printt "popc\n"
+	println "popc"
 	popc
 ENDM
 
-print: MACRO
+print_mapped: MACRO
 x = \1
-printt "{x}\n"
+println "{x}"
 ENDM
 
-printt "main charmap\n"
+println "main charmap"
 
 charmap "ab", $0
 
-	print "ab"
+	print_mapped "ab"
 
 	new_ map1
 
-	print "ab"
+	print_mapped "ab"
 
 	new_ map2, main
 
-	print "ab"
+	print_mapped "ab"
 
 	set_ map1
 
-	print "ab"
+	print_mapped "ab"
 
 	new_ map3
 
 charmap "ab", $1
 
-	print "ab"
+	print_mapped "ab"
 
 	new_ map4, map3
 
@@ -57,25 +57,25 @@
 charmap "ab", $1
 charmap "cd", $2
 
-	print "ab"
-	print "cd"
+	print_mapped "ab"
+	print_mapped "cd"
 
 	set_ map3
 
-	print "ab"
-	print "cd"
+	print_mapped "ab"
+	print_mapped "cd"
 
 	set_ main
 
 SECTION "sec0", ROM0
 
-	print "ab"
+	print_mapped "ab"
 
-printt "modify main charmap\n"
+println "modify main charmap"
 charmap "ef", $3
 
-	print "ab"
-	print "ef"
+	print_mapped "ab"
+	print_mapped "ef"
 
 	set_ map1
 
@@ -85,17 +85,17 @@
 
 	set_ map3
 
-	print "ab"
-	print "cd"
-	print "ef"
+	print_mapped "ab"
+	print_mapped "cd"
+	print_mapped "ef"
 
 	pop_
 
-	print "ab"
+	print_mapped "ab"
 
 	pop_
 
-	print "ab"
+	print_mapped "ab"
 
 	new_ map1
 
--- a/test/asm/narg-nosect.asm
+++ b/test/asm/narg-nosect.asm
@@ -1,1 +1,1 @@
-	PRINTT "{_NARG}\n"
+	PRINTLN "{_NARG}"
--- a/test/asm/nested-brackets.asm
+++ b/test/asm/nested-brackets.asm
@@ -1,6 +1,5 @@
 STRING equs "OK"
 WRAPPER equs "TRIN"
-	PRINTT "{S{WRAPPER}G}\n"
+	PRINTLN "{S{WRAPPER}G}"
 
-	PRINTT "{S{WRAPPER}G"
-	PRINTT "\n"
+	PRINTLN "{S{WRAPPER}G"
--- a/test/asm/nested-macrodef.asm
+++ b/test/asm/nested-macrodef.asm
@@ -1,5 +1,5 @@
 outer_ok: MACRO
-definition equs "inner_ok: MACRO\nPRINTT \"Hello!\\n\"\nENDM"
+definition equs "inner_ok: MACRO\nPRINTLN \"Hello!\"\nENDM"
 definition
 	PURGE definition
 ENDM
@@ -9,7 +9,7 @@
 
 
 outer_arg: MACRO
-definition equs "inner_arg: MACRO\nPRINTT \"outer: \1\\ninner: \\1\\n\"\nENDM"
+definition equs "inner_arg: MACRO\nPRINTLN \"outer: \1\\ninner: \\1\"\nENDM"
 definition
 	PURGE definition
 ENDM
--- a/test/asm/operator-precedence.asm
+++ b/test/asm/operator-precedence.asm
@@ -1,7 +1,2 @@
-print: MACRO
-	printv \1
-	printt "\n"
-ENDM
-
-	print 1 == 1 || 1 == 2
-	print (1 == 1) || (1 == 2)
+	println 1 == 1 || 1 == 2
+	println (1 == 1) || (1 == 2)
--- a/test/asm/opt-b.asm
+++ b/test/asm/opt-b.asm
@@ -1,3 +1,2 @@
 OPT b.X
-PRINTV %..X.X.X.
-PRINTT "\n"
+PRINTLN %..X.X.X.
--- a/test/asm/opt-g.asm
+++ b/test/asm/opt-g.asm
@@ -1,3 +1,2 @@
 OPT g.x0X
-PRINTV `.x.x0X0X
-PRINTT "\n"
+PRINTLN `.x.x0X0X
--- a/test/asm/overflow.asm
+++ b/test/asm/overflow.asm
@@ -1,8 +1,7 @@
 SECTION "sec", ROM0
 
 print_x: MACRO
-	printv x
-	printt "\n"
+	println x
 ENDM
 
 x = 2147483647
--- a/test/asm/overflow.err
+++ b/test/asm/overflow.err
@@ -1,8 +1,8 @@
+warning: overflow.asm(23): [-Wdiv]
+    Division of -2147483648 by -1 yields -2147483648
 warning: overflow.asm(24): [-Wdiv]
     Division of -2147483648 by -1 yields -2147483648
-warning: overflow.asm(25): [-Wdiv]
-    Division of -2147483648 by -1 yields -2147483648
-warning: overflow.asm(39): [-Wlarge-constant]
+warning: overflow.asm(38): [-Wlarge-constant]
     Integer constant is too large
-warning: overflow.asm(42): [-Wlarge-constant]
+warning: overflow.asm(41): [-Wlarge-constant]
     Graphics constant is too long, only 8 first pixels considered
--- a/test/asm/pc-bank.asm
+++ b/test/asm/pc-bank.asm
@@ -6,6 +6,6 @@
 SECTION "Something else", ROMX
 Y = BANK("Fixed bank")
 
-    PRINTT "@: {X}\nStr: {Y}\n"
+    PRINTLN "@: {X}\nStr: {Y}"
 
 ERR = BANK(@)
--- a/test/asm/pc-def.asm
+++ b/test/asm/pc-def.asm
@@ -1,5 +1,5 @@
 IF DEF(@)
-	PRINTT "defined\n"
+	PRINTLN "defined"
 ELSE
-	PRINTT "not defined\n"
+	PRINTLN "not defined"
 ENDC
--- a/test/asm/pc.asm
+++ b/test/asm/pc.asm
@@ -1,7 +1,7 @@
 SECTION "fixed", ROM0[420]
-	PRINTT "{@}\n"
+	PRINTLN "{@}"
 	ds 69
-	PRINTT "{@}\n"
+	PRINTLN "{@}"
 
 ; FIXME: expected to land at $0000
 SECTION "floating", ROM0
--- a/test/asm/ram-code.asm
+++ b/test/asm/ram-code.asm
@@ -1,8 +1,8 @@
 SECTION "test", ROM0[1]
 	call Target
-	PRINTT "PC in ROM: {@}\n"
+	PRINTLN "PC in ROM: {@}"
 	LOAD "new", WRAMX[$D001],BANK[1]
-	PRINTT "PC in WRAM: {@}\n"
+	PRINTLN "PC in WRAM: {@}"
 	assert @ == $D001
 Target:	dl DEAD << 16 | BEEF
 	db BANK(@)
@@ -29,4 +29,4 @@
 Byte:
 	db
 
-	PRINTT "{Target}\n{Target.end}\n{After}\n"
+	PRINTLN "{Target}\n{Target.end}\n{After}"
--- a/test/asm/redef-equs.asm
+++ b/test/asm/redef-equs.asm
@@ -1,7 +1,7 @@
 s EQUS "Hello, "
 REDEF s EQUS "{s}world!"
 ; prints "Hello, world!"
-PRINTT "{s}\n"
+PRINTLN "{s}"
 
 list: MACRO
 LIST_NAME EQUS "\1"
@@ -15,9 +15,9 @@
 ENDM
 
 	list FOO
-	PRINTT "{FOO}\n"
+	PRINTLN "{FOO}"
 	list FOO, 1, A, 2, B
-	PRINTT "{FOO}\n"
+	PRINTLN "{FOO}"
 
 N EQU 42
 REDEF N EQUS "X"
--- a/test/asm/rept-shift.asm
+++ b/test/asm/rept-shift.asm
@@ -1,9 +1,9 @@
 m: macro
-	PRINTT "\1 "
+	PRINT "\1 "
 	REPT 4
 		SHIFT
 	ENDR
-	PRINTT "\1s!\n"
+	PRINTLN "\1s!"
 
 	; Shifting a little more to check that over-shifting doesn't crash
 	SHIFT
@@ -11,7 +11,7 @@
 	REPT 256
 		SHIFT
 	ENDR
-	PRINTT "\1\n"
+	PRINTLN "\1"
 endm
 
  m This, used, not, to, work
--- a/test/asm/section-union.asm
+++ b/test/asm/section-union.asm
@@ -25,7 +25,7 @@
 	ENDC
 	PURGE EXPECTED
 
-	PRINTT "\1 is at {\1} ({RESULT})\n"
+	PRINTLN "\1 is at {\1} ({RESULT})"
 	PURGE RESULT
 ENDM
 
--- a/test/asm/shift.asm
+++ b/test/asm/shift.asm
@@ -4,7 +4,7 @@
 
 	; ...as well as the constexpr system
 result\@ equ \1
-	printt "\1 = {result\@}\n"
+	println "\1 = {result\@}"
 endm
 
 section "test", ROM0[0]
--- a/test/asm/strcat.asm
+++ b/test/asm/strcat.asm
@@ -1,9 +1,4 @@
-print: MACRO
-	PRINTT \1
-	PRINTT "\n"
-ENDM
-
-	print STRCAT()
-	print STRCAT("Durrr")
-	print STRCAT("Left"\, "right")
-	print STRCAT("Whoa"\, "\, "\, "baby!")
+	println STRCAT()
+	println STRCAT("Durrr")
+	println STRCAT("Left", "right")
+	println STRCAT("Whoa", ", ", "baby!")
--- a/test/asm/strfmt.asm
+++ b/test/asm/strfmt.asm
@@ -1,24 +1,26 @@
 VAL EQUS STRFMT("Hello %s! I am %d years old today!", "world", $f)
-PRINTT "{VAL}\n"
+PRINTLN "{VAL}"
 
 N = -42
-PRINTT STRFMT("signed %010d == unsigned %010u\n", N, N)
+PRINTLN STRFMT("signed %010d == unsigned %010u", N, N)
 
 N = 112
 FMT EQUS "X"
-PRINTT STRFMT("\tdb %#03{s:FMT} %% 26\t; %#03{FMT}\n", N, N % 26)
+PRINTLN STRFMT("\tdb %#03{s:FMT} %% 26\t; %#03{FMT}", N, N % 26)
 
 TEMPLATE EQUS "\"%s are %s\\n\""
-PRINTT STRFMT(TEMPLATE, "roses", "red")
-PRINTT STRFMT(TEMPLATE, "violets", "blue")
-PRINTT STRFMT(TEMPLATE, "void", 0, "extra")
+PRINT STRFMT(TEMPLATE, "roses", "red")
+PRINT STRFMT(TEMPLATE, "violets", "blue")
+PRINT STRFMT(TEMPLATE, "void", 0, "extra")
 
-PRINTT STRCAT(STRFMT(STRFMT("%%%s.%d%s", "", 9, "f"), 3.14159), \
-	STRFMT(" ~ %s\n", STRFMT("%s%x", "thr", 238)))
+PRINTLN STRCAT(STRFMT(STRFMT("%%%s.%d%s", "", 9, "f"), 3.14159), \
+	STRFMT(" ~ %s", STRFMT("%s%x", "thr", 238)))
 
-PRINTT STRFMT("%d eol %", 1)
-PRINTT "\n"
+N = 1.23456
+PRINTLN STRFMT("%.f -> %.3f -> %f", N, N, N)
 
-PRINTT STRFMT("invalid %w spec\n", 42)
+PRINTLN STRFMT("%d eol %", 1)
 
-PRINTT STRFMT("one=%d two=%d three=%d\n", 1)
+PRINTLN STRFMT("invalid %w spec", 42)
+
+PRINTLN STRFMT("one=%d two=%d three=%d", 1)
--- a/test/asm/strfmt.err
+++ b/test/asm/strfmt.err
@@ -2,10 +2,10 @@
     Formatting number as type 's'
 ERROR: strfmt.asm(14):
     STRFMT: 1 unformatted argument(s)
-ERROR: strfmt.asm(19):
-    STRFMT: Illegal '%' at end of format string
 ERROR: strfmt.asm(22):
-    STRFMT: Invalid format spec for argument 1
+    STRFMT: Illegal '%' at end of format string
 ERROR: strfmt.asm(24):
+    STRFMT: Invalid format spec for argument 1
+ERROR: strfmt.asm(26):
     STRFMT: Not enough arguments for format spec
 error: Assembly aborted (5 errors)!
--- a/test/asm/strfmt.out
+++ b/test/asm/strfmt.out
@@ -5,6 +5,7 @@
 violets are blue
 void are 0
 3.141586304 ~ three
+1 -> 1.235 -> 1.23456
 1 eol %
 invalid % spec
 one=1 two=% three=%
--- a/test/asm/string-formatting.asm
+++ b/test/asm/string-formatting.asm
@@ -4,13 +4,13 @@
 pi equ 3.14159
 s equs "hello"
 
-	printt "<{ -6d:n}> <{+06u:n}> <{5x:n}> <{#16b:n}>\n"
-	printt "<{u:m}> <{+3d:m}> <{#016o:m}>\n"
-	printt "<{f:pi}> <{06f:f}> <{.10f:f}>\n"
-	printt "<{#-10s:s}> <{10s:s}>\n"
+	println "<{ -6d:n}> <{+06u:n}> <{5x:n}> <{#16b:n}>"
+	println "<{u:m}> <{+3d:m}> <{#016o:m}>"
+	println "<{f:pi}> <{06.f:f}> <{.10f:f}>"
+	println "<{#-10s:s}> <{10s:s}>"
 
 foo: macro
-	printt "<{\1}>\n"
+	println "<{\1}>"
 endm
 
 	foo  -6d:n ; space is trimmed
--- a/test/asm/strlen.asm
+++ b/test/asm/strlen.asm
@@ -1,8 +1,7 @@
 SECTION "sec", ROM0
 
 xstrlen: MACRO
-	PRINTV STRLEN(\1)
-	PRINTT "\n"
+	PRINTLN STRLEN(\1)
 ENDM
 
 	xstrlen "ABC"
--- a/test/asm/strsub.asm
+++ b/test/asm/strsub.asm
@@ -1,8 +1,7 @@
 SECTION "sec", ROM0
 
 xstrsub: MACRO
-	PRINTT STRSUB(\1, \2, \3)
-	PRINTT "\n"
+	PRINTLN STRSUB(\1, \2, \3)
 ENDM
 
 	xstrsub "ABC", 1, 1
--- a/test/asm/strsub.err
+++ b/test/asm/strsub.err
@@ -1,14 +1,14 @@
-warning: strsub.asm(13) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
+warning: strsub.asm(12) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
     STRSUB: Length too big: 32
-warning: strsub.asm(14) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
+warning: strsub.asm(13) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
     STRSUB: Length too big: 300
-warning: strsub.asm(15) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
+warning: strsub.asm(14) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
     STRSUB: Position starts at 1
-warning: strsub.asm(15) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
+warning: strsub.asm(14) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
     STRSUB: Length too big: 300
-warning: strsub.asm(17) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
+warning: strsub.asm(16) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
     STRSUB: Position 4 is past the end of the string
-warning: strsub.asm(17) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
+warning: strsub.asm(16) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
     STRSUB: Length too big: 1
-warning: strsub.asm(20) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
+warning: strsub.asm(19) -> strsub.asm::xstrsub(4): [-Wbuiltin-args]
     STRSUB: Length too big: 10
--- a/test/asm/strupr-strlwr.asm
+++ b/test/asm/strupr-strlwr.asm
@@ -1,4 +1,4 @@
 foo equs strupr("xii")
 bar equs strlwr("LOL")
 
-	printt "foo={foo} bar={bar}\n"
+	println "foo={foo} bar={bar}"
--- a/test/asm/sym-collision.asm
+++ b/test/asm/sym-collision.asm
@@ -20,15 +20,15 @@
 	; Completely by accident, but cool
 	PURGE dork
 
-	PRINTT "aqfj: {aqfj}\n"
-	PRINTT "cxje: {cxje}\n"
-	PRINTT "dgsd: {dgsd}\n"
-	PRINTT "dork: {dork}\n"
-	PRINTT "lxok: {lxok}\n"
-	PRINTT "psgp: {psgp}\n"
-	PRINTT "sfly: {sfly}\n"
-	PRINTT "syyq: {syyq}\n"
-	PRINTT "ussg: {ussg}\n"
-	PRINTT "xlmm: {xlmm}\n"
-	PRINTT "xtzp: {xtzp}\n"
-	PRINTT "zxfr: {zxfr}\n"
+	PRINTLN "aqfj: {aqfj}"
+	PRINTLN "cxje: {cxje}"
+	PRINTLN "dgsd: {dgsd}"
+	PRINTLN "dork: {dork}"
+	PRINTLN "lxok: {lxok}"
+	PRINTLN "psgp: {psgp}"
+	PRINTLN "sfly: {sfly}"
+	PRINTLN "syyq: {syyq}"
+	PRINTLN "ussg: {ussg}"
+	PRINTLN "xlmm: {xlmm}"
+	PRINTLN "xtzp: {xtzp}"
+	PRINTLN "zxfr: {zxfr}"
--- a/test/asm/symbol-override.asm
+++ b/test/asm/symbol-override.asm
@@ -1,6 +1,6 @@
 V set 0
 V set 1
-    PRINTT "V={V}\n"
+    PRINTLN "V={V}"
 
 W equ 1
 W set 0
--- a/test/asm/test.sh
+++ b/test/asm/test.sh
@@ -28,7 +28,7 @@
 # Add the version constants test, outputting the closest tag to the HEAD
 if git describe --tags --abbrev=0 > version.out; then
 	cat > version.asm <<EOF
-PRINTT "v{d:__RGBDS_MAJOR__}.{d:__RGBDS_MINOR__}.{d:__RGBDS_PATCH__}\n"
+PRINTLN "v{d:__RGBDS_MAJOR__}.{d:__RGBDS_MINOR__}.{d:__RGBDS_PATCH__}"
 EOF
 else
 	echo "${bold}${orange}Warning: cannot run version test!${rescolors}${resbold}"
--- a/test/asm/unique-id.asm
+++ b/test/asm/unique-id.asm
@@ -1,15 +1,15 @@
-print EQUS "WARN \"\\@\""
+warn_unique EQUS "WARN \"\\@\""
 
 m: macro
-    print
+    warn_unique
     REPT 2
-    	print
+    	warn_unique
     ENDR
-    print
+    warn_unique
 endm
 	; TODO: Ideally we'd test now as well, but it'd cause a fatal error
-	;print
+	;warn_unique
 	m
-	;print
+	;warn_unique
 	m
-	print
+	warn_unique
--- a/test/asm/unique-id.err
+++ b/test/asm/unique-id.err
@@ -16,4 +16,4 @@
     _u4
 FATAL: unique-id.asm(15):
     Macro argument '\@' not defined
-while expanding symbol "print"
+while expanding symbol "warn_unique"
--- a/test/asm/use-label-outside-section.asm
+++ b/test/asm/use-label-outside-section.asm
@@ -1,3 +1,2 @@
 lab:
-	PRINTV lab-lab
-	PRINTT "\n"
+	PRINTLN lab-lab
--- a/test/asm/weird-comments.asm
+++ b/test/asm/weird-comments.asm
@@ -1,2 +1,2 @@
-PRINTT /* // PRINTT "this is **comm //ented out\n" */ "this is not commented out\n"
-PRINTT /*//*/ "this is not commented out\n"
\ No newline at end of file
+PRINTLN /* // PRINT "this is **comm //ented out\n" */ "this is not commented out"
+PRINTLN /*//*/ "this is not commented out"
\ No newline at end of file