home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / _file.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  9KB  |  398 lines

  1. /***
  2. *_file.c - Definition of _iob[], initializer and terminator.
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Defines _iob[], the array of stdio control structures, the initializer
  8. *       and terminator routines, and the multithread locking for stdio.
  9. *
  10. *******************************************************************************/
  11.  
  12. #ifdef _WIN32
  13.  
  14.  
  15. #include <cruntime.h>
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include <file2.h>
  19. #include <internal.h>
  20. #include <malloc.h>
  21. #include <rterr.h>
  22. #include <dbgint.h>
  23. #include <mtdll.h>
  24.  
  25. /*
  26.  * Buffer for stdin.
  27.  */
  28.  
  29. char _bufin[_INTERNAL_BUFSIZ];
  30.  
  31. /*
  32.  * FILE descriptors; preset for stdin/out/err (note that the __tmpnum field
  33.  * is not initialized)
  34.  */
  35. FILE _iob[_IOB_ENTRIES] = {
  36.         /* _ptr, _cnt, _base,  _flag, _file, _charbuf, _bufsiz */
  37.  
  38.         /* stdin (_iob[0]) */
  39.  
  40.         { _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },
  41.  
  42.         /* stdout (_iob[1]) */
  43.  
  44.         { NULL, 0, NULL, _IOWRT, 1, 0, 0 },
  45.  
  46.         /* stderr (_iob[3]) */
  47.  
  48.         { NULL, 0, NULL, _IOWRT, 2, 0, 0 },
  49.  
  50. };
  51.  
  52. /*
  53.  * Pointer to array of FILE * or _FILEX * structures.
  54.  */
  55. void ** __piob;
  56.  
  57. /*
  58.  * Number of open streams (set to _NSTREAM by default)
  59.  */
  60. #ifdef CRTDLL
  61. int _nstream = _NSTREAM_;
  62. #else  /* CRTDLL */
  63. int _nstream;
  64. #endif  /* CRTDLL */
  65.  
  66.  
  67. /*
  68.  * Initializer and terminator for stdio
  69.  */
  70. void __cdecl __initstdio(void);
  71. void __cdecl __endstdio(void);
  72.  
  73. #ifdef _MSC_VER
  74.  
  75. #pragma data_seg(".CRT$XIC")
  76. static _PVFV pinit = __initstdio;
  77.  
  78. #pragma data_seg(".CRT$XPX")
  79. static _PVFV pterm = __endstdio;
  80.  
  81. #pragma data_seg()
  82.  
  83. #endif  /* _MSC_VER */
  84.  
  85. #ifndef CRTDLL
  86. /*
  87.  * _cflush is a dummy variable used to pull in _endstdio() when any STDIO
  88.  * routine is included in the user program.
  89.  */
  90. int _cflush = 0;
  91. #endif  /* CRTDLL */
  92.  
  93.  
  94. /***
  95. * __initstdio - Initialize the stdio system
  96. *
  97. *Purpose:
  98. *       Create and initialize the __piob array.
  99. *
  100. *Entry: <void>
  101. *
  102. *Exit:  <void>
  103. *
  104. *Uses:
  105. *
  106. *Exceptions:
  107. *
  108. *******************************************************************************/
  109.  
  110. void __cdecl __initstdio(void)
  111. {
  112.         int i;
  113.  
  114. #ifndef CRTDLL
  115.         /*
  116.          * If the user has not supplied a definition of _nstream, set it
  117.          * to _NSTREAM_. If the user has supplied a value that is too small
  118.          * set _nstream to the minimum acceptable value (_IOB_ENTRIES).
  119.          */
  120.         if ( _nstream ==  0 )
  121.             _nstream = _NSTREAM_;
  122.         else if ( _nstream < _IOB_ENTRIES )
  123.             _nstream = _IOB_ENTRIES;
  124. #endif  /* CRTDLL */
  125.  
  126.         /*
  127.          * Allocate the __piob array. Try for _nstream entries first. If this
  128.          * fails then reset _nstream to _IOB_ENTRIES and try again. If it
  129.          * still fails, bail out with an RTE.
  130.          */
  131.         if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) )) ==
  132.              NULL ) {
  133.             _nstream = _IOB_ENTRIES;
  134.             if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) ))
  135.                  == NULL )
  136.                 _amsg_exit( _RT_STDIOINIT );
  137.         }
  138.  
  139.         /*
  140.          * Initialize the first _IOB_ENTRIES to point to the corresponding
  141.          * entries in _iob[].
  142.          */
  143.         for ( i = 0 ; i < _IOB_ENTRIES ; i++ )
  144.             __piob[i] = (void *)&_iob[i];
  145.  
  146.         for ( i = 0 ; i < 3 ; i++ ) {
  147.             if ( (_osfhnd(i) == (long)INVALID_HANDLE_VALUE) ||
  148.                  (_osfhnd(i) == 0L) )
  149.             {
  150.                 _iob[i]._file = -1;
  151.             }
  152.         }
  153. }
  154.  
  155.  
  156. /***
  157. * __endstdio - Terminate the stdio system
  158. *
  159. *Purpose:
  160. *       Terminate the stdio system
  161. *
  162. *       (1) Flush all streams.  (Do this even if we're going to
  163. *       call fcloseall since that routine won't do anything to the
  164. *       std streams.)
  165. *
  166. *       (2) If returning to caller, close all streams.  This is
  167. *       not necessary if the exe is terminating because the OS will
  168. *       close the files for us (much more efficiently, too).
  169. *
  170. *Entry: <void>
  171. *
  172. *Exit:  <void>
  173. *
  174. *Uses:
  175. *
  176. *Exceptions:
  177. *
  178. *******************************************************************************/
  179.  
  180. void __cdecl __endstdio(void)
  181. {
  182.         /* flush all streams */
  183.         _flushall();
  184.  
  185.         /* if in callable exit, close all streams */
  186.         if (_exitflag)
  187.                 _fcloseall();
  188. }
  189.  
  190.  
  191. #ifdef _MT
  192.  
  193. /***
  194. * _lock_file - Lock a FILE
  195. *
  196. *Purpose:
  197. *       Assert the lock for a stdio-level file
  198. *
  199. *Entry:
  200. *       pf = __piob[] entry (pointer to a FILE or _FILEX)
  201. *
  202. *Exit:
  203. *
  204. *Exceptions:
  205. *
  206. *******************************************************************************/
  207.  
  208. void __cdecl _lock_file (
  209.         void *pf
  210.         )
  211. {
  212.         /*
  213.          * The way the FILE (pointed to by pf) is locked depends on whether
  214.          * it is part of _iob[] or not
  215.          */
  216.         if ( (pf >= (void *)_iob) && (pf <= (void *)(&_iob[_IOB_ENTRIES-1])) )
  217.             /*
  218.              * FILE lies in _iob[] so the lock lies in _locktable[].
  219.              */
  220.             _lock( _STREAM_LOCKS + ((FILE *)pf - _iob) );
  221.         else
  222.             /*
  223.              * Not part of _iob[]. Therefore, *pf is a _FILEX and the
  224.              * lock field of the struct is an initialized critical
  225.              * section.
  226.              */
  227.             EnterCriticalSection( &(((_FILEX *)pf)->lock) );
  228. }
  229.  
  230.  
  231. /***
  232. * _lock_file2(i, s) - Lock the FILE
  233. *
  234. *Purpose:
  235. *       Assert the lock for a stdio-level file given by s == __piob[i].
  236. *
  237. *Entry:
  238. *       s == __piob[i]
  239. *
  240. *Exit:
  241. *
  242. *Exceptions:
  243. *
  244. *******************************************************************************/
  245.  
  246. void __cdecl _lock_file2 (
  247.         int i,
  248.         void *s
  249.         )
  250. {
  251.         /*
  252.          * The way the FILE is locked depends on whether it is part of _iob[]
  253.          * _iob[] or not
  254.          */
  255.         if ( i < _IOB_ENTRIES )
  256.             /*
  257.              * FILE lies in _iob[] so the lock lies in _locktable[].
  258.              */
  259.             _lock( _STREAM_LOCKS + i );
  260.         else
  261.             /*
  262.              * Not part of _iob[]. Therefore, *s is a _FILEX and the
  263.              * lock field of the struct is an initialized critical
  264.              * section.
  265.              */
  266.             EnterCriticalSection( &(((_FILEX *)s)->lock) );
  267. }
  268.  
  269.  
  270. /***
  271. * _unlock_file - Unlock a FILE
  272. *
  273. *Purpose:
  274. *       Release the lock for a stdio-level file
  275. *
  276. *Entry:
  277. *       pf = __piob[] entry (pointer to a FILE or _FILEX)
  278. *
  279. *Exit:
  280. *
  281. *Exceptions:
  282. *
  283. *******************************************************************************/
  284.  
  285. void __cdecl _unlock_file (
  286.         void *pf
  287.         )
  288. {
  289.         /*
  290.          * The way the FILE (pointed to by pf) is unlocked depends on whether
  291.          * it is part of _iob[] or not
  292.          */
  293.         if ( (pf >= (void *)_iob) && (pf <= (void *)(&_iob[_IOB_ENTRIES-1])) )
  294.             /*
  295.              * FILE lies in _iob[] so the lock lies in _locktable[].
  296.              */
  297.             _unlock( _STREAM_LOCKS + ((FILE *)pf - _iob) );
  298.         else
  299.             /*
  300.              * Not part of _iob[]. Therefore, *pf is a _FILEX and the
  301.              * lock field of the struct is an initialized critical
  302.              * section.
  303.              */
  304.             LeaveCriticalSection( &(((_FILEX *)pf)->lock) );
  305. }
  306.  
  307.  
  308. /***
  309. * _unlock_file2(i, s) - Lock the FILE
  310. *
  311. *Purpose:
  312. *       Release the lock for a stdio-level file given by s == __piob[i].
  313. *
  314. *Entry:
  315. *       s == __piob[i]
  316. *
  317. *Exit:
  318. *
  319. *Exceptions:
  320. *
  321. *******************************************************************************/
  322.  
  323. void __cdecl _unlock_file2 (
  324.         int i,
  325.         void *s
  326.         )
  327. {
  328.         /*
  329.          * The way the FILE is locked depends on whether it is part of _iob[]
  330.          * _iob[] or not
  331.          */
  332.         if ( i < _IOB_ENTRIES )
  333.             /*
  334.              * FILE lies in _iob[] so the lock lies in _locktable[].
  335.              */
  336.             _unlock( _STREAM_LOCKS + i );
  337.         else
  338.             /*
  339.              * Not part of _iob[]. Therefore, *s is a _FILEX and the
  340.              * lock field of the struct is an initialized critical
  341.              * section.
  342.              */
  343.             LeaveCriticalSection( &(((_FILEX *)s)->lock) );
  344. }
  345.  
  346. #endif  /* _MT */
  347.  
  348. #else  /* _WIN32 */
  349.  
  350. #ifdef _MAC
  351.  
  352.  
  353. #include <cruntime.h>
  354. #include <stdio.h>
  355. #include <file2.h>
  356.  
  357. /*
  358.  * Buffer for stdin.
  359.  */
  360.  
  361. char _bufin[BUFSIZ];
  362.  
  363.  
  364. /*
  365.  * FILE descriptors; preset for stdin/out/err (note that the __tmpnum field
  366.  * is not initialized)
  367.  */
  368.  
  369. FILE _iob[ _NSTREAM_ ] = {
  370.  
  371.         /* _ptr, _cnt, _base,  _flag, _file, _charbuf, _bufsiz */
  372.  
  373.         /* stdin (_iob[0]) */
  374.  
  375.         { _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, BUFSIZ },
  376.  
  377.         /* stdout (_iob[1]) */
  378.  
  379.         { NULL, 0, NULL, _IOWRT, 1, 0, 0 },
  380.  
  381.         /* stderr (_iob[3]) */
  382.  
  383.         { NULL, 0, NULL, _IOWRT, 2, 0, 0 },
  384.  
  385. };
  386.  
  387.  
  388. /*
  389.  * pointer to end of descriptors
  390.  */
  391.  
  392. FILE * _lastiob = &_iob[_NSTREAM_ - 1];
  393.  
  394.  
  395. #endif  /* _MAC */
  396.  
  397. #endif  /* _WIN32 */
  398.