Subversion Repositories Kolibri OS

Rev

Rev 6536 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 1990, 2007 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  *
  17.  *      %W% (UofMD/Berkeley) %G%
  18.  */
  19.  
  20. /*
  21.  * Information local to this implementation of stdio,
  22.  * in particular, macros and private variables.
  23.  */
  24.  
  25. #include <_ansi.h>
  26. #include <reent.h>
  27. #include <stdarg.h>
  28. #include <stdlib.h>
  29. #include <unistd.h>
  30. #include <stdio.h>
  31. #ifdef __SCLE
  32. # include <io.h>
  33. #endif
  34.  
  35. /* The following define determines if the per-reent stdin, stdout and stderr
  36.    streams are closed during _reclaim_reent().  The stdin, stdout and stderr
  37.    streams are initialized to use file descriptors 0, 1 and 2 respectively.  In
  38.    case _STDIO_CLOSE_PER_REENT_STD_STREAMS is defined these file descriptors
  39.    will be closed via close() provided the owner of the reent structure
  40.    triggerd the on demand reent initilization, see CHECK_INIT(). */
  41. #if !defined(__rtems__) && !defined(__tirtos__)
  42. #define _STDIO_CLOSE_PER_REENT_STD_STREAMS
  43. #endif
  44.  
  45. /* The following macros are supposed to replace calls to _flockfile/_funlockfile
  46.    and __sfp_lock_acquire/__sfp_lock_release.  In case of multi-threaded
  47.    environments using pthreads, it's not sufficient to lock the stdio functions
  48.    against concurrent threads accessing the same data, the locking must also be
  49.    secured against thread cancellation.
  50.  
  51.    The below macros have to be used in pairs.  The _newlib_XXX_start macro
  52.    starts with a opening curly brace, the _newlib_XXX_end macro ends with a
  53.    closing curly brace, so the start macro and the end macro mark the code
  54.    start and end of a critical section.  In case the code leaves the critical
  55.    section before reaching the end of the critical section's code end, use
  56.    the appropriate _newlib_XXX_exit macro. */
  57.  
  58. #if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) \
  59.     && !defined (__rtems__)
  60. #define _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  61. #endif
  62.  
  63. #if defined(__SINGLE_THREAD__) || defined(__IMPL_UNLOCKED__)
  64.  
  65. # define _newlib_flockfile_start(_fp)
  66. # define _newlib_flockfile_exit(_fp)
  67. # define _newlib_flockfile_end(_fp)
  68. # define _newlib_sfp_lock_start()
  69. # define _newlib_sfp_lock_exit()
  70. # define _newlib_sfp_lock_end()
  71.  
  72. #elif defined(_STDIO_WITH_THREAD_CANCELLATION_SUPPORT)
  73. #include <pthread.h>
  74.  
  75. /* Start a stream oriented critical section: */
  76. # define _newlib_flockfile_start(_fp) \
  77.         { \
  78.           int __oldfpcancel; \
  79.           pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldfpcancel); \
  80.           if (!(_fp->_flags2 & __SNLK)) \
  81.             _flockfile (_fp)
  82.  
  83. /* Exit from a stream oriented critical section prematurely: */
  84. # define _newlib_flockfile_exit(_fp) \
  85.           if (!(_fp->_flags2 & __SNLK)) \
  86.             _funlockfile (_fp); \
  87.           pthread_setcancelstate (__oldfpcancel, &__oldfpcancel);
  88.  
  89. /* End a stream oriented critical section: */
  90. # define _newlib_flockfile_end(_fp) \
  91.           if (!(_fp->_flags2 & __SNLK)) \
  92.             _funlockfile (_fp); \
  93.           pthread_setcancelstate (__oldfpcancel, &__oldfpcancel); \
  94.         }
  95.  
  96. /* Start a stream list oriented critical section: */
  97. # define _newlib_sfp_lock_start() \
  98.         { \
  99.           int __oldsfpcancel; \
  100.           pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldsfpcancel); \
  101.           __sfp_lock_acquire ()
  102.  
  103. /* Exit from a stream list oriented critical section prematurely: */
  104. # define _newlib_sfp_lock_exit() \
  105.           __sfp_lock_release (); \
  106.           pthread_setcancelstate (__oldsfpcancel, &__oldsfpcancel);
  107.  
  108. /* End a stream list oriented critical section: */
  109. # define _newlib_sfp_lock_end() \
  110.           __sfp_lock_release (); \
  111.           pthread_setcancelstate (__oldsfpcancel, &__oldsfpcancel); \
  112.         }
  113.  
  114. #else /* !__SINGLE_THREAD__ && !__IMPL_UNLOCKED__ && !_STDIO_WITH_THREAD_CANCELLATION_SUPPORT */
  115.  
  116. # define _newlib_flockfile_start(_fp) \
  117.         { \
  118.                 if (!(_fp->_flags2 & __SNLK)) \
  119.                   _flockfile (_fp)
  120.  
  121. # define _newlib_flockfile_exit(_fp) \
  122.                 if (!(_fp->_flags2 & __SNLK)) \
  123.                   _funlockfile(_fp); \
  124.  
  125. # define _newlib_flockfile_end(_fp) \
  126.                 if (!(_fp->_flags2 & __SNLK)) \
  127.                   _funlockfile(_fp); \
  128.         }
  129.  
  130. # define _newlib_sfp_lock_start() \
  131.         { \
  132.                 __sfp_lock_acquire ()
  133.  
  134. # define _newlib_sfp_lock_exit() \
  135.                 __sfp_lock_release ();
  136.  
  137. # define _newlib_sfp_lock_end() \
  138.                 __sfp_lock_release (); \
  139.         }
  140.  
  141. #endif /* __SINGLE_THREAD__ || __IMPL_UNLOCKED__ */
  142.  
  143. extern wint_t _EXFUN(__fgetwc, (struct _reent *, FILE *));
  144. extern wint_t _EXFUN(__fputwc, (struct _reent *, wchar_t, FILE *));
  145. extern u_char *_EXFUN(__sccl, (char *, u_char *fmt));
  146. extern int    _EXFUN(__svfscanf_r,(struct _reent *,FILE *, _CONST char *,va_list));
  147. extern int    _EXFUN(__ssvfscanf_r,(struct _reent *,FILE *, _CONST char *,va_list));
  148. extern int    _EXFUN(__svfiscanf_r,(struct _reent *,FILE *, _CONST char *,va_list));
  149. extern int    _EXFUN(__ssvfiscanf_r,(struct _reent *,FILE *, _CONST char *,va_list));
  150. extern int    _EXFUN(__svfwscanf_r,(struct _reent *,FILE *, _CONST wchar_t *,va_list));
  151. extern int    _EXFUN(__ssvfwscanf_r,(struct _reent *,FILE *, _CONST wchar_t *,va_list));
  152. extern int    _EXFUN(__svfiwscanf_r,(struct _reent *,FILE *, _CONST wchar_t *,va_list));
  153. extern int    _EXFUN(__ssvfiwscanf_r,(struct _reent *,FILE *, _CONST wchar_t *,va_list));
  154. int           _EXFUN(_svfprintf_r,(struct _reent *, FILE *, const char *,
  155.                                   va_list)
  156.                                 _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
  157. int           _EXFUN(_svfiprintf_r,(struct _reent *, FILE *, const char *,
  158.                                   va_list)
  159.                                 _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
  160. int           _EXFUN(_svfwprintf_r,(struct _reent *, FILE *, const wchar_t *,
  161.                                   va_list));
  162. int           _EXFUN(_svfiwprintf_r,(struct _reent *, FILE *, const wchar_t *,
  163.                                   va_list));
  164. extern FILE  *_EXFUN(__sfp,(struct _reent *));
  165. extern int    _EXFUN(__sflags,(struct _reent *,_CONST char*, int*));
  166. extern int    _EXFUN(__sflush_r,(struct _reent *,FILE *));
  167. #ifdef _STDIO_BSD_SEMANTICS
  168. extern int    _EXFUN(__sflushw_r,(struct _reent *,FILE *));
  169. #endif
  170. extern int    _EXFUN(__srefill_r,(struct _reent *,FILE *));
  171. extern _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(struct _reent *, void *, char *,
  172.                                                _READ_WRITE_BUFSIZE_TYPE));
  173. extern _READ_WRITE_RETURN_TYPE _EXFUN(__seofread,(struct _reent *, void *,
  174.                                                   char *,
  175.                                                   _READ_WRITE_BUFSIZE_TYPE));
  176. extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite,(struct _reent *, void *,
  177.                                                 const char *,
  178.                                                 _READ_WRITE_BUFSIZE_TYPE));
  179. extern _fpos_t _EXFUN(__sseek,(struct _reent *, void *, _fpos_t, int));
  180. extern int    _EXFUN(__sclose,(struct _reent *, void *));
  181. extern int    _EXFUN(__stextmode,(int));
  182. extern _VOID   _EXFUN(__sinit,(struct _reent *));
  183. extern _VOID   _EXFUN(_cleanup_r,(struct _reent *));
  184. extern _VOID   _EXFUN(__smakebuf_r,(struct _reent *, FILE *));
  185. extern int    _EXFUN(__swhatbuf_r,(struct _reent *, FILE *, size_t *, int *));
  186. extern int    _EXFUN(_fwalk,(struct _reent *, int (*)(FILE *)));
  187. extern int    _EXFUN(_fwalk_reent,(struct _reent *, int (*)(struct _reent *, FILE *)));
  188. struct _glue * _EXFUN(__sfmoreglue,(struct _reent *,int n));
  189. extern int _EXFUN(__submore, (struct _reent *, FILE *));
  190.  
  191. #ifdef __LARGE64_FILES
  192. extern _fpos64_t _EXFUN(__sseek64,(struct _reent *, void *, _fpos64_t, int));
  193. extern _READ_WRITE_RETURN_TYPE _EXFUN(__swrite64,(struct _reent *, void *,
  194.                                                   const char *,
  195.                                                   _READ_WRITE_BUFSIZE_TYPE));
  196. #endif
  197.  
  198. /* Called by the main entry point fns to ensure stdio has been initialized.  */
  199.  
  200. #ifdef _REENT_SMALL
  201. #define CHECK_INIT(ptr, fp) \
  202.   do                                                            \
  203.     {                                                           \
  204.       struct _reent *_check_init_ptr = (ptr);                   \
  205.       if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit)  \
  206.         __sinit (_check_init_ptr);                              \
  207.       if ((fp) == (FILE *)&__sf_fake_stdin)                     \
  208.         (fp) = _stdin_r(_check_init_ptr);                       \
  209.       else if ((fp) == (FILE *)&__sf_fake_stdout)               \
  210.         (fp) = _stdout_r(_check_init_ptr);                      \
  211.       else if ((fp) == (FILE *)&__sf_fake_stderr)               \
  212.         (fp) = _stderr_r(_check_init_ptr);                      \
  213.     }                                                           \
  214.   while (0)
  215. #else /* !_REENT_SMALL   */
  216. #define CHECK_INIT(ptr, fp) \
  217.   do                                                            \
  218.     {                                                           \
  219.       struct _reent *_check_init_ptr = (ptr);                   \
  220.       if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit)  \
  221.         __sinit (_check_init_ptr);                              \
  222.     }                                                           \
  223.   while (0)
  224. #endif /* !_REENT_SMALL  */
  225.  
  226. #define CHECK_STD_INIT(ptr) \
  227.   do                                                            \
  228.     {                                                           \
  229.       struct _reent *_check_init_ptr = (ptr);                   \
  230.       if ((_check_init_ptr) && !(_check_init_ptr)->__sdidinit)  \
  231.         __sinit (_check_init_ptr);                              \
  232.     }                                                           \
  233.   while (0)
  234.  
  235. /* Return true and set errno and stream error flag iff the given FILE
  236.    cannot be written now.  */
  237.  
  238. #define cantwrite(ptr, fp)                                     \
  239.   ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \
  240.    __swsetup_r(ptr, fp))
  241.  
  242. /* Test whether the given stdio file has an active ungetc buffer;
  243.    release such a buffer, without restoring ordinary unread data.  */
  244.  
  245. #define HASUB(fp) ((fp)->_ub._base != NULL)
  246. #define FREEUB(ptr, fp) {                    \
  247.         if ((fp)->_ub._base != (fp)->_ubuf) \
  248.                 _free_r(ptr, (char *)(fp)->_ub._base); \
  249.         (fp)->_ub._base = NULL; \
  250. }
  251.  
  252. /* Test for an fgetline() buffer.  */
  253.  
  254. #define HASLB(fp) ((fp)->_lb._base != NULL)
  255. #define FREELB(ptr, fp) { _free_r(ptr,(char *)(fp)->_lb._base); \
  256.       (fp)->_lb._base = NULL; }
  257.  
  258. #ifdef _WIDE_ORIENT
  259. /*
  260.  * Set the orientation for a stream. If o > 0, the stream has wide-
  261.  * orientation. If o < 0, the stream has byte-orientation.
  262.  */
  263. #define ORIENT(fp,ori)                                  \
  264.   do                                                            \
  265.     {                                                           \
  266.           (fp)->_flags |= __SORD;                               \
  267.           if (ori > 0)                                          \
  268.             (fp)->_flags2 |= __SWID;                            \
  269.           else                                                  \
  270.             (fp)->_flags2 &= ~__SWID;                           \
  271.     }                                                           \
  272.   while (0)
  273. #else
  274. #define ORIENT(fp,ori)
  275. #endif
  276.  
  277. /* WARNING: _dcvt is defined in the stdlib directory, not here!  */
  278.  
  279. char *_EXFUN(_dcvt,(struct _reent *, char *, double, int, int, char, int));
  280. char *_EXFUN(_sicvt,(char *, short, char));
  281. char *_EXFUN(_icvt,(char *, int, char));
  282. char *_EXFUN(_licvt,(char *, long, char));
  283. #ifdef __GNUC__
  284. char *_EXFUN(_llicvt,(char *, long long, char));
  285. #endif
  286.  
  287. #define CVT_BUF_SIZE 128
  288.  
  289. #define NDYNAMIC 4      /* add four more whenever necessary */
  290.  
  291. #ifdef __SINGLE_THREAD__
  292. #define __sfp_lock_acquire()
  293. #define __sfp_lock_release()
  294. #define __sinit_lock_acquire()
  295. #define __sinit_lock_release()
  296. #else
  297. _VOID _EXFUN(__sfp_lock_acquire,(_VOID));
  298. _VOID _EXFUN(__sfp_lock_release,(_VOID));
  299. _VOID _EXFUN(__sinit_lock_acquire,(_VOID));
  300. _VOID _EXFUN(__sinit_lock_release,(_VOID));
  301. #endif
  302.  
  303. /* Types used in positional argument support in vfprinf/vfwprintf.
  304.    The implementation is char/wchar_t dependent but the class and state
  305.    tables are only defined once in vfprintf.c. */
  306. typedef enum {
  307.   ZERO,   /* '0' */
  308.   DIGIT,  /* '1-9' */
  309.   DOLLAR, /* '$' */
  310.   MODFR,  /* spec modifier */
  311.   SPEC,   /* format specifier */
  312.   DOT,    /* '.' */
  313.   STAR,   /* '*' */
  314.   FLAG,   /* format flag */
  315.   OTHER,  /* all other chars */
  316.   MAX_CH_CLASS /* place-holder */
  317. } __CH_CLASS;
  318.  
  319. typedef enum {
  320.   START,  /* start */
  321.   SFLAG,  /* seen a flag */
  322.   WDIG,   /* seen digits in width area */
  323.   WIDTH,  /* processed width */
  324.   SMOD,   /* seen spec modifier */
  325.   SDOT,   /* seen dot */
  326.   VARW,   /* have variable width specifier */
  327.   VARP,   /* have variable precision specifier */
  328.   PREC,   /* processed precision */
  329.   VWDIG,  /* have digits in variable width specification */
  330.   VPDIG,  /* have digits in variable precision specification */
  331.   DONE,   /* done */
  332.   MAX_STATE, /* place-holder */
  333. } __STATE;
  334.  
  335. typedef enum {
  336.   NOOP,  /* do nothing */
  337.   NUMBER, /* build a number from digits */
  338.   SKIPNUM, /* skip over digits */
  339.   GETMOD,  /* get and process format modifier */
  340.   GETARG,  /* get and process argument */
  341.   GETPW,   /* get variable precision or width */
  342.   GETPWB,  /* get variable precision or width and pushback fmt char */
  343.   GETPOS,  /* get positional parameter value */
  344.   PWPOS,   /* get positional parameter value for variable width or precision */
  345. } __ACTION;
  346.  
  347. extern _CONST __CH_CLASS __chclass[256];
  348. extern _CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS];
  349. extern _CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS];
  350.