diff --git a/asminc/atmos.inc b/asminc/atmos.inc index 446f2e11c..20bb806f1 100644 --- a/asminc/atmos.inc +++ b/asminc/atmos.inc @@ -1,32 +1,94 @@ ; -; Oric atmos zeropage and ROM definitions +; Oric Atmos definitions +; BASIC 1.1 addresses ; +; --------------------------------------------------------------------------- +; Constants + +SCREEN_XSIZE = 40 ; screen columns +SCREEN_YSIZE = 28 ; screen rows + +FUNCTKEY = $A5 + +FNAME_LEN = 16 ; maximum length of file-name + + ; --------------------------------------------------------------------------- ; Zero page +BASIC_BUF := $35 ; --------------------------------------------------------------------------- ; Low memory -CAPSLOCK := $20C -IRQVec := $245 -CURS_Y := $268 -CURS_X := $269 -STATUS := $26A -TIMER3 := $276 -KEYBUF := $2DF +MODEKEY := $0209 +CAPSLOCK := $020C +PATTERN := $0213 +IRQVec := $0245 +JOINFLAG := $025A ; 0 = don't joiu, $4A = join BASIC programs +VERIFYFLAG := $025B ; 0 = load, 1 = verify +CURS_Y := $0268 +CURS_X := $0269 +STATUS := $026A +TIMER3 := $0276 +CFILE_NAME := $027F +CFOUND_NAME := $0293 +FILESTART := $02A9 +FILEEND := $02AB +AUTORUN := $02AD ; $00 = only load, $C7 = autorun +LANGFLAG := $02AE ; $00 = BASIC, $80 = machine code +KEYBUF := $02DF +PARAM1 := $02E1 ; & $02E2 +PARAM2 := $02E3 ; & $02E4 +PARAM3 := $02E5 ; & $02E6 + + +; --------------------------------------------------------------------------- +; I/O locations + +; 6522 +.struct VIA ; Versatile Interface Adapter + .res $0300 +PRB .byte ; Port Register B +PRA .byte ; Port Register A +DDRB .byte ; Data Direction Register B +DDRA .byte ; Data Direction Register A +T1 .word ; Timer 1 +T1L .word ; Timer 1 Latch +T2 .word ; Timer 2 +SR .byte ; Shift Register +ACR .byte ; Auxiliary Control Register +PCR .byte ; Peripheral Control Register +IFR .byte ; Interrupt Flags Register +IER .byte ; Interrupt Enable Register +PRA2 .byte ; Port Register A without handshaking +.endstruct + +; 6551 +.struct ACIA ; Asynchronous Communications Interface Adapter + .res $031C +DATA .byte +STATUS .byte +CMD .byte ; Command register +CTRL .byte ; Control register +.endstruct + +SCREEN := $BB80 ; --------------------------------------------------------------------------- ; ROM entries +TEXT := $EC21 +HIRES := $EC33 +CURSET := $F0C8 +CURMOV := $F0FD +DRAW := $F110 +CHAR := $F12D +POINT := $F1C8 +PAPER := $F204 +INK := $F210 PRINT := $F77C - - -; --------------------------------------------------------------------------- -; I/O - -SCREEN := $BB80 diff --git a/libsrc/atmos/_scrsize.s b/libsrc/atmos/_scrsize.s index 2dd58399d..7a7af33ee 100644 --- a/libsrc/atmos/_scrsize.s +++ b/libsrc/atmos/_scrsize.s @@ -1,15 +1,17 @@ ; -; Ullrich von Bassewitz, 2003-04-13 +; 2003-04-13, Ullrich von Bassewitz +; 2013-07-16, Greg King ; ; Screen size variables ; .export screensize + .include "atmos.inc" .proc screensize - ldx #40 - ldy #28 + ldx #SCREEN_XSIZE + ldy #SCREEN_YSIZE rts .endproc diff --git a/libsrc/atmos/atmos_load.s b/libsrc/atmos/atmos_load.s index 9e86373f3..b5bec3225 100644 --- a/libsrc/atmos/atmos_load.s +++ b/libsrc/atmos/atmos_load.s @@ -1,20 +1,24 @@ -; Stefan Haubenthal, 2012-05-06 -; based on code by Twilighte +; Based on code by Twilighte. +; 2012-05-06, Stefan Haubenthal +; 2013-07-22, Greg King +; ; void __fastcall__ atmos_load(const char* name); .export _atmos_load .import store_filename + .include "atmos.inc" + .proc _atmos_load sei jsr store_filename ldx #$00 - stx $02ad - stx $02ae - stx $025a - stx $025b + stx AUTORUN ; don't try to run the file + stx LANGFLAG ; BASIC + stx JOINFLAG ; don't join it to another BASIC program + stx VERIFYFLAG ; load the file jsr cload_bit cli rts diff --git a/libsrc/atmos/atmos_save.s b/libsrc/atmos/atmos_save.s index 0bd9e29cc..3d221f6fa 100644 --- a/libsrc/atmos/atmos_save.s +++ b/libsrc/atmos/atmos_save.s @@ -1,23 +1,27 @@ -; Stefan Haubenthal, 2012-05-06 -; based on code by Twilighte +; Based on code by Twilighte. +; 2012-05-06, Stefan Haubenthal +; 2013-07-22, Greg King +; ; void __fastcall__ atmos_save(const char* name, const void* start, const void* end); .export _atmos_save .import popax, store_filename + .include "atmos.inc" + .proc _atmos_save sei - sta $02ab ; file end lo - stx $02ac ; file end hi + sta FILEEND + stx FILEEND+1 jsr popax - sta $02a9 ; file start lo - stx $02aa ; file start hi + sta FILESTART + stx FILESTART+1 jsr popax jsr store_filename lda #00 - sta $02ad + sta AUTORUN jsr csave_bit cli rts diff --git a/libsrc/atmos/cgetc.s b/libsrc/atmos/cgetc.s index 38e7aa873..e13d143d2 100644 --- a/libsrc/atmos/cgetc.s +++ b/libsrc/atmos/cgetc.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 2003-04-13 +; 2003-04-13, Ullrich von Bassewitz +; 2013-07-26, Greg King ; ; char cgetc (void); ; @@ -11,7 +12,6 @@ .include "atmos.inc" - ; ------------------------------------------------------------------------ ; @@ -41,8 +41,8 @@ @L2: and #$7F ; Mask out avail flag sta KEYBUF - ldy $209 - cpy #$A5 + ldy MODEKEY + cpy #FUNCTKEY bne @L3 ora #$80 ; FUNCT pressed diff --git a/libsrc/atmos/clrscr.s b/libsrc/atmos/clrscr.s index 9dce665e9..2230d6e0a 100644 --- a/libsrc/atmos/clrscr.s +++ b/libsrc/atmos/clrscr.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 2003-04-13 +; 2003-04-13, Ullrich von Bassewitz +; 2013-07-16, Greg King ; .export _clrscr @@ -27,7 +28,7 @@ ; Clear full pages. Y is still zero - ldx #>(28*40) + ldx #>(SCREEN_YSIZE * SCREEN_XSIZE) lda #' ' @L1: sta (ptr2),y iny ; Bump low byte of address @@ -40,7 +41,7 @@ @L2: sta (ptr2),y iny - cpy #<(28*40) + cpy #<(SCREEN_YSIZE * SCREEN_XSIZE) bne @L2 rts diff --git a/libsrc/atmos/cputc.s b/libsrc/atmos/cputc.s index 9f65be500..a0ef14b70 100644 --- a/libsrc/atmos/cputc.s +++ b/libsrc/atmos/cputc.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 2003-04-13 +; 2003-04-13, Ullrich von Bassewitz +; 2013-07-16, Greg King ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); @@ -41,7 +42,7 @@ output: advance: iny - cpy #40 + cpy #SCREEN_XSIZE bne L3 inc CURS_Y ; new line ldy #0 ; + cr @@ -85,12 +86,12 @@ L3: sty CURS_X .rodata ScrTabLo: - .repeat 28, Line - .byte <(SCREEN + Line * 40) + .repeat SCREEN_YSIZE, Line + .byte <(SCREEN + Line * SCREEN_XSIZE) .endrep ScrTabHi: - .repeat 28, Line - .byte >(SCREEN + Line * 40) + .repeat SCREEN_YSIZE, Line + .byte >(SCREEN + Line * SCREEN_XSIZE) .endrep diff --git a/libsrc/atmos/joy/atmos-pase.s b/libsrc/atmos/joy/atmos-pase.s index c505a1b0f..0c657584b 100644 --- a/libsrc/atmos/joy/atmos-pase.s +++ b/libsrc/atmos/joy/atmos-pase.s @@ -1,14 +1,15 @@ ; ; P.A.S.E. joystick driver for the Atmos -; May be used multiple times when linked to the statically application. +; Can be used multiple times when statically linked to the application. ; -; Stefan Haubenthal, 2009-12-21 -; Based on Ullrich von Bassewitz, 2002-12-20 +; 2002-12-20, Based on Ullrich von Bassewitz's code. +; 2009-12-21, Stefan Haubenthal +; 2013-07-15, Greg King ; .include "joy-kernel.inc" .include "joy-error.inc" -; .include "atmos.inc" + .include "atmos.inc" ; ------------------------------------------------------------------------ @@ -49,10 +50,6 @@ JOY_COUNT = 2 ; Number of joysticks we support -PRA = $0301 -DDRA = $0303 -PRA2 = $030F - ; ------------------------------------------------------------------------ ; Data. @@ -99,24 +96,24 @@ COUNT: READ: tay - lda PRA + lda VIA::PRA pha - lda DDRA + lda VIA::DDRA pha lda #%11000000 - sta DDRA + sta VIA::DDRA lda #%10000000 - sta PRA2 - lda PRA2 + sta VIA::PRA2 + lda VIA::PRA2 sta temp1 lda #%01000000 - sta PRA2 - lda PRA + sta VIA::PRA2 + lda VIA::PRA sta temp2 pla - sta DDRA + sta VIA::DDRA pla - sta PRA2 + sta VIA::PRA2 ldx #0 tya diff --git a/libsrc/atmos/mainargs.s b/libsrc/atmos/mainargs.s index 3e1f6467b..42a94da51 100644 --- a/libsrc/atmos/mainargs.s +++ b/libsrc/atmos/mainargs.s @@ -1,19 +1,19 @@ ; -; Ullrich von Bassewitz, 2003-03-07 -; Stefan Haubenthal, 2011-01-28 +; 2003-03-07, Ullrich von Bassewitz +; 2011-01-28, Stefan Haubenthal +; 2013-07-15, Greg King ; ; Setup arguments for main ; .constructor initmainargs, 24 .import __argc, __argv + + .include "atmos.inc" .macpack generic MAXARGS = 10 ; Maximum number of arguments allowed REM = $9d ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name -BASIC_BUF = $35 -FNAM = $293 ;--------------------------------------------------------------------------- @@ -29,8 +29,8 @@ FNAM = $293 ; Because the buffer, that we're copying into, was zeroed out, ; we don't need to add a NUL character. ; - ldy #NAME_LEN - 1 ; limit the length -L0: lda FNAM,y + ldy #FNAME_LEN - 1 ; limit the length +L0: lda CFOUND_NAME,y sta name,y dey bpl L0 @@ -114,7 +114,7 @@ done: lda # -; 2012-08-11, Greg King +; 2013-07-15, Greg King ; .include "zeropage.inc" @@ -79,21 +79,7 @@ ERROR: .res 1 ; Error code MODE: .res 1 ; Graphics mode PALETTE: .res 2 -; Constants and table -; BASIC 1.1 addresses -PATTERN := $213 -PARAM1 := $2E1 ; & $2E2 -PARAM2 := $2E3 ; & $2E4 -PARAM3 := $2E5 ; & $2E6 -TEXT := $EC21 -HIRES := $EC33 -CURSET := $F0C8 -CURMOV := $F0FD -DRAW := $F110 -CHAR := $F12D -POINT := $F1C8 -PAPER := $F204 -INK := $F210 +; Constant table .rodata diff --git a/libsrc/atmos/tgi/atmos-240-200-2.s b/libsrc/atmos/tgi/atmos-240-200-2.s index e58ac36d2..762c7c02d 100644 --- a/libsrc/atmos/tgi/atmos-240-200-2.s +++ b/libsrc/atmos/tgi/atmos-240-200-2.s @@ -2,7 +2,7 @@ ; Graphics driver for the 240x200x2 monochrome mode on the Atmos ; ; Stefan Haubenthal -; 2012-08-11, Greg King +; 2013-07-16, Greg King ; .include "zeropage.inc" @@ -66,10 +66,10 @@ YSIZE = 8 ; System font height ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. -X1 = ptr1 -Y1 = ptr2 -X2 = ptr3 -Y2 = ptr4 +X1 := ptr1 +Y1 := ptr2 +X2 := ptr3 +Y2 := ptr4 ; Absolute variables used in the code @@ -78,19 +78,7 @@ Y2 = ptr4 ERROR: .res 1 ; Error code MODE: .res 1 ; Graphics mode -; Constants and tables -PARAM1 = $2E1 -PARAM2 = $2E3 -PARAM3 = $2E5 -TEXT = $EC21 -HIRES = $EC33 -CURSET = $F0C8 -CURMOV = $F0FD -DRAW = $F110 -CHAR = $F12D -POINT = $F1C8 -PAPER = $F204 -INK = $F210 +; Constant table .rodata @@ -152,7 +140,7 @@ INIT: ; Must set an error code: NO ; -DONE = TEXT +DONE := TEXT ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. @@ -170,7 +158,7 @@ GETERROR: ; CONTROL: - sta $213 + sta PATTERN lda #TGI_ERR_OK sta ERROR rts @@ -181,7 +169,7 @@ CONTROL: ; Must set an error code: NO ; -CLEAR = HIRES +CLEAR := HIRES ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). diff --git a/testcode/lib/sprintf-test.c b/testcode/lib/sprintf-test.c new file mode 100644 index 000000000..36fd4f4a5 --- /dev/null +++ b/testcode/lib/sprintf-test.c @@ -0,0 +1,577 @@ +#include +#include +#include +#if defined(__CC65__) +#include +#endif + + +/* Flag to #ifdef the tests out that crash the old implementation */ +/*#define NOCRASH 1 */ + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +/* Struct used to test the 'n' conversion specifier. It is machine dependent / + * not portable. + */ +typedef union WriteCount WriteCount; +union WriteCount { + signed char C; + int I; + long L; +}; + +/* Count the number of tests and the number of failures */ +static unsigned Tests = 0; +static unsigned Failures = 0; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +static void OneTest (int Line, const char* RString, int RCount, const char* Format, ...) +/* Test one conversion. Line is the line number (to make the life of the + * tester easier), RString the expected result and RCount the expected return + * count. The other parameters are used for formatting. + */ +{ + int Count; + char Buf[128]; + va_list ap; + + /* Count the number of tests */ + ++Tests; + + /* Format the string using the given arguments */ + va_start (ap, Format); + Count = vsprintf (Buf, Format, ap); + va_end (ap); + + /* Check the result */ + if (Count != RCount || strcmp (Buf, RString) != 0) { + ++Failures; + printf ("%3d: \"%s\" (%d)\n" + " \"%s\" (%d)\n", + Line, Buf, Count, RString, RCount); + } +} + + + +static void WriteTest (int Line, const char* Format, WriteCount* W, long Count) +/* Test one write conversion. Line is the line number (to make the life of the + * tester easier), Format is the format specification. W is a WriteCount + * variable and Count is the expected result. + */ +{ + /* Clear the counter in full length */ + W->L = 0x5A5A5A5AL; + + /* Format the string using the given arguments */ + OneTest (Line, "4200", 4, Format, 4200, W); + + /* Check the counter */ + if (W->L != Count) { + ++Failures; + printf ("%3d: n = 0x%08lX\n" + " n = 0x%08lX\n", + Line, W->L, Count); + } +} + + + +int main (void) +{ + WriteCount W; + + + /* The one and only starter to begin with ... */ + OneTest (__LINE__, "hello, world", 12, "hello, world"); + + /* Duplicate percent signs are used to output single ones */ + OneTest (__LINE__, "hello % %", 9, "hello %% %%"); + + /* Simple conversions */ + OneTest (__LINE__, "u", 1, "%c", 'u'); + OneTest (__LINE__, "4200", 4, "%d", 4200); + OneTest (__LINE__, "-4200", 5, "%d", -4200); + OneTest (__LINE__, "4200", 4, "%i", 4200); + OneTest (__LINE__, "-4200", 5, "%i", -4200); + OneTest (__LINE__, "10150", 5, "%o", 4200U); + OneTest (__LINE__, "167630", 6, "%o", -4200U); + OneTest (__LINE__, "hello, world", 12, "hello, %s", "world"); + OneTest (__LINE__, "4200", 4, "%u", 4200U); + OneTest (__LINE__, "61336", 5, "%u", -4200U); + OneTest (__LINE__, "1068", 4, "%x", 4200U); + OneTest (__LINE__, "ef98", 4, "%x", -4200U); + OneTest (__LINE__, "1068", 4, "%X", 4200U); + OneTest (__LINE__, "EF98", 4, "%X", -4200U); + + /* Simple conversions with special values */ + OneTest (__LINE__, "\0", 1, "%c", '\0'); + OneTest (__LINE__, "0", 1, "%d", 0); + OneTest (__LINE__, "0", 1, "%o", 0U); + OneTest (__LINE__, "hello, ", 7, "hello, %s", ""); + OneTest (__LINE__, "0", 1, "%u", 0U); + OneTest (__LINE__, "0", 1, "%x", 0U); + + /* 'h' modifier */ + OneTest (__LINE__, "4200", 4, "%hd", 4200); + OneTest (__LINE__, "-4200", 5, "%hd", -4200); + OneTest (__LINE__, "4200", 4, "%hi", 4200); + OneTest (__LINE__, "-4200", 5, "%hi", -4200); + OneTest (__LINE__, "10150", 5, "%ho", 4200U); + OneTest (__LINE__, "167630", 6, "%ho", -4200U); + OneTest (__LINE__, "4200", 4, "%hu", 4200U); + OneTest (__LINE__, "61336", 5, "%hu", -4200U); + OneTest (__LINE__, "1068", 4, "%hx", 4200U); + OneTest (__LINE__, "ef98", 4, "%hx", -4200U); + OneTest (__LINE__, "1068", 4, "%hX", 4200U); + OneTest (__LINE__, "EF98", 4, "%hX", -4200U); + + /* 'hh' modifier */ + OneTest (__LINE__, "104", 3, "%hhd", 4200); + OneTest (__LINE__, "-104", 4, "%hhd", -4200); + OneTest (__LINE__, "104", 3, "%hhi", 4200); + OneTest (__LINE__, "-104", 4, "%hhi", -4200); + OneTest (__LINE__, "150", 3, "%hho", 4200U); + OneTest (__LINE__, "230", 3, "%hho", -4200U); + OneTest (__LINE__, "104", 3, "%hhu", 4200U); + OneTest (__LINE__, "152", 3, "%hhu", -4200U); + OneTest (__LINE__, "68", 2, "%hhx", 4200U); + OneTest (__LINE__, "98", 2, "%hhx", -4200U); + OneTest (__LINE__, "68", 2, "%hhX", 4200U); + OneTest (__LINE__, "98", 2, "%hhX", -4200U); + + /* 'j' modifier */ + OneTest (__LINE__, "4200123", 7, "%jd", 4200123L); + OneTest (__LINE__, "-4200123", 8, "%jd", -4200123L); + OneTest (__LINE__, "4200123", 7, "%ji", 4200123L); + OneTest (__LINE__, "-4200123", 8, "%ji", -4200123L); + OneTest (__LINE__, "20013273", 8, "%jo", 4200123UL); + OneTest (__LINE__, "37757764505", 11, "%jo", -4200123UL); + OneTest (__LINE__, "4200123", 7, "%ju", 4200123UL); + OneTest (__LINE__, "4290767173", 10, "%ju", -4200123UL); + OneTest (__LINE__, "4016bb", 6, "%jx", 4200123UL); + OneTest (__LINE__, "ffbfe945", 8, "%jx", -4200123UL); + OneTest (__LINE__, "4016BB", 6, "%jX", 4200123UL); + OneTest (__LINE__, "FFBFE945", 8, "%jX", -4200123UL); + + /* 'l' modifier */ + OneTest (__LINE__, "4200123", 7, "%ld", 4200123L); + OneTest (__LINE__, "-4200123", 8, "%ld", -4200123L); + OneTest (__LINE__, "4200123", 7, "%li", 4200123L); + OneTest (__LINE__, "-4200123", 8, "%li", -4200123L); + OneTest (__LINE__, "20013273", 8, "%lo", 4200123UL); + OneTest (__LINE__, "37757764505", 11, "%lo", -4200123UL); + OneTest (__LINE__, "4200123", 7, "%lu", 4200123UL); + OneTest (__LINE__, "4290767173", 10, "%lu", -4200123UL); + OneTest (__LINE__, "4016bb", 6, "%lx", 4200123UL); + OneTest (__LINE__, "ffbfe945", 8, "%lx", -4200123UL); + OneTest (__LINE__, "4016BB", 6, "%lX", 4200123UL); + OneTest (__LINE__, "FFBFE945", 8, "%lX", -4200123UL); + + /* 't' modifier */ + OneTest (__LINE__, "4200", 4, "%td", 4200); + OneTest (__LINE__, "-4200", 5, "%td", -4200); + OneTest (__LINE__, "4200", 4, "%ti", 4200); + OneTest (__LINE__, "-4200", 5, "%ti", -4200); + OneTest (__LINE__, "10150", 5, "%to", 4200U); + OneTest (__LINE__, "167630", 6, "%to", -4200U); + OneTest (__LINE__, "4200", 4, "%tu", 4200U); + OneTest (__LINE__, "61336", 5, "%tu", -4200U); + OneTest (__LINE__, "1068", 4, "%tx", 4200U); + OneTest (__LINE__, "ef98", 4, "%tx", -4200U); + OneTest (__LINE__, "1068", 4, "%tX", 4200U); + OneTest (__LINE__, "EF98", 4, "%tX", -4200U); + + /* 'z' modifier */ + OneTest (__LINE__, "4200", 4, "%zd", 4200); + OneTest (__LINE__, "-4200", 5, "%zd", -4200); + OneTest (__LINE__, "4200", 4, "%zi", 4200); + OneTest (__LINE__, "-4200", 5, "%zi", -4200); + OneTest (__LINE__, "10150", 5, "%zo", 4200U); + OneTest (__LINE__, "167630", 6, "%zo", -4200U); + OneTest (__LINE__, "4200", 4, "%zu", 4200U); + OneTest (__LINE__, "61336", 5, "%zu", -4200U); + OneTest (__LINE__, "1068", 4, "%zx", 4200U); + OneTest (__LINE__, "ef98", 4, "%zx", -4200U); + OneTest (__LINE__, "1068", 4, "%zX", 4200U); + OneTest (__LINE__, "EF98", 4, "%zX", -4200U); + + /* '+' forces a sign for signed conversions */ + OneTest (__LINE__, "u", 1, "%+c", 'u'); + OneTest (__LINE__, "+4200", 5, "%+d", 4200); + OneTest (__LINE__, "-4200", 5, "%+d", -4200); + OneTest (__LINE__, "+4200", 5, "%+i", 4200); + OneTest (__LINE__, "-4200", 5, "%+i", -4200); + OneTest (__LINE__, "10150", 5, "%+o", 4200U); + OneTest (__LINE__, "167630", 6, "%+o", -4200U); + OneTest (__LINE__, "hello, world", 12, "%+s", "hello, world"); + OneTest (__LINE__, "4200", 4, "%+u", 4200U); + OneTest (__LINE__, "61336", 5, "%+u", -4200U); + OneTest (__LINE__, "1068", 4, "%+x", 4200U); + OneTest (__LINE__, "ef98", 4, "%+x", -4200U); + OneTest (__LINE__, "1068", 4, "%+X", 4200U); + OneTest (__LINE__, "EF98", 4, "%+X", -4200U); + + /* ' ': If the first character of a signed conversion is not a sign, or if + * a signed conversion results in no characters, a space is prefixed + * to the result. + */ + OneTest (__LINE__, "u", 1, "% c", 'u'); + OneTest (__LINE__, " 4200", 5, "% d", 4200); + OneTest (__LINE__, "-4200", 5, "% d", -4200); + OneTest (__LINE__, " 4200", 5, "% i", 4200); + OneTest (__LINE__, "-4200", 5, "% i", -4200); + OneTest (__LINE__, "10150", 5, "% o", 4200U); + OneTest (__LINE__, "167630", 6, "% o", -4200U); + OneTest (__LINE__, "hello, world", 12, "% s", "hello, world"); + OneTest (__LINE__, "4200", 4, "% u", 4200U); + OneTest (__LINE__, "61336", 5, "% u", -4200U); + OneTest (__LINE__, "1068", 4, "% x", 4200U); + OneTest (__LINE__, "ef98", 4, "% x", -4200U); + OneTest (__LINE__, "1068", 4, "% X", 4200U); + OneTest (__LINE__, "EF98", 4, "% X", -4200U); + + /* If the ' ' and '+' flags both appear, the ' ' flag is ignored */ + OneTest (__LINE__, "u", 1, "% +c", 'u'); + OneTest (__LINE__, "+4200", 5, "% +d", 4200); + OneTest (__LINE__, "-4200", 5, "% +d", -4200); + OneTest (__LINE__, "+4200", 5, "% +i", 4200); + OneTest (__LINE__, "-4200", 5, "% +i", -4200); + OneTest (__LINE__, "10150", 5, "% +o", 4200U); + OneTest (__LINE__, "167630", 6, "% +o", -4200U); + OneTest (__LINE__, "hello, world", 12, "% +s", "hello, world"); + OneTest (__LINE__, "4200", 4, "% +u", 4200U); + OneTest (__LINE__, "61336", 5, "% +u", -4200U); + OneTest (__LINE__, "1068", 4, "% +x", 4200U); + OneTest (__LINE__, "ef98", 4, "% +x", -4200U); + OneTest (__LINE__, "1068", 4, "% +X", 4200U); + OneTest (__LINE__, "EF98", 4, "% +X", -4200U); + + /* Field width given */ + OneTest (__LINE__, " u", 15, "%15c", 'u'); + OneTest (__LINE__, " 4200", 15, "%15d", 4200); + OneTest (__LINE__, " -4200", 15, "%15d", -4200); + OneTest (__LINE__, " 4200", 15, "%15i", 4200); + OneTest (__LINE__, " -4200", 15, "%15i", -4200); + OneTest (__LINE__, " 10150", 15, "%15o", 4200U); + OneTest (__LINE__, " 167630", 15, "%15o", -4200U); + OneTest (__LINE__, " hello, world", 15, "%15s", "hello, world"); + OneTest (__LINE__, " 4200", 15, "%15u", 4200U); + OneTest (__LINE__, " 61336", 15, "%15u", -4200U); + OneTest (__LINE__, " 1068", 15, "%15x", 4200U); + OneTest (__LINE__, " ef98", 15, "%15x", -4200U); + OneTest (__LINE__, " 1068", 15, "%15X", 4200U); + OneTest (__LINE__, " EF98", 15, "%15X", -4200U); + + /* Field width given as separate argument */ + OneTest (__LINE__, " u", 15, "%*c", 15, 'u'); + OneTest (__LINE__, " 4200", 15, "%*d", 15, 4200); + OneTest (__LINE__, " -4200", 15, "%*d", 15, -4200); + OneTest (__LINE__, " 4200", 15, "%*i", 15, 4200); + OneTest (__LINE__, " -4200", 15, "%*i", 15, -4200); + OneTest (__LINE__, " 10150", 15, "%*o", 15, 4200U); + OneTest (__LINE__, " 167630", 15, "%*o", 15, -4200U); + OneTest (__LINE__, " hello, world", 15, "%*s", 15, "hello, world"); + OneTest (__LINE__, " 4200", 15, "%*u", 15, 4200U); + OneTest (__LINE__, " 61336", 15, "%*u", 15, -4200U); + OneTest (__LINE__, " 1068", 15, "%*x", 15, 4200U); + OneTest (__LINE__, " ef98", 15, "%*x", 15, -4200U); + OneTest (__LINE__, " 1068", 15, "%*X", 15, 4200U); + OneTest (__LINE__, " EF98", 15, "%*X", 15, -4200U); + + /* Field width and '-' flag given */ + OneTest (__LINE__, "u ", 15, "%-15c", 'u'); + OneTest (__LINE__, "4200 ", 15, "%-15d", 4200); + OneTest (__LINE__, "-4200 ", 15, "%-15d", -4200); + OneTest (__LINE__, "4200 ", 15, "%-15i", 4200); + OneTest (__LINE__, "-4200 ", 15, "%-15i", -4200); + OneTest (__LINE__, "10150 ", 15, "%-15o", 4200U); + OneTest (__LINE__, "167630 ", 15, "%-15o", -4200U); + OneTest (__LINE__, "hello, world ", 15, "%-15s", "hello, world"); + OneTest (__LINE__, "4200 ", 15, "%-15u", 4200U); + OneTest (__LINE__, "61336 ", 15, "%-15u", -4200U); + OneTest (__LINE__, "1068 ", 15, "%-15x", 4200U); + OneTest (__LINE__, "ef98 ", 15, "%-15x", -4200U); + OneTest (__LINE__, "1068 ", 15, "%-15X", 4200U); + OneTest (__LINE__, "EF98 ", 15, "%-15X", -4200U); + + /* A negative field width specified via an argument is treated as if the + * '-' flag and a positive field width were given. + * + * Beware: These tests will crash the old printf routine! + */ +#ifndef NOCRASH + OneTest (__LINE__, "u ", 15, "%*c", -15, 'u'); + OneTest (__LINE__, "4200 ", 15, "%*d", -15, 4200); + OneTest (__LINE__, "-4200 ", 15, "%*d", -15, -4200); + OneTest (__LINE__, "4200 ", 15, "%*i", -15, 4200); + OneTest (__LINE__, "-4200 ", 15, "%*i", -15, -4200); + OneTest (__LINE__, "10150 ", 15, "%*o", -15, 4200U); + OneTest (__LINE__, "167630 ", 15, "%*o", -15, -4200U); + OneTest (__LINE__, "hello, world ", 15, "%*s", -15, "hello, world"); + OneTest (__LINE__, "4200 ", 15, "%*u", -15, 4200U); + OneTest (__LINE__, "61336 ", 15, "%*u", -15, -4200U); + OneTest (__LINE__, "1068 ", 15, "%*x", -15, 4200U); + OneTest (__LINE__, "ef98 ", 15, "%*x", -15, -4200U); + OneTest (__LINE__, "1068 ", 15, "%*X", -15, 4200U); + OneTest (__LINE__, "EF98 ", 15, "%*X", -15, -4200U); +#endif + + /* Field width smaller than converted value */ + OneTest (__LINE__, "u", 1, "%1c", 'u'); + OneTest (__LINE__, "4200", 4, "%1d", 4200); + OneTest (__LINE__, "-4200", 5, "%1d", -4200); + OneTest (__LINE__, "4200", 4, "%1i", 4200); + OneTest (__LINE__, "-4200", 5, "%1i", -4200); + OneTest (__LINE__, "10150", 5, "%1o", 4200U); + OneTest (__LINE__, "167630", 6, "%1o", -4200U); + OneTest (__LINE__, "hello, world", 12, "%1s", "hello, world"); + OneTest (__LINE__, "4200", 4, "%1u", 4200U); + OneTest (__LINE__, "61336", 5, "%1u", -4200U); + OneTest (__LINE__, "1068", 4, "%1x", 4200U); + OneTest (__LINE__, "ef98", 4, "%1x", -4200U); + OneTest (__LINE__, "1068", 4, "%1X", 4200U); + OneTest (__LINE__, "EF98", 4, "%1X", -4200U); + + /* Field width specified and '0' flag given */ + OneTest (__LINE__, "000000000004200", 15, "%015d", 4200); + OneTest (__LINE__, "-00000000004200", 15, "%015d", -4200); + OneTest (__LINE__, "000000000004200", 15, "%015i", 4200); + OneTest (__LINE__, "-00000000004200", 15, "%015i", -4200); + OneTest (__LINE__, "000000000010150", 15, "%015o", 4200U); + OneTest (__LINE__, "000000000167630", 15, "%015o", -4200U); + OneTest (__LINE__, "000000000004200", 15, "%015u", 4200U); + OneTest (__LINE__, "000000000061336", 15, "%015u", -4200U); + OneTest (__LINE__, "000000000001068", 15, "%015x", 4200U); + OneTest (__LINE__, "00000000000ef98", 15, "%015x", -4200U); + OneTest (__LINE__, "000000000001068", 15, "%015X", 4200U); + OneTest (__LINE__, "00000000000EF98", 15, "%015X", -4200U); + + /* If the '-' and '0' flags are both specified, '0' is ignored */ + OneTest (__LINE__, "4200 ", 15, "%-015d", 4200); + OneTest (__LINE__, "-4200 ", 15, "%-015d", -4200); + OneTest (__LINE__, "4200 ", 15, "%-015i", 4200); + OneTest (__LINE__, "-4200 ", 15, "%-015i", -4200); + OneTest (__LINE__, "10150 ", 15, "%-015o", 4200U); + OneTest (__LINE__, "167630 ", 15, "%-015o", -4200U); + OneTest (__LINE__, "4200 ", 15, "%-015u", 4200U); + OneTest (__LINE__, "61336 ", 15, "%-015u", -4200U); + OneTest (__LINE__, "1068 ", 15, "%-015x", 4200U); + OneTest (__LINE__, "ef98 ", 15, "%-015x", -4200U); + OneTest (__LINE__, "1068 ", 15, "%-015X", 4200U); + OneTest (__LINE__, "EF98 ", 15, "%-015X", -4200U); + + /* Precision given */ + OneTest (__LINE__, "u", 1, "%.15c", 'u'); + OneTest (__LINE__, "000000000004200", 15, "%.15d", 4200); + OneTest (__LINE__, "-000000000004200", 16, "%.15d", -4200); + OneTest (__LINE__, "000000000004200", 15, "%.15i", 4200); + OneTest (__LINE__, "-000000000004200", 16, "%.15i", -4200); + OneTest (__LINE__, "000000000010150", 15, "%.15o", 4200U); + OneTest (__LINE__, "000000000167630", 15, "%.15o", -4200U); + OneTest (__LINE__, "hello, world", 12, "%.15s", "hello, world"); + OneTest (__LINE__, "000000000004200", 15, "%.15u", 4200U); + OneTest (__LINE__, "000000000061336", 15, "%.15u", -4200U); + OneTest (__LINE__, "000000000001068", 15, "%.15x", 4200U); + OneTest (__LINE__, "00000000000ef98", 15, "%.15x", -4200U); + OneTest (__LINE__, "000000000001068", 15, "%.15X", 4200U); + OneTest (__LINE__, "00000000000EF98", 15, "%.15X", -4200U); + + /* Precision given via argument */ + OneTest (__LINE__, "u", 1, "%.*c", 15, 'u'); + OneTest (__LINE__, "000000000004200", 15, "%.*d", 15, 4200); + OneTest (__LINE__, "-000000000004200", 16, "%.*d", 15, -4200); + OneTest (__LINE__, "000000000004200", 15, "%.*i", 15, 4200); + OneTest (__LINE__, "-000000000004200", 16, "%.*i", 15, -4200); + OneTest (__LINE__, "000000000010150", 15, "%.*o", 15, 4200U); + OneTest (__LINE__, "000000000167630", 15, "%.*o", 15, -4200U); + OneTest (__LINE__, "hello, world", 12, "%.*s", 15, "hello, world"); + OneTest (__LINE__, "000000000004200", 15, "%.*u", 15, 4200U); + OneTest (__LINE__, "000000000061336", 15, "%.*u", 15, -4200U); + OneTest (__LINE__, "000000000001068", 15, "%.*x", 15, 4200U); + OneTest (__LINE__, "00000000000ef98", 15, "%.*x", 15, -4200U); + OneTest (__LINE__, "000000000001068", 15, "%.*X", 15, 4200U); + OneTest (__LINE__, "00000000000EF98", 15, "%.*X", 15, -4200U); + + /* Negative precision is treated as if the precision were omitted */ +#ifndef NOCRASH + OneTest (__LINE__, "u", 1, "%.*c", -15, 'u'); + OneTest (__LINE__, "4200", 4, "%.*d", -15, 4200); + OneTest (__LINE__, "-4200", 5, "%.*d", -15, -4200); + OneTest (__LINE__, "4200", 4, "%.*i", -15, 4200); + OneTest (__LINE__, "-4200", 5, "%.*i", -15, -4200); + OneTest (__LINE__, "10150", 5, "%.*o", -15, 4200U); + OneTest (__LINE__, "167630", 6, "%.*o", -15, -4200U); + OneTest (__LINE__, "hello, world", 12, "%.*s", -15, "hello, world"); + OneTest (__LINE__, "4200", 4, "%.*u", -15, 4200U); + OneTest (__LINE__, "61336", 5, "%.*u", -15, -4200U); + OneTest (__LINE__, "1068", 4, "%.*x", -15, 4200U); + OneTest (__LINE__, "ef98", 4, "%.*x", -15, -4200U); + OneTest (__LINE__, "1068", 4, "%.*X", -15, 4200U); + OneTest (__LINE__, "EF98", 4, "%.*X", -15, -4200U); +#endif + + /* Field width and precision given */ + OneTest (__LINE__, " u", 15, "%15.10c", 'u'); + OneTest (__LINE__, " 0000004200", 15, "%15.10d", 4200); + OneTest (__LINE__, " -0000004200", 15, "%15.10d", -4200); + OneTest (__LINE__, " 0000004200", 15, "%15.10i", 4200); + OneTest (__LINE__, " -0000004200", 15, "%15.10i", -4200); + OneTest (__LINE__, " 0000010150", 15, "%15.10o", 4200U); + OneTest (__LINE__, " 0000167630", 15, "%15.10o", -4200U); + OneTest (__LINE__, " hello, wor", 15, "%15.10s", "hello, world"); + OneTest (__LINE__, " 0000004200", 15, "%15.10u", 4200U); + OneTest (__LINE__, " 0000061336", 15, "%15.10u", -4200U); + OneTest (__LINE__, " 0000001068", 15, "%15.10x", 4200U); + OneTest (__LINE__, " 000000ef98", 15, "%15.10x", -4200U); + OneTest (__LINE__, " 0000001068", 15, "%15.10X", 4200U); + OneTest (__LINE__, " 000000EF98", 15, "%15.10X", -4200U); + + /* For d, i, o, u, x and X conversions, if a precision is specified, the + * '0' flag is ignored. + */ + OneTest (__LINE__, " 0000004200", 15, "%015.10d", 4200); + OneTest (__LINE__, " -0000004200", 15, "%015.10d", -4200); + OneTest (__LINE__, " 0000004200", 15, "%015.10i", 4200); + OneTest (__LINE__, " -0000004200", 15, "%015.10i", -4200); + OneTest (__LINE__, " 0000010150", 15, "%015.10o", 4200U); + OneTest (__LINE__, " 0000167630", 15, "%015.10o", -4200U); + OneTest (__LINE__, " 0000004200", 15, "%015.10u", 4200U); + OneTest (__LINE__, " 0000061336", 15, "%015.10u", -4200U); + OneTest (__LINE__, " 0000001068", 15, "%015.10x", 4200U); + OneTest (__LINE__, " 000000ef98", 15, "%015.10x", -4200U); + OneTest (__LINE__, " 0000001068", 15, "%015.10X", 4200U); + OneTest (__LINE__, " 000000EF98", 15, "%015.10X", -4200U); + + /* Zero precision, explicitly specified */ + OneTest (__LINE__, "u", 1, "%.0c", 'u'); + OneTest (__LINE__, "4200", 4, "%.0d", 4200); + OneTest (__LINE__, "-4200", 5, "%.0d", -4200); + OneTest (__LINE__, "4200", 4, "%.0i", 4200); + OneTest (__LINE__, "-4200", 5, "%.0i", -4200); + OneTest (__LINE__, "10150", 5, "%.0o", 4200U); + OneTest (__LINE__, "167630", 6, "%.0o", -4200U); + OneTest (__LINE__, "", 0, "%.0s", "hello, world"); + OneTest (__LINE__, "4200", 4, "%.0u", 4200U); + OneTest (__LINE__, "61336", 5, "%.0u", -4200U); + OneTest (__LINE__, "1068", 4, "%.0x", 4200U); + OneTest (__LINE__, "ef98", 4, "%.0x", -4200U); + OneTest (__LINE__, "1068", 4, "%.0X", 4200U); + OneTest (__LINE__, "EF98", 4, "%.0X", -4200U); + + /* Zero precision, dot only */ + OneTest (__LINE__, "u", 1, "%.c", 'u'); + OneTest (__LINE__, "4200", 4, "%.d", 4200); + OneTest (__LINE__, "-4200", 5, "%.d", -4200); + OneTest (__LINE__, "4200", 4, "%.i", 4200); + OneTest (__LINE__, "-4200", 5, "%.i", -4200); + OneTest (__LINE__, "10150", 5, "%.o", 4200U); + OneTest (__LINE__, "167630", 6, "%.o", -4200U); + OneTest (__LINE__, "", 0, "%.s", "hello, world"); + OneTest (__LINE__, "4200", 4, "%.u", 4200U); + OneTest (__LINE__, "61336", 5, "%.u", -4200U); + OneTest (__LINE__, "1068", 4, "%.x", 4200U); + OneTest (__LINE__, "ef98", 4, "%.x", -4200U); + OneTest (__LINE__, "1068", 4, "%.X", 4200U); + OneTest (__LINE__, "EF98", 4, "%.X", -4200U); + + /* Zero precision, zero value */ + OneTest (__LINE__, "", 0, "%.0d", 0); + OneTest (__LINE__, "", 0, "%.0i", 0); + OneTest (__LINE__, "", 0, "%.0o", 0U); + OneTest (__LINE__, "", 0, "%.0u", 0U); + OneTest (__LINE__, "", 0, "%.0x", 0U); + OneTest (__LINE__, "", 0, "%.0X", 0U); + + /* Field width and zero precision given */ + OneTest (__LINE__, " u", 15, "%15.0c", 'u'); + OneTest (__LINE__, " 4200", 15, "%15.0d", 4200); + OneTest (__LINE__, " -4200", 15, "%15.0d", -4200); + OneTest (__LINE__, " 4200", 15, "%15.0i", 4200); + OneTest (__LINE__, " -4200", 15, "%15.0i", -4200); + OneTest (__LINE__, " 10150", 15, "%15.0o", 4200U); + OneTest (__LINE__, " 167630", 15, "%15.0o", -4200U); + OneTest (__LINE__, " ", 15, "%15.0s", "hello, world"); + OneTest (__LINE__, " 4200", 15, "%15.0u", 4200U); + OneTest (__LINE__, " 61336", 15, "%15.0u", -4200U); + OneTest (__LINE__, " 1068", 15, "%15.0x", 4200U); + OneTest (__LINE__, " ef98", 15, "%15.0x", -4200U); + OneTest (__LINE__, " 1068", 15, "%15.0X", 4200U); + OneTest (__LINE__, " EF98", 15, "%15.0X", -4200U); + + /* Field width, zero precision and zero value */ + OneTest (__LINE__, " ", 15, "%15.0d", 0); + OneTest (__LINE__, " ", 15, "%15.0i", 0); + OneTest (__LINE__, " ", 15, "%15.0o", 0U); + OneTest (__LINE__, " ", 15, "%15.0u", 0U); + OneTest (__LINE__, " ", 15, "%15.0x", 0U); + OneTest (__LINE__, " ", 15, "%15.0X", 0U); + + /* Alternative form */ + OneTest (__LINE__, "010150", 6, "%#o", 4200U); + OneTest (__LINE__, "0167630", 7, "%#o", -4200U); + OneTest (__LINE__, "0x1068", 6, "%#x", 4200U); + OneTest (__LINE__, "0xef98", 6, "%#x", -4200U); + OneTest (__LINE__, "0X1068", 6, "%#X", 4200U); + OneTest (__LINE__, "0XEF98", 6, "%#X", -4200U); + + /* Alternative form with zero value */ +#ifndef NOCRASH + OneTest (__LINE__, "0", 1, "%#o", 0U); + OneTest (__LINE__, "0", 1, "%#x", 0U); + OneTest (__LINE__, "0", 1, "%#X", 0U); +#endif + + /* Alternative form with zero value and precision 1 */ + OneTest (__LINE__, "0", 1, "%#.1o", 0U); + OneTest (__LINE__, "0", 1, "%#.1x", 0U); + OneTest (__LINE__, "0", 1, "%#.1X", 0U); + + /* Alternative form with non zero value and precision 1 */ + OneTest (__LINE__, "01", 2, "%#.1o", 1U); + OneTest (__LINE__, "0x1", 3, "%#.1x", 1U); + OneTest (__LINE__, "0X1", 3, "%#.1X", 1U); + + /* Alternative form and width given */ + OneTest (__LINE__, " 010150", 15, "%#15o", 4200U); + OneTest (__LINE__, " 0x1068", 15, "%#15x", 4200U); + OneTest (__LINE__, " 0X1068", 15, "%#15X", 4200U); + + /* Alternative form, width and zero padding */ + OneTest (__LINE__, "000000000010150", 15, "%#015o", 4200U); + OneTest (__LINE__, "0x0000000001068", 15, "%#015x", 4200U); + OneTest (__LINE__, "0X0000000001068", 15, "%#015X", 4200U); + + /* n conversion specifier */ + WriteTest (__LINE__, "%d%n", &W, 0x5A5A0004L); + WriteTest (__LINE__, "%d%hn", &W, 0x5A5A0004L); + WriteTest (__LINE__, "%d%hhn", &W, 0x5A5A5A04L); + WriteTest (__LINE__, "%d%ln", &W, 0x00000004L); + + /* Output the result */ + if (Failures) { + printf ("%u tests, %u failures\n", Tests, Failures); + } else { + printf ("%u tests: Ok\n", Tests); + } + + /* Wait for a key so we can read the result */ +#if defined(__CC65__) + cgetc (); +#endif + return 0; +}