From aa1351f84d6002246abcf69fc66277724b99cd98 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 7 Feb 2021 08:35:18 -0600 Subject: [PATCH] Add support for long long in scanf. The 'll' length modifier is now fully supported for the d, i, o, u, x, and X conversion specifiers. The 'n' conversion specifier can also store to a long long, but the value is still limited to 64k. The 'j' length modifier (for intmax_t) is also now treated as specifying a 64-bit value. --- stdio.asm | 106 +++++++++++++++++++++++++-------- stdio.macros | 164 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 209 insertions(+), 61 deletions(-) diff --git a/stdio.asm b/stdio.asm index 3273b5f..3a73d12 100644 --- a/stdio.asm +++ b/stdio.asm @@ -4764,6 +4764,8 @@ bs1 stz read no chars read sta base stz val initialize the value to 0 stz val+2 + stz val+4 + stz val+6 lb1 jsl ~getchar skip leading whitespace... cmp #EOF if EOF then bne ef1 @@ -4804,7 +4806,7 @@ lb1a jsl ~getchar bne lb2 lb1b asl base use base 16 dec ~scanWidth get the next character - beq lb4a + jeq lb4a bpl lb1c stz ~scanWidth lb1c jsl ~getchar @@ -4829,24 +4831,32 @@ lb2 cmp #'0' if the char is a digit then sbc #6 lb2a and #$000F convert it to a value pha save the value - ph4 val update the old value - lda base + ph8 val update the old value ldx #0 - jsl ~UMUL4 - pl4 val + phx + phx + phx + lda base + pha + jsl ~UMUL8 + pl8 val pla add in the new digit clc adc val sta val bcc lb3 inc val+2 + bne lb3 + inc val+4 + bne lb3 + inc val+6 lb3 dec ~scanWidth quit if the max # chars have been beq lb4a scanned bpl lb3a make sure 0 stays a 0 stz ~scanWidth lb3a jsl ~getchar next char inc read - bra lb2 + brl lb2 lb4 jsl ~putback put the last character back dec read @@ -4861,7 +4871,7 @@ lb4b lda ~suppress if input is not suppressed then bne lb7 lda minus if minus then beq lb4c - sub4 #0,val,val negate the value + sub8 #0,val,val negate the value lb4c lda val save the value ldx ~size bpl lb4d @@ -4873,14 +4883,24 @@ lb4d sta [arg] ldy #2 lda val+2 sta [arg],Y + dex + bmi lb6 + iny + iny + lda val+4 + sta [arg],Y + iny + iny + lda val+6 + sta [arg],Y lb6 lda ~suppress if input is not suppressed then bne lb7 ldy #2 remove the parameter from the stack jsr ~RemoveWord lb7 rts -val ds 4 value -base dc i4'10' constant for mul4 +val ds 8 value +base dc i2'10' number base based ds 2 based conversion? minus ds 2 is the value negative? read ds 2 # chars read @@ -5028,6 +5048,14 @@ lb0 sta [arg] lda #0 ldy #2 sta [arg],y + dex + bmi lb0a + iny + iny + sta [arg],y + iny + iny + sta [arg],y lb0a dec ~assignments fix assignment count lb1 ldy #2 remove the parameter from the stack jsr ~RemoveWord @@ -5233,22 +5261,30 @@ lb2 jsl ~getchar if the char is a digit then sbc #6 lb2a and #$000F convert it to a value pha save the value - ph4 val update the old value + ph8 val update the old value + ldx #0 + phx + phx + phx lda base - ldx base+2 - jsl ~UMUL4 - pl4 val + pha + jsl ~UMUL8 + pl8 val pla add in the new digit clc adc val sta val bcc lb3 inc val+2 + bne lb3 + inc val+4 + bne lb3 + inc val+6 lb3 dec ~scanWidth quit if the max # chars have been beq lb4a scanned - bpl lb2 make sure 0 stays a 0 + jpl lb2 make sure 0 stays a 0 stz ~scanWidth - bra lb2 + brl lb2 lb4 lda ch put the last character back jsl ~putback @@ -5273,6 +5309,16 @@ lb4c sta [arg] ldy #2 lda val+2 sta [arg],Y + dex + bmi lb6 + iny + iny + lda val+4 + sta [arg],Y + iny + iny + lda val+6 + sta [arg],Y lb6 lda ~suppress if input is not suppressed then bne lb7 ldy #2 remove the parameter from the stack @@ -5284,6 +5330,8 @@ lb7 rts Init stz read no chars read stz val initialize the value to 0 stz val+2 + stz val+4 + stz val+6 in1 jsl ~getchar skip leading whitespace... cmp #EOF if at EOF then bne in2 @@ -5302,8 +5350,8 @@ in2 tax ...back to slipping whitespace rts ch ds 2 char buffer -val ds 4 value -base dc i4'10' constant for mul4 +val ds 8 value +base dc i2'10' number base based ds 2 based conversion? read ds 2 # chars read end @@ -5503,14 +5551,22 @@ fm2 jsr GetSize get the field width specifier lda [format] if the char is 'l', 'z', 't', or 'j' then and #$00FF cmp #'l' - beq fm2a - cmp #'z' - beq fm2a + bne fm2a + inc ~size + inc4 format check for 'll' + lda [format] + and #$00FF + cmp #'l' + bne fm6 + bra fm2b +fm2a cmp #'z' + beq fm2b cmp #'t' - beq fm2a - cmp #'j' + beq fm2b + cmp #'j' 'j' also specifies a long long size bne fm3 -fm2a inc ~size long specifier + inc ~size +fm2b inc ~size long specifier bra fm4 fm3 cmp #'h' else if it is an 'h' then bne fm5 @@ -5639,8 +5695,8 @@ ch ds 2 temp storage ~scanCount ds 2 # of characters scanned ~scanError ds 2 set to 1 by scanners if an error occurs ~scanWidth ds 2 max # characters to scan -~size ds 2 size specifier; -1 -> char, 1 -> long, -! 0 -> default +~size ds 2 size specifier; -1 -> char, 0 -> default, +! 1 -> long, 2 -> long long end **************************************************************** diff --git a/stdio.macros b/stdio.macros index ae96e34..f3e826f 100644 --- a/stdio.macros +++ b/stdio.macros @@ -256,42 +256,6 @@ ~RESTM MEND MACRO -&LAB SUB4 &M1,&M2,&M3 - LCLB &YISTWO - LCLC &C -&LAB ~SETM - AIF C:&M3,.A -&C AMID "&M2",1,1 - AIF "&C"<>"#",.A -&C AMID "&M1",1,1 - AIF "&C"="{",.A - AIF "&C"="[",.A -&C AMID "&M2",2,L:&M2-1 - AIF &C>=65536,.A - SEC - ~LDA &M1 - ~OP SBC,&M2 - ~STA &M1 - BCS ~&SYSCNT - ~OP.H DEC,&M1 -~&SYSCNT ANOP - AGO .C -.A - AIF C:&M3,.B - LCLC &M3 -&M3 SETC &M1 -.B - SEC - ~LDA &M1 - ~OP SBC,&M2 - ~STA &M3 - ~LDA.H &M1 - ~OP.H SBC,&M2 - ~STA.H &M3 -.C - ~RESTM - MEND - MACRO &LAB ~OP.H &OPC,&OP &LAB ANOP LCLC &C @@ -775,3 +739,131 @@ dc i2'$2002' dc i4'&p' mend + macro +&l sub8 &n1,&n2,&n3 +&l ~setm + ph8 &n1 + ph8 &n2 + jsl ~SUB8 + aif c:&n3,.a + pl8 &n1 + ago .b +.a + pl8 &n3 +.b + ~restm + mend + macro +&l ph8 &n1 + lclc &c +&l anop +&c amid &n1,1,1 + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"="#",.d + aif "&c"="[",.b + aif "&c"<>"{",.c +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 +&n1 setc (&n1) +.b + ldy #6 +~&SYSCNT lda &n1,y + pha + dey + dey + bpl ~&SYSCNT + ago .e +.c + ldx #6 +~&SYSCNT lda &n1,x + pha + dex + dex + bpl ~&SYSCNT + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + bra ~b&SYSCNT +~a&SYSCNT dc i8"&n1" +~b&SYSCNT ldx #6 +~c&SYSCNT lda ~a&SYSCNT,x + pha + dex + dex + bpl ~c&SYSCNT +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + macro +&l pl8 &n1 + lclc &c +&l anop + aif s:longa=1,.a + rep #%00100000 +.a +&c amid &n1,1,1 + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.f +&n1 amid &n1,2,l:&n1-2 + pla + sta (&n1) + ldy #2 + pla + sta (&n1),y + ldy #4 + pla + sta (&n1),y + ldy #6 + pla + sta (&n1),y + ago .d +.b + aif "&c"<>"[",.c + pla + sta &n1 + ldy #2 + pla + sta &n1,y + ldy #4 + pla + sta &n1,y + ldy #6 + pla + sta &n1,y + ago .d +.c + pla + sta &n1 + pla + sta &n1+2 + pla + sta &n1+4 + pla + sta &n1+6 +.d + aif s:longa=1,.e + sep #%00100000 +.e + mexit +.f + mnote "Missing closing '}'",16 + mend + macro +&l jlt &bp +&l bge *+5 + brl &bp + mend + macro +&l jpl &bp +&l bmi *+5 + brl &bp + mend