mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add proper implementation of scanf family.
There are still a few non-standard quirks and things that needs to be properly implemented but that shouldn't be too hard and the most important features are now implemented.
This commit is contained in:
parent
cd728c9af9
commit
bb3e590915
8 changed files with 488 additions and 41 deletions
|
@ -95,7 +95,12 @@ print.o \
|
||||||
read.o \
|
read.o \
|
||||||
readdirents.o \
|
readdirents.o \
|
||||||
rmdir.o \
|
rmdir.o \
|
||||||
scan.o \
|
scanf.o \
|
||||||
|
fscanf.o \
|
||||||
|
sscanf.o \
|
||||||
|
vscanf.o \
|
||||||
|
vfscanf.o \
|
||||||
|
vsscanf.o \
|
||||||
stat.o \
|
stat.o \
|
||||||
truncate.o \
|
truncate.o \
|
||||||
umask.o \
|
umask.o \
|
||||||
|
|
35
libmaxsi/fscanf.cpp
Normal file
35
libmaxsi/fscanf.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
fscanf.cpp
|
||||||
|
Input format conversion.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern "C" int fscanf(FILE* fp, const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int ret = vfscanf(fp, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -86,6 +86,8 @@ extern int fprintf(FILE* restrict stream, const char* restrict format, ...);
|
||||||
extern int fputc(int c, FILE* stream);
|
extern int fputc(int c, FILE* stream);
|
||||||
extern int fputs(const char* restrict s, FILE* restrict stream);
|
extern int fputs(const char* restrict s, FILE* restrict stream);
|
||||||
extern size_t fread(void* restrict ptr, size_t size, size_t nitems, FILE* restrict stream);
|
extern size_t fread(void* restrict ptr, size_t size, size_t nitems, FILE* restrict stream);
|
||||||
|
extern FILE* freopen(const char* restrict filename, const char *restrict mode, FILE* restrict stream);
|
||||||
|
extern int fscanf(FILE* restrict stream, const char* restrict format, ... );
|
||||||
extern int fseek(FILE* stream, long offset, int whence);
|
extern int fseek(FILE* stream, long offset, int whence);
|
||||||
extern int fseeko(FILE* stream, off_t offset, int whence);
|
extern int fseeko(FILE* stream, off_t offset, int whence);
|
||||||
extern long ftell(FILE* stream);
|
extern long ftell(FILE* stream);
|
||||||
|
@ -101,29 +103,33 @@ extern int putc(int c, FILE* stream);
|
||||||
extern int putchar(int c);
|
extern int putchar(int c);
|
||||||
extern int puts(const char* str);
|
extern int puts(const char* str);
|
||||||
extern int remove(const char* path);
|
extern int remove(const char* path);
|
||||||
|
extern int rename(const char* oldname, const char* newname);
|
||||||
extern void rewind(FILE* stream);
|
extern void rewind(FILE* stream);
|
||||||
extern int snprintf(char* restrict s, size_t n, const char* restrict format, ...);
|
extern int snprintf(char* restrict s, size_t n, const char* restrict format, ...);
|
||||||
|
extern void setbuf(FILE* restrict stream, char* restrict buf);
|
||||||
extern char* sortix_gets(void);
|
extern char* sortix_gets(void);
|
||||||
extern int sortix_puts(const char* str);
|
extern int sortix_puts(const char* str);
|
||||||
extern int sprintf(char* restrict s, const char* restrict format, ...);
|
extern int sprintf(char* restrict s, const char* restrict format, ...);
|
||||||
|
extern int scanf(const char* restrict format, ...);
|
||||||
extern int sscanf(const char* restrict s, const char* restrict format, ...);
|
extern int sscanf(const char* restrict s, const char* restrict format, ...);
|
||||||
extern int ungetc(int c, FILE* stream);
|
extern int ungetc(int c, FILE* stream);
|
||||||
extern int vfprintf(FILE* restrict stream, const char* restrict format, __gnuc_va_list ap);
|
extern int vfprintf(FILE* restrict stream, const char* restrict format, __gnuc_va_list ap);
|
||||||
|
extern int vfscanf(FILE* restrict stream, const char* restrict format, __gnuc_va_list arg);
|
||||||
extern int vprintf(const char* restrict format, __gnuc_va_list ap);
|
extern int vprintf(const char* restrict format, __gnuc_va_list ap);
|
||||||
|
extern int vscanf(const char* restrict format, __gnuc_va_list arg);
|
||||||
extern int vsnprintf(char* restrict, size_t, const char* restrict, __gnuc_va_list);
|
extern int vsnprintf(char* restrict, size_t, const char* restrict, __gnuc_va_list);
|
||||||
extern int vsprintf(char* restrict s, const char* restrict format, __gnuc_va_list ap);
|
extern int vsprintf(char* restrict s, const char* restrict format, __gnuc_va_list ap);
|
||||||
|
extern int vsscanf(const char* restrict s, const char* restrict format, __gnuc_va_list arg);
|
||||||
|
|
||||||
/* TODO: These are not implemented in libmaxsi/sortix yet. */
|
/* TODO: These are not implemented in libmaxsi/sortix yet. */
|
||||||
#if defined(__SORTIX_SHOW_UNIMPLEMENTED)
|
#if defined(__SORTIX_SHOW_UNIMPLEMENTED)
|
||||||
extern char* ctermid(char* s);
|
extern char* ctermid(char* s);
|
||||||
extern FILE *fmemopen(void* restrict buf, size_t size, const char* restrict mode);
|
extern FILE *fmemopen(void* restrict buf, size_t size, const char* restrict mode);
|
||||||
extern FILE* freopen(const char* restrict filename, const char *restrict mode, FILE* restrict stream);
|
|
||||||
extern FILE* open_memstream(char** bufp, size_t* sizep);
|
extern FILE* open_memstream(char** bufp, size_t* sizep);
|
||||||
extern FILE* popen(const char* command, const char* mode);
|
extern FILE* popen(const char* command, const char* mode);
|
||||||
extern FILE* tmpfile(void);
|
extern FILE* tmpfile(void);
|
||||||
extern int dprintf(int fildes, const char* restrict format, ...);
|
extern int dprintf(int fildes, const char* restrict format, ...);
|
||||||
extern int fgetpos(FILE* restrict stream, fpos_t* restrict pos);
|
extern int fgetpos(FILE* restrict stream, fpos_t* restrict pos);
|
||||||
extern int fscanf(FILE* restrict stream, const char* restrict format, ... );
|
|
||||||
extern int fsetpos(FILE* stream, const fpos_t* pos);
|
extern int fsetpos(FILE* stream, const fpos_t* pos);
|
||||||
extern int ftrylockfile(FILE* file);
|
extern int ftrylockfile(FILE* file);
|
||||||
extern int getchar_unlocked(void);
|
extern int getchar_unlocked(void);
|
||||||
|
@ -131,17 +137,11 @@ extern int getc_unlocked(FILE* stream);
|
||||||
extern int pclose(FILE* steam);
|
extern int pclose(FILE* steam);
|
||||||
extern int putchar_unlocked(int c);
|
extern int putchar_unlocked(int c);
|
||||||
extern int putc_unlocked(int c, FILE* steam);
|
extern int putc_unlocked(int c, FILE* steam);
|
||||||
extern int rename(const char* oldname, const char* newname);
|
|
||||||
extern int renameat(int oldfd, const char* oldname, int newfd, const char* newname);
|
extern int renameat(int oldfd, const char* oldname, int newfd, const char* newname);
|
||||||
extern int scanf(const char* restrict format, ...);
|
|
||||||
extern int setvbuf(FILE* restrict stream, char* restrict buf, int type, size_t size);
|
extern int setvbuf(FILE* restrict stream, char* restrict buf, int type, size_t size);
|
||||||
extern int vdprintf(int fildes, const char* restrict format, __gnuc_va_list ap);
|
extern int vdprintf(int fildes, const char* restrict format, __gnuc_va_list ap);
|
||||||
extern int vfscanf(FILE* restrict stream, const char* restrict format, __gnuc_va_list arg);
|
|
||||||
extern int vscanf(const char* restrict format, __gnuc_va_list arg);
|
|
||||||
extern int vsscanf(const char* restrict s, const char* restrict format, __gnuc_va_list arg);
|
|
||||||
extern void flockfile(FILE* file);
|
extern void flockfile(FILE* file);
|
||||||
extern void funlockfile(FILE* file);
|
extern void funlockfile(FILE* file);
|
||||||
extern void setbuf(FILE* restrict stream, char* restrict buf);
|
|
||||||
|
|
||||||
#if __POSIX_OBSOLETE <= 200801
|
#if __POSIX_OBSOLETE <= 200801
|
||||||
extern char* tmpnam(char* s);
|
extern char* tmpnam(char* s);
|
||||||
|
|
35
libmaxsi/scanf.cpp
Normal file
35
libmaxsi/scanf.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
scanf.cpp
|
||||||
|
Input format conversion.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern "C" int scanf(const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int ret = vscanf(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
35
libmaxsi/sscanf.cpp
Normal file
35
libmaxsi/sscanf.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
sscanf.cpp
|
||||||
|
Input format conversion.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern "C" int sscanf(const char* str, const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int ret = vsscanf(str, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
317
libmaxsi/vfscanf.cpp
Normal file
317
libmaxsi/vfscanf.cpp
Normal file
|
@ -0,0 +1,317 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
vfscanf.cpp
|
||||||
|
Input format conversion.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
enum scanmode
|
||||||
|
{
|
||||||
|
MODE_INIT,
|
||||||
|
MODE_CONVSPEC,
|
||||||
|
MODE_SCANINT,
|
||||||
|
MODE_SCANINT_REAL,
|
||||||
|
MODE_SCANSTRING,
|
||||||
|
MODE_SCANSTRING_REAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum scantype
|
||||||
|
{
|
||||||
|
TYPE_SHORT,
|
||||||
|
TYPE_SHORTSHORT,
|
||||||
|
TYPE_INT,
|
||||||
|
TYPE_LONG,
|
||||||
|
TYPE_LONGLONG,
|
||||||
|
TYPE_SIZE,
|
||||||
|
TYPE_PTRDIFF,
|
||||||
|
TYPE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool IsTypeModifier(char c)
|
||||||
|
{
|
||||||
|
return c == 'h' || c == 'j' || c == 'l' || c == 'L' || c == 't' || c == 'z';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int debase(char c, int base)
|
||||||
|
{
|
||||||
|
if ( c == '0' )
|
||||||
|
return 0;
|
||||||
|
int ret = -1;
|
||||||
|
if ( '0' <= c && c <= '9' ) { ret = c - '0' + 0; }
|
||||||
|
if ( 'a' <= c && c <= 'f' ) { ret = c - 'a' + 10; }
|
||||||
|
if ( 'A' <= c && c <= 'F' ) { ret = c - 'A' + 10; }
|
||||||
|
if ( base <= ret )
|
||||||
|
return -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int vfscanf(FILE* fp, const char* origformat, va_list ap)
|
||||||
|
{
|
||||||
|
union { const char* format; const unsigned char* formatuc; };
|
||||||
|
format = origformat;
|
||||||
|
int matcheditems = 0;
|
||||||
|
size_t fieldwidth;
|
||||||
|
bool escaped = false;
|
||||||
|
bool discard;
|
||||||
|
bool negint;
|
||||||
|
bool intunsigned;
|
||||||
|
bool leadingzero;
|
||||||
|
bool hasprefix;
|
||||||
|
bool string;
|
||||||
|
size_t intparsed;
|
||||||
|
uintmax_t intvalue;
|
||||||
|
int ic;
|
||||||
|
int base;
|
||||||
|
int cval;
|
||||||
|
const size_t UNDO_MAX = 4;
|
||||||
|
int undodata[UNDO_MAX];
|
||||||
|
size_t undoable = 0;
|
||||||
|
size_t strwritten;
|
||||||
|
char* strdest;
|
||||||
|
enum scantype scantype;
|
||||||
|
enum scanmode scanmode = MODE_INIT;
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
ic = fgetc(fp);
|
||||||
|
unsigned char uc = ic; char c = uc;
|
||||||
|
switch (scanmode)
|
||||||
|
{
|
||||||
|
case MODE_INIT:
|
||||||
|
if ( !*format )
|
||||||
|
goto break_loop;
|
||||||
|
if ( isspace(*formatuc) )
|
||||||
|
{
|
||||||
|
if ( isspace(ic) )
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
do format++;
|
||||||
|
while ( isspace(*formatuc) );
|
||||||
|
}
|
||||||
|
if ( *format == '%' && !escaped )
|
||||||
|
{
|
||||||
|
format++;
|
||||||
|
scanmode = MODE_CONVSPEC;
|
||||||
|
ungetc(ic, fp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
escaped = false;
|
||||||
|
if ( *format != c ) { ungetc(ic, fp); goto break_loop; }
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
case MODE_CONVSPEC:
|
||||||
|
discard = false;
|
||||||
|
if ( *format == '*' ) { discard = true; format++; }
|
||||||
|
fieldwidth = 0;
|
||||||
|
while ( '0'<= *format && *format <= '9' )
|
||||||
|
fieldwidth = fieldwidth * 10 + *format++ - '0';
|
||||||
|
scantype = TYPE_INT;
|
||||||
|
while ( IsTypeModifier(*format) )
|
||||||
|
switch ( *format++ )
|
||||||
|
{
|
||||||
|
case 'h': scantype = scantype == TYPE_SHORT ? TYPE_SHORTSHORT
|
||||||
|
: TYPE_SHORT; break;
|
||||||
|
case 'j': scantype = TYPE_MAX; break;
|
||||||
|
case 'l': scantype = scantype == TYPE_LONG ? TYPE_LONGLONG
|
||||||
|
: TYPE_LONG; break;
|
||||||
|
case 'L': scantype = TYPE_LONGLONG; break;
|
||||||
|
case 't': scantype = TYPE_PTRDIFF; break;
|
||||||
|
case 'z': scantype = TYPE_SIZE; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( char convc = *format++ )
|
||||||
|
{
|
||||||
|
case '%':
|
||||||
|
escaped = true;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Warning: scanf does not support %c (%i)\n",
|
||||||
|
convc, convc);
|
||||||
|
fprintf(stderr, "Bailing out to prevent problems.\n");
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
continue;
|
||||||
|
case 'd':
|
||||||
|
base = 10; scanmode = MODE_SCANINT; intunsigned = false; break;
|
||||||
|
case 'i':
|
||||||
|
base = 0; scanmode = MODE_SCANINT; intunsigned = false; break;
|
||||||
|
case 'o':
|
||||||
|
base = 0; scanmode = MODE_SCANINT; intunsigned = true; break;
|
||||||
|
case 'u':
|
||||||
|
base = 10; scanmode = MODE_SCANINT; intunsigned = true; break;
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
base = 16; scanmode = MODE_SCANINT; intunsigned = true; break;
|
||||||
|
case 'c':
|
||||||
|
string = false; scanmode = MODE_SCANSTRING; break;
|
||||||
|
case 's':
|
||||||
|
string = true; scanmode = MODE_SCANSTRING; break;
|
||||||
|
}
|
||||||
|
ungetc(ic, fp);
|
||||||
|
continue;
|
||||||
|
case MODE_SCANINT:
|
||||||
|
intparsed = 0;
|
||||||
|
intvalue = 0;
|
||||||
|
leadingzero = false;
|
||||||
|
negint = false;
|
||||||
|
hasprefix = false;
|
||||||
|
undoable = 0;
|
||||||
|
scanmode = MODE_SCANINT_REAL;
|
||||||
|
case MODE_SCANINT_REAL:
|
||||||
|
if ( fieldwidth )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: field width not supported for integers in scanf.\n");
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ( !undoable && isspace(ic) )
|
||||||
|
continue;
|
||||||
|
if ( undoable < UNDO_MAX )
|
||||||
|
undodata[undoable++] = ic;
|
||||||
|
if ( c == '-' && !intunsigned && !negint )
|
||||||
|
{
|
||||||
|
negint = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( !intparsed && c == '0' && !hasprefix &&
|
||||||
|
(!base || base == 8 || base == 16) && !leadingzero )
|
||||||
|
leadingzero = true;
|
||||||
|
if ( intparsed == 1 && (c == 'x' || c == 'X') && !hasprefix &&
|
||||||
|
(!base || base == 16) && leadingzero )
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
leadingzero = false;
|
||||||
|
hasprefix = true;
|
||||||
|
intparsed = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ( intparsed == 1 && '1' <= c && c <= '7' && !hasprefix &&
|
||||||
|
(!base || base == 8) && leadingzero )
|
||||||
|
{
|
||||||
|
base = 8;
|
||||||
|
hasprefix = true;
|
||||||
|
leadingzero = false;
|
||||||
|
}
|
||||||
|
else if ( !intparsed && '0' <= c && c <= '9' && !hasprefix &&
|
||||||
|
(!base || base == 10) && !leadingzero )
|
||||||
|
{
|
||||||
|
base = 10;
|
||||||
|
leadingzero = false;
|
||||||
|
hasprefix = true;
|
||||||
|
}
|
||||||
|
cval = debase(c, base);
|
||||||
|
if ( cval < 0 )
|
||||||
|
{
|
||||||
|
if ( !intparsed )
|
||||||
|
{
|
||||||
|
while ( undoable )
|
||||||
|
ungetc(undodata[--undoable], fp);
|
||||||
|
goto break_loop;
|
||||||
|
}
|
||||||
|
scanmode = MODE_INIT;
|
||||||
|
undoable = 0;
|
||||||
|
ungetc(ic, fp);
|
||||||
|
if ( discard ) { discard = false; continue; }
|
||||||
|
uintmax_t uintmaxval = intvalue;
|
||||||
|
// TODO: Possible truncation of INTMAX_MIN!
|
||||||
|
intmax_t intmaxval = uintmaxval;
|
||||||
|
if ( negint ) intmaxval = -intmaxval;
|
||||||
|
bool un = intunsigned;
|
||||||
|
switch ( scantype )
|
||||||
|
{
|
||||||
|
case TYPE_SHORTSHORT:
|
||||||
|
if ( un ) *va_arg(ap, unsigned char*) = uintmaxval;
|
||||||
|
else *va_arg(ap, signed char*) = intmaxval;
|
||||||
|
break;
|
||||||
|
case TYPE_SHORT:
|
||||||
|
if ( un ) *va_arg(ap, unsigned short*) = uintmaxval;
|
||||||
|
else *va_arg(ap, signed short*) = intmaxval;
|
||||||
|
break;
|
||||||
|
case TYPE_INT:
|
||||||
|
if ( un ) *va_arg(ap, unsigned int*) = uintmaxval;
|
||||||
|
else *va_arg(ap, signed int*) = intmaxval;
|
||||||
|
break;
|
||||||
|
case TYPE_LONG:
|
||||||
|
if ( un ) *va_arg(ap, unsigned long*) = uintmaxval;
|
||||||
|
else *va_arg(ap, signed long*) = intmaxval;
|
||||||
|
break;
|
||||||
|
case TYPE_LONGLONG:
|
||||||
|
if ( un ) *va_arg(ap, unsigned long long*) = uintmaxval;
|
||||||
|
else *va_arg(ap, signed long long*) = intmaxval;
|
||||||
|
break;
|
||||||
|
case TYPE_PTRDIFF:
|
||||||
|
*va_arg(ap, ptrdiff_t*) = intmaxval;
|
||||||
|
break;
|
||||||
|
case TYPE_SIZE:
|
||||||
|
if ( un ) *va_arg(ap, size_t*) = uintmaxval;
|
||||||
|
else *va_arg(ap, ssize_t*) = intmaxval;
|
||||||
|
break;
|
||||||
|
case TYPE_MAX:
|
||||||
|
if ( un ) *va_arg(ap, uintmax_t*) = uintmaxval;
|
||||||
|
else *va_arg(ap, intmax_t*) = intmaxval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
matcheditems++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
intvalue = intvalue * (uintmax_t) base + (uintmax_t) cval;
|
||||||
|
intparsed++;
|
||||||
|
continue;
|
||||||
|
case MODE_SCANSTRING:
|
||||||
|
if ( !fieldwidth )
|
||||||
|
fieldwidth = string ? SIZE_MAX : 1;
|
||||||
|
scanmode = MODE_SCANSTRING_REAL;
|
||||||
|
strwritten = 0;
|
||||||
|
strdest = discard ? NULL : va_arg(ap, char*);
|
||||||
|
case MODE_SCANSTRING_REAL:
|
||||||
|
if ( string && !strwritten && isspace(ic) )
|
||||||
|
continue;
|
||||||
|
if ( string && strwritten &&
|
||||||
|
(ic == EOF || isspace(ic) || strwritten == fieldwidth) )
|
||||||
|
{
|
||||||
|
ungetc(ic, fp);
|
||||||
|
if ( !discard )
|
||||||
|
strdest[strwritten] = '\0';
|
||||||
|
matcheditems++;
|
||||||
|
scanmode = MODE_INIT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( !string && strwritten == fieldwidth )
|
||||||
|
{
|
||||||
|
ungetc(ic, fp);
|
||||||
|
scanmode = MODE_INIT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( ic == EOF )
|
||||||
|
goto break_loop;
|
||||||
|
if ( !discard )
|
||||||
|
strdest[strwritten++] = c;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break_loop:
|
||||||
|
return matcheditems;
|
||||||
|
}
|
31
libmaxsi/vscanf.cpp
Normal file
31
libmaxsi/vscanf.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
vscanf.cpp
|
||||||
|
Input format conversion.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern "C" int vscanf(const char* format, va_list ap)
|
||||||
|
{
|
||||||
|
return vfscanf(stdin, format, ap);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||||
|
|
||||||
This file is part of LibMaxsi.
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
@ -17,42 +17,31 @@
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
scan.cpp
|
vsscanf.cpp
|
||||||
The scanf family of functions.
|
Input format conversion.
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <libmaxsi/platform.h>
|
#include <errno.h>
|
||||||
#include <libmaxsi/syscall.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace Maxsi {
|
extern "C" int vsscanf(const char* str, const char* format, va_list ap)
|
||||||
|
|
||||||
|
|
||||||
// TODO: This is an ugly hack to help build binutils.
|
|
||||||
#warning Ugly sscanf hack to help build binutils
|
|
||||||
extern "C" int sscanf(const char* s, const char* format, ...)
|
|
||||||
{
|
{
|
||||||
if ( strcmp(format, "%x") != 0 )
|
const char* filename = "/ugly-vsscanf-hack";
|
||||||
{
|
FILE* fp = fopen(filename, "w+");
|
||||||
fprintf(stderr, "sscanf hack doesn't implement: '%s'\n", format);
|
if ( !fp )
|
||||||
abort();
|
return -1;
|
||||||
|
int ret = -1;
|
||||||
|
size_t len = strlen(str);
|
||||||
|
if ( fwrite(str, sizeof(char), len, fp) == len )
|
||||||
|
if ( fseek(fp, 0, SEEK_SET) == 0 )
|
||||||
|
ret = vfscanf(fp, format, ap);
|
||||||
|
int savederrno = errno;
|
||||||
|
fclose(fp);
|
||||||
|
unlink(filename);
|
||||||
|
errno = savederrno;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
va_list list;
|
|
||||||
va_start(list, format);
|
|
||||||
unsigned* dec = va_arg(list, unsigned*);
|
|
||||||
*dec = strtol(s, NULL, 16);
|
|
||||||
return strlen(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" int fscanf(FILE* /*fp*/, const char* /*format*/, ...)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "fscanf(3) is not implemented\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Maxsi
|
|
Loading…
Reference in a new issue