From 73f38fc5460cb68662dd237022bda636ad734045 Mon Sep 17 00:00:00 2001 From: Ori Bernstein Date: Tue, 12 May 2020 10:48:33 -0700 Subject: [PATCH] [ape] add missing conversion flags for scanf We're missing type flags for: hh: char ll: vlong z: size_t t: ptrdiff_t j: intmax_t The lack of '%lld' was causing us to fail when parsing timezone files. This brings us in line with the specifiers in the C99 standard, section 7.19.6.2p11 --- sys/include/ape/inttypes.h | 2 ++ sys/src/ape/lib/ap/gen/strtoll.c | 7 +++++++ sys/src/ape/lib/ap/stdio/vfscanf.c | 29 ++++++++++++++++++++++++----- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/sys/include/ape/inttypes.h b/sys/include/ape/inttypes.h index 658e338db..0a8fbea51 100644 --- a/sys/include/ape/inttypes.h +++ b/sys/include/ape/inttypes.h @@ -27,4 +27,6 @@ #define PRIu32 "u" #define PRIu64 "llu" +extern intmax_t strtoimax(const char *, char **, int); + #endif diff --git a/sys/src/ape/lib/ap/gen/strtoll.c b/sys/src/ape/lib/ap/gen/strtoll.c index e633d2d08..96e3cf7fc 100644 --- a/sys/src/ape/lib/ap/gen/strtoll.c +++ b/sys/src/ape/lib/ap/gen/strtoll.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -101,3 +102,9 @@ Return: return -n; return n; } + +intmax_t +strtoimax(char *nptr, char **endptr, int base) +{ + return strtoll(nptr, endptr, base); +} diff --git a/sys/src/ape/lib/ap/stdio/vfscanf.c b/sys/src/ape/lib/ap/stdio/vfscanf.c index 95c14b7b2..5cbc1fee5 100644 --- a/sys/src/ape/lib/ap/stdio/vfscanf.c +++ b/sys/src/ape/lib/ap/stdio/vfscanf.c @@ -96,7 +96,16 @@ int vfscanf(FILE *f, const char *s, va_list args) } else width=-1; - type=*fmtp=='h' || *fmtp=='l' || *fmtp=='L'?*fmtp++:'n'; + type = 'n'; + if(*fmtp=='h' || *fmtp=='l' || *fmtp=='L' || *fmtp=='j' || *fmtp=='z' || *fmtp=='t') + type = *fmtp++; + if(type == 'l' && *fmtp == 'l'){ + type = 'V'; + fmtp++; + }else if(type == 'h' && *fmtp == 'h'){ + type = 'H'; + fmtp++; + } if(!icvt[*fmtp]) goto NonSpecial; if(!(*icvt[*fmtp])(f, &args, store, width, type)) return ncvt?ncvt:EOF; @@ -137,7 +146,7 @@ icvt_n(FILE *, va_list *args, int store, int, int type) static int icvt_fixed(FILE *f, va_list *args, int store, int width, int type, int unsgned, int base){ - unsigned long int num=0; + unsigned long long num=0; int sign=1, ndig=0, dig; int c; do @@ -194,18 +203,28 @@ Done: switch(unsgned){ case SIGNED: switch(type){ - case 'h': *va_arg(*args, short *)=num*sign; break; - case 'n': *va_arg(*args, int *)=num*sign; break; + case 'H': *va_arg(*args, char *)=num*sign; break; + case 'h': *va_arg(*args, short *)=num*sign; break; + case 'n': *va_arg(*args, int *)=num*sign; break; case 'l': - case 'L': *va_arg(*args, long *)=num*sign; break; + case 'L': *va_arg(*args, long *)=num*sign; break; + case 'j': + case 'V': *va_arg(*args, long long*)=num*sign; break; + case 'z': *va_arg(*args, ssize_t*)=num*sign; break; + case 't': *va_arg(*args, ptrdiff_t*)=num*sign; break; } break; case UNSIGNED: switch(type){ + case 'H': *va_arg(*args, unsigned char *)=num*sign; break; case 'h': *va_arg(*args, unsigned short *)=num*sign; break; case 'n': *va_arg(*args, unsigned int *)=num*sign; break; case 'l': case 'L': *va_arg(*args, unsigned long *)=num*sign; break; + case 'j': + case 'V': *va_arg(*args, unsigned long long *)=num*sign; break; + case 'z': *va_arg(*args, size_t*)=num*sign; break; + case 't': *va_arg(*args, ptrdiff_t*)=num*sign; break; } break; case POINTER: