home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume36 / chiaro / part03 < prev    next >
Text File  |  1993-03-25  |  56KB  |  1,665 lines

  1. Newsgroups: comp.sources.misc
  2. From: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  3. Subject: v36i073:  chiaro - Image Utilities, Part03/18
  4. Message-ID: <1993Mar25.180955.19956@sparky.imd.sterling.com>
  5. X-Md4-Signature: 333f4ee5e8f18c13f5e9976edf54844d
  6. Date: Thu, 25 Mar 1993 18:09:55 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  10. Posting-number: Volume 36, Issue 73
  11. Archive-name: chiaro/part03
  12. Environment: UNIX, Sun, DECstation, 3B1
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  src/fb.c src/shorten.awk src/token.c
  19. # Wrapped by kent@sparky on Thu Mar 25 11:20:02 1993
  20. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 3 (of 18)."'
  23. if test -f 'src/fb.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'src/fb.c'\"
  25. else
  26.   echo shar: Extracting \"'src/fb.c'\" \(45520 characters\)
  27.   sed "s/^X//" >'src/fb.c' <<'END_OF_FILE'
  28. X/***************************************************************************
  29. X*   FB.C                                                                   *
  30. X*   MODULE:  FB (File Buffer)                                              *
  31. X*   OS:      UNIX                                                          *
  32. X*                                                                          *
  33. X*   Copyright (c) 1993 James W. Birdsall. All Rights Reserved.             *
  34. X*                                                                          *
  35. X*   $Id: fb.c,v 1.7 1993/03/02 00:50:57 jwbirdsa Exp $
  36. X*                                                                          *
  37. X*   This file contains the File Buffer module, which implements high-      *
  38. X*   performance read/write buffering of files.                             *
  39. X*                                                                          *
  40. X*   Functions in this file are:                                            *
  41. X*     fb_init          initializes file buffering package                  *
  42. X*     fb_open          opens a file with buffering                         *
  43. X*     fb_retrofit      buffers an already-open file                        *
  44. X*     fb_close         closes a buffered file                              *
  45. X*                                                                          *
  46. X*     fb_seek          resets the file pointer in a buffered file          *
  47. X*     fb_tell          returns current file pointer in buffered file       *
  48. X*                                                                          *
  49. X*     fb_read          reads from a buffered file                          *
  50. X*     fb_getc          reads a single character from a buffered file       *
  51. X*                                                                          *
  52. X*     fb_errstring     returns a string corresponding to an error          *
  53. X*                                                                          *
  54. X*   The following functions are available only if READONLY was not defined *
  55. X*   at compile time (otherwise, dummy functions):                          *
  56. X*                                                                          *
  57. X*     fb_write         writes to a buffered file                           *
  58. X*     fb_putc          writes a single character to a buffered file        *
  59. X*                                                                          *
  60. X***************************************************************************/
  61. X
  62. X#include "config.h"
  63. X
  64. X/*
  65. X** system includes <>
  66. X*/
  67. X
  68. X#include <stdio.h>
  69. X#include <ctype.h>
  70. X#include <sys/types.h>
  71. X#include <sys/stat.h>
  72. X#ifndef NO_STDLIB
  73. X#include <stdlib.h>
  74. X#else
  75. X#ifndef NO_MALLOCHDR
  76. X#include <malloc.h>
  77. X#endif
  78. X#endif
  79. X#ifndef NO_MEMOP
  80. X#include <memory.h>
  81. X#endif
  82. X
  83. X/*
  84. X** custom includes ""
  85. X*/
  86. X
  87. X#include "depend.h"
  88. X#include "fb.h"
  89. X
  90. X/*
  91. X** local #defines
  92. X*/
  93. X
  94. X/* A macro to set fb_error and return with the same value. */
  95. X
  96. X#define RETURN(x)     return(fb_error = (x))
  97. X
  98. X/* A macro to check for FB module initialization and RETURN. */
  99. X
  100. X#define INITCHECK()   if (0 == fb_isinit) RETURN(FB_NOTINIT_E)
  101. X
  102. X
  103. X/*
  104. X** misc: copyright strings, version macros, etc.
  105. X*/
  106. X
  107. X/*
  108. X**typedefs
  109. X*/
  110. X
  111. X/*
  112. X** global variables
  113. X*/
  114. X
  115. XULONG fb_error;                         /* error/status storage */
  116. X
  117. X/*
  118. X** static globals
  119. X*/
  120. X
  121. Xstatic int fb_numopen;                  /* number of files open */
  122. Xstatic int fb_tablesize;                /* max number of files open */
  123. Xstatic int fb_buflen;                   /* length of buffer */
  124. Xstatic int fb_isinit = 0;               /* initialization flag */
  125. X
  126. Xstatic char CONST rcsid[] = "$Id: fb.c,v 1.7 1993/03/02 00:50:57 jwbirdsa Exp $";
  127. X
  128. X
  129. X/*
  130. X** function prototypes
  131. X*/
  132. X
  133. X/* function prototypes courtesy of the 'mkptypes' program */
  134. X#ifdef  __STDC__
  135. X# define P_(s) s
  136. X#else
  137. X# define P_(s) ()
  138. X#endif
  139. X
  140. Xstatic ULONG fb_flbuf P_((FB *filehandle));
  141. Xstatic int fb_bufget P_((FB *filehandle));
  142. X
  143. X#undef P_
  144. X
  145. X#ifdef NO_MALLOCHDR
  146. Xextern UCHAR *malloc();
  147. Xextern VOID free();
  148. X#endif
  149. X
  150. X
  151. X/*
  152. X** functions
  153. X*/
  154. X
  155. X/***************************************************************************
  156. X*   FUNCTION: fb_init                                                      *
  157. X*                                                                          *
  158. X*   DESCRIPTION:                                                           *
  159. X*                                                                          *
  160. X*       Initializes the FB module.                                         *
  161. X*                                                                          *
  162. X*   ENTRY:                                                                 *
  163. X*                                                                          *
  164. X*       tablesize  - maximum number of files that can be open at once      *
  165. X*       buffersize - size (in bytes) of standard buffer                    *
  166. X*                                                                          *
  167. X*   EXIT:                                                                  *
  168. X*                                                                          *
  169. X*       Returns an error/status code.                                      *
  170. X*                                                                          *
  171. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  172. X*                                                                          *
  173. X*       Sets up various global variables. Sets the initialization flag     *
  174. X*       fb_isinit to 1.                                                    *
  175. X*                                                                          *
  176. X*       Note that tablesize does not actually affect how much memory is    *
  177. X*       used, since there is no static file table. However, future         *
  178. X*       revisions may introduce one, so it should be set accurately.       *
  179. X*                                                                          *
  180. X***************************************************************************/
  181. XULONG
  182. X#ifdef __STDC__
  183. Xfb_init(int tablesize, int buffersize)
  184. X#else
  185. Xfb_init(tablesize, buffersize)
  186. Xint tablesize;
  187. Xint buffersize;
  188. X#endif
  189. X{
  190. X    /* Check for initialization already. */
  191. X
  192. X    if (fb_isinit)
  193. X    {
  194. X        RETURN(FB_REINIT_E);
  195. X    }
  196. X
  197. X    /* Set up global variables. */
  198. X
  199. X    if (tablesize < 0)
  200. X    {
  201. X        RETURN(FB_BADPARAM_E);
  202. X    }
  203. X    fb_tablesize = tablesize;
  204. X    fb_numopen = 0;
  205. X
  206. X    /* Check buffer size. */
  207. X
  208. X    if ((buffersize < FB_MINBUFFER) && (buffersize >= 0))
  209. X    {
  210. X        /* If too small, adjust to minimum buffer size. */
  211. X
  212. X        fb_buflen = FB_MINBUFFER;
  213. X    }
  214. X#ifdef INT16
  215. X    else if (buffersize < 0)
  216. X    {
  217. X        /* Buffer too large (wrapped to negative). Only on 16-bit machines. */
  218. X
  219. X        fb_buflen = FB_MAXBUFFER;
  220. X    }
  221. X#endif
  222. X    else
  223. X    {
  224. X        /* Buffer size OK. */
  225. X
  226. X        fb_buflen = buffersize;
  227. X    }
  228. X
  229. X    /* Set initialization flag. */
  230. X
  231. X    fb_isinit = 1;
  232. X
  233. X    RETURN(ST_SUCCESS);
  234. X} /* end of fb_init() */
  235. X
  236. X
  237. X/***************************************************************************
  238. X*   FUNCTION: fb_open                                                      *
  239. X*                                                                          *
  240. X*   DESCRIPTION:                                                           *
  241. X*                                                                          *
  242. X*       Opens a file, with buffering.                                      *
  243. X*                                                                          *
  244. X*   ENTRY:                                                                 *
  245. X*                                                                          *
  246. X*       filename - ASCIIZ filespec of file to be opened                    *
  247. X*       filemode - mode for open: 'r' read or 'w' write                    *
  248. X*       length   - pointer to long for return of file length               *
  249. X*                                                                          *
  250. X*   EXIT:                                                                  *
  251. X*                                                                          *
  252. X*       Returns a FB handle on success, NULL on failure.                   *
  253. X*                                                                          *
  254. X*       Sets the global fb_error to an error/status code.                  *
  255. X*                                                                          *
  256. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  257. X*                                                                          *
  258. X***************************************************************************/
  259. XFB *
  260. X#ifdef __STDC__
  261. Xfb_open(char *filename, char filemode, long *length)
  262. X#else
  263. Xfb_open(filename, filemode, length)
  264. Xchar *filename;
  265. Xchar filemode;
  266. Xlong *length;
  267. X#endif
  268. X{
  269. X    char *modestring;                     /* file mode string for fopen() */
  270. X    FB *filehandle;                       /* FB handle */
  271. X    char c;
  272. X#ifndef NO_STAT
  273. X    struct stat info;                     /* file info structure */
  274. X#endif
  275. X
  276. X    /* Check for initialization. */
  277. X
  278. X    if (0 == fb_isinit)
  279. X    {
  280. X        fb_error = FB_NOTINIT_E;
  281. X        return (FB *) NULL;
  282. X    }
  283. X
  284. X    /* Check filemode. */
  285. X
  286. X    c = tolower(filemode);
  287. X#ifndef READONLY
  288. X    if ((c != 'r') && (c != 'w'))
  289. X#else
  290. X    if (c != 'r')
  291. X#endif
  292. X    {
  293. X        fb_error = FB_BADPARAM_E;
  294. X        return (FB *) NULL;
  295. X    }
  296. X    if ('r' == c)
  297. X    {
  298. X        modestring = FOPEN_READ_BINARY;
  299. X    }
  300. X#ifndef READONLY
  301. X    else
  302. X    {
  303. X        modestring = FOPEN_WRITE_BINARY;
  304. X    }  
  305. X#endif
  306. X
  307. X    /* Check for free handle. */
  308. X
  309. X    if (fb_numopen >= fb_tablesize)
  310. X    {
  311. X        fb_error = FB_NOHANDLE_E;
  312. X        return (FB *) NULL;
  313. X    }
  314. X
  315. X    /* Allocate FB. */
  316. X
  317. X    if ((filehandle = (FB *) malloc(sizeof(FB))) == (FB *) NULL)
  318. X    {
  319. X        fb_error = FB_NOMEM_E;
  320. X        return (FB *) NULL;
  321. X    }
  322. X
  323. X    /* Allocate buffer. */
  324. X
  325. X    filehandle->buffer = (UCHAR *) malloc(fb_buflen * sizeof(UCHAR));
  326. X    if (((UCHAR *) NULL) == filehandle->buffer)
  327. X    {
  328. X        fb_error = FB_NOMEMBUF_E;
  329. X        free(filehandle);
  330. X        return (FB *) NULL;
  331. X    }
  332. X
  333. X    /* Open file. */
  334. X
  335. X    if ((filehandle->rawfile = fopen(filename, modestring)) == (FILE *) NULL)
  336. X    {
  337. X        fb_error = FB_NOFILE_E;
  338. X        free(filehandle->buffer);
  339. X        free(filehandle);
  340. X        return (FB *) NULL;
  341. X    }
  342. X
  343. X    /* Get file length (if open for read). */
  344. X
  345. X#ifndef READONLY
  346. X    if ('r' == c)
  347. X    {
  348. X#endif
  349. X        if (fstat(fileno(filehandle->rawfile), &info))
  350. X        {
  351. X            fb_error = FB_FILEERR_F;
  352. X            fclose(filehandle->rawfile);
  353. X            free(filehandle->buffer);
  354. X            free(filehandle);
  355. X            return (FB *) NULL;
  356. X        }
  357. X
  358. X        /* Return length of file, in bytes. */
  359. X
  360. X        *length = info.st_size;
  361. X#ifndef READONLY
  362. X    }
  363. X#endif
  364. X
  365. X    /* Set up variables. */
  366. X
  367. X    filehandle->bufvalid = 0;
  368. X    filehandle->bufloc = 0;
  369. X    filehandle->bufoffset = 0;
  370. X    filehandle->filemode = c;
  371. X
  372. X    /* Adjust global variables. */
  373. X    fb_numopen++;
  374. X
  375. X    /* All OK. */
  376. X
  377. X    fb_error = ST_SUCCESS;
  378. X
  379. X    return filehandle;
  380. X} /* end of fb_open() */
  381. X
  382. X
  383. X/***************************************************************************
  384. X*   FUNCTION: fb_retrofit                                                  *
  385. X*                                                                          *
  386. X*   DESCRIPTION:                                                           *
  387. X*                                                                          *
  388. X*       Adds buffering to a file already opened.                           *
  389. X*                                                                          *
  390. X*   ENTRY:                                                                 *
  391. X*                                                                          *
  392. X*       rawfile  - file handle of file to be buffered                      *
  393. X*       filemode - mode of the file: 'r' read or 'w' write                 *
  394. X*                  IT IS IMPERATIVE THAT THIS MODE BE ACCURATE             *
  395. X*                                                                          *
  396. X*   EXIT:                                                                  *
  397. X*                                                                          *
  398. X*       Returns a FB handle on success, NULL on failure.                   *
  399. X*                                                                          *
  400. X*       Sets the global fb_error to an error/status code.                  *
  401. X*                                                                          *
  402. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  403. X*                                                                          *
  404. X***************************************************************************/
  405. XFB *
  406. X#ifdef __STDC__
  407. Xfb_retrofit(FILE *rawfile, char filemode)
  408. X#else
  409. Xfb_retrofit(rawfile, filemode)
  410. XFILE *rawfile;
  411. Xchar filemode;
  412. X#endif
  413. X{
  414. X    char mode;                      /* file mode */
  415. X    FB *filehandle;                 /* FB handle */
  416. X
  417. X    /* Check for initialization. */
  418. X
  419. X    if (0 == fb_isinit)
  420. X    {
  421. X        fb_error = FB_NOTINIT_E;
  422. X        return (FB *) NULL;
  423. X    }
  424. X
  425. X    /* Check filemode. */
  426. X
  427. X    mode = tolower(filemode);
  428. X#ifndef READONLY
  429. X    if ((mode != 'r') && (mode != 'w'))
  430. X#else
  431. X    if (mode != 'r')
  432. X#endif
  433. X    {
  434. X        fb_error = FB_BADPARAM_E;
  435. X        return (FB *) NULL;
  436. X    }
  437. X
  438. X    /* Check for free handle. */
  439. X
  440. X    if (fb_numopen >= fb_tablesize)
  441. X    {
  442. X        fb_error = FB_NOHANDLE_E;
  443. X        return (FB *) NULL;
  444. X    }
  445. X
  446. X    /* Allocate FB. */
  447. X
  448. X    if ((filehandle = (FB *) malloc(sizeof(FB))) == (FB *) NULL)
  449. X    {
  450. X        fb_error = FB_NOMEM_E;
  451. X        return (FB *) NULL;
  452. X    }
  453. X
  454. X    /* Allocate buffer. */
  455. X
  456. X    filehandle->buffer = (UCHAR *) malloc(fb_buflen * sizeof(UCHAR));
  457. X    if (((UCHAR *) NULL) == filehandle->buffer)
  458. X    {
  459. X        fb_error = FB_NOMEMBUF_E;
  460. X        free(filehandle);
  461. X        return (FB *) NULL;
  462. X    }
  463. X
  464. X    /* Get position in file. */
  465. X
  466. X    if ((filehandle->bufoffset = ftell(rawfile)) == -1L)
  467. X    {
  468. X        fb_error = FB_FILEERR_F;
  469. X        free(filehandle->buffer);
  470. X        free(filehandle);
  471. X        return (FB *) NULL;
  472. X    }
  473. X
  474. X    /* Set up variables. */
  475. X
  476. X    filehandle->bufvalid = 0;
  477. X    filehandle->bufloc = 0;
  478. X    filehandle->rawfile = rawfile;
  479. X    filehandle->filemode = mode;
  480. X
  481. X    /* Adjust global variables. */
  482. X
  483. X    fb_numopen++;
  484. X
  485. X    /* All OK. */
  486. X
  487. X    fb_error = ST_SUCCESS;
  488. X
  489. X    return filehandle;
  490. X} /* end of fb_retrofit() */
  491. X
  492. X
  493. X/***************************************************************************
  494. X*   FUNCTION: fb_close                                                     *
  495. X*                                                                          *
  496. X*   DESCRIPTION:                                                           *
  497. X*                                                                          *
  498. X*       Flushes buffers as necessary and closes a buffered file.           *
  499. X*                                                                          *
  500. X*   ENTRY:                                                                 *
  501. X*                                                                          *
  502. X*       filehandle - FB handle of file to be closed                        *
  503. X*                                                                          *
  504. X*   EXIT:                                                                  *
  505. X*                                                                          *
  506. X*       Returns an error/status code.                                      *
  507. X*                                                                          *
  508. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  509. X*                                                                          *
  510. X***************************************************************************/
  511. XULONG
  512. X#ifdef __STDC__
  513. Xfb_close(FB *filehandle)
  514. X#else
  515. Xfb_close(filehandle)
  516. XFB *filehandle;
  517. X#endif
  518. X{
  519. X    /* Check for initialization. */
  520. X
  521. X    INITCHECK();
  522. X
  523. X#ifndef READONLY
  524. X    /* File open for writing? */
  525. X
  526. X    if ('w' == filehandle->filemode)
  527. X    {
  528. X        /* Characters in buffer? */
  529. X
  530. X        if (filehandle->bufvalid > 0)
  531. X        {
  532. X            /* Flush buffer to disk. */
  533. X
  534. X            if (fb_flbuf(filehandle))
  535. X            {
  536. X                return fb_error;
  537. X            }
  538. X        }
  539. X    }
  540. X#endif
  541. X
  542. X    /* Close raw file. */
  543. X
  544. X    if (fclose(filehandle->rawfile))
  545. X    {
  546. X        RETURN(FB_FILEERR_F);
  547. X    }
  548. X
  549. X    /* Free memory. */
  550. X
  551. X    free(filehandle->buffer);
  552. X    free(filehandle);
  553. X
  554. X    /* Adjust global variables. */
  555. X
  556. X    fb_numopen--;
  557. X
  558. X    /* All OK. */
  559. X
  560. X    RETURN(ST_SUCCESS);
  561. X} /* end of fb_close() */
  562. X
  563. X
  564. X/***************************************************************************
  565. X*   FUNCTION: fb_seek                                                      *
  566. X*                                                                          *
  567. X*   DESCRIPTION:                                                           *
  568. X*                                                                          *
  569. X*       Repositions the file pointer in a buffered file.                   *
  570. X*                                                                          *
  571. X*   ENTRY:                                                                 *
  572. X*                                                                          *
  573. X*       filehandle - handle of file                                        *
  574. X*       offset     - desired offset in bytes from beginning of file        *
  575. X*                                                                          *
  576. X*   EXIT:                                                                  *
  577. X*                                                                          *
  578. X*       Returns an error/status code.                                      *
  579. X*                                                                          *
  580. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  581. X*                                                                          *
  582. X*       Flushes buffers to disk if file is in write mode.                  *
  583. X*                                                                          *
  584. X***************************************************************************/
  585. XULONG
  586. X#ifdef __STDC__
  587. Xfb_seek(FB *filehandle, long offset)
  588. X#else
  589. Xfb_seek(filehandle, offset)
  590. XFB *filehandle;
  591. Xlong offset;
  592. X#endif
  593. X{
  594. X    /* Check for initialization. */
  595. X
  596. X    INITCHECK();
  597. X
  598. X    if (('r' == filehandle->filemode) &&
  599. X        ((offset >= (filehandle->bufoffset - filehandle->bufvalid)) &&
  600. X         (offset < filehandle->bufoffset)))
  601. X    {
  602. X        /* 
  603. X        ** If file is open for reading and the new position is within
  604. X        ** the current buffer, reset the index.
  605. X        */
  606. X
  607. X        filehandle->bufloc = (int) (offset - (filehandle->bufoffset -
  608. X                                              filehandle->bufvalid));
  609. X        RETURN(ST_SUCCESS);
  610. X    }
  611. X
  612. X#ifndef READONLY
  613. X    /* File open for writing? */
  614. X
  615. X    if ('w' == filehandle->filemode)
  616. X    {
  617. X        /* Is the new position within buffer? */
  618. X
  619. X        if ((offset >= filehandle->bufoffset) &&
  620. X            (offset < (filehandle->bufoffset + fb_buflen)))
  621. X        {
  622. X            /* Reset index. */
  623. X
  624. X            filehandle->bufloc = (int) (offset - filehandle->bufoffset);
  625. X            RETURN(ST_SUCCESS);
  626. X        }
  627. X
  628. X        /* Else, are there characters in buffer? */
  629. X
  630. X        if (filehandle->bufvalid > 0)
  631. X        {
  632. X            /* Flush buffers to disk before resetting position. */
  633. X
  634. X            if (fb_flbuf(filehandle))
  635. X            {
  636. X                return fb_error;
  637. X            }
  638. X        }
  639. X    }
  640. X#endif
  641. X
  642. X    /* Set raw file to new position. */
  643. X
  644. X    if (fseek(filehandle->rawfile, offset, SEEK_SET))
  645. X    {
  646. X        RETURN(FB_FILEERR_F);
  647. X    }
  648. X
  649. X    /* Reset variables. */
  650. X
  651. X    filehandle->bufvalid = 0;
  652. X    filehandle->bufloc = 0;
  653. X    filehandle->bufoffset = offset;
  654. X
  655. X    /* All OK. */
  656. X
  657. X    RETURN(ST_SUCCESS);
  658. X} /* end of fb_seek */
  659. X
  660. X
  661. X/***************************************************************************
  662. X*   FUNCTION: fb_tell                                                      *
  663. X*                                                                          *
  664. X*   DESCRIPTION:                                                           *
  665. X*                                                                          *
  666. X*       Returns the current file pointer in a buffered file.               *
  667. X*                                                                          *
  668. X*   ENTRY:                                                                 *
  669. X*                                                                          *
  670. X*       filehandle - handle of file                                        *
  671. X*                                                                          *
  672. X*   EXIT:                                                                  *
  673. X*                                                                          *
  674. X*       Returns the offset in bytes of the current position from the       *
  675. X*       beginning of a file, or -1L on error.                              *
  676. X*                                                                          *
  677. X*       Sets the global fb_error to an error/status code.                  *
  678. X*                                                                          *
  679. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  680. X*                                                                          *
  681. X***************************************************************************/
  682. Xlong
  683. X#ifdef __STDC__
  684. Xfb_tell(FB *filehandle)
  685. X#else
  686. Xfb_tell(filehandle)
  687. XFB *filehandle;
  688. X#endif
  689. X{
  690. X    /* Check for initialization. */
  691. X
  692. X    if (0 == fb_isinit)
  693. X    {
  694. X        fb_error = FB_NOTINIT_E;
  695. X        return -1L;
  696. X    }
  697. X
  698. X    /* All OK. */
  699. X
  700. X    fb_error = ST_SUCCESS;
  701. X
  702. X    /* Calculate offset and return. */
  703. X
  704. X    if ('r' == filehandle->filemode)
  705. X    {
  706. X        return ((long)(filehandle->bufoffset - filehandle->bufvalid +
  707. X                       filehandle->bufloc));
  708. X    }
  709. X    else
  710. X    {
  711. X        return ((long)(filehandle->bufoffset + filehandle->bufloc));
  712. X    }
  713. X} /* end of fb_tell() */
  714. X
  715. X
  716. X/***************************************************************************
  717. X*   FUNCTION: fb_flush                                                     *
  718. X*                                                                          *
  719. X*   DESCRIPTION:                                                           *
  720. X*                                                                          *
  721. X*       Flushes buffers. For files in write mode, the buffers are written  *
  722. X*       to disk. For files in read mode, the current buffer contents are   *
  723. X*       dumped and the buffers re-loaded from disk.                        *
  724. X*                                                                          *
  725. X*   ENTRY:                                                                 *
  726. X*                                                                          *
  727. X*       filehandle - handle of file                                        *
  728. X*                                                                          *
  729. X*   EXIT:                                                                  *
  730. X*                                                                          *
  731. X*       Returns an error/status code.                                      *
  732. X*                                                                          *
  733. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  734. X*                                                                          *
  735. X***************************************************************************/
  736. XULONG
  737. X#ifdef __STDC__
  738. Xfb_flush(FB *filehandle)
  739. X#else
  740. Xfb_flush(filehandle)
  741. XFB *filehandle;
  742. X#endif
  743. X{
  744. X
  745. X    /* Check for initialization. */
  746. X
  747. X    INITCHECK();
  748. X
  749. X    if ('r' == filehandle->filemode)
  750. X    {
  751. X        /* File in read mode, refill buffer from disk. */
  752. X
  753. X        fb_bufget(filehandle);
  754. X        return fb_error;
  755. X    }
  756. X#ifndef READONLY
  757. X    else if ('w' == filehandle->filemode)
  758. X    {
  759. X        /* File in write mode, flush buffer to disk. */
  760. X
  761. X        fb_flbuf(filehandle);
  762. X        return fb_error;
  763. X    }
  764. X#endif
  765. X
  766. X    /* Else error. */
  767. X
  768. X    RETURN(FB_BADPARAM_E);
  769. X} /* end of fb_flush() */
  770. X
  771. X
  772. X/***************************************************************************
  773. X*   FUNCTION: fb_read                                                      *
  774. X*                                                                          *
  775. X*   DESCRIPTION:                                                           *
  776. X*                                                                          *
  777. X*       Reads bytes from a buffered file. Note that fb_getc() is more      *
  778. X*       efficient if only one byte is desired.                             *
  779. X*                                                                          *
  780. X*   ENTRY:                                                                 *
  781. X*                                                                          *
  782. X*       filehandle - handle of file                                        *
  783. X*       buffer     - buffer to read bytes into                             *
  784. X*       count      - number of bytes to read                               *
  785. X*                                                                          *
  786. X*   EXIT:                                                                  *
  787. X*                                                                          *
  788. X*       Returns number of bytes actually read. Short count can occur       *
  789. X*       on error or EOF.                                                   *
  790. X*                                                                          *
  791. X*       Sets global fb_error to an error/status code.                      *
  792. X*                                                                          *
  793. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  794. X*                                                                          *
  795. X***************************************************************************/
  796. Xint
  797. X#ifdef __STDC__
  798. Xfb_read(FB *filehandle, UCHAR *buffer, int count)
  799. X#else
  800. Xfb_read(filehandle, buffer, count)
  801. XFB *filehandle;
  802. XUCHAR *buffer;
  803. Xint count;
  804. X#endif
  805. X{
  806. X    int bufavail;                 /* bytes available in buffer */
  807. X    int bytesread;                /* bytes read from disk */
  808. X
  809. X    /* Check for initialization. */
  810. X
  811. X    if (0 == fb_isinit)
  812. X    {
  813. X        fb_error = FB_NOTINIT_E;
  814. X        return 0;
  815. X    }
  816. X
  817. X    /* Check parameters. */
  818. X
  819. X    if ((filehandle->filemode != 'r') || (count <= 0))
  820. X    {
  821. X        /* if file is not in read mode, or count is negative, error */
  822. X        fb_error = FB_BADPARAM_E;
  823. X        return 0;
  824. X    }
  825. X
  826. X    /* Get bytes remaining in buffer. */
  827. X
  828. X    bufavail = filehandle->bufvalid - filehandle->bufloc;
  829. X
  830. X    /* If enough in buffer, read from buffer. */
  831. X
  832. X    if (count <= bufavail)
  833. X    {
  834. X        /* Copy bytes from buffer to destination. */
  835. X
  836. X        memcpy(buffer, (filehandle->buffer + filehandle->bufloc),
  837. X               (count * sizeof(UCHAR)));
  838. X
  839. X        /* Update variables. */
  840. X
  841. X        filehandle->bufloc += count;
  842. X
  843. X        /* All OK. */
  844. X
  845. X        fb_error = ST_SUCCESS;
  846. X        return count;
  847. X    }
  848. X    else
  849. X    {
  850. X        /* Copy what's in buffer. */
  851. X
  852. X        memcpy(buffer, (filehandle->buffer + filehandle->bufloc),
  853. X               (bufavail * sizeof(UCHAR)));
  854. X
  855. X        /* Finish reading directly from disk. */
  856. X
  857. X        bytesread = fread((buffer + bufavail), sizeof(UCHAR),
  858. X                          (count - bufavail), filehandle->rawfile);
  859. X
  860. X
  861. X        if (bytesread != (count - bufavail))
  862. X        {
  863. X            /* Short read. If EOF, return FB_EOF_W; otherwise, error. */
  864. X
  865. X            fb_error = (feof(filehandle->rawfile) ? FB_EOF_W : FB_FILEERR_F);
  866. X
  867. X            /* Adjust variables. */
  868. X
  869. X            filehandle->bufvalid = 0;
  870. X            filehandle->bufloc = 0;
  871. X            filehandle->bufoffset += bytesread;
  872. X
  873. X            /* Return number of bytes actually delivered. */
  874. X
  875. X            return (bytesread + bufavail);
  876. X        }
  877. X        else
  878. X        {
  879. X            /* Full read, all OK. Update variables. */
  880. X
  881. X            filehandle->bufoffset += bytesread;
  882. X
  883. X            /* Refill buffer. */
  884. X
  885. X            fb_bufget(filehandle);
  886. X
  887. X            /* All OK. */
  888. X
  889. X            fb_error = ST_SUCCESS;
  890. X            return count;
  891. X        } /* end of if short read... else... */
  892. X    } /* end of if enough in buffer... else... */
  893. X} /* end of fb_read() */
  894. X
  895. X
  896. X/***************************************************************************
  897. X*   FUNCTION: fb_getc                                                      *
  898. X*                                                                          *
  899. X*   DESCRIPTION:                                                           *
  900. X*                                                                          *
  901. X*       Gets a single byte from a buffered file.                           *
  902. X*                                                                          *
  903. X*   ENTRY:                                                                 *
  904. X*                                                                          *
  905. X*       filehandle - handle of file                                        *
  906. X*                                                                          *
  907. X*   EXIT:                                                                  *
  908. X*                                                                          *
  909. X*       Returns an integer with byte in LSB, or -1 (0xFFFF) on error.      *
  910. X*                                                                          *
  911. X*       Sets global fb_error to an error/status code.                      *
  912. X*                                                                          *
  913. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  914. X*                                                                          *
  915. X***************************************************************************/
  916. Xint
  917. X#ifdef __STDC__
  918. Xfb_getc(FB *filehandle)
  919. X#else
  920. Xfb_getc(filehandle)
  921. XFB *filehandle;
  922. X#endif
  923. X{
  924. X    /* Check for initialization. */
  925. X
  926. X    if (0 == fb_isinit)
  927. X    {
  928. X        fb_error = FB_NOTINIT_E;
  929. X        return -1;
  930. X    }
  931. X
  932. X    /* Check filemode. */
  933. X
  934. X    if (filehandle->filemode != 'r')
  935. X    {
  936. X        fb_error = FB_BADPARAM_E;
  937. X        return -1;
  938. X    }
  939. X
  940. X    /* If buffer empty, refill. */
  941. X
  942. X    if (filehandle->bufloc >= filehandle->bufvalid)
  943. X    {
  944. X        /* If refill gets no chars, error. */
  945. X
  946. X        if (fb_bufget(filehandle) == 0)
  947. X        {
  948. X            return -1;
  949. X        }
  950. X    }
  951. X
  952. X    /* All OK. */
  953. X
  954. X    fb_error = ST_SUCCESS;
  955. X
  956. X    /* Return a character. */
  957. X
  958. X    return (((int)(filehandle->buffer[filehandle->bufloc++])) & 0x00FF);
  959. X} /* end of fb_getc() */
  960. X
  961. X
  962. X/***************************************************************************
  963. X*   FUNCTION: fb_write                                                     *
  964. X*                                                                          *
  965. X*   DESCRIPTION:                                                           *
  966. X*                                                                          *
  967. X*       Writes bytes to a buffered file. Note that fb_putc() is more       *
  968. X*       efficient if only a single byte is to be written.                  *
  969. X*                                                                          *
  970. X*   ENTRY:                                                                 *
  971. X*                                                                          *
  972. X*       filehandle - handle of file                                        *
  973. X*       buffer     - bytes to write                                        *
  974. X*       count      - number of bytes to write                              *
  975. X*                                                                          *
  976. X*   EXIT:                                                                  *
  977. X*                                                                          *
  978. X*       Returns an error/status code.                                      *
  979. X*                                                                          *
  980. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  981. X*                                                                          *
  982. X***************************************************************************/
  983. XULONG
  984. X#ifdef __STDC__
  985. Xfb_write(FB *filehandle, UCHAR *buffer, int count)
  986. X#else
  987. Xfb_write(filehandle, buffer, count)
  988. XFB *filehandle;
  989. XUCHAR *buffer;
  990. Xint count;
  991. X#endif
  992. X{
  993. X#ifdef READONLY
  994. X
  995. X    return FB_BADFUNC_F;
  996. X
  997. X#else
  998. X
  999. X    int buffree;                      /* free bytes in buffer */
  1000. X
  1001. X    /* Check for initialization. */
  1002. X
  1003. X    INITCHECK();
  1004. X
  1005. X    /* Check parameters. */
  1006. X
  1007. X    if ((filehandle->filemode != 'w') || (count <= 0))
  1008. X    {
  1009. X        /* If file is not in write mode, or count is negative, error. */
  1010. X
  1011. X        RETURN(FB_BADPARAM_E);
  1012. X    }
  1013. X
  1014. X    /* Get free byte count in buffer. */
  1015. X
  1016. X    buffree = fb_buflen - filehandle->bufvalid;
  1017. X
  1018. X    /* If enough space in buffer, write to buffer. */
  1019. X
  1020. X    if (buffree > count)
  1021. X    {
  1022. X        /* Copy from input to buffer. */
  1023. X
  1024. X        memcpy((filehandle->buffer + filehandle->bufloc), buffer,
  1025. X               (count * sizeof(UCHAR)));
  1026. X
  1027. X        /* Update variables. */
  1028. X
  1029. X        filehandle->bufloc += count;
  1030. X        if (filehandle->bufvalid < filehandle->bufloc)
  1031. X        {
  1032. X            filehandle->bufvalid = filehandle->bufloc;
  1033. X        }
  1034. X
  1035. X        /* All OK. */
  1036. X
  1037. X        RETURN(ST_SUCCESS);
  1038. X    }
  1039. X    else
  1040. X    {
  1041. X        /* Else flush buffers and write directly to disk. */
  1042. X
  1043. X        if (fb_flbuf(filehandle))
  1044. X        {
  1045. X            return fb_error;
  1046. X        }
  1047. X        if (fwrite(buffer, sizeof(UCHAR), count, filehandle->rawfile) != count)
  1048. X        {
  1049. X            RETURN(FB_FILEERR_F);
  1050. X        }
  1051. X
  1052. X        /* All OK, update variables. */
  1053. X
  1054. X        filehandle->bufvalid = 0;
  1055. X        filehandle->bufloc = 0;
  1056. X        filehandle->bufoffset += count;
  1057. X        RETURN(ST_SUCCESS);
  1058. X    }
  1059. X#endif /* READONLY */
  1060. X} /* end of fb_write() */
  1061. X
  1062. X
  1063. X/***************************************************************************
  1064. X*   FUNCTION: fb_putc                                                      *
  1065. X*                                                                          *
  1066. X*   DESCRIPTION:                                                           *
  1067. X*                                                                          *
  1068. X*       Writes a single byte to a buffered file.                           *
  1069. X*                                                                          *
  1070. X*   ENTRY:                                                                 *
  1071. X*                                                                          *
  1072. X*       filehandle - handle of file                                        *
  1073. X*       c          - byte to be written                                    *
  1074. X*                                                                          *
  1075. X*   EXIT:                                                                  *
  1076. X*                                                                          *
  1077. X*       Returns an error/status code.                                      *
  1078. X*                                                                          *
  1079. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1080. X*                                                                          *
  1081. X***************************************************************************/
  1082. XULONG
  1083. X#ifdef __STDC__
  1084. Xfb_putc(FB *filehandle, UCHAR c)
  1085. X#else
  1086. Xfb_putc(filehandle, c)
  1087. XFB *filehandle;
  1088. XUCHAR c;
  1089. X#endif
  1090. X{
  1091. X#ifdef READONLY
  1092. X
  1093. X    return FB_BADFUNC_F;
  1094. X
  1095. X#else
  1096. X
  1097. X    /* Check for initialization. */
  1098. X
  1099. X    INITCHECK();
  1100. X
  1101. X    /* Check file mode. */
  1102. X
  1103. X    if (filehandle->filemode != 'w')
  1104. X    {
  1105. X        RETURN(FB_BADPARAM_E);
  1106. X    }
  1107. X
  1108. X    /* If buffer full, flush first. */
  1109. X
  1110. X    if (filehandle->bufvalid >= fb_buflen)
  1111. X    {
  1112. X        if (fb_flbuf(filehandle))
  1113. X        {
  1114. X            return fb_error;
  1115. X        }
  1116. X    }
  1117. X
  1118. X    /* Put character in buffer, update variables. */
  1119. X
  1120. X    filehandle->buffer[filehandle->bufloc++] = c;
  1121. X    if (filehandle->bufvalid < filehandle->bufloc)
  1122. X    {
  1123. X        filehandle->bufvalid = filehandle->bufloc;
  1124. X    }
  1125. X
  1126. X    /* All OK. */
  1127. X
  1128. X    RETURN(ST_SUCCESS);
  1129. X#endif /* READONLY */
  1130. X} /* end of fb_putc() */
  1131. X
  1132. X
  1133. X/***************************************************************************
  1134. X*   FUNCTION: fb_errstring                                                 *
  1135. X*                                                                          *
  1136. X*   DESCRIPTION:                                                           *
  1137. X*                                                                          *
  1138. X*       Returns a string corresponding to the given error.                 *
  1139. X*                                                                          *
  1140. X*   ENTRY:                                                                 *
  1141. X*                                                                          *
  1142. X*       errcode - error code to be translated                              *
  1143. X*                                                                          *
  1144. X*   EXIT:                                                                  *
  1145. X*                                                                          *
  1146. X*       Returns a pointer to the appropriate string, or NULL if there is   *
  1147. X*       no appropriate string.                                             *
  1148. X*                                                                          *
  1149. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1150. X*                                                                          *
  1151. X***************************************************************************/
  1152. Xchar *
  1153. X#ifdef __STDC__
  1154. Xfb_errstring(ULONG errcode)
  1155. X#else
  1156. Xfb_errstring(errcode)
  1157. XULONG errcode;
  1158. X#endif
  1159. X{
  1160. X    char *temp;
  1161. X
  1162. X    /* If not an FB module error code, return NULL. */
  1163. X
  1164. X    if (MODULE(errcode) != MODULE(FB_MODULE))
  1165. X    {
  1166. X        return NULL;
  1167. X    }
  1168. X
  1169. X    /* Process by code. */
  1170. X
  1171. X    switch (ERRSEV(errcode))
  1172. X    {
  1173. X        case ERRSEV(FB_EOF_W):
  1174. X            temp = "End of file.";
  1175. X            break;
  1176. X        case ERRSEV(FB_NOMEM_E):
  1177. X            temp = "Out of memory in FB module.";
  1178. X            break;
  1179. X        case ERRSEV(FB_BADPARAM_E):
  1180. X            temp = "A bad parameter was passed to FB module function.";
  1181. X            break;
  1182. X        case ERRSEV(FB_NOHANDLE_E):
  1183. X            temp = "No free FB handles available.";
  1184. X            break;
  1185. X        case ERRSEV(FB_NOFILE_E):
  1186. X            temp = "Cannot find named file.";
  1187. X            break;
  1188. X        case ERRSEV(FB_NOTINIT_E):
  1189. X            temp = "FB module not initialized.";
  1190. X            break;
  1191. X        case ERRSEV(FB_REINIT_E):
  1192. X            temp = "Attempt to reinitialize FB module.";
  1193. X            break;
  1194. X        case ERRSEV(FB_NOMEMBUF_E):
  1195. X            temp = "No memory for file buffer in FB module.";
  1196. X            break;
  1197. X
  1198. X        case ERRSEV(FB_FILEERR_F):
  1199. X            temp = "Error accessing file.";
  1200. X            break;
  1201. X        case ERRSEV(FB_BUG_F):
  1202. X            temp = "Internal error, should never happen.";
  1203. X            break;
  1204. X        case ERRSEV(FB_BADFUNC_F):
  1205. X            temp = "Function not supported in read-only mode.";
  1206. X            break;
  1207. X
  1208. X        default:
  1209. X            temp = NULL;
  1210. X            break;
  1211. X    }
  1212. X
  1213. X    return temp;
  1214. X} /* end of fb_errstring() */
  1215. X
  1216. X#ifndef READONLY
  1217. X
  1218. X/***************************************************************************
  1219. X*   FUNCTION: fb_flbuf STATIC                                              *
  1220. X*                                                                          *
  1221. X*   DESCRIPTION:                                                           *
  1222. X*                                                                          *
  1223. X*       Flushes write buffers to disk.                                     *
  1224. X*                                                                          *
  1225. X*   ENTRY:                                                                 *
  1226. X*                                                                          *
  1227. X*       filehandle - handle of file                                        *
  1228. X*                                                                          *
  1229. X*   EXIT:                                                                  *
  1230. X*                                                                          *
  1231. X*       Returns an error/status code.                                      *
  1232. X*                                                                          *
  1233. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1234. X*                                                                          *
  1235. X***************************************************************************/
  1236. Xstatic ULONG
  1237. X#ifdef __STDC__
  1238. Xfb_flbuf(FB *filehandle)
  1239. X#else
  1240. Xfb_flbuf(filehandle)
  1241. XFB *filehandle;
  1242. X#endif
  1243. X{
  1244. X    int byteswritten;
  1245. X    UCHAR *src, *dest;
  1246. X    int loop;
  1247. X
  1248. X    /*
  1249. X    ** No parameter or initialization checking -- should have been done
  1250. X    ** by caller.
  1251. X    */
  1252. X
  1253. X    /* If no bytes to write, return. */
  1254. X
  1255. X    if (0 == filehandle->bufvalid)
  1256. X    {
  1257. X        RETURN(ST_SUCCESS);
  1258. X    }
  1259. X
  1260. X    /* Make sure at right place in file. */
  1261. X
  1262. X    if (fseek(filehandle->rawfile, filehandle->bufoffset, SEEK_SET))
  1263. X    {
  1264. X        RETURN(FB_FILEERR_F);
  1265. X    }
  1266. X
  1267. X    /* Write to disk. */
  1268. X
  1269. X    byteswritten = fwrite(filehandle->buffer, sizeof(UCHAR),
  1270. X                          filehandle->bufvalid, filehandle->rawfile);
  1271. X
  1272. X    /* If short write, attempt some recovery. */
  1273. X
  1274. X    if (byteswritten != filehandle->bufvalid)
  1275. X    {
  1276. X        /* Copy unwritten bytes to beginning of buffer. */
  1277. X
  1278. X        src = (filehandle->buffer + byteswritten);
  1279. X        dest = filehandle->buffer; 
  1280. X        for (loop = 0; loop < (filehandle->bufvalid - byteswritten); loop++)
  1281. X        {
  1282. X            *(dest++) = *(src++);
  1283. X        }
  1284. X
  1285. X        /* Update variables. */
  1286. X
  1287. X        filehandle->bufloc -= byteswritten;
  1288. X        filehandle->bufvalid -= byteswritten;
  1289. X        filehandle->bufoffset += byteswritten;
  1290. X        RETURN(FB_FILEERR_F);
  1291. X    }
  1292. X    else
  1293. X    {
  1294. X        /* Else all written OK. Update variables. */
  1295. X
  1296. X        filehandle->bufloc = 0;
  1297. X        filehandle->bufvalid = 0;
  1298. X        filehandle->bufoffset += byteswritten;
  1299. X        RETURN(ST_SUCCESS);
  1300. X    }
  1301. X} /* end of static fb_flbuf() */
  1302. X
  1303. X#endif /* !READONLY */
  1304. X
  1305. X
  1306. X/***************************************************************************
  1307. X*   FUNCTION: fb_bufget STATIC                                             *
  1308. X*                                                                          *
  1309. X*   DESCRIPTION:                                                           *
  1310. X*                                                                          *
  1311. X*       Refills the buffer from disk.                                      *
  1312. X*                                                                          *
  1313. X*   ENTRY:                                                                 *
  1314. X*                                                                          *
  1315. X*       filehandle - handle of file                                        *
  1316. X*                                                                          *
  1317. X*   EXIT:                                                                  *
  1318. X*                                                                          *
  1319. X*       Returns number of bytes read into buffer. Short count can occur    *
  1320. X*       on error or EOF.                                                   *
  1321. X*                                                                          *
  1322. X*       Sets global fb_error to an error/status code.                      *
  1323. X*                                                                          *
  1324. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1325. X*                                                                          *
  1326. X***************************************************************************/
  1327. Xstatic int
  1328. X#ifdef __STDC__
  1329. Xfb_bufget(FB *filehandle)
  1330. X#else
  1331. Xfb_bufget(filehandle)
  1332. XFB *filehandle;
  1333. X#endif
  1334. X{
  1335. X    int bytesread;
  1336. X
  1337. X    /*
  1338. X    ** No parameter or initialization checking -- should have been done
  1339. X    ** by caller.
  1340. X    */
  1341. X
  1342. X    /* Make sure at correct position in file. */
  1343. X
  1344. X    if (fseek(filehandle->rawfile, filehandle->bufoffset, SEEK_SET))
  1345. X    {
  1346. X        fb_error = FB_FILEERR_F;
  1347. X        return 0;
  1348. X    }
  1349. X
  1350. X    /* Read into buffer. */
  1351. X
  1352. X    bytesread = fread(filehandle->buffer, sizeof(UCHAR), fb_buflen,
  1353. X                      filehandle->rawfile);
  1354. X
  1355. X
  1356. X    if (bytesread != fb_buflen)
  1357. X    {
  1358. X        /* Short read, set return. */
  1359. X
  1360. X        if (feof(filehandle->rawfile))
  1361. X        {
  1362. X            /* EOF encountered -- update variables. */
  1363. X
  1364. X            filehandle->bufvalid = bytesread;
  1365. X            filehandle->bufloc = 0;
  1366. X            filehandle->bufoffset += bytesread;
  1367. X
  1368. X            /* Return EOF warning. */
  1369. X
  1370. X            fb_error = FB_EOF_W;
  1371. X            return bytesread;
  1372. X        }
  1373. X        else
  1374. X        {
  1375. X            /* Read error. */
  1376. X
  1377. X            fb_error = FB_FILEERR_F;
  1378. X            return bytesread;
  1379. X        }
  1380. X    }
  1381. X    else
  1382. X    {
  1383. X        /* Full read -- update variables. */
  1384. X
  1385. X        filehandle->bufvalid = bytesread;
  1386. X        filehandle->bufloc = 0;
  1387. X        filehandle->bufoffset += bytesread;
  1388. X
  1389. X        /* All OK. */
  1390. X
  1391. X        fb_error = ST_SUCCESS;
  1392. X        return bytesread;
  1393. X    }
  1394. X} /* end of static fb_bufget() */
  1395. X
  1396. END_OF_FILE
  1397.   if test 45520 -ne `wc -c <'src/fb.c'`; then
  1398.     echo shar: \"'src/fb.c'\" unpacked with wrong size!
  1399.   fi
  1400.   # end of 'src/fb.c'
  1401. fi
  1402. if test -f 'src/shorten.awk' -a "${1}" != "-c" ; then 
  1403.   echo shar: Will not clobber existing file \"'src/shorten.awk'\"
  1404. else
  1405.   echo shar: Extracting \"'src/shorten.awk'\" \(86 characters\)
  1406.   sed "s/^X//" >'src/shorten.awk' <<'END_OF_FILE'
  1407. XBEGIN    { foonum = 0 }
  1408. X
  1409. X{    printf("s/%s/FOO%d/g\n", $1, foonum);
  1410. X    foonum = foonum + 1;
  1411. X}
  1412. END_OF_FILE
  1413.   if test 86 -ne `wc -c <'src/shorten.awk'`; then
  1414.     echo shar: \"'src/shorten.awk'\" unpacked with wrong size!
  1415.   fi
  1416.   # end of 'src/shorten.awk'
  1417. fi
  1418. if test -f 'src/token.c' -a "${1}" != "-c" ; then 
  1419.   echo shar: Will not clobber existing file \"'src/token.c'\"
  1420. else
  1421.   echo shar: Extracting \"'src/token.c'\" \(6386 characters\)
  1422.   sed "s/^X//" >'src/token.c' <<'END_OF_FILE'
  1423. X/***************************************************************************
  1424. X*   TOKEN.C                                                                *
  1425. X*   MODULE:  FM (Formats)                                                  *
  1426. X*   OS:      UNIX                                                          *
  1427. X*                                                                          *
  1428. X*   Copyright (c) 1993 James W. Birdsall. All Rights Reserved.             *
  1429. X*                                                                          *
  1430. X*   $Id: token.c,v 1.1 1993/02/15 01:55:24 jwbirdsa Exp $
  1431. X*                                                                          *
  1432. X*   Token-getting functions needed by various image format processors.     *
  1433. X*                                                                          *
  1434. X***************************************************************************/
  1435. X
  1436. X#include "config.h"
  1437. X
  1438. X/*
  1439. X** system includes <>
  1440. X*/
  1441. X
  1442. X#include <stdio.h>
  1443. X#include <ctype.h>
  1444. X#ifndef NO_MALLOCHDR
  1445. X#include <malloc.h>
  1446. X#endif
  1447. X
  1448. X
  1449. X/*
  1450. X** custom includes ""
  1451. X*/
  1452. X
  1453. X#include "depend.h"
  1454. X#include "formats.h"
  1455. X#include "token.h"
  1456. X
  1457. X
  1458. X/*
  1459. X** local #defines
  1460. X*/
  1461. X
  1462. X/*
  1463. X** misc: copyright strings, version macros, etc.
  1464. X*/
  1465. X
  1466. X/*
  1467. X** typedefs
  1468. X*/
  1469. X
  1470. X/*
  1471. X** global variables
  1472. X*/
  1473. X
  1474. X/*
  1475. X** static globals
  1476. X*/
  1477. X
  1478. X/*
  1479. X** function prototypes
  1480. X*/
  1481. X
  1482. X/*
  1483. X** functions
  1484. X*/
  1485. X
  1486. X
  1487. X/***************************************************************************
  1488. X*   FUNCTION:  fm_token                                                    *
  1489. X*                                                                          *
  1490. X*   DESCRIPTION:                                                           *
  1491. X*                                                                          *
  1492. X*       Skips any leading whitespace in the file, collects all contiguous  *
  1493. X*       non-whitespace characters, and skips any trailing whitespace.      *
  1494. X*       Returns the collected characters in a malloc'ed buffer.            *
  1495. X*                                                                          *
  1496. X*   ENTRY:                                                                 *
  1497. X*                                                                          *
  1498. X*       infile - file from which to get tokens                             *
  1499. X*                                                                          *
  1500. X*   EXIT:                                                                  *
  1501. X*                                                                          *
  1502. X*       Returns NULL on error.                                             *
  1503. X*                                                                          *
  1504. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1505. X*                                                                          *
  1506. X***************************************************************************/
  1507. Xchar *
  1508. X#ifdef __STDC__
  1509. Xfm_token(FILE *infile)
  1510. X#else
  1511. Xfm_token(infile)
  1512. XFILE *infile;
  1513. X#endif
  1514. X{
  1515. X    char *retbuf;
  1516. X    int retcount;
  1517. X    long startpos;
  1518. X    int c;
  1519. X
  1520. X    /* Skip leading whitespace. */
  1521. X
  1522. X    if ((c = fgetc(infile)) == EOF)
  1523. X    {
  1524. X        return NULL;
  1525. X    }
  1526. X    /* Use isascii() to make sure isspace() will work. */
  1527. X    while (isascii(c) && isspace(c))
  1528. X    {
  1529. X        if ((c = fgetc(infile)) == EOF)
  1530. X        {
  1531. X            return NULL;
  1532. X        }
  1533. X    }
  1534. X
  1535. X    /* Record position of first non-whitespace, initialize count.  */
  1536. X
  1537. X    startpos = ftell(infile) - 1;
  1538. X    retcount = 0;
  1539. X
  1540. X    /* Count contiguous nonwhitespace characters. */
  1541. X
  1542. X    while (isascii(c) && (isspace(c) == 0))
  1543. X    {
  1544. X        retcount++;
  1545. X        if ((c = fgetc(infile)) == EOF)
  1546. X        {
  1547. X            return NULL;
  1548. X        }
  1549. X    }
  1550. X
  1551. X    /* Go back to first non-whitespace. */
  1552. X
  1553. X    if (fseek(infile, startpos, SEEK_SET) == -1)
  1554. X    {
  1555. X        return NULL;
  1556. X    }
  1557. X        
  1558. X    /* Allocate return buffer. */
  1559. X
  1560. X    if ((retbuf = ((char *) malloc(retcount + 1))) == NULL)
  1561. X    {
  1562. X        return NULL;
  1563. X    }
  1564. X
  1565. X    /* Read into buffer. */
  1566. X
  1567. X    if (fread(retbuf, sizeof(char), retcount, infile) != retcount)
  1568. X    {
  1569. X        free(retbuf);
  1570. X        return NULL;
  1571. X    }
  1572. X    retbuf[retcount] = '\0';
  1573. X
  1574. X    /* Skip trailing whitespace. */
  1575. X
  1576. X    if ((c = fgetc(infile)) == EOF)
  1577. X    {
  1578. X        free(retbuf);
  1579. X        return NULL;
  1580. X    }
  1581. X    while (isascii(c) && isspace(c))
  1582. X    {
  1583. X        if ((c = fgetc(infile)) == EOF)
  1584. X        {
  1585. X            free(retbuf);
  1586. X            return NULL;
  1587. X        }
  1588. X    }
  1589. X
  1590. X    /* Back up one position so file is positioned at next token. */
  1591. X
  1592. X    if (fseek(infile, -1L, SEEK_CUR) == -1)
  1593. X    {
  1594. X        free(retbuf);
  1595. X        return NULL;
  1596. X    }
  1597. X
  1598. X    return retbuf;
  1599. X} /* end of fm_token() */
  1600. X
  1601. X
  1602. X/***************************************************************************
  1603. X*   FUNCTION:  fm_eol                                                      *
  1604. X*                                                                          *
  1605. X*   DESCRIPTION:                                                           *
  1606. X*                                                                          *
  1607. X*       Forwards the file to the end of the current line. Useful for       *
  1608. X*       skipping comments.                                                 *
  1609. X*                                                                          *
  1610. X*   ENTRY:                                                                 *
  1611. X*                                                                          *
  1612. X*       infile - file to be forwarded                                      *
  1613. X*                                                                          *
  1614. X*   EXIT:                                                                  *
  1615. X*                                                                          *
  1616. X*       Returns error/status code.                                         *
  1617. X*                                                                          *
  1618. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1619. X*                                                                          *
  1620. X***************************************************************************/
  1621. XULONG
  1622. X#ifdef __STDC__
  1623. Xfm_eol(FILE *infile)
  1624. X#else
  1625. Xfm_eol(infile)
  1626. XFILE *infile;
  1627. X#endif
  1628. X{
  1629. X    int c;
  1630. X
  1631. X    while (((c = fgetc(infile)) != EOF) && (c != '\n')) ;
  1632. X
  1633. X    if (EOF == c)
  1634. X    {
  1635. X        return (feof(infile) ? FM_EOF_W : FM_FILEERR_E);
  1636. X    }
  1637. X    
  1638. X    return ST_SUCCESS;
  1639. X} /* end of fm_eol() */
  1640. X
  1641. END_OF_FILE
  1642.   if test 6386 -ne `wc -c <'src/token.c'`; then
  1643.     echo shar: \"'src/token.c'\" unpacked with wrong size!
  1644.   fi
  1645.   # end of 'src/token.c'
  1646. fi
  1647. echo shar: End of archive 3 \(of 18\).
  1648. cp /dev/null ark3isdone
  1649. MISSING=""
  1650. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1651.     if test ! -f ark${I}isdone ; then
  1652.     MISSING="${MISSING} ${I}"
  1653.     fi
  1654. done
  1655. if test "${MISSING}" = "" ; then
  1656.     echo You have unpacked all 18 archives.
  1657.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1658. else
  1659.     echo You still must unpack the following archives:
  1660.     echo "        " ${MISSING}
  1661. fi
  1662. exit 0
  1663. exit 0 # Just in case...
  1664.