From 7bd40a855acf6c0970bb69528275f3af0bc9557d Mon Sep 17 00:00:00 2001 From: jean Date: Thu, 28 Dec 2000 11:57:10 +0000 Subject: [PATCH] copy some functions from crtdll svn path=/trunk/; revision=1482 --- reactos/lib/msvcrt/float/isnan.c | 77 ++ reactos/lib/msvcrt/io/close.c | 14 + reactos/lib/msvcrt/io/fmode.c | 9 + reactos/lib/msvcrt/io/isatty.c | 14 + reactos/lib/msvcrt/io/lseek.c | 9 + reactos/lib/msvcrt/io/open.c | 273 ++++++ reactos/lib/msvcrt/io/read.c | 22 + reactos/lib/msvcrt/io/setmode.c | 19 + reactos/lib/msvcrt/io/write.c | 23 + reactos/lib/msvcrt/math/modf.c | 141 +++ reactos/lib/msvcrt/math/pow.c | 85 ++ reactos/lib/msvcrt/signal/signal.c | 107 ++ reactos/lib/msvcrt/stdio/allocfil.c | 98 ++ reactos/lib/msvcrt/stdio/fclose.c | 51 + reactos/lib/msvcrt/stdio/feof.c | 19 + reactos/lib/msvcrt/stdio/ferror.c | 13 + reactos/lib/msvcrt/stdio/fflush.c | 111 +++ reactos/lib/msvcrt/stdio/fgets.c | 22 + reactos/lib/msvcrt/stdio/filbuf.c | 130 +++ reactos/lib/msvcrt/stdio/flsbuf.c | 179 ++++ reactos/lib/msvcrt/stdio/fopen.c | 77 ++ reactos/lib/msvcrt/stdio/fprintf.c | 56 ++ reactos/lib/msvcrt/stdio/fputc.c | 17 + reactos/lib/msvcrt/stdio/fputs.c | 38 + reactos/lib/msvcrt/stdio/fread.c | 83 ++ reactos/lib/msvcrt/stdio/fwalk.c | 18 + reactos/lib/msvcrt/stdio/fwrite.c | 84 ++ reactos/lib/msvcrt/stdio/getc.c | 57 ++ reactos/lib/msvcrt/stdio/printf.c | 54 + reactos/lib/msvcrt/stdio/putc.c | 54 + reactos/lib/msvcrt/stdio/putchar.c | 22 + reactos/lib/msvcrt/stdio/puts.c | 17 + reactos/lib/msvcrt/stdio/remove.c | 9 + reactos/lib/msvcrt/stdio/setvbuf.c | 62 ++ reactos/lib/msvcrt/stdio/sprintf.c | 84 ++ reactos/lib/msvcrt/stdio/stdhnd.c | 44 + reactos/lib/msvcrt/stdio/vfprintf.c | 863 ++++++++++++++++ reactos/lib/msvcrt/stdio/vfwprint.c | 865 ++++++++++++++++ reactos/lib/msvcrt/stdio/vprintf.c | 47 + reactos/lib/msvcrt/stdio/vsprintf.c | 68 ++ reactos/lib/msvcrt/stdlib/abort.c | 8 +- reactos/lib/msvcrt/stdlib/atexit.c | 4 +- reactos/lib/msvcrt/sys_stat/fstat.c | 42 + reactos/lib/msvcrt/time/ctime.c | 1413 +++++++++++++++++++++++++++ reactos/lib/msvcrt/time/posixrul.h | 49 + reactos/lib/msvcrt/time/time.c | 219 +++++ reactos/lib/msvcrt/time/tzfile.h | 160 +++ 47 files changed, 5924 insertions(+), 6 deletions(-) create mode 100644 reactos/lib/msvcrt/float/isnan.c create mode 100644 reactos/lib/msvcrt/io/close.c create mode 100644 reactos/lib/msvcrt/io/fmode.c create mode 100644 reactos/lib/msvcrt/io/isatty.c create mode 100644 reactos/lib/msvcrt/io/lseek.c create mode 100644 reactos/lib/msvcrt/io/open.c create mode 100644 reactos/lib/msvcrt/io/read.c create mode 100644 reactos/lib/msvcrt/io/setmode.c create mode 100644 reactos/lib/msvcrt/io/write.c create mode 100644 reactos/lib/msvcrt/math/modf.c create mode 100644 reactos/lib/msvcrt/math/pow.c create mode 100644 reactos/lib/msvcrt/signal/signal.c create mode 100644 reactos/lib/msvcrt/stdio/allocfil.c create mode 100644 reactos/lib/msvcrt/stdio/fclose.c create mode 100644 reactos/lib/msvcrt/stdio/feof.c create mode 100644 reactos/lib/msvcrt/stdio/ferror.c create mode 100644 reactos/lib/msvcrt/stdio/fflush.c create mode 100644 reactos/lib/msvcrt/stdio/fgets.c create mode 100644 reactos/lib/msvcrt/stdio/filbuf.c create mode 100644 reactos/lib/msvcrt/stdio/flsbuf.c create mode 100644 reactos/lib/msvcrt/stdio/fopen.c create mode 100644 reactos/lib/msvcrt/stdio/fprintf.c create mode 100644 reactos/lib/msvcrt/stdio/fputc.c create mode 100644 reactos/lib/msvcrt/stdio/fputs.c create mode 100644 reactos/lib/msvcrt/stdio/fread.c create mode 100644 reactos/lib/msvcrt/stdio/fwalk.c create mode 100644 reactos/lib/msvcrt/stdio/fwrite.c create mode 100644 reactos/lib/msvcrt/stdio/getc.c create mode 100644 reactos/lib/msvcrt/stdio/printf.c create mode 100644 reactos/lib/msvcrt/stdio/putc.c create mode 100644 reactos/lib/msvcrt/stdio/putchar.c create mode 100644 reactos/lib/msvcrt/stdio/puts.c create mode 100644 reactos/lib/msvcrt/stdio/remove.c create mode 100644 reactos/lib/msvcrt/stdio/setvbuf.c create mode 100644 reactos/lib/msvcrt/stdio/sprintf.c create mode 100644 reactos/lib/msvcrt/stdio/stdhnd.c create mode 100644 reactos/lib/msvcrt/stdio/vfprintf.c create mode 100644 reactos/lib/msvcrt/stdio/vfwprint.c create mode 100644 reactos/lib/msvcrt/stdio/vprintf.c create mode 100644 reactos/lib/msvcrt/stdio/vsprintf.c create mode 100644 reactos/lib/msvcrt/sys_stat/fstat.c create mode 100644 reactos/lib/msvcrt/time/ctime.c create mode 100644 reactos/lib/msvcrt/time/posixrul.h create mode 100644 reactos/lib/msvcrt/time/time.c create mode 100644 reactos/lib/msvcrt/time/tzfile.h diff --git a/reactos/lib/msvcrt/float/isnan.c b/reactos/lib/msvcrt/float/isnan.c new file mode 100644 index 00000000000..d6f4ac04e1a --- /dev/null +++ b/reactos/lib/msvcrt/float/isnan.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +int _isnan(double __x) +{ + double_t * x = (double_t *)&__x; + return ( x->exponent == 0x7ff && ( x->mantissah != 0 || x->mantissal != 0 )); +} + +int _isnanl(long double __x) +{ + + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + + long_double_t * x = (long_double_t *)&__x; + + + /* IEEE 854 NaN's have the maximum possible + exponent and a nonzero mantissa. */ + + return (( x->exponent == 0x7fff) + && ( (x->mantissah & 0x80000000) != 0) + && ( (x->mantissah & (unsigned int)0x7fffffff) != 0 || x->mantissal != 0 )); +} + + +int _isinf(double __x) +{ + double_t * x = (double_t *)&__x; + return ( x->exponent == 0x7ff && ( x->mantissah == 0 && x->mantissal == 0 )); +} + + + +int _finite( double x ) +{ + return !_isinf(x); +} + +int _isinfl(long double __x) +{ + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + + long_double_t * x = (long_double_t *)&__x; + + + /* An IEEE 854 infinity has an exponent with the + maximum possible value and a zero mantissa. */ + + + if ( x->exponent == 0x7fff && ( (x->mantissah == 0x80000000 ) && x->mantissal == 0 )) + return x->sign ? -1 : 1; + return 0; +} + + diff --git a/reactos/lib/msvcrt/io/close.c b/reactos/lib/msvcrt/io/close.c new file mode 100644 index 00000000000..2ca7aa8bd30 --- /dev/null +++ b/reactos/lib/msvcrt/io/close.c @@ -0,0 +1,14 @@ +#include +#include +#include + + +int _close(int _fd) +{ + if ( _fd == -1 ) + return -1; + if ( CloseHandle(_get_osfhandle(_fd)) == FALSE ) + return -1; + return __fileno_close(_fd); + +} diff --git a/reactos/lib/msvcrt/io/fmode.c b/reactos/lib/msvcrt/io/fmode.c new file mode 100644 index 00000000000..fc89be40a53 --- /dev/null +++ b/reactos/lib/msvcrt/io/fmode.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#undef _fmode +unsigned int _fmode = O_TEXT; + +unsigned int *_fmode_dll = &_fmode; + diff --git a/reactos/lib/msvcrt/io/isatty.c b/reactos/lib/msvcrt/io/isatty.c new file mode 100644 index 00000000000..a452414ba66 --- /dev/null +++ b/reactos/lib/msvcrt/io/isatty.c @@ -0,0 +1,14 @@ +#include +#include + + +int _isatty( int fd ) +{ + struct stat buf; + + if (_fstat (fd, &buf) < 0) + return 0; + if (S_ISCHR (buf.st_mode)) + return 1; + return 0; +} diff --git a/reactos/lib/msvcrt/io/lseek.c b/reactos/lib/msvcrt/io/lseek.c new file mode 100644 index 00000000000..c5854459b7c --- /dev/null +++ b/reactos/lib/msvcrt/io/lseek.c @@ -0,0 +1,9 @@ +#include +#include +#include + +long _lseek(int _fildes, long _offset, int _whence) +{ + return _llseek((HFILE)filehnd(_fildes),_offset,_whence); +} + diff --git a/reactos/lib/msvcrt/io/open.c b/reactos/lib/msvcrt/io/open.c new file mode 100644 index 00000000000..c3a8a6b2289 --- /dev/null +++ b/reactos/lib/msvcrt/io/open.c @@ -0,0 +1,273 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/open.c + * PURPOSE: Opens a file and translates handles to fileno + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +// rember to interlock the allocation of fileno when making this thread safe + +// possibly store extra information at the handle + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _fileno_modes_type +{ + HANDLE hFile; + int mode; + int fd; +} fileno_modes_type; + +fileno_modes_type *fileno_modes = NULL; + +int maxfno = 5; +int minfno = 5; + +char __is_text_file(FILE *p) +{ + if ( p == NULL || fileno_modes == NULL ) + return FALSE; + return (!((p)->_flag&_IOSTRG) && (fileno_modes[(p)->_file].mode&O_TEXT)); +} + + + + +int __fileno_alloc(HANDLE hFile, int mode); + + +int _open(const char *_path, int _oflag,...) +{ + HANDLE hFile; + DWORD dwDesiredAccess = 0; + DWORD dwShareMode = 0; + DWORD dwCreationDistribution = 0; + DWORD dwFlagsAndAttributes = 0; + + if (( _oflag & S_IREAD ) == S_IREAD) + dwShareMode = FILE_SHARE_READ; + else if ( ( _oflag & S_IWRITE) == S_IWRITE ) { + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + } + + /* + * + * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.) + * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.) + * + */ + if (( _oflag & _O_RDWR ) == _O_RDWR ) + dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA | + FILE_WRITE_DATA | FILE_READ_ATTRIBUTES | + FILE_WRITE_ATTRIBUTES; + else if (( _oflag & O_RDONLY ) == O_RDONLY ) + dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES + | FILE_WRITE_ATTRIBUTES; + else if (( _oflag & _O_WRONLY ) == _O_WRONLY ) + dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA | + FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES; + + if (( _oflag & S_IREAD ) == S_IREAD ) + dwShareMode |= FILE_SHARE_READ; + + if (( _oflag & S_IWRITE ) == S_IWRITE ) + dwShareMode |= FILE_SHARE_WRITE; + + if (( _oflag & (_O_CREAT | _O_EXCL ) ) == (_O_CREAT | _O_EXCL) ) + dwCreationDistribution |= CREATE_NEW; + + else if (( _oflag & O_TRUNC ) == O_TRUNC ) { + if (( _oflag & O_CREAT ) == O_CREAT ) + dwCreationDistribution |= CREATE_ALWAYS; + else if (( _oflag & O_RDONLY ) != O_RDONLY ) + dwCreationDistribution |= TRUNCATE_EXISTING; + } + else if (( _oflag & _O_APPEND ) == _O_APPEND ) + dwCreationDistribution |= OPEN_EXISTING; + else if (( _oflag & _O_CREAT ) == _O_CREAT ) + dwCreationDistribution |= OPEN_ALWAYS; + else + dwCreationDistribution |= OPEN_EXISTING; + + if (( _oflag & _O_RANDOM ) == _O_RANDOM ) + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; + if (( _oflag & _O_SEQUENTIAL ) == _O_SEQUENTIAL ) + dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; + + if (( _oflag & _O_TEMPORARY ) == _O_TEMPORARY ) + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + + if (( _oflag & _O_SHORT_LIVED ) == _O_SHORT_LIVED ) + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + + hFile = CreateFileA(_path, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDistribution, + dwFlagsAndAttributes, + NULL); + if (hFile == (HANDLE)-1) + return -1; + return __fileno_alloc(hFile,_oflag); + +// _O_APPEND Moves file pointer to end of file before every write operation. + +} + + + + +int +__fileno_alloc(HANDLE hFile, int mode) +{ + + int i; + /* Check for bogus values */ + if (hFile < 0) + return -1; + + for(i=minfno;i= maxfno ) + return (void *)-1; + + if ( fileno_modes[fileno].fd == -1 ) + return (void *)-1; + return fileno_modes[fileno].hFile; +} + +int __fileno_dup2( int handle1, int handle2 ) +{ + if ( handle1 >= maxfno ) + return -1; + + if ( handle1 < 0 ) + return -1; + if ( handle2 >= maxfno ) + return -1; + + if ( handle2 < 0 ) + return -1; + + memcpy(&fileno_modes[handle1],&fileno_modes[handle2],sizeof(fileno_modes)); + + + return handle1; +} + +int __fileno_setmode(int _fd, int _newmode) +{ + int m; + if ( _fd < minfno ) + return -1; + + if ( _fd >= maxfno ) + return -1; + + m = fileno_modes[_fd].mode; + fileno_modes[_fd].mode = _newmode; + return m; +} + +int __fileno_getmode(int _fd) +{ + if ( _fd < minfno ) + return -1; + + if ( _fd >= maxfno ) + return -1; + + return fileno_modes[_fd].mode; + +} + + +int __fileno_close(int _fd) +{ + if ( _fd < 0 ) + return -1; + + if ( _fd >= maxfno ) + return -1; + + fileno_modes[_fd].fd = -1; + fileno_modes[_fd].hFile = (HANDLE)-1; + return 0; +} + +int _open_osfhandle (void *osfhandle, int flags ) +{ + return __fileno_alloc((HANDLE)osfhandle, flags); +} + +void *_get_osfhandle( int fileno ) +{ + return filehnd(fileno); +} diff --git a/reactos/lib/msvcrt/io/read.c b/reactos/lib/msvcrt/io/read.c new file mode 100644 index 00000000000..520e2ec9a4b --- /dev/null +++ b/reactos/lib/msvcrt/io/read.c @@ -0,0 +1,22 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/read.c + * PURPOSE: Reads a file + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + +size_t _read(int _fd, void *_buf, size_t _nbyte) +{ + size_t _rbyte; + + if (!ReadFile(_get_osfhandle(_fd),_buf,_nbyte,&_rbyte,NULL)) + { + return -1; + } + return _rbyte; +} diff --git a/reactos/lib/msvcrt/io/setmode.c b/reactos/lib/msvcrt/io/setmode.c new file mode 100644 index 00000000000..ea6f7e8b1bb --- /dev/null +++ b/reactos/lib/msvcrt/io/setmode.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/setmode.c + * PURPOSE: Sets the file translation mode + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include +#include + + +int _setmode(int _fd, int _newmode) +{ + return __fileno_setmode(_fd, _newmode); +} diff --git a/reactos/lib/msvcrt/io/write.c b/reactos/lib/msvcrt/io/write.c new file mode 100644 index 00000000000..51dac7b85f1 --- /dev/null +++ b/reactos/lib/msvcrt/io/write.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/write.c + * PURPOSE: Writes to a file + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + + + +size_t _write(int _fd, const void *_buf, size_t _nbyte) +{ + size_t _wbyte; + + if ( !WriteFile(_get_osfhandle(_fd),_buf,_nbyte,&_wbyte,NULL) ) { + return -1; + } + return _wbyte; +} diff --git a/reactos/lib/msvcrt/math/modf.c b/reactos/lib/msvcrt/math/modf.c new file mode 100644 index 00000000000..6864e52e044 --- /dev/null +++ b/reactos/lib/msvcrt/math/modf.c @@ -0,0 +1,141 @@ +/* @(#)s_modf.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include +#include +#include + + + +//static const double one = 1.0; + +double modf(double __x, double *__i) +{ + + double_t * x = (double_t *)&__x; + double_t * iptr = ( double_t *)__i; + + int j0; + unsigned int i; + j0 = x->exponent - 0x3ff; /* exponent of x */ + if(j0<20) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + *__i = 0.0; + iptr->sign = x->sign; + return __x; + } else { + + if ( x->mantissah == 0 && x->mantissal == 0 ) { + *__i = __x; + return 0.0; + } + + i = (0x000fffff)>>j0; + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah&(~i); + iptr->mantissal = 0; + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + return __x - *__i; + } + } else if (j0>51) { /* no fraction part */ + *__i = __x; + if ( _isnan(__x) || _isinf(__x) ) + return __x; + + + __x = 0.0; + x->sign = iptr->sign; + return __x; + } else { /* fraction part in low x */ + + + i = ((unsigned)(0xffffffff))>>(j0-20); + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah; + iptr->mantissal = x->mantissal&(~i); + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + return __x - *__i; + } +} + + +long double modfl(long double __x, long double *__i) +{ + + + long_double_t * x = (long_double_t *)&__x; + long_double_t * iptr = (long_double_t *)__i; + + int j0; + unsigned int i; + j0 = x->exponent - 0x3fff; /* exponent of x */ + + + if(j0<32) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + *__i = 0.0L; + iptr->sign = x->sign; + return __x; + } else { + + i = ((unsigned int)(0xffffffff))>>(j0+1); + if ( x->mantissal == 0 && (x->mantissal & i) == 0 ) { + *__i = __x; + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah&((~i)); + iptr->mantissal = 0; + + + return __x - *__i; + } + } else if (j0>63) { /* no fraction part */ + *__i = __x; + if ( _isnanl(__x) || _isinfl(__x) ) + return __x; + + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } else { /* fraction part in low x */ + + i = ((unsigned int)(0xffffffff))>>(j0-32); + if ( x->mantissal == 0 ) { + *__i = __x; + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah; + iptr->mantissal = x->mantissal&(~i); + + return __x - *__i; + + + } +} diff --git a/reactos/lib/msvcrt/math/pow.c b/reactos/lib/msvcrt/math/pow.c new file mode 100644 index 00000000000..37810ac5362 --- /dev/null +++ b/reactos/lib/msvcrt/math/pow.c @@ -0,0 +1,85 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +double pow (double __x, double __y); + +double __log2 (double __x); + +double __log2 (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double pow (double __x, double __y) +{ + register double __value, __exponent; + long __p = (long) __y; + + if (__x == 0.0 && __y > 0.0) + return 0.0; + if (__y == (double) __p) + { + double __r = 1.0; + if (__p == 0) + return 1.0; + if (__p < 0) + { + __p = -__p; + __x = 1.0 / __x; + } + while (1) + { + if (__p & 1) + __r *= __x; + __p >>= 1; + if (__p == 0) + return __r; + __x *= __x; + } + /* NOTREACHED */ + } + __asm __volatile__ + ("fmul %%st(1) # y * log2(x)\n\t" + "fst %%st(1)\n\t" + "frndint # int(y * log2(x))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(y * log2(x))\n\t" + "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__log2 (__x)), "1" (__y)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} + +long double powl (long double __x,long double __y) +{ + return pow(__x,__y/2)*pow(__x,__y/2); +} + diff --git a/reactos/lib/msvcrt/signal/signal.c b/reactos/lib/msvcrt/signal/signal.c new file mode 100644 index 00000000000..2e221f42cae --- /dev/null +++ b/reactos/lib/msvcrt/signal/signal.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include + +void _default_handler(int signal); + +typedef struct _sig_element +{ + int signal; + char *signame; + _p_sig_fn_t handler; +} sig_element; + +static sig_element signal_list[SIGMAX] = + { + { 0, "Signal 0", SIG_DFL }, + { SIGABRT, "Aborted",SIG_DFL }, + { SIGFPE, "Erroneous arithmetic operation",SIG_DFL }, + { SIGILL, "Illegal instruction",SIG_DFL }, + { SIGINT, "Interrupt",SIG_DFL }, + { SIGSEGV, "Invalid access to storage",SIG_DFL }, + { SIGTERM, "Terminated",SIG_DFL }, + { SIGHUP, "Hangup",SIG_DFL }, + { SIGQUIT, "Quit",SIG_DFL }, + { SIGPIPE, "Broken pipe",SIG_DFL }, + { SIGKILL, "Killed",SIG_DFL }, + { SIGALRM, "Alarm clock",SIG_DFL }, + { 0, "Stopped (signal)",SIG_DFL }, + { 0, "Stopped",SIG_DFL }, + { 0, "Continued",SIG_DFL }, + { 0, "Child exited",SIG_DFL }, + { 0, "Stopped (tty input)",SIG_DFL }, + { 0, "Stopped (tty output)",SIG_DFL }, + { 0, NULL, SIG_DFL } + }; + +int nsignal = 21; + +_p_sig_fn_t signal(int sig, _p_sig_fn_t func) +{ + _p_sig_fn_t temp; + int i; + if(sig <= 0 || sig > SIGMAX || sig == SIGKILL) + { + __set_errno(EINVAL); + return SIG_ERR; + } +// check with IsBadCodePtr + + if ( func < (_p_sig_fn_t)4096 ) { + __set_errno(EINVAL); + return SIG_ERR; + } + + for(i=0;i SIGMAX) + return -1; + for(i=0;i +#include +#include +#include + + +FILE * __alloc_file(void); + +char __validfp (FILE *f) +{ + if ( (unsigned int)f < 256) + return FALSE; + + if( f == NULL || (int)f== -1 ) + return FALSE; + + return TRUE; +} + +/* A FILE* is considered "free" if its flag is zero. */ + +FILE *__alloc_file(void) +{ + __file_rec *fr = __file_rec_list; + __file_rec **last_fr = &__file_rec_list; + FILE *rv=0; + int i; + + /* Try to find an empty slot */ + while (fr) + { + last_fr = &(fr->next); + + /* If one of the existing slots is available, return it */ + for (i=0; icount; i++) + { + if (fr->files[i]->_flag == 0) + { + return fr->files[i]; + } + } + + /* If this one is full, go to the next */ + if (fr->count == __FILE_REC_MAX) + fr = fr->next; + else + /* it isn't full, we can add to it */ + break; + } + if (!fr) + { + /* add another one to the end, make it empty */ + fr = *last_fr = (__file_rec *)malloc(sizeof(__file_rec)); + if (fr == 0) + return 0; + fr->next = 0; + fr->count = 0; + } + /* fr is a pointer to a rec with empty slots in it */ + rv = fr->files[fr->count] = (FILE *)malloc(sizeof(FILE)); + if (rv == 0) + return 0; + memset(rv, 0, sizeof(FILE)); + fr->count ++; + return rv; +} + + +int _fcloseall( void ) +{ + __file_rec *fr = __file_rec_list; + __file_rec **last_fr = &__file_rec_list; + + int total_closed = 0; + int i = 0; + + /* Try to find an empty slot */ + while (fr) + { + last_fr = &(fr->next); + + /* If one of the existing slots is available, return it */ + for (i=0; icount; i++) + if (fr->files[i]->_flag != 0) { + fclose(fr->files[i]); + total_closed++; + } + + /* If this one is full, go to the next */ + if (fr->count == __FILE_REC_MAX) + fr = fr->next; + else + /* it isn't full, we can add to it */ + break; + } + return total_closed; +} diff --git a/reactos/lib/msvcrt/stdio/fclose.c b/reactos/lib/msvcrt/stdio/fclose.c new file mode 100644 index 00000000000..1b141c5ca5a --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fclose.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + +// changed check for writable stream + + +int +fclose(FILE *f) +{ + int r = 0; + + if (f == NULL) { + __set_errno (EINVAL); + return EOF; + } + + + +// flush only if stream was opened for writing + if ( !(f->_flag&_IOSTRG) ) { + if ( OPEN4WRITING(f) ) + r = fflush(f); + + if (_close(fileno(f)) < 0) + r = EOF; + if (f->_flag&_IOMYBUF) + free(f->_base); + +// Kernel might do this later + if (f->_flag & _IORMONCL && f->_name_to_remove) + { + remove(f->_name_to_remove); + free(f->_name_to_remove); + f->_name_to_remove = 0; + } + } + f->_cnt = 0; + f->_base = 0; + f->_ptr = 0; + f->_bufsiz = 0; + f->_flag = 0; + f->_file = -1; + return r; +} diff --git a/reactos/lib/msvcrt/stdio/feof.c b/reactos/lib/msvcrt/stdio/feof.c new file mode 100644 index 00000000000..8f6f01fec41 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/feof.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +#ifdef feof +#undef feof +int feof(FILE *stream); +#endif + +int feof(FILE *stream) +{ + if (stream == NULL) { + __set_errno (EINVAL); + return EOF; + } + + return stream->_flag & _IOEOF; +} diff --git a/reactos/lib/msvcrt/stdio/ferror.c b/reactos/lib/msvcrt/stdio/ferror.c new file mode 100644 index 00000000000..06d77c132cd --- /dev/null +++ b/reactos/lib/msvcrt/stdio/ferror.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#ifdef ferror +#undef ferror +int ferror(FILE *stream); +#endif + +int ferror(FILE *stream) +{ + return stream->_flag & _IOERR; +} diff --git a/reactos/lib/msvcrt/stdio/fflush.c b/reactos/lib/msvcrt/stdio/fflush.c new file mode 100644 index 00000000000..6d7197d1bea --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fflush.c @@ -0,0 +1,111 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/kbhit.c + * PURPOSE: Checks for keyboard hits + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + + +int fflush(FILE *f) +{ + char *base; + int n, rn; + + + + if (f == NULL) + { + int e = errno; + + __set_errno(0); + _fwalk((void (*)(FILE *))fflush); + if (_errno) + return EOF; + __set_errno(e); + return 0; + } + + +// nothing to do if stream can not be written to + + if ( !OPEN4WRITING(f) ) { + __set_errno (EINVAL); + return 0; + } + +// discard any unget characters + + f->_flag &= ~_IOUNGETC; + + +// check for buffered dirty block + + if ( (f->_flag&(_IODIRTY|_IONBF)) ==_IODIRTY && f->_base != NULL) + { + + base = f->_base; + + +// if the buffer is read ahead and dirty we will flush it entirely +// else the buffer is appended to the file to the extend it has valid bytes + + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + rn = n = f->_ptr - base + f->_cnt; + else + rn = n = f->_ptr - base; + + f->_ptr = base; + + if ((f->_flag & _IOFBF) == _IOFBF) { + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + _lseek(fileno(f),-rn, SEEK_CUR); + } + + f->_flag &= ~_IOAHEAD; + + + f->_cnt = (f->_flag&(_IOLBF|_IONBF)) ? 0 : f->_bufsiz; + +// how can write return less than rn without being on error ??? + +// possibly commit the flushed data +// better open the file in write through mode + + do { + n = _write(fileno(f), base, rn); + if (n <= 0) { + f->_flag |= _IOERR; + return EOF; + } + rn -= n; + base += n; + } while (rn > 0); + f->_flag &= ~_IODIRTY; + + } + if (OPEN4READING(f) && OPEN4WRITING(f) ) + { + f->_cnt = 0; + f->_ptr = f->_base; + } + return 0; +} + +int _flushall( void ) +{ + return fflush(NULL); +} \ No newline at end of file diff --git a/reactos/lib/msvcrt/stdio/fgets.c b/reactos/lib/msvcrt/stdio/fgets.c new file mode 100644 index 00000000000..df78963c78c --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fgets.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char * +fgets(char *s, int n, FILE *f) +{ + int c=0; + char *cs; + + cs = s; + while (--n>0 && (c = getc(f)) != EOF) + { + *cs++ = c; + if (c == '\n') + break; + } + if (c == EOF && cs == s) + return NULL; + *cs++ = '\0'; + return s; +} diff --git a/reactos/lib/msvcrt/stdio/filbuf.c b/reactos/lib/msvcrt/stdio/filbuf.c new file mode 100644 index 00000000000..2bab0044ae0 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/filbuf.c @@ -0,0 +1,130 @@ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int _readcnv(int fn, void *buf, size_t siz ); + +int +_filbuf(FILE *f) +{ + int size; + char c; + + + if ( !OPEN4READING(f)) { + __set_errno (EINVAL); + return EOF; + } + + + if (f->_flag&(_IOSTRG|_IOEOF)) + return EOF; + f->_flag &= ~_IOUNGETC; + + if (f->_base==NULL && (f->_flag&_IONBF)==0) { + size = 4096; + if ((f->_base = malloc(size+1)) == NULL) + { + // error ENOMEM + f->_flag |= _IONBF; + f->_flag &= ~(_IOFBF|_IOLBF); + } + else + { + f->_flag |= _IOMYBUF; + f->_bufsiz = size; + } + } + + + if (f->_flag&_IONBF) + f->_base = &c; + + +// fush stdout before reading from stdin + if (f == stdin) { + if (stdout->_flag&_IOLBF) + fflush(stdout); + if (stderr->_flag&_IOLBF) + fflush(stderr); + } + +// if we have a dirty stream we flush it + if ( (f->_flag &_IODIRTY) == _IODIRTY ) + fflush(f); + + + + f->_cnt = _read(fileno(f), f->_base, f->_flag & _IONBF ? 1 : f->_bufsiz ); + f->_flag |= _IOAHEAD; + + if(__is_text_file(f) && f->_cnt>0) + { + /* truncate text file at Ctrl-Z */ + char *cz=memchr(f->_base, 0x1A, f->_cnt); + if(cz) + { + int newcnt = cz - f->_base; + lseek(fileno(f), -(f->_cnt - newcnt), SEEK_CUR); + f->_cnt = newcnt; + } + } + + f->_ptr = f->_base; + + if (f->_flag & _IONBF) + f->_base = NULL; // statically allocated buffer for sprintf + + +//check for error + if (--f->_cnt < 0) { + if (f->_cnt == -1) { + f->_flag |= _IOEOF; + } else + f->_flag |= _IOERR; + f->_cnt = 0; + +// should set errno + + return EOF; + } + + return *f->_ptr++ & 0377; +} + +wint_t _filwbuf(FILE *fp) +{ + return (wint_t )_filbuf(fp); +} + +// convert the carriage return line feed pairs + +int _readcnv(int fn, void *buf, size_t siz ) +{ + char *bufp = (char *)buf; + int _bufsiz = siz; + int cr = 0; + int n; + + n = _read(fn, buf, siz ); + + while (_bufsiz > 0) { + if (*bufp == '\r') + cr++; + else if ( cr != 0 ) + *bufp = *(bufp + cr); + bufp++; + _bufsiz--; + } + return n + cr; +} + diff --git a/reactos/lib/msvcrt/stdio/flsbuf.c b/reactos/lib/msvcrt/stdio/flsbuf.c new file mode 100644 index 00000000000..574525a7c02 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/flsbuf.c @@ -0,0 +1,179 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + +int cntcr(char *bufp, int bufsiz); +int convert(char *endp, int bufsiz,int n); +int _writecnv(int fn, void *buf, size_t bufsiz); + +int +_flsbuf(int c, FILE *f) +{ + char *base; + int n, rn; + char c1; + int size; + + + + if (!OPEN4WRITING(f)) { + __set_errno (EINVAL); + return EOF; + } + +// no file associated with buffer +// this is a memory stream + + if ( fileno(f) == -1 ) + return c; + + /* if the buffer is not yet allocated, allocate it */ + if ((base = f->_base) == NULL && (f->_flag & _IONBF) == 0) + { + size = 4096; + if ((f->_base = base = malloc (size)) == NULL) + { + f->_flag |= _IONBF; + f->_flag &= ~(_IOFBF|_IOLBF); + } + else + { + f->_flag |= _IOMYBUF; + f->_cnt = f->_bufsiz = size; + f->_ptr = base; + rn = 0; + if (f == stdout && isatty (fileno (stdout))) + f->_flag |= _IOLBF; + } + } + + if (f->_flag & _IOLBF) + { + /* in line-buffering mode we get here on each character */ + *f->_ptr++ = c; + rn = f->_ptr - base; + if (c == '\n' || rn >= f->_bufsiz) + { + /* time for real flush */ + f->_ptr = base; + f->_cnt = 0; + } + else + { + /* we got here because _cnt is wrong, so fix it */ + /* Negative _cnt causes all output functions + to call _flsbuf for each character, thus realizing line-buffering */ + f->_cnt = -rn; + return c; + } + } + else if (f->_flag & _IONBF) + { + c1 = c; + rn = 1; + base = &c1; + f->_cnt = 0; + } + else /* _IOFBF */ + { + rn = f->_ptr - base; + f->_ptr = base; + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + _lseek(fileno(f),-(rn+f->_cnt), SEEK_CUR); + f->_cnt = f->_bufsiz; + f->_flag &= ~_IOAHEAD; + } + + + + f->_flag &= ~_IODIRTY; + while (rn > 0) + { + n = _write(fileno(f), base, rn); + if (n <= 0) + { + f->_flag |= _IOERR; + return EOF; + } + rn -= n; + base += n; + } + + + if ((f->_flag&(_IOLBF|_IONBF)) == 0) + { + f->_cnt--; + *f->_ptr++ = c; + } + return c; +} + +wint_t _flswbuf(wchar_t c,FILE *fp) +{ + return (wint_t )_flsbuf((int)c,fp); +} + + +int _writecnv(int fn, void *buf, size_t siz) +{ + char *bufp = (char *)buf; + int bufsiz = siz; + + char *tmp; + int cr1 = 0; + int cr2 = 0; + + int n; + + + cr1 = cntcr(bufp,bufsiz); + + tmp = malloc(cr1); + memcpy(tmp,bufp+bufsiz-cr1,cr1); + cr2 = cntcr(tmp,cr1); + + convert(bufp,bufsiz-cr2,cr1-cr2); + n = _write(fn, bufp, bufsiz + cr1); + + convert(tmp,cr1,cr2); + n += _write(fn, tmp, cr1 + cr2); + free(tmp); + return n; + + +} + +int convert(char *endp, int bufsiz,int n) +{ + endp = endp + bufsiz + n; + while (bufsiz > 0) { + *endp = *(endp - n); + if (*endp == '\n') { + *endp--; + n--; + *endp = '\r'; + } + endp--; + bufsiz--; + } + return n; +} +int cntcr(char *bufp, int bufsiz) +{ + int cr = 0; + while (bufsiz > 0) { + if (*bufp == '\n') + cr++; + bufp++; + bufsiz--; + } + + return cr; +} \ No newline at end of file diff --git a/reactos/lib/msvcrt/stdio/fopen.c b/reactos/lib/msvcrt/stdio/fopen.c new file mode 100644 index 00000000000..ee416820693 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fopen.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include + +//might change fopen(file,mode) -> fsopen(file,mode,_SH_DENYNO); + +FILE * __alloc_file(void); + + +FILE* fopen(const char *file, const char *mode) +{ + FILE *f; + int fd, rw, oflags = 0; + char tbchar; + + if (file == 0) + return 0; + if (mode == 0) + return 0; + + f = __alloc_file(); + if (f == NULL) + return NULL; + + rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); + + switch (*mode) + { + case 'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case 'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case 'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return (NULL); + } + if (mode[1] == '+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == 't') + oflags |= O_TEXT; + else if (tbchar == 'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + fd = _open(file, oflags, 0); + if (fd < 0) + return NULL; + +// ms crtdll ensures that writes will end up at the end of file in append mode +// we just move the file pointer to the end of file initially + if (*mode == 'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} diff --git a/reactos/lib/msvcrt/stdio/fprintf.c b/reactos/lib/msvcrt/stdio/fprintf.c new file mode 100644 index 00000000000..9ac7b6b0082 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fprintf.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +fprintf(register FILE *iop, const char *fmt, ...) +{ + int len; + char localbuf[BUFSIZ]; + va_list a=0; + + + va_start( a, fmt ); + if (iop->_flag & _IONBF) + { + iop->_flag &= ~_IONBF; + iop->_ptr = iop->_base = localbuf; + iop->_bufsiz = BUFSIZ; + len = vfprintf(iop,fmt,a); + fflush(iop); + iop->_flag |= _IONBF; + iop->_base = NULL; + iop->_bufsiz = 0; + iop->_cnt = 0; + } + else + len = vfprintf(iop, fmt, a); + return ferror(iop) ? EOF : len; +} + +int +fwprintf(register FILE *iop, const wchar_t *fmt, ...) +{ + int len; + wchar_t localbuf[BUFSIZ]; + va_list a=0; + + + va_start( a, fmt ); + if (iop->_flag & _IONBF) + { + iop->_flag &= ~_IONBF; + iop->_ptr = iop->_base = (char *)localbuf; + iop->_bufsiz = BUFSIZ; + len = vfwprintf(iop,fmt,a); + fflush(iop); + iop->_flag |= _IONBF; + iop->_base = NULL; + iop->_bufsiz = 0; + iop->_cnt = 0; + } + else + len = vfwprintf(iop, fmt, a); + return ferror(iop) ? EOF : len; +} diff --git a/reactos/lib/msvcrt/stdio/fputc.c b/reactos/lib/msvcrt/stdio/fputc.c new file mode 100644 index 00000000000..c63635a154b --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fputc.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +fputc(int c, FILE *fp) +{ + return putc(c, fp); +} + +wint_t +fputwc(wchar_t c, FILE *fp) +{ + return fputwc(c,fp); +} + diff --git a/reactos/lib/msvcrt/stdio/fputs.c b/reactos/lib/msvcrt/stdio/fputs.c new file mode 100644 index 00000000000..d8fbfff9eed --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fputs.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int +fputs(const char *s, FILE *f) +{ + + int r = 0; + int c; + int unbuffered; + char localbuf[BUFSIZ]; + + unbuffered = f->_flag & _IONBF; + if (unbuffered) + { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = localbuf; + f->_bufsiz = BUFSIZ; + } + + while ((c = *s++)) + r = putc(c, f); + + if (unbuffered) + { + fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } + + return(r); + +} diff --git a/reactos/lib/msvcrt/stdio/fread.c b/reactos/lib/msvcrt/stdio/fread.c new file mode 100644 index 00000000000..c9f72385c98 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fread.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + + +// carriage return line feed conversion is done in filbuf and flsbuf +#if 0 +size_t +fread(void *p, size_t size, size_t count, FILE *iop) +{ + char *ptr = (char *)p; + int to_read; + + to_read = size * count; + + + + while ( to_read > 0 ) { + *ptr = getc(iop) ; + if ( *ptr == EOF ) + break; + to_read--; + ptr++; + } + + + + return count- (to_read/size); +} + + +#else +size_t fread(void *vptr, size_t size, size_t count, FILE *iop) +{ + char *ptr = (char *)vptr; + size_t to_read ,n_read; + + to_read = size * count; + + if (!OPEN4READING(iop)) + { + __set_errno (EINVAL); + return 0; + } + + if (!__validfp (iop) ) + { + __set_errno (EINVAL); + return 0; + } + if (feof (iop) || ferror (iop)) + return 0; + + if (vptr == NULL || to_read == 0) + return 0; + + + while(iop->_cnt > 0 && to_read > 0 ) { + to_read--; + *ptr++ = getc(iop); + } + + // if the buffer is dirty it will have to be written now + // otherwise the file pointer won't match anymore. + + fflush(iop); + + // check to see if this will work with in combination with ungetc + + n_read = _read(fileno(iop), ptr, to_read); + if ( n_read != -1 ) + to_read -= n_read; + + // the file buffer is empty and there is no read ahead information anymore. + + iop->_flag &= ~_IOAHEAD; + + return count- (to_read/size); +} +#endif + diff --git a/reactos/lib/msvcrt/stdio/fwalk.c b/reactos/lib/msvcrt/stdio/fwalk.c new file mode 100644 index 00000000000..11be7eb9ad6 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fwalk.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +// not exported by crtdll +__file_rec *__file_rec_list; + +void +_fwalk(void (*func)(FILE *)) +{ + __file_rec *fr; + int i; + + for (fr=__file_rec_list; fr; fr=fr->next) + for (i=0; icount; i++) + if (fr->files[i]->_flag) + func(fr->files[i]); +} diff --git a/reactos/lib/msvcrt/stdio/fwrite.c b/reactos/lib/msvcrt/stdio/fwrite.c new file mode 100644 index 00000000000..4dcc8d7e5ce --- /dev/null +++ b/reactos/lib/msvcrt/stdio/fwrite.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +#if 0 +size_t +fwrite(const void *p, size_t size, size_t count, FILE *iop) +{ + char *ptr = (char *)p; + size_t to_write; + + + to_write = size * count; + + + + while ( to_write > 0 ) { + if ( putc(*ptr,iop) == EOF ) + break; + to_write--; + ptr++; + } + + + + return count -to_write/size; + +} + + +#else +size_t fwrite(const void *vptr, size_t size, size_t count, FILE *iop) + { + size_t to_write, n_written; + char *ptr = (char *)vptr; + + to_write = size*count; + if (!OPEN4WRITING(iop) ) + { + __set_errno (EINVAL); + return 0; + } + + + if (iop == NULL ) + { + __set_errno (EINVAL); + return 0; + } + + if (ferror (iop)) + return 0; + if (vptr == NULL || to_write == 0) + return 0; + + + while(iop->_cnt > 0 && to_write > 0 ) { + to_write--; + putc(*ptr++,iop); + } + + // if the buffer is dirty it will have to be written now + // otherwise the file pointer won't match anymore. + + fflush(iop); + + n_written = _write(fileno(iop), ptr,to_write); + if ( n_written != -1 ) + to_write -= n_written; + + // check to see if this will work with in combination with ungetc + + + // the file buffer is empty and there is no read ahead information anymore. + + iop->_flag &= ~_IOAHEAD; + + return count - (to_write/size); + +} + +#endif \ No newline at end of file diff --git a/reactos/lib/msvcrt/stdio/getc.c b/reactos/lib/msvcrt/stdio/getc.c new file mode 100644 index 00000000000..fe87af39952 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/getc.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include + +//getc can be a macro +#undef getc + +int getc(FILE *fp) +{ + int c = -1; +// check for invalid stream + + if ( !__validfp (fp) ) { + __set_errno(EINVAL); + return EOF; + } +// check for read access on stream + + if ( !OPEN4READING(fp) ) { + __set_errno(EINVAL); + return -1; + } + + if(fp->_cnt > 0) { + fp->_cnt--; + c = (int)*fp->_ptr++; + } + else { + c = _filbuf(fp); + } + return c; +} + +// not exported + +wint_t getwc(FILE *fp) +{ + + // might check on multi bytes if text mode + + if(fp->_cnt > 0) { + fp->_cnt -= sizeof(wchar_t); + return (wint_t )*((wchar_t *)(fp->_ptr))++; + } + else { + return _filwbuf(fp); + } + + // never reached + return -1; +} + + + + diff --git a/reactos/lib/msvcrt/stdio/printf.c b/reactos/lib/msvcrt/stdio/printf.c new file mode 100644 index 00000000000..2e8a45bce03 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/printf.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +/* Write formatted output to stdout from the format string FORMAT. */ +/* VARARGS1 */ +int +printf (const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vprintf (format, arg); + va_end (arg); + return done; +} + +int +wprintf (const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vwprintf (format, arg); + va_end (arg); + return done; +} + +#ifdef USE_IN_LIBIO +# undef _IO_printf +/* This is for libg++. */ +strong_alias (printf, _IO_printf); +#endif + diff --git a/reactos/lib/msvcrt/stdio/putc.c b/reactos/lib/msvcrt/stdio/putc.c new file mode 100644 index 00000000000..0764d07f98e --- /dev/null +++ b/reactos/lib/msvcrt/stdio/putc.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + +// putc can be a macro +#undef putc + +int putc(int c, FILE *fp) +{ + +// valid stream macro should check that fp +// is dword aligned + if (!__validfp (fp)) { + __set_errno(EINVAL); + return -1; + } +// check for write access on fp + + if ( !OPEN4WRITING(fp) ) { + __set_errno(EINVAL); + return -1; + } + + fp->_flag |= _IODIRTY; + if (fp->_cnt > 0 ) { + fp->_cnt--; + *(fp)->_ptr++ = (unsigned char)c; + return (int)(unsigned char)c; + } + else { + return _flsbuf((unsigned char)c,fp); + } + return EOF; +} + +wint_t putwc(wchar_t c, FILE *fp) +{ + // might check on multi bytes if text mode + + if (fp->_cnt > 0 ) { + fp->_cnt-= sizeof(wchar_t); + *((wchar_t *)(fp->_ptr))++ = c; + return (wint_t)c; + } + else + return _flswbuf(c,fp); + + return -1; + + +} diff --git a/reactos/lib/msvcrt/stdio/putchar.c b/reactos/lib/msvcrt/stdio/putchar.c new file mode 100644 index 00000000000..ce2b083bb18 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/putchar.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/getch.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include + +#undef putc +#undef putchar + +int putchar(int c) +{ + int r = putc(c, stdout); + if (stdout->_flag & _IOLBF) + fflush(stdout); + return r; +} diff --git a/reactos/lib/msvcrt/stdio/puts.c b/reactos/lib/msvcrt/stdio/puts.c new file mode 100644 index 00000000000..11d6eb65ed4 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/puts.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +#undef putchar +int +puts(const char *s) +{ + + int c; + while ((c = *s++)) + putchar(c); + return putchar('\n'); + +} diff --git a/reactos/lib/msvcrt/stdio/remove.c b/reactos/lib/msvcrt/stdio/remove.c new file mode 100644 index 00000000000..8fc77bdbda7 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/remove.c @@ -0,0 +1,9 @@ +#include + +int remove(const char *fn) +{ + if (!DeleteFileA(fn)) + return -1; + return 0; +} + diff --git a/reactos/lib/msvcrt/stdio/setvbuf.c b/reactos/lib/msvcrt/stdio/setvbuf.c new file mode 100644 index 00000000000..2f095e3d05d --- /dev/null +++ b/reactos/lib/msvcrt/stdio/setvbuf.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + + +int setvbuf(FILE *f, char *buf, int type, size_t len) +{ + int mine=0; + if (!__validfp (f) ) { + __set_errno (EINVAL); + return 0; + } + if ( f->_base != NULL ) + fflush(f); + switch (type) + { + case _IOFBF: + case _IOLBF: + if (len <= 0) { + __set_errno (EINVAL); + return EOF; + } + if (buf == 0) + { + buf = (char *)malloc(len+1); + if (buf == NULL) { + __set_errno (ENOMEM); + return -1; + } + mine = 1; + } + /* FALLTHROUGH */ + case _IONBF: + if (f->_base != NULL && f->_flag & _IOMYBUF) + free(f->_base); + f->_cnt = 0; + + f->_flag &= ~(_IONBF|_IOFBF|_IOLBF|_IOUNGETC); + f->_flag |= type; + if (type != _IONBF) + { + if (mine) + f->_flag |= _IOMYBUF; + f->_ptr = f->_base = buf; + f->_bufsiz = len; + } + else + { + f->_base = 0; + f->_bufsiz = 0; + } + return 0; + default: + __set_errno (EINVAL); + return EOF; + } +} diff --git a/reactos/lib/msvcrt/stdio/sprintf.c b/reactos/lib/msvcrt/stdio/sprintf.c new file mode 100644 index 00000000000..855bc55a2c3 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/sprintf.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include + +#undef sprintf +#undef wsprintf +int +sprintf(char *str, const char *fmt, ...) +{ + va_list arg; + int done; + + va_start (arg, fmt); + done = vsprintf (str, fmt, arg); + va_end (arg); + return done; +} + +int +swprintf(wchar_t *str, const wchar_t *fmt, ...) +{ + va_list arg; + int done; + + va_start (arg, fmt); + done = vswprintf (str, fmt, arg); + va_end (arg); + return done; +} + + + +/* Write formatted output into S, according to the format + string FORMAT, writing no more than MAXLEN characters. */ +/* VARARGS3 */ +int +_snprintf (char *s, size_t maxlen,const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = _vsnprintf (s, maxlen, format, arg); + va_end (arg); + + return done; +} + +int +_snwprintf (wchar_t *s, size_t maxlen,const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = _vsnwprintf (s, maxlen, format, arg); + va_end (arg); + + return done; +} + + diff --git a/reactos/lib/msvcrt/stdio/stdhnd.c b/reactos/lib/msvcrt/stdio/stdhnd.c new file mode 100644 index 00000000000..6e8e6ad42d8 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/stdhnd.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +//#include + + + +FILE _crtdll_iob[5] = +{ + // stdin +{ + NULL, 0, NULL, + _IOREAD | _IOLBF , + 0, 0,0, NULL +}, + // stdout +{ + NULL, 0, NULL, + _IOWRT | _IOLBF |_IOSTRG, + 1,0,0, NULL +}, + // stderr +{ + NULL, 0, NULL, + _IOWRT | _IONBF, + 2,0,0, NULL +}, + // stdaux +{ + NULL, 0, NULL, + _IOREAD | _IOWRT | _IONBF, + 3,0,0, NULL +}, + // stdprn +{ + NULL, 0, NULL, + _IOWRT | _IONBF, + 4, 0,0,NULL +} +}; + +FILE (*_iob)[] = &_crtdll_iob; + + diff --git a/reactos/lib/msvcrt/stdio/vfprintf.c b/reactos/lib/msvcrt/stdio/vfprintf.c new file mode 100644 index 00000000000..b2f7365a820 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/vfprintf.c @@ -0,0 +1,863 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int _isnanl(double x); +int _isinfl(double x); +int _isnan(double x); +int _isinf(double x); + + + +int +__vfprintf (FILE *fp, const char *fmt0, va_list argp); + +int +vfprintf(FILE *f, const char *fmt, va_list ap) +{ + int len; + char localbuf[BUFSIZ]; + + if (f->_flag & _IONBF) + { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = localbuf; + f->_bufsiz = BUFSIZ; + len = __vfprintf(f,fmt, ap); + (void)fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } + else + len = __vfprintf(f,fmt, ap); + return (ferror(f) ? EOF : len); +} + + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Appropiated for the reactos kernel, March 1998 -- David Welch + */ + +#include + +#include +#include +#include +#include +#include +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ +#define ZEROTRUNC 128 /* truncate zero 's */ + + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + + +static int do_div(long long *n,int base) +{ + int __res = ((unsigned long long) *n) % (unsigned) base; + *n = ((unsigned long long) *n) / (unsigned) base; + return __res; +} + + +static void number(FILE * f, long long num, int base, int size, int precision ,int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (sign) + putc(sign,f); + if (type & SPECIAL) { + if (base==8) { + putc('0',f); + } + else if (base==16) { + putc('0', f); + putc(digits[33],f); + } + } + if (!(type & LEFT)) + while (size-- > 0) + putc(c,f); + while (i < precision--) + putc('0', f); + while (i-- > 0) + putc(tmp[i],f); + while (size-- > 0) + putc(' ', f); + return; +} + + +static void numberf(FILE * f, double __n, char exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + double frac, intr; + double p; + char sign; + char c; + char ro = 0; + + double_t *n = (double_t *)&__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type); + putc( exp_sign,f); + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + number(f,ie, 10,2, 2,type ); + return; + } + + if ( exp_sign == 'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = '0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modf(intr, &intr); + + p *=10; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (sign) + putc( sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc('0', f); + while (i-- > 0) + putc(tmp[i],f); + while (size-- > 0) + putc(' ', f); + } +} + + +static void numberfl(FILE * f, long double __n, char exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + long double frac, intr; + long double p; + char sign; + char c; + char ro = 0; + + long_double_t *n = (long_double_t *)&__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type); + putc( exp_sign,f); + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + number(f,ie, 10,2, 2,type ); + return; + } + + if ( exp_sign == 'f' ) { + + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = '0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modfl(intr, &intr); + + p *=10; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (sign) + putc(sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc( '0', f); + while (i-- > 0) + putc(tmp[i],f); + while (size-- > 0) + putc(' ', f); + } +} + + +int __vfprintf(FILE *f, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + long double _ldouble; + double _double; + const char *s; + const short int* sw; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */ + + for (; *fmt ; ++fmt) { + if (*fmt != '%') { + putc(*fmt,f); + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + // %Z can be just stand alone or as size_t qualifier + if ( *fmt == 'Z' ) { + qualifier = *fmt; + switch ( *(fmt+1)) { + case 'o': + case 'b': + case 'X': + case 'x': + case 'd': + case 'i': + case 'u': + ++fmt; + break; + default: + break; + } + } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') { + qualifier = *fmt; + fmt += 3; + } + + // go fine with ll instead of L + if ( *fmt == 'l' ) { + ++fmt; + qualifier = 'L'; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + putc(' ', f); + if (qualifier == 'l' || qualifier == 'w') + putc((unsigned char) va_arg(args, wchar_t), f); + else + putc((unsigned char) va_arg(args, int), f); + while (--field_width > 0) + putc(' ', f); + continue; + + case 'C': + if (!(flags & LEFT)) + while (--field_width > 0) + putc(' ', f); + if (qualifier == 'h') + putc((unsigned char) va_arg(args, int), f); + else + putc((unsigned char) va_arg(args, wchar_t), f); + while (--field_width > 0) + putc(' ', f); + continue; + + case 's': + if (qualifier == 'l' || qualifier == 'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putc(' ', f); + for (i = 0; i < len; ++i) + putc((unsigned char)(*sw++), f); + while (len < field_width--) + putc(' ', f); + } else { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putc(' ', f); + for (i = 0; i < len; ++i) + putc(*s++, f); + while (len < field_width--) + putc(' ', f); + } + continue; + + case 'S': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putc(' ', f); + for (i = 0; i < len; ++i) + putc(*s++, f); + while (len < field_width--) + putc(' ', f); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putc(' ', f); + for (i = 0; i < len; ++i) + putc((unsigned char)(*sw++), f); + while (len < field_width--) + putc(' ', f); + } + continue; + +#if 0 + case 'Z': + if (qualifier == 'w') { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if (pus == NULL) { + s = ""; + while ((*s) != 0) + putc(*s++, f); + } else { + for (i = 0; pus->Buffer[i] && i < pus->Length; i++) + putc((unsigned char)(pus->Buffer[i]), f); + } + } else { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if (pus == NULL) { + s = ""; + while ((*s) != 0) + putc(*s++, f); + } else { + for (i = 0; pus->Buffer[i] && i < pus->Length; i++) + putc(pus->Buffer[i], f); + } + } + continue; +#endif + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (qualifier == 'l' || qualifier == 'L' ) { + _ldouble = va_arg(args, long double); + + if ( _isnanl(_ldouble) ) { + s = "Nan"; + len = 3; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } + else if ( _isinfl(_ldouble) < 0 ) { + s = "-Inf"; + len = 4; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } + else if ( _isinfl(_ldouble) > 0 ) { + s = "+Inf"; + len = 4; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + numberfl(f,_ldouble,*fmt,field_width,precision,flags); + } + } else { + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) { + s = "Nan"; + len = 3; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } else if ( _isinf(_double) < 0 ) { + s = "-Inf"; + len = 4; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } else if ( _isinf(_double) > 0 ) { + s = "+Inf"; + len = 4; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + numberf(f,_double,*fmt,field_width,precision,flags); + } + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + number(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = 0; + } else { + int * ip = va_arg(args, int *); + *ip = 0; + } + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'b': + base = 2; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (*fmt != '%') + putc('%', f); + if (*fmt) + putc(*fmt, f); + else + --fmt; + continue; + } + + if (qualifier == 'I') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + if (flags & SIGN) + num = va_arg(args, short); + else + num = va_arg(args, unsigned short); + } + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + number(f, num, base, field_width, precision, flags); + } + //putc('\0',f); + return 0; +} + +/* EOF */ diff --git a/reactos/lib/msvcrt/stdio/vfwprint.c b/reactos/lib/msvcrt/stdio/vfwprint.c new file mode 100644 index 00000000000..d362fb580f5 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/vfwprint.c @@ -0,0 +1,865 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int _isnanl(double x); +int _isinfl(double x); +int _isnan(double x); +int _isinf(double x); + +extern int putwc (wchar_t wc, FILE* fileWrite); + +int +__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list argp); + + +int +vfwprintf(FILE *f, const wchar_t *fmt, va_list ap) +{ + int len; + wchar_t localbuf[BUFSIZ]; + + if (f->_flag & _IONBF) { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = (char *)localbuf; + f->_bufsiz = BUFSIZ; + len = __vfwprintf(f,fmt,ap); + (void)fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } else + len = __vfwprintf(f,fmt,ap); + + return (ferror(f) ? EOF : len); + +// return 0; +} + + + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Appropiated for the reactos kernel, March 1998 -- David Welch + */ + +#include + +#include +#include +#include +#include +#include +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ +#define ZEROTRUNC 128 /* truncate zero 's */ + + +static int skip_wtoi(const wchar_t **s) +{ + int i=0; + + while (iswdigit(**s)) + i = i*10 + *((*s)++) - L'0'; + return i; +} + + +static int do_div(long long *n,int base) +{ + int __res = ((unsigned long long) *n) % (unsigned) base; + *n = ((unsigned long long) *n) / (unsigned) base; + return __res; +} + + +static void number(FILE * f, long long num, int base, int size, int precision ,int type) +{ + wchar_t c,sign,tmp[66]; + const wchar_t *digits=L"0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return; + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = L'-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]=L'0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (sign) + putwc(sign,f); + if (type & SPECIAL) { + if (base==8) { + putwc(L'0',f); + } + else if (base==16) { + putwc(L'0', f); + putwc(digits[33],f); + } + } + if (!(type & LEFT)) + while (size-- > 0) + putwc(c,f); + while (i < precision--) + putwc(L'0', f); + while (i-- > 0) + putwc(tmp[i],f); + while (size-- > 0) + putwc(L' ', f); + return; +} + + +static void numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + double frac, intr; + double p; + wchar_t sign; + wchar_t c; + char ro = 0; + + double_t *n = (double_t *)&__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + numberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type); + putwc( exp_sign,f); + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + number(f,ie, 10,2, 2,type ); + return; + } + + if ( exp_sign == 'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = L'-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = L'0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modf(intr, &intr); + + p *=10; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1 ) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (sign) + putwc( sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putwc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putwc(L'0', f); + while (i-- > 0) + putwc(tmp[i],f); + while (size-- > 0) + putwc(L' ', f); + } +} + + +static void numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + //int x; + wchar_t *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + long double frac, intr; + long double p; + wchar_t sign; + wchar_t c; + char ro = 0; + + long_double_t *n = (long_double_t *)&__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + numberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type); + putwc( exp_sign,f); + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + number(f,ie, 10,2, 2,type ); + return; + } + + if ( exp_sign == L'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = L'-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = L'.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = L'0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modfl(intr, &intr); + + p *=10; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (sign) + putwc(sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putwc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc( '0', f); + while (i-- > 0) + putwc(tmp[i],f); + while (size-- > 0) + putwc(L' ', f); + } +} + + +int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + long double _ldouble; + double _double; + const char *s; + const wchar_t* sw; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */ + + for (; *fmt ; ++fmt) { + if (*fmt != L'%') { + putwc(*fmt,f); + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case L'-': flags |= LEFT; goto repeat; + case L'+': flags |= PLUS; goto repeat; + case L' ': flags |= SPACE; goto repeat; + case L'#': flags |= SPECIAL; goto repeat; + case L'0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isxdigit(*fmt)) + field_width = skip_wtoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == L'.') { + ++fmt; + if (iswdigit(*fmt)) + precision = skip_wtoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + // %Z can be just stand alone or as size_t qualifier + if ( *fmt == 'Z' ) { + qualifier = *fmt; + switch ( *(fmt+1)) { + case L'o': + case L'b': + case L'X': + case L'x': + case L'd': + case L'i': + case L'u': + ++fmt; + break; + default: + break; + } + } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') { + qualifier = *fmt; + fmt += 3; + } + + // go fine with ll instead of L + if ( *fmt == L'l' ) { + ++fmt; + qualifier = L'L'; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case L'c': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) + putwc(L' ', f); + if (qualifier == L'h') + putwc((wchar_t) va_arg(args, int), f); + else + putwc((wchar_t) va_arg(args, wchar_t), f); + while (--field_width > 0) + putwc(L' ', f); + continue; + + case L'C': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) + putwc(L' ', f); + if (qualifier == L'l' || qualifier == L'w') + putwc((unsigned char) va_arg(args, wchar_t), f); + else + putwc((unsigned char) va_arg(args, int), f); + while (--field_width > 0) + putwc(L' ', f); + continue; + + case L's': /* finished */ + if (qualifier == L'h') { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putwc(L' ', f); + for (i = 0; i < len; ++i) + putwc((wchar_t)(*s++), f); + while (len < field_width--) + putwc(L' ', f); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putwc(L' ', f); + for (i = 0; i < len; ++i) + putwc(*sw++, f); + while (len < field_width--) + putwc(L' ', f); + } + continue; + + case L'S': + if (qualifier == L'l' || qualifier == L'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putwc(L' ', f); + for (i = 0; i < len; ++i) + putwc(*sw++, f); + while (len < field_width--) + putwc(L' ', f); + } else { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putwc(L' ', f); + for (i = 0; i < len; ++i) + putwc((wchar_t)(*s++), f); + while (len < field_width--) + putwc(L' ', f); + } + continue; + +#if 0 + case L'Z': /* finished */ + if (qualifier == L'w') { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if (pus == NULL) { + sw = L""; + while ((*sw) != 0) + putwc(*sw++, f); + } else { + for (i = 0; pus->Buffer[i] && i < pus->Length; i++) + putwc(pus->Buffer[i], f); + } + } else { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if (pus == NULL) { + sw = L""; + while ((*sw) != 0) + putwc(*sw++, f); + } else { + for (i = 0; pus->Buffer[i] && i < pus->Length; i++) + putwc((wchar_t)pus->Buffer[i], f); + } + } + continue; +#endif + + case L'e': /* finished */ + case L'E': + case L'f': + case L'g': + case L'G': + if (qualifier == L'l' || qualifier == L'L' ) { + _ldouble = va_arg(args, long double); + + if ( _isnanl(_ldouble) ) { + sw = L"Nan"; + len = 3; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } + else if ( _isinfl(_ldouble) < 0 ) { + sw = L"-Inf"; + len = 4; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } + else if ( _isinfl(_ldouble) > 0 ) { + sw = L"+Inf"; + len = 4; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + numberfl(f,_ldouble,*fmt,field_width,precision,flags); + } + } else { + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) { + sw = L"Nan"; + len = 3; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } else if ( _isinf(_double) < 0 ) { + sw = L"-Inf"; + len = 4; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } else if ( _isinf(_double) > 0 ) { + sw = L"+Inf"; + len = 4; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + numberf(f,_double,*fmt,field_width,precision,flags); + } + } + continue; + + case L'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + number(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case L'n': + if (qualifier == L'l') { + long * ip = va_arg(args, long *); + *ip = 0; + } else { + int * ip = va_arg(args, int *); + *ip = 0; + } + continue; + + /* integer number formats - set up the flags and "break" */ + case L'o': + base = 8; + break; + + case L'b': + base = 2; + break; + + case L'X': + flags |= LARGE; + case L'x': + base = 16; + break; + + case L'd': + case L'i': + flags |= SIGN; + case L'u': + break; + + default: + if (*fmt != L'%') + putwc(L'%', f); + if (*fmt) + putwc(*fmt, f); + else + --fmt; + continue; + } + + if (qualifier == L'I') + num = va_arg(args, unsigned long long); + else if (qualifier == L'l') + num = va_arg(args, unsigned long); + else if (qualifier == L'h') { + if (flags & SIGN) + num = va_arg(args, short); + else + num = va_arg(args, unsigned short); + } + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + number(f, num, base, field_width, precision, flags); + } + //putwc(L'\0',f); + return 0; +} + +/* EOF */ diff --git a/reactos/lib/msvcrt/stdio/vprintf.c b/reactos/lib/msvcrt/stdio/vprintf.c new file mode 100644 index 00000000000..780d960809a --- /dev/null +++ b/reactos/lib/msvcrt/stdio/vprintf.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#undef __OPTIMIZE__ /* Avoid inline `vprintf' function. */ +#include +#include + +#undef vprintf +#undef vwprintf + +/* Write formatted output to stdout according to the + format string FORMAT, using the argument list in ARG. */ +int +vprintf (format, arg) + const char *format; + va_list arg; +{ + int ret = vfprintf (stdout, format, arg); + fflush(stdout); + return ret; +} + +int +vwprintf (format, arg) + const wchar_t *format; + va_list arg; +{ + int ret = vfwprintf (stdout, format, arg); + fflush(stdout); + return ret; +} diff --git a/reactos/lib/msvcrt/stdio/vsprintf.c b/reactos/lib/msvcrt/stdio/vsprintf.c new file mode 100644 index 00000000000..362c29f8f12 --- /dev/null +++ b/reactos/lib/msvcrt/stdio/vsprintf.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int +vsprintf(char *str, const char *fmt, va_list ap) +{ + FILE f; + int len; + + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = INT_MAX; + f._file = -1; + len = vfprintf(&f,fmt, ap); + *f._ptr = 0; + return len; +} + +int +vswprintf(wchar_t *str, const wchar_t *fmt, va_list ap) +{ + FILE f; + int len; + + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = INT_MAX; + f._file = -1; + len = vfwprintf(&f,fmt, ap); + *f._ptr = 0; + return len; +} + + +int +_vsnprintf(char *str, size_t maxlen, const char *fmt, va_list ap) +{ + FILE f; + int len; + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = maxlen; + f._file = -1; + len = vfprintf(&f,fmt, ap); + // what if the buffer is full ?? + *f._ptr = 0; + return len; +} + +int +_vsnwprintf(wchar_t *str, size_t maxlen, const wchar_t *fmt, va_list ap) +{ + FILE f; + int len; + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = maxlen; + f._file = -1; + len = vfwprintf(&f,fmt, ap); + // what if the buffer is full ?? + *f._ptr = 0; + return len; +} + + diff --git a/reactos/lib/msvcrt/stdlib/abort.c b/reactos/lib/msvcrt/stdlib/abort.c index b76a2275e99..3c33587b678 100644 --- a/reactos/lib/msvcrt/stdlib/abort.c +++ b/reactos/lib/msvcrt/stdlib/abort.c @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include +#include +#include +#include char *msg ="Abort\n\r"; diff --git a/reactos/lib/msvcrt/stdlib/atexit.c b/reactos/lib/msvcrt/stdlib/atexit.c index fd80fde5f53..462fa07fdb5 100644 --- a/reactos/lib/msvcrt/stdlib/atexit.c +++ b/reactos/lib/msvcrt/stdlib/atexit.c @@ -1,6 +1,6 @@ /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include +#include +#include int atexit(void (*a)(void)) diff --git a/reactos/lib/msvcrt/sys_stat/fstat.c b/reactos/lib/msvcrt/sys_stat/fstat.c new file mode 100644 index 00000000000..458e31bb260 --- /dev/null +++ b/reactos/lib/msvcrt/sys_stat/fstat.c @@ -0,0 +1,42 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/sys/fstat.c + * PURPOSE: Gather file information + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include +#include +#include +#include + + +int +_fstat(int fd, struct stat *statbuf) +{ + + BY_HANDLE_FILE_INFORMATION FileInformation; + + if (!statbuf) + { + __set_errno(EINVAL); + return -1; + } + + if ( !GetFileInformationByHandle(_get_osfhandle(fd),&FileInformation) ) { + __set_errno (EBADF); + return -1; + } + statbuf->st_ctime = FileTimeToUnixTime( &FileInformation.ftCreationTime,NULL); + statbuf->st_atime = FileTimeToUnixTime( &FileInformation.ftLastAccessTime,NULL); + statbuf->st_mtime = FileTimeToUnixTime( &FileInformation.ftLastWriteTime,NULL); + + statbuf->st_dev = fd; + statbuf->st_size = FileInformation.nFileSizeLow; + return 0; +} diff --git a/reactos/lib/msvcrt/time/ctime.c b/reactos/lib/msvcrt/time/ctime.c new file mode 100644 index 00000000000..9f33c97ebe1 --- /dev/null +++ b/reactos/lib/msvcrt/time/ctime.c @@ -0,0 +1,1413 @@ + +// fix djdir + +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* This file has been modified by DJ Delorie. These modifications are +** Copyright (C) 1995 DJ Delorie, 24 Kirsten Ave, Rochester NH, +** 03867-2954, USA. +*/ + +/* + * Copyright (c) 1987, 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)ctime.c 5.23 (Berkeley) 6/22/90"; +#endif /* LIBC_SCCS and not lint */ + +/* +** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu). +** POSIX-style TZ environment variable handling from Guy Harris +** (guy@auspex.com). +*/ + + + + +#include +#include +#include +#include +#include +#include + +#include +#include "tzfile.h" + +#include + +#include "posixrul.h" + +#define P(s) s +#define alloc_size_t size_t +#define qsort_size_t size_t +#define fread_size_t size_t +#define fwrite_size_t size_t + +#define ACCESS_MODE O_RDONLY|O_BINARY +#define OPEN_MODE O_RDONLY|O_BINARY + +/* +** Someone might make incorrect use of a time zone abbreviation: +** 1. They might reference tzname[0] before calling tzset (explicitly +** or implicitly). +** 2. They might reference tzname[1] before calling tzset (explicitly +** or implicitly). +** 3. They might reference tzname[1] after setting to a time zone +** in which Daylight Saving Time is never observed. +** 4. They might reference tzname[0] after setting to a time zone +** in which Standard Time is never observed. +** 5. They might reference tm.TM_ZONE after calling offtime. +** What's best to do in the above cases is open to debate; +** for now, we just set things up so that in any of the five cases +** WILDABBR is used. Another possibility: initialize tzname[0] to the +** string "tzname[0] used before set", and similarly for the other cases. +** And another: initialize tzname[0] to "ERA", with an explanation in the +** manual page of what this "time zone abbreviation" means (doing this so +** that tzname[0] has the "normal" length of three characters). +*/ +int _daylight_dll; +int _timezone_dll; + +static char WILDABBR[] = " "; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif /* !defined TRUE */ + +static const char GMT[] = "GMT"; + +struct ttinfo { /* time type information */ + long tt_gmtoff; /* GMT offset in seconds */ + int tt_isdst; /* used to set tm_isdst */ + int tt_abbrind; /* abbreviation list index */ + int tt_ttisstd; /* TRUE if transition is std time */ +}; + +struct lsinfo { /* leap second information */ + time_t ls_trans; /* transition time */ + long ls_corr; /* correction to apply */ +}; + +struct state { + int leapcnt; + int timecnt; + int typecnt; + int charcnt; + time_t ats[TZ_MAX_TIMES]; + unsigned char types[TZ_MAX_TIMES]; + struct ttinfo ttis[TZ_MAX_TYPES]; + char chars[(TZ_MAX_CHARS + 1 > sizeof GMT) ? TZ_MAX_CHARS + 1 : sizeof GMT]; + struct lsinfo lsis[TZ_MAX_LEAPS]; +}; + +struct rule { + int r_type; /* type of rule--see below */ + int r_day; /* day number of rule */ + int r_week; /* week number of rule */ + int r_mon; /* month number of rule */ + long r_time; /* transition time of rule */ +}; + +#define JULIAN_DAY 0 /* Jn - Julian day */ +#define DAY_OF_YEAR 1 /* n - day of year */ +#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ + +/* +** Prototypes for static functions. +*/ + +static long detzcode P((const char * codep)); +static const char * getzname P((const char * strp)); +static const char * getnum P((const char * strp, int * nump, int min, + int max)); +static const char * getsecs P((const char * strp, long * secsp)); +static const char * getoffset P((const char * strp, long * offsetp)); +static const char * getrule P((const char * strp, struct rule * rulep)); +static void gmtload P((struct state * sp)); +static void gmtsub P((const time_t * timep, long offset, + struct tm * tmp)); +static void localsub P((const time_t * timep, long offset, + struct tm * tmp)); +static void normalize P((int * tensptr, int * unitsptr, int base)); +static void settzname P((void)); +static time_t time1 P((struct tm * tmp, void (* funcp)(const time_t * const, const long, struct tm * const), + long offset)); +static time_t time2 P((struct tm *tmp, void (* funcp)(const time_t * const, const long, struct tm * const), + long offset, int * okayp)); +static void timesub P((const time_t * timep, long offset, + const struct state * sp, struct tm * tmp)); +static int tmcomp P((const struct tm * atmp, + const struct tm * btmp)); +static time_t transtime P((time_t janfirst, int year, + const struct rule * rulep, long offset)); +static int tzload P((const char * name, struct state * sp)); +static int tzparse P((const char * name, struct state * sp, + int lastditch)); +static void tzsetwall(void); + +#ifdef ALL_STATE +static struct state *lclptr; +static struct state *gmtptr; +#endif /* defined ALL_STATE */ + +#ifndef ALL_STATE +static struct state lclmem; +static struct state gmtmem; +#define lclptr (&lclmem) +#define gmtptr (&gmtmem) +#endif /* State Farm */ + +static int lcl_is_set; +static int gmt_is_set; + +char * _tzname[2] = { + WILDABBR, + WILDABBR +}; + +static long +detzcode(const char * const codep) +{ + long result; + int i; + + result = 0; + for (i = 0; i < 4; ++i) + result = (result << 8) | (codep[i] & 0xff); + return result; +} + +static void +settzname(void) +{ + const struct state * const sp = lclptr; + int i; + + _tzname[0] = WILDABBR; + _tzname[1] = WILDABBR; +#ifdef ALL_STATE + if (sp == NULL) + { + _tzname[0] = _tzname[1] = GMT; + return; + } +#endif /* defined ALL_STATE */ + for (i = 0; i < sp->typecnt; ++i) + { + register const struct ttinfo * const ttisp = &sp->ttis[i]; + + _tzname[ttisp->tt_isdst] = + (char *)&sp->chars[ttisp->tt_abbrind]; +#if 0 + if (ttisp->tt_isdst) + _daylight = 1; + if (i == 0 || !ttisp->tt_isdst) + _timezone_dll = -(ttisp->tt_gmtoff); + if (i == 0 || ttisp->tt_isdst) + _altzone = -(ttisp->tt_gmtoff); +#endif + } + /* + ** And to get the latest zone names into tzname. . . + */ + for (i = 0; i < sp->timecnt; ++i) + { + const struct ttinfo * const ttisp = &sp->ttis[sp->types[i]]; + + _tzname[ttisp->tt_isdst] = (char *)&sp->chars[ttisp->tt_abbrind]; + } +} + +static char * +tzdir(void) +{ + static char dir[80]={0}, *cp; + if (dir[0] == 0) + { + if ((cp = getenv("TZDIR"))) + { + strcpy(dir, cp); + } + else if ((cp = getenv("DJDIR"))) + { + strcpy(dir, cp); + strcat(dir, "/zoneinfo"); + } + else + strcpy(dir, "./"); + } + return dir; +} + +static int +tzload(const char *name, struct state * const sp) +{ + const char * p; + int i; + int fid; + char fullname[FILENAME_MAX + 1]; + const struct tzhead * tzhp; + char buf[sizeof *sp + sizeof *tzhp]; + int ttisstdcnt; + + if (name == NULL && (name = TZDEFAULT) == NULL) + return -1; + + if (name[0] == ':') + ++name; + if (name[0] != '/') + { + if ((p = tzdir()) == NULL) + return -1; + if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) + return -1; + strcpy(fullname, p); + strcat(fullname, "/"); + strcat(fullname, name); + name = fullname; + } + + if ((fid = open(name, OPEN_MODE)) == -1) + { + const char *base = strrchr(name, '/'); + if (base) + base++; + else + base = name; + if (strcmp(base, "posixrules")) + return -1; + + /* We've got a built-in copy of posixrules just in case */ + memcpy(buf, _posixrules_data, sizeof(_posixrules_data)); + i = sizeof(_posixrules_data); + } + else + { + i = read(fid, buf, sizeof buf); + if (close(fid) != 0 || i < sizeof *tzhp) + return -1; + } + + tzhp = (struct tzhead *) buf; + ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt); + sp->leapcnt = (int) detzcode(tzhp->tzh_leapcnt); + sp->timecnt = (int) detzcode(tzhp->tzh_timecnt); + sp->typecnt = (int) detzcode(tzhp->tzh_typecnt); + sp->charcnt = (int) detzcode(tzhp->tzh_charcnt); + if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || + sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || + sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || + sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || + (ttisstdcnt != sp->typecnt && ttisstdcnt != 0)) + return -1; + if (i < sizeof *tzhp + + sp->timecnt * (4 + sizeof (char)) + + sp->typecnt * (4 + 2 * sizeof (char)) + + sp->charcnt * sizeof (char) + + sp->leapcnt * 2 * 4 + + ttisstdcnt * sizeof (char)) + return -1; + p = buf + sizeof *tzhp; + for (i = 0; i < sp->timecnt; ++i) + { + sp->ats[i] = detzcode(p); + p += 4; + } + for (i = 0; i < sp->timecnt; ++i) + { + sp->types[i] = (unsigned char) *p++; + if (sp->types[i] >= sp->typecnt) + return -1; + } + for (i = 0; i < sp->typecnt; ++i) + { + struct ttinfo * ttisp; + + ttisp = &sp->ttis[i]; + ttisp->tt_gmtoff = detzcode(p); + p += 4; + ttisp->tt_isdst = (unsigned char) *p++; + if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) + return -1; + ttisp->tt_abbrind = (unsigned char) *p++; + if (ttisp->tt_abbrind < 0 || + ttisp->tt_abbrind > sp->charcnt) + return -1; + } + for (i = 0; i < sp->charcnt; ++i) + sp->chars[i] = *p++; + sp->chars[i] = '\0'; /* ensure '\0' at end */ + for (i = 0; i < sp->leapcnt; ++i) + { + struct lsinfo * lsisp; + + lsisp = &sp->lsis[i]; + lsisp->ls_trans = detzcode(p); + p += 4; + lsisp->ls_corr = detzcode(p); + p += 4; + } + for (i = 0; i < sp->typecnt; ++i) + { + struct ttinfo * ttisp; + + ttisp = &sp->ttis[i]; + if (ttisstdcnt == 0) + ttisp->tt_ttisstd = FALSE; + else + { + ttisp->tt_ttisstd = *p++; + if (ttisp->tt_ttisstd != TRUE && + ttisp->tt_ttisstd != FALSE) + return -1; + } + } + return 0; +} + +static const int mon_lengths[2][MONSPERYEAR] = { +{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, +{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static const int year_lengths[2] = { +DAYSPERNYEAR, DAYSPERLYEAR +}; + +/* +** Given a pointer into a time zone string, scan until a character that is not +** a valid character in a zone name is found. Return a pointer to that +** character. +*/ + +static const char * +getzname(const char *strp) +{ + char c; + + while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' && + c != '+') + ++strp; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a number from that string. +** Check that the number is within a specified range; if it is not, return +** NULL. +** Otherwise, return a pointer to the first character not part of the number. +*/ + +static const char * +getnum(const char *strp, int * const nump, const int min, const int max) +{ + char c; + int num; + + if (strp == NULL || !isdigit(*strp)) + return NULL; + num = 0; + while ((c = *strp) != '\0' && isdigit(c)) + { + num = num * 10 + (c - '0'); + if (num > max) + return NULL; + ++strp; + } + if (num < min) + return NULL; + *nump = num; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a number of seconds, +** in hh[:mm[:ss]] form, from the string. +** If any error occurs, return NULL. +** Otherwise, return a pointer to the first character not part of the number +** of seconds. +*/ + +static const char * +getsecs(const char *strp, long * const secsp) +{ + int num; + + strp = getnum(strp, &num, 0, HOURSPERDAY); + if (strp == NULL) + return NULL; + *secsp = num * SECSPERHOUR; + if (*strp == ':') + { + ++strp; + strp = getnum(strp, &num, 0, MINSPERHOUR - 1); + if (strp == NULL) + return NULL; + *secsp += num * SECSPERMIN; + if (*strp == ':') + { + ++strp; + strp = getnum(strp, &num, 0, SECSPERMIN - 1); + if (strp == NULL) + return NULL; + *secsp += num; + } + } + return strp; +} + +/* +** Given a pointer into a time zone string, extract an offset, in +** [+-]hh[:mm[:ss]] form, from the string. +** If any error occurs, return NULL. +** Otherwise, return a pointer to the first character not part of the time. +*/ + +static const char * +getoffset(const char *strp, long * const offsetp) +{ + int neg; + + if (*strp == '-') + { + neg = 1; + ++strp; + } + else if (isdigit(*strp) || *strp++ == '+') + neg = 0; + else + return NULL; /* illegal offset */ + strp = getsecs(strp, offsetp); + if (strp == NULL) + return NULL; /* illegal time */ + if (neg) + *offsetp = -*offsetp; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a rule in the form +** date[/time]. See POSIX section 8 for the format of "date" and "time". +** If a valid rule is not found, return NULL. +** Otherwise, return a pointer to the first character not part of the rule. +*/ + +static const char * +getrule(const char *strp, struct rule * const rulep) +{ + if (*strp == 'J') + { + /* + ** Julian day. + */ + rulep->r_type = JULIAN_DAY; + ++strp; + strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); + } + else if (*strp == 'M') + { + /* + ** Month, week, day. + */ + rulep->r_type = MONTH_NTH_DAY_OF_WEEK; + ++strp; + strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); + if (strp == NULL) + return NULL; + if (*strp++ != '.') + return NULL; + strp = getnum(strp, &rulep->r_week, 1, 5); + if (strp == NULL) + return NULL; + if (*strp++ != '.') + return NULL; + strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); + } + else if (isdigit(*strp)) + { + /* + ** Day of year. + */ + rulep->r_type = DAY_OF_YEAR; + strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); + } + else + return NULL; /* invalid format */ + if (strp == NULL) + return NULL; + if (*strp == '/') + { + /* + ** Time specified. + */ + ++strp; + strp = getsecs(strp, &rulep->r_time); + } + else + rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ + return strp; +} + +/* +** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the +** year, a rule, and the offset from GMT at the time that rule takes effect, +** calculate the Epoch-relative time that rule takes effect. +*/ + +static time_t +transtime(const time_t janfirst, const int year, const struct rule * const rulep, const long offset) +{ + int leapyear; + time_t value=0; + int i; + int d, m1, yy0, yy1, yy2, dow; + + leapyear = isleap(year); + switch (rulep->r_type) + { + + case JULIAN_DAY: + /* + ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap + ** years. + ** In non-leap years, or if the day number is 59 or less, just + ** add SECSPERDAY times the day number-1 to the time of + ** January 1, midnight, to get the day. + */ + value = janfirst + (rulep->r_day - 1) * SECSPERDAY; + if (leapyear && rulep->r_day >= 60) + value += SECSPERDAY; + break; + + case DAY_OF_YEAR: + /* + ** n - day of year. + ** Just add SECSPERDAY times the day number to the time of + ** January 1, midnight, to get the day. + */ + value = janfirst + rulep->r_day * SECSPERDAY; + break; + + case MONTH_NTH_DAY_OF_WEEK: + /* + ** Mm.n.d - nth "dth day" of month m. + */ + value = janfirst; + for (i = 0; i < rulep->r_mon - 1; ++i) + value += mon_lengths[leapyear][i] * SECSPERDAY; + + /* + ** Use Zeller's Congruence to get day-of-week of first day of + ** month. + */ + m1 = (rulep->r_mon + 9) % 12 + 1; + yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; + yy1 = yy0 / 100; + yy2 = yy0 % 100; + dow = ((26 * m1 - 2) / 10 + + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; + if (dow < 0) + dow += DAYSPERWEEK; + + /* + ** "dow" is the day-of-week of the first day of the month. Get + ** the day-of-month (zero-origin) of the first "dow" day of the + ** month. + */ + d = rulep->r_day - dow; + if (d < 0) + d += DAYSPERWEEK; + for (i = 1; i < rulep->r_week; ++i) + { + if (d + DAYSPERWEEK >= + mon_lengths[leapyear][rulep->r_mon - 1]) + break; + d += DAYSPERWEEK; + } + + /* + ** "d" is the day-of-month (zero-origin) of the day we want. + */ + value += d * SECSPERDAY; + break; + } + + /* + ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in + ** question. To get the Epoch-relative time of the specified local + ** time on that day, add the transition time and the current offset + ** from GMT. + */ + return value + rulep->r_time + offset; +} + +/* +** Given a POSIX section 8-style TZ string, fill in the rule tables as +** appropriate. +*/ + +static int +tzparse(const char *name, struct state * const sp, const int lastditch) +{ + const char * stdname; + const char * dstname=0; + int stdlen; + int dstlen; + long stdoffset; + long dstoffset; + time_t * atp; + unsigned char * typep; + char * cp; + int load_result; + + stdname = name; + if (lastditch) + { + stdlen = strlen(name); /* length of standard zone name */ + name += stdlen; + if (stdlen >= sizeof sp->chars) + stdlen = (sizeof sp->chars) - 1; + } + else + { + name = getzname(name); + stdlen = name - stdname; + if (stdlen < 3) + return -1; + } + if (*name == '\0') + return -1; + else + { + name = getoffset(name, &stdoffset); + if (name == NULL) + return -1; + } + load_result = tzload(TZDEFRULES, sp); + if (load_result != 0) + sp->leapcnt = 0; /* so, we're off a little */ + if (*name != '\0') + { + dstname = name; + name = getzname(name); + dstlen = name - dstname; /* length of DST zone name */ + if (dstlen < 3) + return -1; + if (*name != '\0' && *name != ',' && *name != ';') + { + name = getoffset(name, &dstoffset); + if (name == NULL) + return -1; + } + else + dstoffset = stdoffset - SECSPERHOUR; + if (*name == ',' || *name == ';') + { + struct rule start; + struct rule end; + int year; + time_t janfirst; + time_t starttime; + time_t endtime; + + ++name; + if ((name = getrule(name, &start)) == NULL) + return -1; + if (*name++ != ',') + return -1; + if ((name = getrule(name, &end)) == NULL) + return -1; + if (*name != '\0') + return -1; + sp->typecnt = 2; /* standard time and DST */ + /* + ** Two transitions per year, from EPOCH_YEAR to 2037. + */ + sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); + if (sp->timecnt > TZ_MAX_TIMES) + return -1; + sp->ttis[0].tt_gmtoff = -dstoffset; + sp->ttis[0].tt_isdst = 1; + sp->ttis[0].tt_abbrind = stdlen + 1; + sp->ttis[1].tt_gmtoff = -stdoffset; + sp->ttis[1].tt_isdst = 0; + sp->ttis[1].tt_abbrind = 0; + atp = sp->ats; + typep = sp->types; + janfirst = 0; + for (year = EPOCH_YEAR; year <= 2037; ++year) + { + starttime = transtime(janfirst, year, &start, + stdoffset); + endtime = transtime(janfirst, year, &end, + dstoffset); + if (starttime > endtime) + { + *atp++ = endtime; + *typep++ = 1; /* DST ends */ + *atp++ = starttime; + *typep++ = 0; /* DST begins */ + } + else + { + *atp++ = starttime; + *typep++ = 0; /* DST begins */ + *atp++ = endtime; + *typep++ = 1; /* DST ends */ + } + janfirst += + year_lengths[isleap(year)] * SECSPERDAY; + } + } + else + { + int sawstd; + int sawdst; + long stdfix; + long dstfix; + long oldfix; + int isdst; + int i; + + if (*name != '\0') + return -1; + if (load_result != 0) + return -1; + /* + ** Compute the difference between the real and + ** prototype standard and summer time offsets + ** from GMT, and put the real standard and summer + ** time offsets into the rules in place of the + ** prototype offsets. + */ + sawstd = FALSE; + sawdst = FALSE; + stdfix = 0; + dstfix = 0; + for (i = 0; i < sp->typecnt; ++i) + { + if (sp->ttis[i].tt_isdst) + { + oldfix = dstfix; + dstfix = + sp->ttis[i].tt_gmtoff + dstoffset; + if (sawdst && (oldfix != dstfix)) + return -1; + sp->ttis[i].tt_gmtoff = -dstoffset; + sp->ttis[i].tt_abbrind = stdlen + 1; + sawdst = TRUE; + } + else + { + oldfix = stdfix; + stdfix = + sp->ttis[i].tt_gmtoff + stdoffset; + if (sawstd && (oldfix != stdfix)) + return -1; + sp->ttis[i].tt_gmtoff = -stdoffset; + sp->ttis[i].tt_abbrind = 0; + sawstd = TRUE; + } + } + /* + ** Make sure we have both standard and summer time. + */ + if (!sawdst || !sawstd) + return -1; + /* + ** Now correct the transition times by shifting + ** them by the difference between the real and + ** prototype offsets. Note that this difference + ** can be different in standard and summer time; + ** the prototype probably has a 1-hour difference + ** between standard and summer time, but a different + ** difference can be specified in TZ. + */ + isdst = FALSE; /* we start in standard time */ + for (i = 0; i < sp->timecnt; ++i) + { + const struct ttinfo * ttisp; + + /* + ** If summer time is in effect, and the + ** transition time was not specified as + ** standard time, add the summer time + ** offset to the transition time; + ** otherwise, add the standard time offset + ** to the transition time. + */ + ttisp = &sp->ttis[sp->types[i]]; + sp->ats[i] += + (isdst && !ttisp->tt_ttisstd) ? + dstfix : stdfix; + isdst = ttisp->tt_isdst; + } + } + } + else + { + dstlen = 0; + sp->typecnt = 1; /* only standard time */ + sp->timecnt = 0; + sp->ttis[0].tt_gmtoff = -stdoffset; + sp->ttis[0].tt_isdst = 0; + sp->ttis[0].tt_abbrind = 0; + } + sp->charcnt = stdlen + 1; + if (dstlen != 0) + sp->charcnt += dstlen + 1; + if (sp->charcnt > sizeof sp->chars) + return -1; + cp = sp->chars; + (void) strncpy(cp, stdname, stdlen); + cp += stdlen; + *cp++ = '\0'; + if (dstlen != 0) + { + (void) strncpy(cp, dstname, dstlen); + *(cp + dstlen) = '\0'; + } + return 0; +} + +static void +gmtload(struct state * const sp) +{ + if (tzload(GMT, sp) != 0) + (void) tzparse(GMT, sp, TRUE); +} + +void +_tzset(void) +{ + const char * name; + + name = getenv("TZ"); + if (name == NULL) + { + tzsetwall(); + return; + } + lcl_is_set = TRUE; +#ifdef ALL_STATE + if (lclptr == NULL) + { + lclptr = (struct state *) malloc(sizeof *lclptr); + if (lclptr == NULL) + { + settzname(); /* all we can do */ + return; + } + } +#endif /* defined ALL_STATE */ + if (*name == '\0') + { + /* + ** User wants it fast rather than right. + */ + lclptr->leapcnt = 0; /* so, we're off a little */ + lclptr->timecnt = 0; + lclptr->ttis[0].tt_gmtoff = 0; + lclptr->ttis[0].tt_abbrind = 0; + (void) strcpy(lclptr->chars, GMT); + } + else if (tzload(name, lclptr) != 0) + if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) + gmtload(lclptr); + settzname(); +} + +void +tzsetwall(void) +{ + lcl_is_set = TRUE; +#ifdef ALL_STATE + if (lclptr == NULL) + { + lclptr = (struct state *) malloc(sizeof *lclptr); + if (lclptr == NULL) + { + settzname(); /* all we can do */ + return; + } + } +#endif /* defined ALL_STATE */ + if (tzload((char *) NULL, lclptr) != 0) + gmtload(lclptr); + settzname(); +} + +/* +** The easy way to behave "as if no library function calls" localtime +** is to not call it--so we drop its guts into "localsub", which can be +** freely called. (And no, the PANS doesn't require the above behavior-- +** but it *is* desirable.) +** +** The unused offset argument is for the benefit of mktime variants. +*/ + +/*ARGSUSED*/ +static void +localsub(const time_t * const timep, const long offset, struct tm * const tmp) +{ + const struct state * sp; + const struct ttinfo * ttisp; + int i; + const time_t t = *timep; + + if (!lcl_is_set) + _tzset(); + sp = lclptr; +#ifdef ALL_STATE + if (sp == NULL) + { + gmtsub(timep, offset, tmp); + return; + } +#endif /* defined ALL_STATE */ + if (sp->timecnt == 0 || t < sp->ats[0]) + { + i = 0; + while (sp->ttis[i].tt_isdst) + if (++i >= sp->typecnt) + { + i = 0; + break; + } + } + else + { + for (i = 1; i < sp->timecnt; ++i) + if (t < sp->ats[i]) + break; + i = sp->types[i - 1]; + } + ttisp = &sp->ttis[i]; + /* + ** To get (wrong) behavior that's compatible with System V Release 2.0 + ** you'd replace the statement below with + ** t += ttisp->tt_gmtoff; + ** timesub(&t, 0L, sp, tmp); + */ + timesub(&t, ttisp->tt_gmtoff, sp, tmp); + tmp->tm_isdst = ttisp->tt_isdst; + _tzname[tmp->tm_isdst] = (char *)&sp->chars[ttisp->tt_abbrind]; + tmp->tm_zone = (char *)&sp->chars[ttisp->tt_abbrind]; +} + +struct tm * +localtime(const time_t * const timep) +{ + static struct tm tm; + + localsub(timep, 0L, &tm); + return &tm; +} + +/* +** gmtsub is to gmtime as localsub is to localtime. +*/ + +static void +gmtsub(const time_t * const timep, const long offset, struct tm * const tmp) +{ + if (!gmt_is_set) + { + gmt_is_set = TRUE; +#ifdef ALL_STATE + gmtptr = (struct state *) malloc(sizeof *gmtptr); + if (gmtptr != NULL) +#endif /* defined ALL_STATE */ + gmtload(gmtptr); + } + timesub(timep, offset, gmtptr, tmp); + /* + ** Could get fancy here and deliver something such as + ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero, + ** but this is no time for a treasure hunt. + */ + if (offset != 0) + tmp->tm_zone = WILDABBR; + else + { +#ifdef ALL_STATE + if (gmtptr == NULL) + tmp->TM_ZONE = GMT; + else + tmp->TM_ZONE = gmtptr->chars; +#endif /* defined ALL_STATE */ +#ifndef ALL_STATE + tmp->tm_zone = gmtptr->chars; +#endif /* State Farm */ + } +} + +struct tm * +gmtime(const time_t * const timep) +{ + static struct tm tm; + + gmtsub(timep, 0L, &tm); + return &tm; +} + +static void +timesub(const time_t * const timep, const long offset, const struct state * const sp, struct tm * const tmp) +{ + const struct lsinfo * lp; + long days; + long rem; + int y; + int yleap; + const int * ip; + long corr; + int hit; + int i; + + corr = 0; + hit = FALSE; +#ifdef ALL_STATE + i = (sp == NULL) ? 0 : sp->leapcnt; +#endif /* defined ALL_STATE */ +#ifndef ALL_STATE + i = sp->leapcnt; +#endif /* State Farm */ + while (--i >= 0) + { + lp = &sp->lsis[i]; + if (*timep >= lp->ls_trans) + { + if (*timep == lp->ls_trans) + hit = ((i == 0 && lp->ls_corr > 0) || + lp->ls_corr > sp->lsis[i - 1].ls_corr); + corr = lp->ls_corr; + break; + } + } + days = *timep / SECSPERDAY; + rem = *timep % SECSPERDAY; +#ifdef mc68k + if (*timep == 0x80000000) + { + /* + ** A 3B1 muffs the division on the most negative number. + */ + days = -24855; + rem = -11648; + } +#endif /* mc68k */ + rem += (offset - corr); + while (rem < 0) + { + rem += SECSPERDAY; + --days; + } + while (rem >= SECSPERDAY) + { + rem -= SECSPERDAY; + ++days; + } + tmp->tm_hour = (int) (rem / SECSPERHOUR); + rem = rem % SECSPERHOUR; + tmp->tm_min = (int) (rem / SECSPERMIN); + tmp->tm_sec = (int) (rem % SECSPERMIN); + if (hit) + /* + ** A positive leap second requires a special + ** representation. This uses "... ??:59:60". + */ + ++(tmp->tm_sec); + tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); + if (tmp->tm_wday < 0) + tmp->tm_wday += DAYSPERWEEK; + y = EPOCH_YEAR; + if (days >= 0) + for ( ; ; ) + { + yleap = isleap(y); + if (days < (long) year_lengths[yleap]) + break; + ++y; + days = days - (long) year_lengths[yleap]; + } + else + do { + --y; + yleap = isleap(y); + days = days + (long) year_lengths[yleap]; + } while (days < 0); + tmp->tm_year = y - TM_YEAR_BASE; + tmp->tm_yday = (int) days; + ip = mon_lengths[yleap]; + for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) + days = days - (long) ip[tmp->tm_mon]; + tmp->tm_mday = (int) (days + 1); + tmp->tm_isdst = 0; + tmp->tm_gmtoff = offset; +} + +/* +** A la X3J11 +*/ + +char * +asctime(const struct tm *timeptr) +{ + static const char wday_name[DAYSPERWEEK][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static const char mon_name[MONSPERYEAR][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + static char result[26]; + + (void) sprintf(result, "%.3s %.3s%3d %02d:%02d:%02d %d\n", + wday_name[timeptr->tm_wday], + mon_name[timeptr->tm_mon], + timeptr->tm_mday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec, + TM_YEAR_BASE + timeptr->tm_year); + return result; +} + +char * +ctime(const time_t * const timep) +{ + return asctime(localtime(timep)); +} + +/* +** Adapted from code provided by Robert Elz, who writes: +** The "best" way to do mktime I think is based on an idea of Bob +** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** It does a binary search of the time_t space. Since time_t's are +** just 32 bits, its a max of 32 iterations (even at 64 bits it +** would still be very reasonable). +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static void +normalize(int * const tensptr, int * const unitsptr, const int base) +{ + if (*unitsptr >= base) + { + *tensptr += *unitsptr / base; + *unitsptr %= base; + } + else if (*unitsptr < 0) + { + --*tensptr; + *unitsptr += base; + if (*unitsptr < 0) + { + *tensptr -= 1 + (-*unitsptr) / base; + *unitsptr = base - (-*unitsptr) % base; + } + } +} + +static int +tmcomp(const struct tm * const atmp, const struct tm * const btmp) +{ + int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t +time2(struct tm *tmp, void (*const funcp)(const time_t *const,const long,struct tm *), const long offset, int * const okayp) +{ + const struct state * sp; + int dir; + int bits; + int i, j ; + int saved_seconds; + time_t newt; + time_t t; + struct tm yourtm, mytm; + + *okayp = FALSE; + yourtm = *tmp; + if (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0) + normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN); + normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR); + normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY); + normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR); + while (yourtm.tm_mday <= 0) + { + --yourtm.tm_year; + yourtm.tm_mday += + year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)]; + } + for ( ; ; ) + { + i = mon_lengths[isleap(yourtm.tm_year + + TM_YEAR_BASE)][yourtm.tm_mon]; + if (yourtm.tm_mday <= i) + break; + yourtm.tm_mday -= i; + if (++yourtm.tm_mon >= MONSPERYEAR) + { + yourtm.tm_mon = 0; + ++yourtm.tm_year; + } + } + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (time_t) 1 << bits; + for ( ; ; ) + { + (*funcp)(&t, offset, &mytm); + dir = tmcomp(&mytm, &yourtm); + if (dir != 0) + { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) + break; + /* + ** Right time, wrong type. + ** Hunt for right time, right type. + ** It's okay to guess wrong since the guess + ** gets checked. + */ + sp = (const struct state *) + ((funcp == localsub) ? lclptr : gmtptr); +#ifdef ALL_STATE + if (sp == NULL) + return WRONG; +#endif /* defined ALL_STATE */ + for (i = 0; i < sp->typecnt; ++i) + { + if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) + continue; + for (j = 0; j < sp->typecnt; ++j) + { + if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) + continue; + newt = t + sp->ttis[j].tt_gmtoff - + sp->ttis[i].tt_gmtoff; + (*funcp)(&newt, offset, &mytm); + if (tmcomp(&mytm, &yourtm) != 0) + continue; + if (mytm.tm_isdst != yourtm.tm_isdst) + continue; + /* + ** We have a match. + */ + t = newt; + goto label; + } + } + return WRONG; + } + label: + t += saved_seconds; + (*funcp)(&t, offset, tmp); + *okayp = TRUE; + return t; +} + +static time_t +time1(struct tm * const tmp, void (*const funcp)(const time_t * const, const long, struct tm *), const long offset) +{ + time_t t; + const struct state * sp; + int samei, otheri; + int okay; + + if (tmp->tm_isdst > 1) + tmp->tm_isdst = 1; + t = time2(tmp, funcp, offset, &okay); + if (okay || tmp->tm_isdst < 0) + return t; + /* + ** We're supposed to assume that somebody took a time of one type + ** and did some math on it that yielded a "struct tm" that's bad. + ** We try to divine the type they started from and adjust to the + ** type they need. + */ + sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr); +#ifdef ALL_STATE + if (sp == NULL) + return WRONG; +#endif /* defined ALL_STATE */ + for (samei = 0; samei < sp->typecnt; ++samei) + { + if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) + continue; + for (otheri = 0; otheri < sp->typecnt; ++otheri) + { + if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) + continue; + tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - + sp->ttis[samei].tt_gmtoff; + tmp->tm_isdst = !tmp->tm_isdst; + t = time2(tmp, funcp, offset, &okay); + if (okay) + return t; + tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - + sp->ttis[samei].tt_gmtoff; + tmp->tm_isdst = !tmp->tm_isdst; + } + } + return WRONG; +} + +time_t +mktime(struct tm * tmp) +{ + return time1(tmp, localsub, 0L); +} + + + + diff --git a/reactos/lib/msvcrt/time/posixrul.h b/reactos/lib/msvcrt/time/posixrul.h new file mode 100644 index 00000000000..48c5ceeab0d --- /dev/null +++ b/reactos/lib/msvcrt/time/posixrul.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* generated with bin2h from DJGPP/zoneinfo/posixrules */ + +unsigned char _posixrules_data[] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,16,0,0,0,2,0,0,0,8,0,151,254,240,1,135,225,224,2,119,224,240,3,112,254,96,4,96,253,112,5,80, +224,96,6,64,223,112,7,48,194,96,7,141,25,112,9,16,164,96,9,173,148,240,10,240,134,96,11,224,133,112,12,217,162, +224,13,192,103,112,14,185,132,224,15,169,131,240,16,153,102,224,17,137,101,240,18,121,72,224,19,105,71,240,20,89,42,224, +21,73,41,240,22,57,12,224,23,41,11,240,24,34,41,96,25,8,237,240,26,2,11,96,26,242,10,112,27,225,237,96,28, +209,236,112,29,193,207,96,30,177,206,112,31,161,177,96,32,118,0,240,33,129,147,96,34,85,226,240,35,106,175,224,36,53, +196,240,37,74,145,224,38,21,166,240,39,42,115,224,39,254,195,112,41,10,85,224,41,222,165,112,42,234,55,224,43,190,135, +112,44,211,84,96,45,158,105,112,46,179,54,96,47,126,75,112,48,147,24,96,49,103,103,240,50,114,250,96,51,71,73,240, +52,82,220,96,53,39,43,240,54,50,190,96,55,7,13,240,56,27,218,224,56,230,239,240,57,251,188,224,58,198,209,240,59, +219,158,224,60,175,238,112,61,187,128,224,62,143,208,112,63,155,98,224,64,111,178,112,65,132,127,96,66,79,148,112,67,100, +97,96,68,47,118,112,69,68,67,96,70,15,88,112,71,36,37,96,71,248,116,240,73,4,7,96,73,216,86,240,74,227,233, +96,75,184,56,240,76,205,5,224,77,152,26,240,78,172,231,224,79,119,252,240,80,140,201,224,81,97,25,112,82,108,171,224, +83,64,251,112,84,76,141,224,85,32,221,112,86,44,111,224,87,0,191,112,88,21,140,96,88,224,161,112,89,245,110,96,90, +192,131,112,91,213,80,96,92,169,159,240,93,181,50,96,94,137,129,240,95,149,20,96,96,105,99,240,97,126,48,224,98,73, +69,240,99,94,18,224,100,41,39,240,101,61,244,224,102,18,68,112,103,29,214,224,103,242,38,112,104,253,184,224,105,210,8, +112,106,221,154,224,107,177,234,112,108,198,183,96,109,145,204,112,110,166,153,96,111,113,174,112,112,134,123,96,113,90,202,240, +114,102,93,96,115,58,172,240,116,70,63,96,117,26,142,240,118,47,91,224,118,250,112,240,120,15,61,224,120,218,82,240,121, +239,31,224,122,186,52,240,123,207,1,224,124,163,81,112,125,174,227,224,126,131,51,112,127,142,197,224,128,99,21,112,129,119, +226,96,130,66,247,112,131,87,196,96,132,34,217,112,133,55,166,96,134,11,245,240,135,23,136,96,135,235,215,240,136,247,106, +96,137,203,185,240,138,215,76,96,139,171,155,240,140,192,104,224,141,139,125,240,142,160,74,224,143,107,95,240,144,128,44,224, +145,84,124,112,146,96,14,224,147,52,94,112,148,63,240,224,149,20,64,112,150,41,13,96,150,244,34,112,152,8,239,96,152, +212,4,112,153,232,209,96,154,189,32,240,155,200,179,96,156,157,2,240,157,168,149,96,158,124,228,240,159,136,119,96,160,92, +198,240,161,113,147,224,162,60,168,240,163,81,117,224,164,28,138,240,165,49,87,224,166,5,167,112,167,17,57,224,167,229,137, +112,168,241,27,224,169,197,107,112,170,218,56,96,171,165,77,112,172,186,26,96,173,133,47,112,174,153,252,96,175,101,17,112, +176,121,222,96,177,78,45,240,178,89,192,96,179,46,15,240,180,57,162,96,181,13,241,240,182,34,190,224,182,237,211,240,184, +2,160,224,184,205,181,240,185,226,130,224,186,182,210,112,187,194,100,224,188,150,180,112,189,162,70,224,190,118,150,112,191,130, +40,224,192,86,120,112,193,107,69,96,194,54,90,112,195,75,39,96,196,22,60,112,197,43,9,96,197,255,88,240,199,10,235, +96,199,223,58,240,200,234,205,96,201,191,28,240,202,211,233,224,203,158,254,240,204,179,203,224,205,126,224,240,206,147,173,224, +207,103,253,112,208,115,143,224,209,71,223,112,210,83,113,224,211,39,193,112,212,51,83,224,213,7,163,112,214,28,112,96,214, +231,133,112,215,252,82,96,216,199,103,112,217,220,52,96,218,176,131,240,219,188,22,96,220,144,101,240,221,155,248,96,222,112, +71,240,223,133,20,224,224,80,41,240,225,100,246,224,226,48,11,240,227,68,216,224,228,15,237,240,229,36,186,224,229,249,10, +112,231,4,156,224,231,216,236,112,232,228,126,224,233,184,206,112,234,205,155,96,235,152,176,112,236,173,125,96,237,120,146,112, +238,141,95,96,239,97,174,240,240,109,65,96,241,65,144,240,242,77,35,96,243,33,114,240,244,45,5,96,245,1,84,240,246, +22,33,224,246,225,54,240,247,246,3,224,248,193,24,240,249,213,229,224,250,160,250,240,251,181,199,224,252,138,23,112,253,149, +169,224,254,105,249,112,255,117,139,224,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,255,255,199,192,1,0,255,255,185,176,0,4,69,68,84, +0,69,83,84,0,0,0 +}; diff --git a/reactos/lib/msvcrt/time/time.c b/reactos/lib/msvcrt/time/time.c new file mode 100644 index 00000000000..3a49372b2c2 --- /dev/null +++ b/reactos/lib/msvcrt/time/time.c @@ -0,0 +1,219 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/time.c + * PURPOSE: Get system time + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +/* + * DOS file system functions + * + * Copyright 1993 Erik Bos + * Copyright 1996 Alexandre Julliard + */ + +#include +#include +#include + +VOID STDCALL GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime ); + +time_t +time(time_t *t) +{ + FILETIME SystemTime; + DWORD Remainder; + GetSystemTimeAsFileTime(&SystemTime); + return FileTimeToUnixTime( &SystemTime,&Remainder ); +} + +/*********************************************************************** + * DOSFS_UnixTimeToFileTime + * + * Convert a Unix time to FILETIME format. + * The FILETIME structure is a 64-bit value representing the number of + * 100-nanosecond intervals since January 1, 1601, 0:00. + * 'remainder' is the nonnegative number of 100-ns intervals + * corresponding to the time fraction smaller than 1 second that + * couldn't be stored in the time_t value. + */ +void UnixTimeToFileTime( time_t unix_time, FILETIME *filetime, + DWORD remainder ) +{ + /* NOTES: + + CONSTANTS: + The time difference between 1 January 1601, 00:00:00 and + 1 January 1970, 00:00:00 is 369 years, plus the leap years + from 1604 to 1968, excluding 1700, 1800, 1900. + This makes (1968 - 1600) / 4 - 3 = 89 leap days, and a total + of 134774 days. + + Any day in that period had 24 * 60 * 60 = 86400 seconds. + + The time difference is 134774 * 86400 * 10000000, which can be written + 116444736000000000 + 27111902 * 2^32 + 3577643008 + 413 * 2^48 + 45534 * 2^32 + 54590 * 2^16 + 32768 + + If you find that these constants are buggy, please change them in all + instances in both conversion functions. + + VERSIONS: + There are two versions, one of them uses long long variables and + is presumably faster but not ISO C. The other one uses standard C + data types and operations but relies on the assumption that negative + numbers are stored as 2's complement (-1 is 0xffff....). If this + assumption is violated, dates before 1970 will not convert correctly. + This should however work on any reasonable architecture where WINE + will run. + + DETAILS: + + Take care not to remove the casts. I have tested these functions + (in both versions) for a lot of numbers. I would be interested in + results on other compilers than GCC. + + The operations have been designed to account for the possibility + of 64-bit time_t in future UNICES. Even the versions without + internal long long numbers will work if time_t only is 64 bit. + A 32-bit shift, which was necessary for that operation, turned out + not to work correctly in GCC, besides giving the warning. So I + used a double 16-bit shift instead. Numbers are in the ISO version + represented by three limbs, the most significant with 32 bit, the + other two with 16 bit each. + + As the modulo-operator % is not well-defined for negative numbers, + negative divisors have been avoided in DOSFS_FileTimeToUnixTime. + + There might be quicker ways to do this in C. Certainly so in + assembler. + + Claus Fischer, fischer@iue.tuwien.ac.at + */ + + + + + unsigned long a0; /* 16 bit, low bits */ + unsigned long a1; /* 16 bit, medium bits */ + unsigned long a2; /* 32 bit, high bits */ + + /* Copy the unix time to a2/a1/a0 */ + a0 = unix_time & 0xffff; + a1 = (unix_time >> 16) & 0xffff; + /* This is obsolete if unix_time is only 32 bits, but it does not hurt. + Do not replace this by >> 32, it gives a compiler warning and it does + not work. */ + a2 = (unix_time >= 0 ? (unix_time >> 16) >> 16 : + ~((~unix_time >> 16) >> 16)); + + /* Multiply a by 10000000 (a = a2/a1/a0) + Split the factor into 10000 * 1000 which are both less than 0xffff. */ + a0 *= 10000; + a1 = a1 * 10000 + (a0 >> 16); + a2 = a2 * 10000 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + a0 *= 1000; + a1 = a1 * 1000 + (a0 >> 16); + a2 = a2 * 1000 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + /* Add the time difference and the remainder */ + a0 += 32768 + (remainder & 0xffff); + a1 += 54590 + (remainder >> 16 ) + (a0 >> 16); + a2 += 27111902 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + /* Set filetime */ + filetime->dwLowDateTime = (a1 << 16) + a0; + filetime->dwHighDateTime = a2; +} + + +/*********************************************************************** + * DOSFS_FileTimeToUnixTime + * + * Convert a FILETIME format to Unix time. + * If not NULL, 'remainder' contains the fractional part of the filetime, + * in the range of [0..9999999] (even if time_t is negative). + */ +time_t FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder ) +{ + /* Read the comment in the function DOSFS_UnixTimeToFileTime. */ + + unsigned long a0; /* 16 bit, low bits */ + unsigned long a1; /* 16 bit, medium bits */ + unsigned long a2; /* 32 bit, high bits */ + unsigned long r; /* remainder of division */ + unsigned int carry; /* carry bit for subtraction */ + int negative; /* whether a represents a negative value */ + + /* Copy the time values to a2/a1/a0 */ + a2 = (unsigned long)filetime->dwHighDateTime; + a1 = ((unsigned long)filetime->dwLowDateTime ) >> 16; + a0 = ((unsigned long)filetime->dwLowDateTime ) & 0xffff; + + /* Subtract the time difference */ + if (a0 >= 32768 ) a0 -= 32768 , carry = 0; + else a0 += (1 << 16) - 32768 , carry = 1; + + if (a1 >= 54590 + carry) a1 -= 54590 + carry, carry = 0; + else a1 += (1 << 16) - 54590 - carry, carry = 1; + + a2 -= 27111902 + carry; + + /* If a is negative, replace a by (-1-a) */ + negative = (a2 >= ((unsigned long)1) << 31); + if (negative) + { + /* Set a to -a - 1 (a is a2/a1/a0) */ + a0 = 0xffff - a0; + a1 = 0xffff - a1; + a2 = ~a2; + } + + /* Divide a by 10000000 (a = a2/a1/a0), put the rest into r. + Split the divisor into 10000 * 1000 which are both less than 0xffff. */ + a1 += (a2 % 10000) << 16; + a2 /= 10000; + a0 += (a1 % 10000) << 16; + a1 /= 10000; + r = a0 % 10000; + a0 /= 10000; + + a1 += (a2 % 1000) << 16; + a2 /= 1000; + a0 += (a1 % 1000) << 16; + a1 /= 1000; + r += (a0 % 1000) * 10000; + a0 /= 1000; + + /* If a was negative, replace a by (-1-a) and r by (9999999 - r) */ + if (negative) + { + /* Set a to -a - 1 (a is a2/a1/a0) */ + a0 = 0xffff - a0; + a1 = 0xffff - a1; + a2 = ~a2; + + r = 9999999 - r; + } + + if (remainder) *remainder = r; + + /* Do not replace this by << 32, it gives a compiler warning and it does + not work. */ + return ((((time_t)a2) << 16) << 16) + (a1 << 16) + a0; + +} + + + diff --git a/reactos/lib/msvcrt/time/tzfile.h b/reactos/lib/msvcrt/time/tzfile.h new file mode 100644 index 00000000000..3999029adb9 --- /dev/null +++ b/reactos/lib/msvcrt/time/tzfile.h @@ -0,0 +1,160 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_tzfile_h__ +#define __dj_include_tzfile_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)tzfile.h 5.9 (Berkeley) 6/11/90 + */ + +/* +** Information about time zone files. +*/ + + /* Time zone object file directory */ +#define TZDIR "/usr/share/zoneinfo" +#define TZDEFAULT "/etc/localtime" +#define TZDEFRULES "posixrules" + +/* +** Each file begins with. . . +*/ + +struct tzhead { + char tzh_reserved[24]; /* reserved for future use */ + char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ + char tzh_leapcnt[4]; /* coded number of leap seconds */ + char tzh_timecnt[4]; /* coded number of transition times */ + char tzh_typecnt[4]; /* coded number of local time types */ + char tzh_charcnt[4]; /* coded number of abbr. chars */ +}; + +/* +** . . .followed by. . . +** +** tzh_timecnt (char [4])s coded transition times a la time(2) +** tzh_timecnt (unsigned char)s types of local time starting at above +** tzh_typecnt repetitions of +** one (char [4]) coded GMT offset in seconds +** one (unsigned char) used to set tm_isdst +** one (unsigned char) that's an abbreviation list index +** tzh_charcnt (char)s '\0'-terminated zone abbreviations +** tzh_leapcnt repetitions of +** one (char [4]) coded leap second transition times +** one (char [4]) total correction after above +** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition +** time is standard time, if FALSE, +** transition time is wall clock time +** if absent, transition times are +** assumed to be wall clock time +*/ + +/* +** In the current implementation, "tzset()" refuses to deal with files that +** exceed any of the limits below. +*/ + +/* +** The TZ_MAX_TIMES value below is enough to handle a bit more than a +** year's worth of solar time (corrected daily to the nearest second) or +** 138 years of Pacific Presidential Election time +** (where there are three time zone transitions every fourth year). +*/ +#define TZ_MAX_TIMES 370 + +#define NOSOLAR /* 4BSD doesn't currently handle solar time */ + +#ifndef NOSOLAR +#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ +#else +#define TZ_MAX_TYPES 10 /* Maximum number of local time types */ +#endif + +#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ + +#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ + +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 + +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_JANUARY 0 +#define TM_FEBRUARY 1 +#define TM_MARCH 2 +#define TM_APRIL 3 +#define TM_MAY 4 +#define TM_JUNE 5 +#define TM_JULY 6 +#define TM_AUGUST 7 +#define TM_SEPTEMBER 8 +#define TM_OCTOBER 9 +#define TM_NOVEMBER 10 +#define TM_DECEMBER 11 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +/* +** Accurate only for the past couple of centuries; +** that will probably do. +*/ + +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_tzfile_h__ */