home *** CD-ROM | disk | FTP | other *** search
- #pragma inline
-
- /*===========================================================================
- close.c
-
- Code to increase the file handle limit under Turbo C.
-
- For versions of Turbo C earlier than BCC++ v3.0, includes a
- replacement for the Turbo C close(), and a function to increase
- the file handle limit. For BCC++ v3.0, just defines some data.
-
-
- To use:
- Compile, and link this file with your program.
- (If you removed the "#pragma startup" statement from this file,
- put a call to increase_handles() in your program, preferably
- early in main()).
-
- Note:
- (1) This code will not increase the number of streams
- available to your program if you use the Turbo C stream
- functions for versions of Turbo C earlier than BCC++ 3.0.
- For the earlier versions of Turbo C, you will need to use the
- lower level file functions such as open(), read(), etc to be
- able to use the extra handles.
-
- (2) If you are using DJGPP then you can easily change the number
- of streams available to your programs by a couple of simple
- changes to the DJGPP library functions (see STREAMS.DOC).
-
- (3) As strange as it may seem, the close() function here is
- not really needed by DJGPP v1.05 because although programs running
- under go32 make use of the Turbo C creat(), open(), read(), and
- write() functions, they nowhere use close()! However close()
- is needed by go32 for other purposes so we may as well use this
- version.
-
- (4) This file contains alternative code for increasing the
- number of file handles. This code uses DOS service 0x67. To
- enable this alternative code, #define USE_DOS67. This is not
- recommended.
-
-
- Tested with Turbo C 1.5, Turbo C++ v1.0, Borland C++ v2.0, Borland C++
- v3.0, MSDOS 3.10, and MSDOS 5.00
-
- Should work with all versions of Turbo C up to Borland C++ v3.0.
-
- W. Metzenthen 17th Feb 1992 version 1.2
- 2nd March 1992 version 1.3 (modified for Turbo C v1.5)
- 6th March 1992 Changed some comments, no code change.
- 26th March 1992 version 1.4, added bcc 3.0 support
- ===========================================================================*/
-
- #define __TCC20__ 0x200
- #define __BCC30__ 0x400
-
-
- /*------------------------------------------------+
- | MAX_FD is the only thing you should ever need |
- | to change. |
- +------------------------------------------------*/
- #if ( __TURBOC__ < __BCC30__)
- /* The maximum number of files under DOS-5.00 is 255, but we can
- get a handle = nn + 2 (where FILES=nn in config.sys)
- returned from DOS (i.e. up to 257 handles if nn=255). */
- #define MAX_FD 257 /* No sense in having more than 257 here */
- #else
- /* Borland C++ v3.0 users lose 2 in the maximum possible number of handles,
- maximum 255 because fd in struct stream is a char. */
- #define MAX_FD 255 /* WARNING: NEVER LARGER THAN 255 */
- #endif
-
-
- /*------------------------------------------------+
- | You should never need to change anything past |
- | this point. |
- +------------------------------------------------*/
-
- /* If you really want to... but it has not been as thoroughly tested. */
- /* #define USE_DOS67 */
-
- void increase_handles(void);
-
- /* Remove the following pragma if you don't want to have increase_handles
- called automatically by the Turbo C start-up code.
- If you do this then you should call increase_handles() in main() before
- any file or stream access. */
- /* Turbo C v1.0, v1.5, (and probably v2.0) do not support #pragma startup */
- #if (__TURBOC__ > __TCC20__) && (__TURBOC__ < __BCC30__)
- #pragma startup increase_handles 70
- #endif
-
-
- /* The code in this source file should work with any version
- of Turbo C up to Borland C++ v3.0 ...
- and perhaps higher versions. */
- #ifndef __TURBOC__
- #error "This code probably only works with Turbo C"
- #endif
-
-
- #include <stdio.h>
- #include <dos.h>
- #include <fcntl.h>
- #include <mem.h>
-
-
- int _openfd[MAX_FD] /* This must be visible globally */
- = {
- O_RDONLY | O_DEVICE, /* stdin */
- O_WRONLY | O_DEVICE, /* stdout */
- O_WRONLY | O_DEVICE, /* stderr */
- O_RDWR | O_DEVICE | O_BINARY, /* stdaux */
- O_WRONLY | O_DEVICE | O_BINARY /* stdprn */
- } ;
-
-
- #if ( __TURBOC__ >= __BCC30__ )
- /*---------------------------------------------------------------------------+
- | |
- | Replacement for _nfile and the _streams array for Borland C++ v3.0 |
- | |
- +---------------------------------------------------------------------------*/
- unsigned int _nfile = MAX_FD;
- #define OFFSET(x) FP_OFF((void far *)&_streams[ x ])
- FILE _streams[MAX_FD] =
- {
- /* stdin is a read-only line-buffered device */
- { 0, _F_TERM|_F_READ|_F_LBUF, 0, 0, 0, NULL, NULL, 0, OFFSET(0) },
- /* stdout is a write-only line-buffered device */
- { 0, _F_TERM|_F_WRIT|_F_LBUF, 1, 0, 0, NULL, NULL, 0, OFFSET(1) },
- /* stderr is a write-only device */
- { 0, _F_TERM|_F_WRIT, 2, 0, 0, NULL, NULL, 0, OFFSET(2) },
- /* stdaux is a read/write binary device */
- { 0, _F_TERM|_F_RDWR|_F_BIN, 3, 0, 0, NULL, NULL, 0, OFFSET(3) },
- /* stdprn is a write-only binary device */
- { 0, _F_TERM|_F_WRIT|_F_BIN, 4, 0, 0, NULL, NULL, 0, OFFSET(4) }
- };
- #else /* not bcc 3.0 */
-
-
- /*--- close() ---------------------------------------------------------------+
- | Replacement for the Turbo C close() function. |
- | Under Turbo C (up to Borland C++ v2.0, but not v3.0) close() is the only |
- | function which checks the file handle number. |
- +---------------------------------------------------------------------------*/
- extern int _close(int);
- extern int pascal __IOERROR(int n);
- int close(int fd)
- {
-
- if ( (fd < 0) || (fd >= MAX_FD) )
- return __IOERROR(6);
- else
- {
- _openfd[fd] = -1; /* Mark the entry as invalid. */
- return _close(fd); /* Do the work. */
- }
-
- }
-
-
- #ifndef USE_DOS67
- /* We need 15 extra bytes to allow us to align our table
- on a paragraph boundary */
- static unsigned char file_list[MAX_FD+15];
- #endif
-
-
- /*--- increase_handles() ----------------------------------------------------+
- | Increase the size of the handle table |
- +---------------------------------------------------------------------------*/
- void increase_handles(void)
- {
-
-
- /* We can use DOS service 0x67 to get a larger table for handles,
- but because of the way in which Turbo C handles the far heap
- we could not then allocate any memory from the far heap.
- This will cause problems with the far-data models (COMPACT,
- LARGE, and HUGE); it will not even be possible to open a stream
- because fopen() uses malloc() via setvbuf(). The use of DOS service
- 0x67 will also result in memory allocation failure with the
- small-data models (TINY, SMALL, and MEDIUM) if farmalloc() etc
- are ever used.
-
- This can be overcome by requesting DOS to change the memory allocation
- strategy before we use DOS service 0x67, but this may cause problems
- in certain programs.
-
- So, to be universally applicable for all data models, we default to
- taking care of the nitty-gritty details ourselves...
- */
-
- #if MAX_FD <= 20
- #error "MAX_FD must be > 20"
- #endif
-
- #ifdef USE_DOS67
- unsigned strategy;
- #else /* USE_DOS67 */
- unsigned char far *newblock; /* Must be a far pointer. */
- unsigned short psp = _psp; /* This is a trick needed only for
- the HUGE model */
- #endif /* USE_DOS67 */
-
-
- /* Set all of the remaining entries in _openfd[] to 0xffff.
- This is probably not required, but we do it just in case... */
- memset(_openfd+5, (MAX_FD-5)*sizeof(int), 0xff);
-
- #ifndef USE_DOS67
- newblock = file_list; /* Our new handle table will go here. */
-
- /* Align to a paragraph boundary. */
- if ( FP_OFF(newblock) & 0x000f )
- newblock = MK_FP(FP_SEG(newblock)+1, FP_OFF(newblock) & 0xfff0);
-
- /* Use asssembler here for efficiency when we are using the small-data
- models */
- #if __TURBOC__ > __TCC20__
- /* The asm {} construct appears to require higher than version 2.0 of
- Turbo C */
- asm {
- push ds
- les di, newblock
- mov ds, psp
- mov si, 0x18
- mov cx, 20
- cld
- repz movsb /* Copy the existing table. */
-
- mov cx, MAX_FD-20
- mov al, 0xff
- repz stosb /* Make the extra entries invalid. */
-
- sub di, MAX_FD /* Back to the start */
- mov ds:[0x34], di
- mov ds:[0x36], es /* Point to the table. */
- mov ds:[0x32], MAX_FD /* Set its size. */
-
- pop ds
- }
- #else /* we are using an early version of Turbo C */
- asm push ds
- asm les di, newblock
- asm mov ds, psp
- asm mov si, 0x18
- asm mov cx, 20
- asm cld
- asm repz movsb /* Copy the existing table. */
-
- asm mov cx, MAX_FD-20
- asm mov al, 0xff
- asm repz stosb /* Make the extra entries invalid. */
-
- asm sub di, MAX_FD /* Back to the start */
- asm mov ds:[0x34], di
- asm mov ds:[0x36], es /* Point to the table. */
- asm mov ds:[0x32], MAX_FD /* Set its size. */
-
- asm pop ds
-
- #endif /* __TURBOC__ > __TCC20__ */
-
- #endif /* Not USE_DOS67 */
-
- #ifdef USE_DOS67
-
- #define LAST_FIT 2
-
- /* DOS service 0x67 only works with DOS version >= 3.3 */
- asm {
- mov ah, 0x30 /* Get the DOS version. */
- int 0x21
- xchg al, ah /* Swap the byte order */
- /* to allow easy comparison. */
- cmp ax, 0x0303
- jb done /* Exit if the DOS version is not
- at least 3.3 */
-
- mov ah, 0x58
- mov al, 0 /* Get allocation strategy */
- mov bx, LAST_FIT
- int 0x21
- mov strategy, ax
-
- mov ah, 0x58
- mov al, 1 /* Set allocation strategy */
- mov bx, LAST_FIT
- int 0x21
-
- mov ah, 0x67 /* Set handle count */
- mov bx, MAX_FD
- int 0x21
-
- mov ah, 0x58
- mov al, 1 /* Set allocation strategy */
- mov bx, strategy
- int 0x21
-
- }
- #endif /* USE_DOS67 */
-
- done: ;
-
- }
-
- #endif /* not bcc 3.0 */
-