1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-29 09:29:31 +00:00

Added printf() support for %d, %i, %x, %o and length specifiers %hhd %ld.

This commit is contained in:
Jesper Gravgaard 2020-04-20 19:00:16 +02:00
parent 28c9b2ada7
commit d7143771ba
12 changed files with 1633 additions and 1010 deletions

View File

@ -24,10 +24,21 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
public static final String INTRINSIC_PRINTF_NAME = "printf";
/** The printf routine used to print formatted strings. */
public static final String PRINTF_STRING = "printf_string";
/** The printf routine used to print signed chars. */
public static final String PRINTF_SCHAR = "printf_schar";
/** The printf routine used to print unsigned chars. */
public static final String PRINTF_UCHAR = "printf_uchar";
/** The printf routine used to print signed integers. */
public static final String PRINTF_SINT = "printf_sint";
/** The printf routine used to print unsigned integers. */
public static final String PRINTF_UINT = "printf_uint";
/** The printf routine used to print signed long integers. */
public static final String PRINTF_SLONG = "printf_slong";
/** The printf routine used to print unsigned long integers. */
public static final String PRINTF_ULONG = "printf_ulong";
public static final String DECIMAL = "DECIMAL";
public static final String HEXADECIMAL = "HEXADECIMAL";
public static final String OCTAL = "OCTAL";
public Pass1PrintfIntrinsicRewrite(Program program) {
super(program);
@ -78,17 +89,13 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
final String paramField = matcher.group(1);
if(paramField != null)
throw new CompileError("printf parameter field not supported", printfCall);
final String flagsField = matcher.group(2);
long leftJustify = (flagsField != null && flagsField.contains("-")) ? 1 : 0;
long signAlways = (flagsField != null && flagsField.contains("+")) ? 1 : 0;
long zeroPadding = (flagsField != null && flagsField.contains("0")) ? 1 : 0;
final String widthField = matcher.group(3);
long width = (widthField == null) ? 0 : Integer.parseInt(widthField);
final String lengthField = matcher.group(4);
final String typeField = matcher.group(5);
// First output the non-matching part before the pattern
@ -96,7 +103,6 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
printfConstantString(prefix, printfCall, stmtIt, formatEncoding);
formatIdx = end;
if(typeField.equals("s")) {
// A formatted string
//struct printf_format_string {
@ -116,14 +122,43 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
// A formatted integer
SymbolVariableRef radix;
String printf_number_procedure;
if(typeField.equals("d")) {
radix = getScope().getLocalConstant("DECIMAL").getRef();
printf_number_procedure = PRINTF_SINT;
} else if(typeField.equals("x")) {
radix = getScope().getLocalConstant("HEXADECIMAL").getRef();
printf_number_procedure = PRINTF_UINT;
boolean signed;
switch(typeField) {
case "d":
case "i":
radix = getScope().getLocalConstant(DECIMAL).getRef();
signed = true;
break;
case "u":
radix = getScope().getLocalConstant(DECIMAL).getRef();
signed = false;
break;
case "x":
radix = getScope().getLocalConstant(HEXADECIMAL).getRef();
signed = false;
break;
case "X":
throw new CompileError("printf hexadecimal upper case not supported", printfCall);
case "o":
radix = getScope().getLocalConstant(OCTAL).getRef();
signed = false;
break;
default:
throw new CompileError("printf type field not supported", printfCall);
}
if(lengthField == null) {
// Integer (16bit)
printf_number_procedure = signed ? PRINTF_SINT : PRINTF_UINT;
} else if(lengthField.equals("hh")) {
// TODO: Handle 8-bits in a better way - since KickC does not do integer promotion!
// Integer (8bit)
printf_number_procedure = signed ? PRINTF_SCHAR : PRINTF_UCHAR;
} else if(lengthField.equals("l")) {
// Integer (32bit)
printf_number_procedure = signed ? PRINTF_SLONG : PRINTF_ULONG;
} else {
throw new CompileError("printf type field not supported", printfCall);
throw new CompileError("printf length field not supported", printfCall);
}
// Format specifying how to format a printed number

View File

@ -41,7 +41,12 @@ public class TestPrograms {
}
@Test
public void testPintf10() throws IOException, URISyntaxException {
public void testPrintf11() throws IOException, URISyntaxException {
compileAndCompare("printf-11.c");
}
@Test
public void testPrintf10() throws IOException, URISyntaxException {
compileAndCompare("printf-10.c");
}

View File

@ -26,37 +26,9 @@ void printf_string(char* str, struct printf_format_string format) {
printf_str(str);
}
// The different supported radix
enum RADIX { BINARY=2, OCTAL=8, DECIMAL=10, HEXADECIMAL=16 };
// Format specifying how to format a printed number
struct printf_format_number {
// The minimal number of chars to output (used for padding with spaces or 0)
char min_length;
// Justify left instead of right, which is the default.
char justify_left;
// Always show a sign for a number, even if is is positive. (Default is to only show sign for negative numbers)
char sign_always;
// Pad the number with zeros to get the min width
char zero_padding;
// The number radix to use for formatting
enum RADIX radix;
};
const char printf_hextab[] = "0123456789abcdef"z;
// Print an unsigned int using a specific format
// Always prints hexadecimals - ignores min_length and flags
void printf_uint(unsigned int uvalue, struct printf_format_number format) {
*screen++ = printf_hextab[(>uvalue)>>4];
*screen++ = printf_hextab[(>uvalue)&0xf];
*screen++ = printf_hextab[(<uvalue)>>4];
*screen++ = printf_hextab[(<uvalue)&0xf];
}
void main() {
unsigned int age = 46;
printf("Hello, I am %s. who are you?", "Jesper");
printf("I am %x years old", age);
char* name = "Jesper";
printf("Hello, I am %s. who are you?", name);
}

47
src/test/kc/printf-11.c Normal file
View File

@ -0,0 +1,47 @@
// Tests printf function call rewriting
// A simple number - with the printf-sub funtions in the same file.
__intrinsic void printf(char* format, ...);
char * screen = 0x0400;
char idx = 0;
void printf_str(char* str) {
while(*str) {
*screen++ = *str++;
}
}
// The different supported radix
enum RADIX { BINARY=2, OCTAL=8, DECIMAL=10, HEXADECIMAL=16 };
// Format specifying how to format a printed number
struct printf_format_number {
// The minimal number of chars to output (used for padding with spaces or 0)
char min_length;
// Justify left instead of right, which is the default.
char justify_left;
// Always show a sign for a number, even if is is positive. (Default is to only show sign for negative numbers)
char sign_always;
// Pad the number with zeros to get the min width
char zero_padding;
// The number radix to use for formatting
enum RADIX radix;
};
const char printf_hextab[] = "0123456789abcdef"z;
// Print an unsigned int using a specific format
// Always prints hexadecimals - ignores min_length and flags
void printf_uint(unsigned int uvalue, struct printf_format_number format) {
*screen++ = printf_hextab[(>uvalue)>>4];
*screen++ = printf_hextab[(>uvalue)&0xf];
*screen++ = printf_hextab[(<uvalue)>>4];
*screen++ = printf_hextab[(<uvalue)&0xf];
}
void main() {
unsigned int pct = 342;
printf("Commodore is %x cool", pct);
}

View File

@ -5,8 +5,7 @@
.pc = $80d "Program"
.label screen = 2
main: {
.label age = $2e
// printf("Hello, I am %s. who are you?", "Jesper")
// printf("Hello, I am %s. who are you?", name)
lda #<$400
sta.z screen
lda #>$400
@ -16,39 +15,21 @@ main: {
lda #>str
sta.z printf_str.str+1
jsr printf_str
// printf("Hello, I am %s. who are you?", "Jesper")
// printf("Hello, I am %s. who are you?", name)
jsr printf_string
// printf("Hello, I am %s. who are you?", "Jesper")
lda #<str2
// printf("Hello, I am %s. who are you?", name)
lda #<str1
sta.z printf_str.str
lda #>str2
sta.z printf_str.str+1
jsr printf_str
// printf("I am %x years old", age)
lda #<str3
sta.z printf_str.str
lda #>str3
sta.z printf_str.str+1
jsr printf_str
// printf("I am %x years old", age)
jsr printf_uint
// printf("I am %x years old", age)
lda #<str4
sta.z printf_str.str
lda #>str4
lda #>str1
sta.z printf_str.str+1
jsr printf_str
// }
rts
name: .text "Jesper"
.byte 0
str: .text "Hello, I am "
.byte 0
str1: .text "Jesper"
.byte 0
str2: .text ". who are you?"
.byte 0
str3: .text "I am "
.byte 0
str4: .text " years old"
str1: .text ". who are you?"
.byte 0
}
// printf_str(byte* zp(4) str)
@ -78,58 +59,15 @@ printf_str: {
!:
jmp __b1
}
// Print an unsigned int using a specific format
// Always prints hexadecimals - ignores min_length and flags
printf_uint: {
// *screen++ = printf_hextab[(>uvalue)>>4]
lda printf_hextab
ldy #0
sta (screen),y
// *screen++ = printf_hextab[(>uvalue)>>4];
inc.z screen
bne !+
inc.z screen+1
!:
// *screen++ = printf_hextab[(>uvalue)&0xf]
lda printf_hextab
ldy #0
sta (screen),y
// *screen++ = printf_hextab[(>uvalue)&0xf];
inc.z screen
bne !+
inc.z screen+1
!:
// *screen++ = printf_hextab[(<uvalue)>>4]
lda printf_hextab+((<main.age)>>4)
ldy #0
sta (screen),y
// *screen++ = printf_hextab[(<uvalue)>>4];
inc.z screen
bne !+
inc.z screen+1
!:
// *screen++ = printf_hextab[(<uvalue)&0xf]
lda printf_hextab+((<main.age)&$f)
ldy #0
sta (screen),y
// *screen++ = printf_hextab[(<uvalue)&0xf];
inc.z screen
bne !+
inc.z screen+1
!:
// }
rts
}
// Print a string value using a specific format
// Handles justification and min length
printf_string: {
// printf_str(str)
lda #<main.str1
lda #<main.name
sta.z printf_str.str
lda #>main.str1
lda #>main.name
sta.z printf_str.str+1
jsr printf_str
// }
rts
}
printf_hextab: .text "0123456789abcdef"

View File

@ -20,62 +20,35 @@ main::@1: scope:[main] from main
main::@2: scope:[main] from main::@1
[8] phi()
[9] call printf_str
to:main::@3
main::@3: scope:[main] from main::@2
[10] phi()
[11] call printf_str
to:main::@4
main::@4: scope:[main] from main::@3
[12] phi()
[13] call printf_uint
to:main::@5
main::@5: scope:[main] from main::@4
[14] phi()
[15] call printf_str
to:main::@return
main::@return: scope:[main] from main::@5
[16] return
main::@return: scope:[main] from main::@2
[10] return
to:@return
(void()) printf_str((byte*) printf_str::str)
printf_str: scope:[printf_str] from main main::@2 main::@3 main::@5 printf_string
[17] (byte*) screen#36 ← phi( main/(byte*) 1024 main::@2/(byte*) screen#18 main::@3/(byte*) screen#18 main::@5/(byte*) screen#23 printf_string/(byte*) screen#18 )
[17] (byte*) printf_str::str#8 ← phi( main/(const byte*) main::str main::@2/(const byte*) main::str2 main::@3/(const byte*) main::str3 main::@5/(const byte*) main::str4 printf_string/(const byte*) main::str1 )
printf_str: scope:[printf_str] from main main::@2 printf_string
[11] (byte*) screen#23 ← phi( main/(byte*) 1024 main::@2/(byte*) screen#10 printf_string/(byte*) screen#10 )
[11] (byte*) printf_str::str#6 ← phi( main/(const byte*) main::str main::@2/(const byte*) main::str1 printf_string/(const byte*) main::name )
to:printf_str::@1
printf_str::@1: scope:[printf_str] from printf_str printf_str::@2
[18] (byte*) screen#18 ← phi( printf_str/(byte*) screen#36 printf_str::@2/(byte*) screen#1 )
[18] (byte*) printf_str::str#6 ← phi( printf_str/(byte*) printf_str::str#8 printf_str::@2/(byte*) printf_str::str#0 )
[19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2
[12] (byte*) screen#10 ← phi( printf_str/(byte*) screen#23 printf_str::@2/(byte*) screen#1 )
[12] (byte*) printf_str::str#4 ← phi( printf_str/(byte*) printf_str::str#6 printf_str::@2/(byte*) printf_str::str#0 )
[13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2
to:printf_str::@return
printf_str::@return: scope:[printf_str] from printf_str::@1
[20] return
[14] return
to:@return
printf_str::@2: scope:[printf_str] from printf_str::@1
[21] *((byte*) screen#18) ← *((byte*) printf_str::str#6)
[22] (byte*) screen#1 ← ++ (byte*) screen#18
[23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6
[15] *((byte*) screen#10) ← *((byte*) printf_str::str#4)
[16] (byte*) screen#1 ← ++ (byte*) screen#10
[17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4
to:printf_str::@1
(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix)
printf_uint: scope:[printf_uint] from main::@4
[24] *((byte*) screen#18) ← *((const to_nomodify byte*) printf_hextab)
[25] (byte*) screen#5 ← ++ (byte*) screen#18
[26] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab)
[27] (byte*) screen#6 ← ++ (byte*) screen#5
[28] *((byte*) screen#6) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age>>(byte) 4)
[29] (byte*) screen#7 ← ++ (byte*) screen#6
[30] *((byte*) screen#7) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age&(byte) $f)
[31] (byte*) screen#23 ← ++ (byte*) screen#7
to:printf_uint::@return
printf_uint::@return: scope:[printf_uint] from printf_uint
[32] return
to:@return
(void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left)
printf_string: scope:[printf_string] from main::@1
[33] phi()
[34] call printf_str
[18] phi()
[19] call printf_str
to:printf_string::@return
printf_string::@return: scope:[printf_string] from printf_string
[35] return
[20] return
to:@return

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +1,33 @@
(label) @1
(label) @begin
(label) @end
(const byte) RADIX::BINARY = (number) 2
(const byte) RADIX::DECIMAL = (number) $a
(const byte) RADIX::HEXADECIMAL = (number) $10
(const byte) RADIX::OCTAL = (number) 8
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@return
(const word) main::age = (word) $2e
(const byte*) main::name = (byte*) "Jesper"
(const byte*) main::str[(byte) $d] = (byte*) "Hello, I am "
(const byte*) main::str1[(byte) 7] = (byte*) "Jesper"
(const byte*) main::str2[(byte) $f] = (byte*) ". who are you?"
(const byte*) main::str3[(byte) 6] = (byte*) "I am "
(const byte*) main::str4[(byte) $b] = (byte*) " years old"
(byte) printf_format_number::justify_left
(byte) printf_format_number::min_length
(byte) printf_format_number::radix
(byte) printf_format_number::sign_always
(byte) printf_format_number::zero_padding
(const byte*) main::str1[(byte) $f] = (byte*) ". who are you?"
(byte) printf_format_string::justify_left
(byte) printf_format_string::min_length
(const to_nomodify byte*) printf_hextab[] = (byte*) "0123456789abcdef"z
(void()) printf_str((byte*) printf_str::str)
(label) printf_str::@1
(label) printf_str::@2
(label) printf_str::@return
(byte*) printf_str::str
(byte*) printf_str::str#0 str zp[2]:4 20002.0
(byte*) printf_str::str#6 str zp[2]:4 10251.25
(byte*) printf_str::str#8 str zp[2]:4 1001.0
(byte*) printf_str::str#4 str zp[2]:4 10251.25
(byte*) printf_str::str#6 str zp[2]:4 1001.0
(void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left)
(label) printf_string::@return
(struct printf_format_string) printf_string::format
(byte) printf_string::format_justify_left
(byte) printf_string::format_min_length
(byte*) printf_string::str
(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix)
(label) printf_uint::@return
(struct printf_format_number) printf_uint::format
(byte) printf_uint::format_justify_left
(byte) printf_uint::format_min_length
(byte) printf_uint::format_radix
(byte) printf_uint::format_sign_always
(byte) printf_uint::format_zero_padding
(word) printf_uint::uvalue
(byte*) screen
(byte*) screen#1 screen zp[2]:2 10001.0
(byte*) screen#18 screen zp[2]:2 1958.0625
(byte*) screen#23 screen zp[2]:2 28.0
(byte*) screen#36 screen zp[2]:2 1135.0
(byte*) screen#5 screen zp[2]:2 151.5
(byte*) screen#6 screen zp[2]:2 151.5
(byte*) screen#7 screen zp[2]:2 151.5
(byte*) screen#10 screen zp[2]:2 2828.7272727272725
(byte*) screen#23 screen zp[2]:2 1113.0
zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 screen#5 screen#7 screen#6 ]
zp[2]:4 [ printf_str::str#6 printf_str::str#8 printf_str::str#0 ]
zp[2]:2 [ screen#23 screen#10 screen#1 ]
zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ]

103
src/test/ref/printf-11.asm Normal file
View File

@ -0,0 +1,103 @@
// Tests printf function call rewriting
// A simple number - with the printf-sub funtions in the same file.
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label screen = 4
main: {
.label pct = $156
// printf("Commodore is %x cool", pct)
lda #<$400
sta.z screen
lda #>$400
sta.z screen+1
lda #<str
sta.z printf_str.str
lda #>str
sta.z printf_str.str+1
jsr printf_str
// printf("Commodore is %x cool", pct)
jsr printf_uint
// printf("Commodore is %x cool", pct)
lda #<str1
sta.z printf_str.str
lda #>str1
sta.z printf_str.str+1
jsr printf_str
// }
rts
str: .text "Commodore is "
.byte 0
str1: .text " cool"
.byte 0
}
// printf_str(byte* zp(2) str)
printf_str: {
.label str = 2
__b1:
// while(*str)
ldy #0
lda (str),y
cmp #0
bne __b2
// }
rts
__b2:
// *screen++ = *str++
ldy #0
lda (str),y
sta (screen),y
// *screen++ = *str++;
inc.z screen
bne !+
inc.z screen+1
!:
inc.z str
bne !+
inc.z str+1
!:
jmp __b1
}
// Print an unsigned int using a specific format
// Always prints hexadecimals - ignores min_length and flags
printf_uint: {
// *screen++ = printf_hextab[(>uvalue)>>4]
lda printf_hextab
ldy #0
sta (screen),y
// *screen++ = printf_hextab[(>uvalue)>>4];
inc.z screen
bne !+
inc.z screen+1
!:
// *screen++ = printf_hextab[(>uvalue)&0xf]
lda printf_hextab+((>main.pct)&$f)
ldy #0
sta (screen),y
// *screen++ = printf_hextab[(>uvalue)&0xf];
inc.z screen
bne !+
inc.z screen+1
!:
// *screen++ = printf_hextab[(<uvalue)>>4]
lda printf_hextab+((<main.pct)>>4)
ldy #0
sta (screen),y
// *screen++ = printf_hextab[(<uvalue)>>4];
inc.z screen
bne !+
inc.z screen+1
!:
// *screen++ = printf_hextab[(<uvalue)&0xf]
lda printf_hextab+((<main.pct)&$f)
ldy #0
sta (screen),y
// *screen++ = printf_hextab[(<uvalue)&0xf];
inc.z screen
bne !+
inc.z screen+1
!:
// }
rts
}
printf_hextab: .text "0123456789abcdef"

View File

@ -0,0 +1,60 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] phi()
[5] call printf_str
to:main::@1
main::@1: scope:[main] from main
[6] phi()
[7] call printf_uint
to:main::@2
main::@2: scope:[main] from main::@1
[8] phi()
[9] call printf_str
to:main::@return
main::@return: scope:[main] from main::@2
[10] return
to:@return
(void()) printf_str((byte*) printf_str::str)
printf_str: scope:[printf_str] from main main::@2
[11] (byte*) screen#25 ← phi( main/(byte*) 1024 main::@2/(byte*) screen#16 )
[11] (byte*) printf_str::str#5 ← phi( main/(const byte*) main::str main::@2/(const byte*) main::str1 )
to:printf_str::@1
printf_str::@1: scope:[printf_str] from printf_str printf_str::@2
[12] (byte*) screen#13 ← phi( printf_str/(byte*) screen#25 printf_str::@2/(byte*) screen#1 )
[12] (byte*) printf_str::str#3 ← phi( printf_str/(byte*) printf_str::str#5 printf_str::@2/(byte*) printf_str::str#0 )
[13] if((byte) 0!=*((byte*) printf_str::str#3)) goto printf_str::@2
to:printf_str::@return
printf_str::@return: scope:[printf_str] from printf_str::@1
[14] return
to:@return
printf_str::@2: scope:[printf_str] from printf_str::@1
[15] *((byte*) screen#13) ← *((byte*) printf_str::str#3)
[16] (byte*) screen#1 ← ++ (byte*) screen#13
[17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#3
to:printf_str::@1
(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix)
printf_uint: scope:[printf_uint] from main::@1
[18] *((byte*) screen#13) ← *((const to_nomodify byte*) printf_hextab)
[19] (byte*) screen#3 ← ++ (byte*) screen#13
[20] *((byte*) screen#3) ← *((const to_nomodify byte*) printf_hextab+>(const word) main::pct&(byte) $f)
[21] (byte*) screen#4 ← ++ (byte*) screen#3
[22] *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct>>(byte) 4)
[23] (byte*) screen#5 ← ++ (byte*) screen#4
[24] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct&(byte) $f)
[25] (byte*) screen#16 ← ++ (byte*) screen#5
to:printf_uint::@return
printf_uint::@return: scope:[printf_uint] from printf_uint
[26] return
to:@return

1075
src/test/ref/printf-11.log Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
(label) @1
(label) @begin
(label) @end
(const byte) RADIX::BINARY = (number) 2
(const byte) RADIX::DECIMAL = (number) $a
(const byte) RADIX::HEXADECIMAL = (number) $10
(const byte) RADIX::OCTAL = (number) 8
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(const word) main::pct = (word) $156
(const byte*) main::str[(byte) $e] = (byte*) "Commodore is "
(const byte*) main::str1[(byte) 6] = (byte*) " cool"
(byte) printf_format_number::justify_left
(byte) printf_format_number::min_length
(byte) printf_format_number::radix
(byte) printf_format_number::sign_always
(byte) printf_format_number::zero_padding
(const to_nomodify byte*) printf_hextab[] = (byte*) "0123456789abcdef"z
(void()) printf_str((byte*) printf_str::str)
(label) printf_str::@1
(label) printf_str::@2
(label) printf_str::@return
(byte*) printf_str::str
(byte*) printf_str::str#0 str zp[2]:2 2002.0
(byte*) printf_str::str#3 str zp[2]:2 1026.25
(byte*) printf_str::str#5 str zp[2]:2 101.0
(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix)
(label) printf_uint::@return
(struct printf_format_number) printf_uint::format
(byte) printf_uint::format_justify_left
(byte) printf_uint::format_min_length
(byte) printf_uint::format_radix
(byte) printf_uint::format_sign_always
(byte) printf_uint::format_zero_padding
(word) printf_uint::uvalue
(byte*) screen
(byte*) screen#1 screen zp[2]:4 1001.0
(byte*) screen#13 screen zp[2]:4 472.28571428571433
(byte*) screen#16 screen zp[2]:4 28.0
(byte*) screen#25 screen zp[2]:4 112.0
(byte*) screen#3 screen zp[2]:4 151.5
(byte*) screen#4 screen zp[2]:4 151.5
(byte*) screen#5 screen zp[2]:4 151.5
zp[2]:2 [ printf_str::str#3 printf_str::str#5 printf_str::str#0 ]
zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 screen#3 screen#5 screen#4 ]