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.
This commit is contained in:
Stephen Heumann 2021-02-07 08:35:18 -06:00
parent 506f9fa965
commit aa1351f84d
2 changed files with 209 additions and 61 deletions

106
stdio.asm
View File

@ -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
****************************************************************

View File

@ -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