Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

616 lines
14 KiB

  1. /*static char *SCCSID = "%W% %E%";*/
  2. /*
  3. * Copyright Microsoft Corporation, 1983-1987
  4. *
  5. * This Module contains Proprietary Information of Microsoft
  6. * Corporation and should be treated as Confidential.
  7. */
  8. /*
  9. * STANDARD I/O:
  10. *
  11. * Standard (buffered) I/O package which is smaller and faster
  12. * than the MS C runtime stdio.
  13. */
  14. #include <fcntl.h>
  15. #include <minlit.h>
  16. #include <memory.h>
  17. #include <io.h>
  18. #include <string.h>
  19. #if NOT defined( _WIN32 )
  20. #define i386
  21. #endif
  22. #include <stdarg.h>
  23. #if OWNSTDIO
  24. #define STDSIZ 128 /* Size for stdin, stdout */
  25. #define BUFSIZ 1024 /* Size for other files */
  26. typedef char IOEBUF[STDSIZ]; /* For stdin, stdout */
  27. #define _NFILE 10
  28. #define _NSTD 2 /* # automatic stdio buffers */
  29. LOCAL IOEBUF _buf0;
  30. LOCAL IOEBUF _buf1;
  31. LOCAL int cffree = _NFILE - _NSTD;
  32. #if DOSX32 // hack needed untill the libc.lib is fixed
  33. int _cflush;
  34. #endif
  35. /*
  36. * typedef struct file
  37. * {
  38. * char *_ptr;
  39. * int _cnt;
  40. * char *_base;
  41. * char _flag;
  42. * char _file;
  43. * int _bsize;
  44. * }
  45. * FILE;
  46. */
  47. FILE _iob[_NFILE] =
  48. {
  49. { NULL, NULL, _buf0, _IOREAD, 0, STDSIZ },
  50. { _buf1, STDSIZ, _buf1, _IOWRT, 1, STDSIZ },
  51. };
  52. typedef struct file2
  53. {
  54. char _flag2;
  55. char _charbuf;
  56. int _bufsiz;
  57. int __tmpnum;
  58. char _padding[2]; /* pad out to size of FILE structure */
  59. }
  60. FILE2;
  61. FILE2 _iob2[_NFILE] =
  62. {
  63. {0x01, '\0', STDSIZ },
  64. {0x00, '\0', 0 }
  65. };
  66. #if (_MSC_VER >= 700)
  67. // 23-Jun-1993 HV Kill the near keyword to make the compiler happy
  68. #define near
  69. /* pointer to end of descriptors */
  70. FILE * near _lastiob = &_iob[ _NFILE -1];
  71. #endif
  72. /*
  73. * LOCAL FUNCTION PROTOTYPES
  74. */
  75. int cdecl _filbuf(f)
  76. REGISTER FILE *f;
  77. {
  78. if((f->_cnt = _read(f->_file,f->_base,f->_bsize)) <= 0)
  79. {
  80. if(!f->_cnt) f->_flag |= _IOEOF;
  81. else f->_flag |= _IOERR;
  82. return(EOF);
  83. }
  84. f->_ptr = f->_base;
  85. --f->_cnt;
  86. return((int) *f->_ptr++ & 0xff);
  87. }
  88. /* Just like _filbuf but don't return 1st char */
  89. void cdecl _xfilbuf(f)
  90. REGISTER FILE *f;
  91. {
  92. if((f->_cnt = _read(f->_file,f->_base,f->_bsize)) <= 0)
  93. {
  94. if(!f->_cnt) f->_flag |= _IOEOF;
  95. else f->_flag |= _IOERR;
  96. }
  97. f->_ptr = f->_base;
  98. }
  99. int cdecl _flsbuf(c,f)
  100. unsigned c;
  101. REGISTER FILE *f;
  102. {
  103. unsigned b;
  104. if(f->_flag & _IONBF)
  105. {
  106. b = c;
  107. if(_write(f->_file,&b,1) != 1)
  108. {
  109. f->_flag |= _IOERR;
  110. return(EOF);
  111. }
  112. f->_cnt = 0;
  113. return((int) c);
  114. }
  115. f->_cnt = f->_bsize - 1;
  116. if(_write(f->_file,f->_base,f->_bsize) != f->_bsize)
  117. {
  118. f->_flag |= _IOERR;
  119. return(EOF);
  120. }
  121. f->_ptr = f->_base;
  122. *f->_ptr++ = (char) c;
  123. return((int) c);
  124. }
  125. #if (_MSC_VER >= 700)
  126. int cdecl _flush(f)
  127. REGISTER FILE *f;
  128. {
  129. return(fflush(f));
  130. }
  131. #endif
  132. int cdecl fflush(f)
  133. REGISTER FILE *f;
  134. {
  135. REGISTER int i;
  136. if(f->_flag & _IONBF) return(0);
  137. if(f->_flag & _IOWRT)
  138. {
  139. i = f->_bsize - f->_cnt;
  140. f->_cnt = f->_bsize;
  141. if(i && _write(f->_file,f->_base,i) != i)
  142. {
  143. f->_flag |= _IOERR;
  144. return(EOF);
  145. }
  146. f->_ptr = f->_base;
  147. return(0);
  148. }
  149. if(f->_flag & _IOREAD)
  150. {
  151. f->_cnt = 0;
  152. return(0);
  153. }
  154. return(EOF);
  155. }
  156. int cdecl fclose(f)
  157. REGISTER FILE *f;
  158. {
  159. int rc; /* Return code from close() */
  160. if(!(f->_flag & _IOPEN))
  161. return(EOF);
  162. fflush(f);
  163. if(f->_file > 2)
  164. {
  165. rc = _close(f->_file);
  166. /* Free the file stream pointer regardless of close() return
  167. * value, since code elsewhere may be intentionally calling
  168. * fclose() on a file whose handle has already been closed.
  169. */
  170. f->_flag = 0;
  171. ++cffree;
  172. return(rc);
  173. }
  174. return(0);
  175. }
  176. long cdecl ftell(f)
  177. REGISTER FILE *f;
  178. {
  179. if(f->_flag & _IONBF) return(_lseek(f->_file,0L,1));
  180. if(f->_flag & _IOREAD) return(_lseek(f->_file,0L,1) - f->_cnt);
  181. if(f->_flag & _IOWRT) return(_lseek(f->_file,0L,1) + f->_bsize - f->_cnt);
  182. return(-1L);
  183. }
  184. int cdecl fseek(f,lfa,mode)
  185. REGISTER FILE *f;
  186. long lfa;
  187. int mode;
  188. {
  189. REGISTER int ilfa;
  190. f->_flag &= ~_IOEOF;
  191. if(f->_flag & _IONBF)
  192. {
  193. if(_lseek(f->_file,lfa,mode) != -1L) return(0);
  194. f->_flag |= _IOERR;
  195. return(EOF);
  196. }
  197. if(mode == 1)
  198. {
  199. if(f->_flag & _IOREAD)
  200. {
  201. if(((long) f->_cnt > lfa && lfa >= 0) ||
  202. (lfa < 0 && (long)(f->_base - f->_ptr) <= lfa))
  203. { /* If we won't go beyond the buffer */
  204. ilfa = (int) lfa;
  205. f->_cnt -= ilfa;
  206. f->_ptr += ilfa;
  207. return(0);
  208. }
  209. lfa -= f->_cnt;
  210. }
  211. }
  212. if(fflush(f)) return(EOF);
  213. if (mode != 2 && (f->_flag & _IOREAD))
  214. {
  215. /*
  216. * If absolute mode, or relative mode AND forward, seek to the
  217. * est preceding 512-byte boundary to optimize disk I/O.
  218. * It could be done for backward relative seeks as well, but we
  219. * would have to check whether the current file pointer (FP) is
  220. * on a 512-byte boundary. If FP were not on a 512-byte boundary,
  221. * we might attempt to seek before the beginning of the file.
  222. * (Example: FP = 0x2445, destination address = 0x0010, lfa = -0x2435,
  223. * mode = 1. Rounding of lfa to 512-boundary yields -0x2600
  224. * which is bogus.) FP will usually not be on a 512 boundary
  225. * at the end of file, for example. Solution is to keep track of
  226. * current FP. This is not worth the effort, especially since
  227. * seeks are rare because of the extended dictionary.
  228. * Use "lfa >= 0" as test, since if mode is 0 this will always be
  229. * true, and it also filters out backward relative seeks.
  230. */
  231. if(lfa >= 0)
  232. {
  233. /*
  234. * Optimization: eliminate relative seeks of 0.
  235. */
  236. if(mode == 0 || lfa & ~0x1ff)
  237. if (_lseek(f->_file, lfa & ~0x1ff, mode) == -1L)
  238. {
  239. f->_flag |= _IOERR;
  240. return(EOF);
  241. }
  242. _xfilbuf(f);
  243. f->_cnt -= lfa & 0x1ff; /* adjust _iobuf fields */
  244. f->_ptr += lfa & 0x1ff;
  245. return(0);
  246. }
  247. }
  248. if(_lseek(f->_file,lfa,mode) == -1L)
  249. {
  250. f->_flag |= _IOERR;
  251. return(EOF);
  252. }
  253. return(0);
  254. }
  255. int cdecl fgetc(f)
  256. REGISTER FILE *f;
  257. {
  258. return(getc(f));
  259. }
  260. int cdecl fputc(c,f)
  261. unsigned c;
  262. REGISTER FILE *f;
  263. {
  264. unsigned b;
  265. if(f->_flag & _IONBF)
  266. {
  267. b = c;
  268. if(_write(f->_file,&b,1) == 1) return((int) c);
  269. f->_flag |= _IOERR;
  270. return(EOF);
  271. }
  272. return(putc(c,f));
  273. }
  274. int cdecl fputs(s,f)
  275. REGISTER char *s;
  276. REGISTER FILE *f;
  277. {
  278. int i;
  279. if(f->_flag & _IONBF)
  280. {
  281. i = strlen(s);
  282. if(_write(f->_file,s,i) == i) return(0);
  283. f->_flag |= _IOERR;
  284. return(EOF);
  285. }
  286. for(; *s; ++s)
  287. if(putc(*s,f) == EOF) return(EOF);
  288. return(0);
  289. }
  290. int cdecl fread(pobj,cbobj,nobj,f)
  291. char *pobj;
  292. unsigned cbobj;
  293. unsigned nobj;
  294. FILE *f;
  295. {
  296. REGISTER int i; /* # bytes left to read */
  297. REGISTER unsigned j; /* # bytes to transfer to buffer */
  298. // special case for one block -- try to avoid all this junk
  299. if (cbobj == 1 && nobj <= (unsigned)f->_cnt)
  300. {
  301. memcpy(pobj, f->_ptr, nobj);
  302. f->_cnt -= nobj;
  303. f->_ptr += nobj;
  304. return nobj;
  305. }
  306. i = nobj*cbobj; /* Initial request ==> bytes */
  307. do
  308. {
  309. j = (i <= f->_cnt)? i: f->_cnt; /* Determine how much we can move */
  310. memcpy( pobj,f->_ptr,j); /* Move it */
  311. f->_cnt -= j; /* Update file count */
  312. f->_ptr += j; /* Update file pointer */
  313. i -= j; /* Update request count */
  314. pobj += j; /* Update buffer pointer */
  315. if (i && !f->_cnt) _xfilbuf(f); /* Fill buffer if necessary */
  316. } while (i && !(f->_flag & (_IOEOF|_IOERR)));
  317. return(nobj - i/cbobj);
  318. }
  319. /*
  320. * fwrite : standard library routine
  321. */
  322. int cdecl fwrite(pobj,cbobj,nobj,f)
  323. char *pobj; /* Pointer to buffer */
  324. int cbobj; /* # bytes per object */
  325. int nobj; /* # objects */
  326. register FILE *f; /* File stream */
  327. {
  328. register int cb; /* # bytes remaining to write */
  329. /* Check for error initially so we don't trash data unnecessarily. */
  330. if(ferror(f))
  331. return(0);
  332. /* Initialize count of bytes remaining to write. */
  333. cb = nobj * cbobj;
  334. if (cb > f->_cnt) // doesn't fit -- must flush
  335. if (fflush(f))
  336. return 0;
  337. if (cb > f->_cnt) // bigger than the buffer... don't bother copying
  338. {
  339. if (_write(f->_file, pobj, cb) != cb)
  340. return 0;
  341. }
  342. else
  343. {
  344. memcpy(f->_ptr, pobj, cb);
  345. f->_cnt -= cb;
  346. f->_ptr += cb;
  347. }
  348. return nobj;
  349. }
  350. int cdecl ungetc(c,f)
  351. int c;
  352. FILE *f;
  353. {
  354. if(!(f->_flag & _IONBF) && f->_cnt < f->_bsize && c != EOF)
  355. {
  356. ++f->_cnt;
  357. *--f->_ptr = (char) c;
  358. return(c);
  359. }
  360. return(EOF);
  361. }
  362. void cdecl flushall ()
  363. {
  364. FlsStdio();
  365. }
  366. #if (_MSC_VER >= 700)
  367. void cdecl _flushall ()
  368. {
  369. FlsStdio();
  370. }
  371. #endif
  372. void cdecl FlsStdio()
  373. {
  374. FILE *p;
  375. for(p = _iob; p < &_iob[_NSTD]; p++)
  376. if(p->_flag & _IOPEN) fclose(p);
  377. }
  378. /*
  379. * makestream
  380. *
  381. * Makes a file stream structure for a possibly already-opened file.
  382. * Does common work for fopen, fdopen.
  383. * If name parameter is NULL, then file has been opened, else use the
  384. * name.
  385. * RETURNS pointer to stream or NULL.
  386. */
  387. LOCAL FILE * NEAR cdecl makestream(mode,name,fh)
  388. char *mode;
  389. char *name;
  390. int fh;
  391. {
  392. REGISTER int i;
  393. REGISTER FILE *f;
  394. int openmode;
  395. int iOpenRet;
  396. if(!cffree--)
  397. {
  398. cffree = 0;
  399. return(NULL);
  400. }
  401. for(i = _NSTD; _iob[i]._flag & _IOPEN; ++i);
  402. f = &_iob[i];
  403. f->_base = NULL;
  404. f->_bsize = 0;
  405. f->_flag = _IONBF;
  406. if(name == NULL)
  407. f->_file = (char) fh;
  408. if(*mode == 'r')
  409. {
  410. openmode = O_RDONLY;
  411. if(mode[1] == 't')
  412. openmode |= O_TEXT;
  413. else if(mode[1] == 'b')
  414. openmode |= O_BINARY;
  415. if(name != NULL)
  416. {
  417. iOpenRet = _open(name,openmode);
  418. if (iOpenRet == -1)
  419. {
  420. ++cffree;
  421. return(NULL);
  422. }
  423. else
  424. {
  425. f->_file = (char) iOpenRet;
  426. }
  427. }
  428. f->_cnt = 0;
  429. f->_flag |= _IOREAD;
  430. return(f);
  431. }
  432. f->_cnt = f->_bsize;
  433. f->_ptr = f->_base;
  434. openmode = O_CREAT | O_TRUNC | O_WRONLY;
  435. if(mode[1] == 't')
  436. openmode |= O_TEXT;
  437. else if(mode[1] == 'b')
  438. openmode |= O_BINARY;
  439. if(name != NULL)
  440. {
  441. iOpenRet = _open(name,openmode, 0600);
  442. if (iOpenRet == -1)
  443. {
  444. ++cffree;
  445. return(NULL);
  446. }
  447. else
  448. {
  449. f->_file = (char) iOpenRet;
  450. }
  451. }
  452. f->_flag |= _IOWRT;
  453. return(f);
  454. }
  455. /*
  456. * fopen : (standard library routine)
  457. *
  458. * WARNING: This is a LIMITED version of fopen(). Only "r" and
  459. * "w" modes are supported.
  460. */
  461. FILE * cdecl fopen(name,mode)
  462. char *name;
  463. char *mode;
  464. {
  465. return(makestream(mode,name,0));
  466. }
  467. /*
  468. * fdopen : (standard library routine)
  469. *
  470. * WARNING: This is a LIMITED version of fdopen(). Only "r" and
  471. * "w" modes are supported.
  472. */
  473. FILE * cdecl fdopen(fh,mode)
  474. int fh;
  475. char *mode;
  476. {
  477. return(makestream(mode,NULL,fh));
  478. }
  479. /*
  480. * setvbuf : standard library routine
  481. *
  482. * WARNING: This is a LIMITED version of setvbuf(). Only
  483. * type _IOFBF is supported.
  484. */
  485. int cdecl setvbuf (fh, buf, type, size)
  486. FILE *fh;
  487. char *buf;
  488. int type;
  489. int size;
  490. {
  491. if(fflush(fh) || type != _IOFBF)
  492. return(EOF);
  493. fh->_base = buf;
  494. fh->_flag &= ~_IONBF;
  495. fh->_bsize = size;
  496. if(fh->_flag & _IOWRT)
  497. {
  498. fh->_cnt = size;
  499. fh->_ptr = buf;
  500. }
  501. return(0);
  502. }
  503. #endif
  504. int
  505. __cdecl
  506. printf(char *fmt, ...)
  507. {
  508. va_list marker;
  509. int ret;
  510. va_start(marker, fmt);
  511. ret = vfprintf(stdout, fmt, marker);
  512. fflush(stdout);
  513. va_end(marker);
  514. return ret;
  515. }
  516. //
  517. // DLH Can't use fprintf or vfprintf from MSVCRT.DLL, since the FILE structure
  518. // is too different.
  519. //
  520. int cdecl fprintf(struct file *f, const char *fmt, ...)
  521. {
  522. va_list marker;
  523. int ret;
  524. va_start(marker, fmt);
  525. ret = vfprintf(f, fmt, marker);
  526. fflush(f);
  527. va_end(marker);
  528. return ret;
  529. }
  530. int cdecl vfprintf(struct file *f, const char *fmt, va_list pArgs)
  531. {
  532. int cb;
  533. static char szBuf[4096];
  534. cb = vsprintf(szBuf, fmt, pArgs);
  535. fwrite(szBuf, 1, cb, f);
  536. return cb;
  537. }