home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 125.img / PRO-C4.ZIP / BENCH1.ZIP / BENCH / IADELIM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-28  |  26.5 KB  |  1,226 lines

  1. /* ==( bench/iadelim.c )== */
  2.  
  3. /* ----------------------------------------------- */
  4. /* Pro-C  Copyright (C) 1988 - 1990 Vestronix Inc. */
  5. /* Modification to this source is not supported    */
  6. /* by Vestronix Inc.                               */
  7. /*            All Rights Reserved                  */
  8. /* ----------------------------------------------- */
  9. /* Written   BRC  18-Apr-90                        */
  10. /* Modified  ???  28-Mar-90  See comments below    */
  11. /* ----------------------------------------------- */
  12. /* %W%  (%H% %T%) */
  13.  
  14. /*
  15. **  Modifications
  16. **
  17. **  18-Apr-90  BRC - code based on earlier IO6.C
  18. */
  19.  
  20. /*
  21. **  -- D R A F T --  Delimited ASCII Sequential I/O via IOGEN.C interface 
  22. **
  23. **  Beta version ... this is not yet certain -- BRC
  24. */
  25.  
  26. /*
  27. **  This module handles the interface between the i/o calls from within
  28. **  PRO-C and a delimited ASCII file with varying length records and fields
  29. */
  30.  
  31. #include <stdio.h>
  32. #include <iodef.h>
  33. #include <iomsg.h>
  34. #include <proc.io>
  35. #include <bench.h>
  36. #include <iosup.h>
  37.  
  38.  
  39. /* Open control (Geo will correct this into o_open & o_creat 13-Dec-89) */
  40.  
  41. #ifdef QNX
  42. #define OPN_FILE(fname) sopen(fname,O_BINARY|O_RDWR|O_CACHE,SH_DENYNO)
  43. #define CRT_FILE(fname) sopen(fname,O_BINARY|O_RDWR|O_CACHE|O_CREAT,SH_DENYNO,S_IREAD|S_IWRITE)
  44. #define LOCK_BLK(fd,pos,len) lockf(fd,F_LOCK,len)
  45. #define LOCK_TST(fd,pos,len) lockf(fd,F_TLOCK,len)
  46. #define LOCK_REL(fd,pos,len) lockf(fd,F_ULOCK,len)
  47. #endif
  48.  
  49.  
  50. #ifdef MSC
  51. #define OPN_FILE(fname) open(fname,O_BINARY|O_RDWR)
  52. #define CRT_FILE(fname) open(fname,O_BINARY|O_RDWR|O_CREAT,S_IREAD|S_IWRITE)
  53. #define LOCK_BLK(fd,pos,len) locking(fd,LK_LOCK,len)
  54. #define LOCK_TST(fd,pos,len) locking(fd,LK_NBLCK,len)
  55. #define LOCK_REL(fd,pos,len) locking(fd,LK_UNLCK,len)
  56. #endif
  57.  
  58.  
  59. #ifdef __TURBOC__
  60. #define OPN_FILE(fname) open(fname,O_BINARY|O_RDWR)
  61. #define CRT_FILE(fname) open(fname,O_BINARY|O_RDWR|O_CREAT,S_IREAD|S_IWRITE)
  62. #define LOCK_BLK(fd,pos,len) lock(fd,pos,(long)len)
  63. #define LOCK_TST(fd,pos,len) lock(fd,pos,(long)len)
  64. #define LOCK_REL(fd,pos,len) lock(fd,pos,(long)len)
  65. #endif
  66.  
  67.  
  68. #ifdef __WATCOMC__
  69. #define OPN_FILE(fname) open(fname,O_BINARY|O_RDWR|,S_IREAD|S_IWRITE)
  70. #define CRT_FILE(fname) open(fname,O_BINARY|O_RDWR|O_CREAT,S_IREAD|S_IWRITE)
  71. #define LOCK_BLK(fd,pos,len) (0)
  72. #define LOCK_TST(fd,pos,len) (0)
  73. #define LOCK_REL(fd,pos,len) (0)
  74. #endif
  75.  
  76.  
  77. #ifdef LATTICE
  78. #define OPN_FILE(fname) open(fname,O_RAW|O_RDWR|)
  79. #define CRT_FILE(fname) open(fname,O_RAW|O_RDWR|O_CREAT,S_IREAD|S_IWRITE)
  80. #define LOCK_BLK(fd,pos,len) lockf(fd,F_LOCK,len)
  81. #define LOCK_TST(fd,pos,len) lockf(fd,F_TLOCK,len)
  82. #define LOCK_REL(fd,pos,len) lockf(fd,F_ULOCK,len)
  83. #endif
  84.  
  85.  
  86. #ifdef __ZTC__
  87. #define OPN_FILE(fname) open(fname,O_RDWR)
  88. #define CRT_FILE(fname) creat(fname,S_IREAD|S_IWRITE)
  89. #define LOCK_BLK(fd,pos,len) (0)
  90. #define LOCK_TST(fd,pos,len) (0)
  91. #define LOCK_REL(fd,pos,len) (0)
  92. #endif
  93.  
  94.  
  95. #ifdef UNIX
  96. #define OPN_FILE(fname) open(fname,O_RDWR)
  97. #define CRT_FILE(fname) open(fname,O_RDWR|O_CREAT,0664)
  98. #define LOCK_BLK(fd,pos,len) lockf(fd,F_LOCK,len)
  99. #define LOCK_TST(fd,pos,len) lockf(fd,F_TLOCK,len)
  100. #define LOCK_REL(fd,pos,len) lockf(fd,F_ULOCK,len)
  101. #endif
  102.  
  103.  
  104. #ifndef USELOCK
  105. #undef  USELOCK    /* Dummy out this if no locking */
  106. #endif
  107.  
  108.  
  109. /****************************************************************************/
  110. /*                           Function Prototypes                            */
  111. /****************************************************************************/
  112.  
  113. #ifdef ANSI
  114.  
  115. static int i_addrec(int, char *);
  116. static int i_close_file(int, char *);
  117. static int i_commit(int, char *);
  118. static int i_delrec(int, char *);
  119. static int i_filename(int, char *);
  120. static int i_findkey(int, char *);
  121. static int i_firstkey(int, char *);
  122. static int i_init_file(int, char *);
  123. static int i_lastkey(int, char *);
  124. static int i_lockrec(int, char *);
  125. static int i_login(int, char *);
  126. static int i_logoff(int, char *);
  127. static int i_nextrec(int, char *);
  128. static int i_open_file(int, char *);
  129. static int i_prevrec(int, char *);
  130. static int i_rereadrec(int, char *);
  131. static int i_rollback(int, char *);
  132. static int i_selectinx(int, char *);
  133. static int i_transact(int, char *);
  134. static int i_unlock_rec(int, char *);
  135. static int i_updrec(int, char *);
  136.  
  137. static int uniqueness(int, char *, long);
  138. static int eatline(FILE *fp);
  139. static int eatsep(FILE *fp);
  140. static int keycmp(int, char *);
  141. static int read_rec(int, char *);
  142. static int slipback(int);
  143. static int write_rec(int, char *);
  144.  
  145. extern char *io_tran(int);
  146. extern void assign_IO_AD(int);
  147.  
  148. #else
  149.  
  150. static int i_addrec();
  151. static int i_close_file();
  152. static int i_commit();
  153. static int i_delrec();
  154. static int i_filename();
  155. static int i_findkey();
  156. static int i_firstkey();
  157. static int i_init_file();
  158. static int i_lastkey();
  159. static int i_lockrec();
  160. static int i_login();
  161. static int i_logoff();
  162. static int i_nextrec();
  163. static int i_open_file();
  164. static int i_prevrec();
  165. static int i_rereadrec();
  166. static int i_rollback();
  167. static int i_selectinx();
  168. static int i_transact();
  169. static int i_unlock_rec();
  170. static int i_updrec();
  171.  
  172. static int uniqueness();
  173. static int eatline();
  174. static int eatsep();
  175. static int keycmp();
  176. static int read_rec();
  177. static int slipback();
  178. static int write_rec();
  179.  
  180. extern char *io_tran();
  181. extern void assign_IO_AD();
  182.  
  183. #endif
  184.  
  185.  
  186.  
  187. /*
  188. **  Plus any externs required by the file manager for error codes etc.
  189. **
  190. **  Definition for Each Open File
  191. */
  192.  
  193. /* structure for ASCII file specific values */
  194. struct asc_def
  195. {
  196.    FILE *fp;        /* fdopen() return */
  197.    long offset;        /* Current offset into file for Read/Write */
  198.    char *localbuf;    /* Local Record Buffer for Read/Write */
  199.    char *localbuf2;    /* Spare Local Record Buffer for Read/Write */
  200.    long lockoff;
  201. };
  202.  
  203. #define COMMENT_CHAR    '#'
  204.  
  205. static struct asc_def afd[MAX_FILES];
  206.  
  207.  
  208. /*
  209. **
  210. ** Interface Functions
  211. **
  212. */
  213.  
  214.  
  215. /*
  216. **  Sets up File Name extension - dummy function here
  217. */
  218. static int
  219. i_filename(fd_sys, buffer)
  220. int fd_sys;
  221. char *buffer;
  222. {
  223.    return(IOGOOD);
  224. }
  225.  
  226.  
  227. /*
  228. **  File initialization - all descriptors start out as -1
  229. */
  230. static int
  231. i_init_file(fd_sys, buffer)
  232. int fd_sys;
  233. char *buffer;
  234. {
  235.    int n;
  236.  
  237.    /* initialize all descriptors to -1 */
  238.    for (n = 0; n < MAX_FILES; n++)
  239.    {
  240.       fd[n].fd_num = -1;
  241.       afd[n].fp = (FILE *)0;
  242.    }
  243.       
  244.    return(IOGOOD);
  245. }
  246.  
  247.  
  248. /*
  249. **  File open function - required parameters are in fd structure
  250. */
  251. static int
  252. i_open_file(fd_sys, buffer)
  253. int fd_sys;
  254. char *buffer;
  255. {
  256.    struct fd_def *fptr = &fd[fd_sys];
  257.    struct asc_def *aptr = &afd[fd_sys];
  258.    int fds, iostat = IOGOOD;
  259.  
  260.    /* delete the file if the mode is OUTPUT */
  261.    if (fptr->openmode & OUTPUT_FLAG)
  262.       unlink(fptr->filname);
  263.  
  264.    if ((fds = OPN_FILE(fptr->filname)) < 0)
  265.       fds = CRT_FILE(fptr->filname);
  266.  
  267.    /* failed to Open or Create */
  268.    if (fds < 0)
  269.    {
  270.       errmsg(FileNotFound_s, fptr->filname);
  271.       iostat = IOBADOPEN;
  272.    }
  273.    else
  274.    {
  275.       if (!(aptr->fp = fdopen(fds, "r+")))
  276.      iostat = IOBADOPEN;
  277.       else
  278.       {
  279.      fptr->fd_num = fds;
  280.      aptr->localbuf = alloc(fptr->rec_len);
  281.      aptr->localbuf2 = alloc(fptr->rec_len);
  282.      aptr->lockoff = -1L;
  283.       }
  284.    }
  285.  
  286.    return(iostat);
  287. }
  288.  
  289.  
  290. /*
  291. **  Close down FILE pointer and blot out the descriptor as well
  292. */
  293. static int
  294. i_close_file(fd_sys, buffer)
  295. int fd_sys;
  296. char *buffer;
  297. {
  298.    free(afd[fd_sys].localbuf);
  299.    afd[fd_sys].localbuf = NULL;
  300.  
  301.    free(afd[fd_sys].localbuf2);
  302.    afd[fd_sys].localbuf2 = NULL;
  303.  
  304.    fclose(afd[fd_sys].fp);
  305.    afd[fd_sys].fp = (FILE *)0;
  306.    fd[fd_sys].fd_num = -1;
  307.  
  308.    return(IOGOOD);
  309. }
  310.  
  311.  
  312. /*
  313. **  Unlock the current record if the index changes -- the rest in IOGEN.C
  314. */
  315. static int
  316. i_selectinx(fd_sys, buffer)
  317. int fd_sys;
  318. char *buffer;
  319. {
  320.    if (afd[fd_sys].lockoff >= 0L)
  321.       /* just paranioa so ignore the return value */
  322.       i_unlock_rec(fd_sys, NULL);
  323.  
  324.    return(IOGOOD);
  325. }
  326.  
  327.  
  328. /*
  329. **  Retrieve the first record matching an EXACT or a PARTIAL key spec.
  330. */
  331. static int
  332. i_findkey(fd_sys, buffer)
  333. int fd_sys;
  334. char *buffer;
  335. {
  336.    struct fd_def *fptr = &fd[fd_sys];
  337.    struct asc_def *aptr = &afd[fd_sys];
  338.    int cmp_ok, iostat = IOGOOD;
  339.  
  340.    /* Set up record offsets */
  341.    cmp_ok = keycmp(fd_sys, buffer);
  342.  
  343.    fseek(aptr->fp, 0L, SEEK_SET);
  344.    do
  345.    {
  346.       if ((iostat = read_rec(fd_sys, aptr->localbuf)) == IOGOOD)
  347.       {
  348.      cmp_ok = keycmp(-1, NULL);
  349.      cmp_ok = fptr->exact ? cmp_ok != 0 : cmp_ok < 0;
  350.       }
  351.    }
  352.    while (iostat == IOGOOD && cmp_ok);
  353.  
  354.    if (iostat == IOEOF)
  355.       iostat = IONOKEY;
  356.    else if (iostat == IOGOOD && (iostat = i_lockrec(fd_sys, NULL)) == IOGOOD)
  357.       memcpy(buffer, aptr->localbuf, fptr->rec_len);
  358.  
  359.    return(iostat);
  360. }
  361.  
  362.  
  363. /*
  364. **  Find the first physical record in the file
  365. */
  366. static int
  367. i_firstkey(fd_sys, buffer)
  368. int fd_sys;
  369. char *buffer;
  370. {
  371.    struct fd_def *fptr = &fd[fd_sys];
  372.    struct asc_def *aptr = &afd[fd_sys];
  373.    int iostat = IOGOOD;
  374.  
  375.    fseek(aptr->fp, 0L, SEEK_SET);
  376.    if ((iostat = read_rec(fd_sys, aptr->localbuf)) == IOGOOD)
  377.       if ((iostat = i_lockrec(fd_sys, NULL)) == IOGOOD)
  378.      memcpy(buffer, aptr->localbuf, fptr->rec_len);
  379.  
  380.    return(iostat);
  381. }
  382.  
  383.  
  384. /*
  385. **  Find the last physical record in the file
  386. */
  387. static int
  388. i_lastkey(fd_sys, buffer)
  389. int fd_sys;
  390. char *buffer;
  391. {
  392.    struct fd_def *fptr = &fd[fd_sys];
  393.    struct asc_def *aptr = &afd[fd_sys];
  394.    int iostat = IOGOOD;
  395.  
  396.    fseek(aptr->fp, 0L, SEEK_END);
  397.    aptr->offset = ftell(aptr->fp);
  398.    if ((iostat = slipback(fd_sys)) == IOGOOD)
  399.       iostat = read_rec(fd_sys, aptr->localbuf);
  400.  
  401.    if (iostat == IOGOOD && (iostat = i_lockrec(fd_sys, NULL)) == IOGOOD)
  402.       memcpy(buffer, aptr->localbuf, fptr->rec_len);
  403.  
  404.    return(iostat);
  405. }
  406.  
  407.  
  408. /*
  409. **  Find the next record in the file
  410. **
  411. **  - IOGEN does checking for blocks of duplicate key records in an EXACT 
  412. **    search but sequential files are not indexed; thus this function
  413. **    will continue traversing the file to find all matches
  414. */
  415. static int
  416. i_nextrec(fd_sys, buffer)
  417. int fd_sys;
  418. char *buffer;
  419. {
  420.    struct fd_def *fptr = &fd[fd_sys];
  421.    struct asc_def *aptr = &afd[fd_sys];
  422.    int cmp_ok, iostat = IONOKEY;
  423.    long lastoff;
  424.  
  425.    /* Set up record offsets */
  426.    cmp_ok = keycmp(fd_sys, buffer);
  427.  
  428.    if (aptr->offset >= 0L)
  429.    {
  430.       fseek(aptr->fp, aptr->offset, SEEK_SET);
  431.       do
  432.       {
  433.      lastoff = aptr->offset;
  434.      if ((iostat = read_rec(fd_sys, aptr->localbuf)) == IOGOOD)
  435.         if (lastoff == aptr->offset)
  436.            iostat = read_rec(fd_sys, aptr->localbuf);
  437.      cmp_ok = fptr->exact ? keycmp(-1, NULL) != 0 : FALSE;
  438.       }
  439.       while (iostat == IOGOOD && cmp_ok);
  440.    }
  441.  
  442.    if (iostat == IOEOF)
  443.       aptr->offset = lastoff;
  444.  
  445.    if (fptr->exact && iostat == IOEOF)
  446.       iostat = IONONEXT;
  447.    
  448.    if (iostat == IOGOOD && (iostat = i_lockrec(fd_sys, NULL)) == IOGOOD)
  449.       memcpy(buffer, aptr->localbuf, fptr->rec_len);
  450.    
  451.      return(iostat);
  452. }
  453.  
  454.  
  455. /*
  456. **  Find the previous record in the file
  457. **
  458. **  - IOGEN does checking for blocks of duplicate key records in an EXACT 
  459. **    search but sequential files are not indexed; thus this function
  460. **    will continue traversing the file to find all matches
  461. */
  462. static int
  463. i_prevrec(fd_sys, buffer)
  464. int fd_sys;
  465. char *buffer;
  466. {
  467.    struct fd_def *fptr = &fd[fd_sys];
  468.    struct asc_def *aptr = &afd[fd_sys];
  469.    int cmp_ok, iostat = IONOKEY;
  470.  
  471.    /* Set up record offsets */
  472.    cmp_ok = keycmp(fd_sys, buffer);
  473.  
  474.    if (aptr->offset >= 0L)
  475.    {
  476.       fseek(aptr->fp, aptr->offset, SEEK_SET);
  477.       do
  478.       {
  479.      if ((iostat = slipback(fd_sys)) != IOGOOD)
  480.         break;
  481.      else if ((iostat = read_rec(fd_sys, aptr->localbuf)) != IOGOOD)
  482.         break;
  483.      else
  484.         cmp_ok = fptr->exact ? keycmp(-1, NULL) != 0 : FALSE;
  485.       }
  486.       while (iostat == IOGOOD && cmp_ok);
  487.    }
  488.  
  489.    if (fptr->exact && iostat == IOTOF)
  490.       iostat = IONONEXT;
  491.  
  492.    if (iostat == IOGOOD && (iostat = i_lockrec(fd_sys, NULL)) == IOGOOD)
  493.       memcpy(buffer, aptr->localbuf, fptr->rec_len);
  494.  
  495.    return(iostat);
  496. }
  497.  
  498.  
  499. /*
  500. **  re-read/reposition record pointer function - dummy function here
  501. */
  502. static int
  503. i_rereadrec(fd_sys, buffer)
  504. int fd_sys;
  505. char *buffer;
  506. {
  507.    return(IOGOOD);
  508. }
  509.  
  510.  
  511. /*
  512. **  ADD a the record in BUFFER
  513. */
  514. static int
  515. i_addrec(fd_sys, buffer)
  516. int fd_sys;
  517. char *buffer;
  518. {
  519.    struct fd_def *fptr = &fd[fd_sys];
  520.    struct asc_def *aptr = &afd[fd_sys];
  521.    int iostat;
  522.  
  523.    if ((iostat = uniqueness(fd_sys, buffer, -1L)) == IOGOOD)
  524.    {
  525.       do
  526.       {
  527.      fseek(aptr->fp, 0L, SEEK_END);
  528.      aptr->offset = ftell(aptr->fp);
  529.       }
  530.       while ((iostat = i_lockrec(fd_sys, NULL)) == IOLOCKED);
  531.  
  532.       if (iostat == IOGOOD)
  533.       {
  534.      if ((iostat = write_rec(fd_sys, buffer)) == IOGOOD)
  535.         iostat = i_unlock_rec(fd_sys, NULL);
  536.      else
  537.         i_unlock_rec(fd_sys, NULL);
  538.       }
  539.    }
  540.  
  541.    return(iostat);
  542. }
  543.  
  544.  
  545. /*
  546. **  Update the locked record with the contents of BUFFER
  547. */
  548. static int
  549. i_updrec(fd_sys, buffer)
  550. int fd_sys;
  551. char *buffer;
  552. {
  553.    struct fd_def *fptr = &fd[fd_sys];
  554.    struct asc_def *aptr = &afd[fd_sys];
  555.    long lock;
  556.    int iostat = IONOLOCK;
  557.  
  558.    if ((lock = aptr->lockoff) >= 0L &&
  559.      (iostat = uniqueness(fd_sys, buffer, lock)) == IOGOOD)
  560.    {
  561.       if (aptr->lockoff != lock)
  562.       {
  563.      aptr->offset = lock;
  564.      iostat = i_lockrec(fd_sys, NULL);
  565.       }
  566.  
  567.       if (iostat == IOGOOD)
  568.       {
  569.      fseek(aptr->fp, lock, SEEK_SET);
  570.      fputc(COMMENT_CHAR, aptr->fp);
  571.      iostat = i_unlock_rec(fd_sys, NULL);
  572.  
  573.      do
  574.      {
  575.         fseek(aptr->fp, 0L, SEEK_END);
  576.         aptr->offset = ftell(aptr->fp);
  577.      }
  578.      while ((iostat = i_lockrec(fd_sys, NULL)) == IOLOCKED);
  579.  
  580.      if (iostat == IOGOOD)
  581.      {
  582.         if ((iostat = write_rec(fd_sys, buffer)) == IOGOOD)
  583.            iostat = i_unlock_rec(fd_sys, NULL);
  584.         else
  585.            i_unlock_rec(fd_sys, NULL);
  586.      }
  587.       }
  588.    }
  589.  
  590.    if (iostat == IONOKEY)
  591.    {
  592.       if (aptr->lockoff != lock)
  593.       {
  594.      aptr->offset = lock;
  595.      iostat = i_lockrec(fd_sys, NULL);
  596.       }
  597.    }
  598.  
  599.    return(iostat);
  600. }
  601.  
  602.  
  603. /*
  604. **  Delete the locked record  --  records are not actually removed,
  605. **  they are just commented out
  606. */
  607. static int
  608. i_delrec(fd_sys, buffer)
  609. int fd_sys;
  610. char *buffer;
  611. {
  612.    struct fd_def *fptr = &fd[fd_sys];
  613.    struct asc_def *aptr = &afd[fd_sys];
  614.    int iostat = IONOLOCK;
  615.  
  616.    /* Deleted records are just commented out and left */
  617.  
  618.    if (aptr->lockoff >= 0L)
  619.    {
  620.       fseek(aptr->fp, aptr->lockoff, SEEK_SET);
  621.       fputc(COMMENT_CHAR, aptr->fp);
  622.       iostat = i_unlock_rec(fd_sys, NULL);
  623.    }
  624.  
  625.    return(iostat);
  626. }
  627.  
  628.  
  629. /*
  630. **  LOCK the current record
  631. */  
  632. static int
  633. i_lockrec(fd_sys, buffer)
  634. int fd_sys;
  635. char *buffer;
  636. {
  637.    struct fd_def *fptr = &fd[fd_sys];
  638.    struct asc_def *aptr = &afd[fd_sys];
  639.    int iostat = IOGOOD;
  640.  
  641. #ifdef USELOCK
  642.    if (fptr->lockmode)
  643.    {
  644.       if (aptr->lockoff >= 0L)
  645.      i_unlock_rec(fd_sys);
  646.  
  647.       fflush(aptr->fp);
  648.  
  649.       if (lseek(fptr->fd_num, aptr->offset, SEEK_SET) != aptr->offset)
  650.      iostat = IOERROR;
  651.       else if (fptr->lockmode == -1);
  652.       {
  653.      if (LOCK_BLK(fptr->fd_num, aptr->offset, fptr->rec_len))
  654.         iostat = IOLOCKED;
  655.       }
  656.       else
  657.       {
  658.      if (LOCK_TST(fptr->fd_num, aptr->offset, fptr->rec_len))
  659.         iostat = IOLOCKED;
  660.       }
  661.    }
  662. #endif
  663.  
  664.    aptr->lockoff = aptr->offset;
  665.  
  666.    return(iostat);
  667. }
  668.  
  669.  
  670. /*
  671. **  UNLOCK the currently locked record
  672. */
  673. static int
  674. i_unlock_rec(fd_sys, buffer)
  675. int fd_sys;
  676. char *buffer;
  677. {
  678.    struct fd_def *fptr = &fd[fd_sys];
  679.    struct asc_def *aptr = &afd[fd_sys];
  680.    int iostat = IOGOOD;
  681.  
  682. #ifdef USELOCK
  683.    if (aptr->lockoff >= 0L)
  684.    {
  685.       fflush(aptr->fp);
  686.    
  687.       if (lseek(fptr->fd_num, aptr->lockoff, SEEK_SET) != aptr->lockoff)
  688.      iostat = IOERROR;
  689.       else if (LOCK_REL(fptr->fd_num, aptr->lockoff, fptr->rec_len))
  690.      iostat = IONOLOCK;
  691.    }
  692. #endif
  693.  
  694.    aptr->lockoff = -1L;
  695.  
  696.    return(iostat);
  697. }
  698.  
  699.  
  700. /*
  701. **  Login - dummy call
  702. */
  703. static int
  704. i_login(fd_sys, buffer)
  705. int fd_sys;
  706. char *buffer;
  707. {
  708.    return(IOGOOD);
  709. }
  710.  
  711.  
  712. /*
  713. **  Logoff - dummy call 
  714. */
  715. static int
  716. i_logoff(fd_sys, buffer)
  717. int fd_sys;
  718. char *buffer;
  719. {
  720.    return(IOGOOD);
  721. }
  722.  
  723.  
  724. /*
  725. **  End (Commit) transaction - dummy call
  726. */
  727. static int
  728. i_commit(fd_sys, buffer)
  729. int fd_sys;
  730. char *buffer;
  731. {
  732.    return(IOGOOD);
  733. }
  734.  
  735.  
  736. /*
  737. **  Rollback (Abort) transaction - dummy call
  738. */
  739. static int
  740. i_rollback(fd_sys, buffer)
  741. int fd_sys;
  742. char *buffer;
  743. {
  744.    return(IOGOOD);
  745. }
  746.  
  747.  
  748. /*
  749. **  Start transaction - dummy call
  750. */
  751. static int
  752. i_transact(fd_sys, buffer)
  753. int fd_sys;
  754. char *buffer;
  755. {
  756.    return(IOGOOD);
  757. }
  758.  
  759.  
  760. static int
  761. uniqueness(fd_sys, buffer, offset)
  762. int fd_sys;
  763. char *buffer;
  764. long offset;
  765. {
  766.    struct fd_def *fptr = &fd[fd_sys];
  767.    struct asc_def *aptr = &afd[fd_sys];
  768.    int cur_key, exact, lockmode;
  769.    int key, iostat = IOGOOD;
  770.  
  771.    for (key = 0; key < fptr->key_cnt; key++)
  772.    {
  773.       if (fptr->keys[key].keytype == KEY_UNIQUE)
  774.       {
  775.      memcpy(aptr->localbuf2, buffer, fptr->rec_len);
  776.  
  777.      cur_key = fptr->cur_key, fptr->cur_key = key;
  778.      exact = fptr->exact, fptr->exact = 1;
  779.      lockmode = fptr->lockmode, fptr->lockmode = 0;
  780.  
  781.      iostat = i_findkey(fd_sys, aptr->localbuf2);
  782.      while (iostat == IOGOOD && aptr->offset == offset)
  783.         iostat = i_nextrec(fd_sys, aptr->localbuf2);
  784.  
  785.      fptr->cur_key = cur_key;
  786.      fptr->exact = exact;
  787.      fptr->lockmode = lockmode;
  788.  
  789.      if (iostat == IONOKEY)
  790.         iostat = IOGOOD;
  791.      else if (iostat == IOGOOD)
  792.         iostat = IODUP;
  793.       }
  794.       if (iostat != IOGOOD)
  795.      break;
  796.    }
  797.  
  798.    return(iostat);
  799. }
  800.  
  801.  
  802. static int
  803. keycmp(fd_sys, buffer)
  804. int fd_sys;
  805. char *buffer;
  806. {
  807.    static char *src, *key;
  808.    static int klen, kstart, ktype;
  809.    struct fd_def *fptr = &fd[fd_sys];
  810.    struct asc_def *aptr = &afd[fd_sys];
  811.    struct keyinfo *kptr = &fptr->keys[fptr->cur_key];
  812.    int cmp = -1, iostat = IOGOOD;
  813.  
  814.    /* Set up record offsets */
  815.    if (fd_sys >= 0)
  816.    {
  817.       ktype  = fptr->flds[fptr->cur_key].fldtype;
  818.       klen   = fptr->flds[fptr->cur_key].fldlen;
  819.       if (ktype == DATTYP && klen == sizeof(long))
  820.      ktype = LNGTYP;
  821.       kstart = fptr->flds[fptr->cur_key].fldstart;
  822.       key    = buffer + kstart;
  823.       src    = aptr->localbuf + kstart;
  824.    }
  825.  
  826.    /* treat unknown types as unequal (less than) */
  827.  
  828.    switch (ktype)
  829.    {
  830.    case CHRTYP:
  831.    case DATTYP:
  832.    case MEMTYP:
  833.       cmp = strncmp(src, key, klen);
  834.       break;
  835.  
  836.    case INTTYP:
  837.    case LNGTYP:
  838.       if (klen == sizeof(short))
  839.      cmp = (int)(*(short *)src - *(short *)key);
  840.       else if (klen == sizeof(int))
  841.      cmp = (int)(*(int *)src - *(int *)key);
  842.       else if (klen == sizeof(long))
  843.      cmp = (int)(*(long *)src - *(long *)key);
  844.       break;
  845.  
  846.    case FLTTYP:
  847.    case DBLTYP:
  848.       if (klen == sizeof(float))
  849.      cmp = (int)(*(float *)src - *(float *)key);
  850.       else if (klen == sizeof(double))
  851.      cmp = (int)(*(double *)src - *(double *)key);
  852.       break;
  853.    }
  854.  
  855.    if (cmp < -1)
  856.       cmp = -1;
  857.    else if (cmp > 1)
  858.       cmp = 1;
  859.  
  860.    return(cmp);
  861. }
  862.  
  863.  
  864. /*
  865. ** Slurps up a string of field separators and returns the next char.
  866. */
  867. static int
  868. eatsep(fp)
  869. FILE *fp;
  870. {
  871.    int c;
  872.  
  873.    while ((c = getc(fp)) != EOF || !feof(fp))
  874.    {
  875.       if (c == ',' || c == ';' || c == ':' || c == ' ')
  876.      continue;
  877.       else if (c == '\n' || isprint(c))
  878.      break;
  879.    }
  880.  
  881.    return(c);
  882. }
  883.  
  884.  
  885. /*
  886. ** Gobble the remainder of a line
  887. */
  888. static int
  889. eatline(fp)
  890. FILE *fp;
  891. {
  892.    int c;
  893.  
  894.    while ((c = getc(fp)) != EOF || !feof(fp))
  895.       if (c == '\n')
  896.      break;
  897.  
  898.    return(c);
  899. }
  900.  
  901.  
  902. /*
  903. ** Read an ASCII delimited record, skipping comments
  904. */
  905. static int
  906. read_rec(fd_sys, buffer)
  907. int fd_sys;
  908. char *buffer;
  909. {
  910.    struct fd_def *fptr = &fd[fd_sys];
  911.    struct asc_def *aptr = &afd[fd_sys];
  912.    int field, i, c, c2, iostat = IOGOOD;
  913.    int fstart, flen, ftype;
  914.    char *fbuf, *fname;
  915.    long bigint;
  916.    double bigfloat;
  917.    char buf[30];
  918.  
  919.    do
  920.    {
  921.       aptr->offset = ftell(aptr->fp);
  922.       if ((c = eatsep(aptr->fp)) == COMMENT_CHAR)
  923.      c = eatline(aptr->fp);
  924.    }
  925.    while (c == '\n');
  926.  
  927.    for (field = 0; field < fptr->fld_cnt; field++)
  928.    {
  929.       ftype  = fptr->flds[field].fldtype;
  930.       flen   = fptr->flds[field].fldlen;
  931.       if (ftype == DATTYP && flen == sizeof(long))
  932.      ftype = LNGTYP;
  933.       fstart = fptr->flds[field].fldstart;
  934.       fbuf   = buffer + fstart;
  935.       fname  = fptr->flds[field].fldname;
  936.  
  937.       if (field)
  938.      c = eatsep(aptr->fp);
  939.  
  940.       if (c == EOF && feof(aptr->fp))
  941.      iostat = field ? IOERROR : IOEOF;
  942.       else
  943.       {
  944.      ungetc(c, aptr->fp);
  945.  
  946.      strcpy(buf, "UNKNOWN");
  947.      switch (ftype)
  948.      {
  949.      case CHRTYP:
  950.      case DATTYP:
  951.      case MEMTYP:
  952.         if ((c = fgetc(aptr->fp)) != '"')
  953.            iostat = IOERROR;
  954.         else
  955.         {
  956.            c = i = 0;
  957.            do
  958.            {
  959.           c2 = c, c = fgetc(aptr->fp);
  960.           if (c == EOF && feof(aptr->fp))
  961.              iostat = IOEOF;
  962.           else if (c2 == '"' && c != '"')
  963.           {
  964.              ungetc(c, aptr->fp);
  965.              if (i < flen)
  966.             fbuf[i] = 0;
  967.              break;
  968.           }
  969.           else if (c != '"' || c2 == '"')
  970.           {
  971.              if (i < flen)
  972.             fbuf[i] = (char)c;
  973.              i++;
  974.              if (c == '"')
  975.             c = 0;
  976.           }
  977.            }
  978.            while (iostat == IOGOOD);
  979.         }
  980.         sprintf(buf, "\"%s\"", fbuf);
  981.         break;
  982.  
  983.      case INTTYP:
  984.      case LNGTYP:
  985.         bigint = 0L;
  986.         if (fscanf(aptr->fp, "%ld", &bigint) != 1)
  987.            iostat = IOERROR;
  988.         else if (flen == sizeof(short))
  989.            *(short *)fbuf = (short)bigint;
  990.         else if (flen == sizeof(int))
  991.            *(int *)fbuf = (int)bigint;
  992.         else if (flen == sizeof(long))
  993.            *(long *)fbuf = bigint;
  994.         sprintf(buf, "%ld", bigint);
  995.         break;
  996.  
  997.      case FLTTYP:
  998.      case DBLTYP:
  999.         bigfloat = 0.0;
  1000.         if (fscanf(aptr->fp, "%lg", &bigfloat) != 1)
  1001.            iostat = IOERROR;
  1002.         else if (flen == sizeof(float))
  1003.            *(float *)fbuf = (float)bigfloat;
  1004.         else if (flen == sizeof(double))
  1005.            *(double *)fbuf = bigfloat;
  1006.         sprintf(buf, "%lg (FP)", bigfloat);
  1007.         break;
  1008.      }
  1009.       }
  1010.  
  1011.       if (iostat != IOGOOD)
  1012.      break;
  1013.    }
  1014.  
  1015.    /* this is so multiple EOF's don't mess the pointer */
  1016.    if (iostat != IOEOF)
  1017.    {
  1018.       if (iostat != IOGOOD)
  1019.      aptr->offset = -1L;
  1020.       else if ((c = eatsep(aptr->fp)) != '\n')
  1021.      iostat = IOERROR;
  1022.    }
  1023.  
  1024.    return(iostat);
  1025. }
  1026.  
  1027.  
  1028. /*
  1029. ** Write an ASCII delimited record
  1030. */
  1031. static int
  1032. write_rec(fd_sys, buffer)
  1033. int fd_sys;
  1034. char *buffer;
  1035. {
  1036.    struct fd_def *fptr = &fd[fd_sys];
  1037.    struct asc_def *aptr = &afd[fd_sys];
  1038.    int field, i, c, iostat = IOGOOD;
  1039.    int fstart, flen, ftype;
  1040.    char *fbuf, *fname;
  1041.    long bigint;
  1042.    double bigfloat;
  1043.  
  1044.    fseek(aptr->fp, aptr->offset, SEEK_SET);
  1045.  
  1046.    for (field = 0; field < fptr->fld_cnt; field++)
  1047.    {
  1048.       ftype  = fptr->flds[field].fldtype;
  1049.       flen   = fptr->flds[field].fldlen;
  1050.       if (ftype == DATTYP && flen == sizeof(long))
  1051.      ftype = LNGTYP;
  1052.       fstart = fptr->flds[field].fldstart;
  1053.       fbuf   = buffer + fstart;
  1054.       fname  = fptr->flds[field].fldname;
  1055.  
  1056.       if (field)
  1057.      fputc(',', aptr->fp);
  1058.  
  1059.       switch (ftype)
  1060.       {
  1061.       case CHRTYP:
  1062.       case DATTYP:
  1063.       case MEMTYP:
  1064.      fputc('"', aptr->fp);
  1065.      for (i = 0; i < flen; i++)
  1066.      {
  1067.         if (!(c = fbuf[i]))
  1068.            break;
  1069.         else if (c == '"')
  1070.            fputc('"', aptr->fp);
  1071.         fputc(c, aptr->fp);
  1072.      }
  1073.      fputc('"', aptr->fp);
  1074.      break;
  1075.  
  1076.       case INTTYP:
  1077.       case LNGTYP:
  1078.      bigint = 0L;
  1079.      if (flen == sizeof(short))
  1080.         bigint = (long)*(short *)fbuf;
  1081.      else if (flen == sizeof(int))
  1082.         bigint = (long)*(int *)fbuf;
  1083.      else if (flen == sizeof(long))
  1084.         bigint = *(long *)fbuf;
  1085.      else
  1086.         fprintf(aptr->fp, "<len=%d>", flen);
  1087.      fprintf(aptr->fp, "%ld", bigint);
  1088.      break;
  1089.  
  1090.       case FLTTYP:
  1091.       case DBLTYP:
  1092.      bigfloat = 0.0;
  1093.      if (flen == sizeof(float))
  1094.         bigfloat = (double)*(float *)fbuf;
  1095.      else if (flen == sizeof(double))
  1096.         bigfloat = *(double *)fbuf;
  1097.      else
  1098.         fprintf(aptr->fp, "<len=%d>", flen);
  1099.      fprintf(aptr->fp, "%lg", bigfloat);
  1100.      break;
  1101.  
  1102.       default:
  1103.      fputc('?', aptr->fp);
  1104.      break;
  1105.       }
  1106.    }
  1107.    fputc('\n', aptr->fp);
  1108.    fflush(aptr->fp);
  1109.  
  1110.    return(IOGOOD);
  1111. }
  1112.  
  1113.  
  1114. static int
  1115. slipback(fd_sys)
  1116. int fd_sys;
  1117. {
  1118.    struct fd_def *fptr = &fd[fd_sys];
  1119.    struct asc_def *aptr = &afd[fd_sys];
  1120.    int c, iostat = IOGOOD;
  1121.    long topoff, here, startoff;
  1122.    int inc = 0;
  1123.  
  1124.    topoff = here = startoff = aptr->offset;
  1125.  
  1126.    do
  1127.    {
  1128. /*
  1129. errmsg("SLIPBACK-%d: looping (topoff=%ld, here=%ld, startoff=%ld)", ++inc, topoff, here, startoff);
  1130. */
  1131.  
  1132.       if (here < startoff)
  1133.       {
  1134.      /* find the next real record */
  1135.      fseek(aptr->fp, topoff = here, SEEK_SET);
  1136.      /* c = (topoff > 0L) ? eatline(aptr->fp) : '\n'; */
  1137.      c = eatline(aptr->fp);
  1138.      while (c == '\n')
  1139.      {
  1140.         here = ftell(aptr->fp);
  1141.         if ((c = eatsep(aptr->fp)) == COMMENT_CHAR)
  1142.            c = eatline(aptr->fp);
  1143.      }
  1144.  
  1145.      if (here == startoff)
  1146.         break;
  1147.      else if (here > startoff)
  1148.         iostat = IOTOF;
  1149.       }
  1150.       else
  1151.       {
  1152.      /* backup a bit */
  1153.      if (topoff > BUFSIZ / 2)
  1154.         topoff -= BUFSIZ / 2;
  1155.      else if (topoff)
  1156.         topoff = 0L;
  1157.      else
  1158.      {
  1159.         iostat = IOTOF;
  1160.         break;
  1161.      }
  1162.  
  1163.      /* find the next real record */
  1164.      fseek(aptr->fp, topoff, SEEK_SET);
  1165.      c = (topoff > 0L) ? eatline(aptr->fp) : '\n';
  1166.      while (c == '\n')
  1167.      {
  1168.         here = ftell(aptr->fp);
  1169.         if ((c = eatsep(aptr->fp)) == COMMENT_CHAR)
  1170.            c = eatline(aptr->fp);
  1171.      }
  1172.       }
  1173.  
  1174.       if (c == EOF && feof(aptr->fp))
  1175.      iostat = IOERROR;
  1176.    }
  1177.    while (iostat == IOGOOD);
  1178.  
  1179.    if (iostat == IOGOOD)
  1180.    {
  1181.       aptr->offset = topoff;
  1182.       fseek(aptr->fp, aptr->offset, SEEK_SET);
  1183.    }
  1184.    else if (iostat != IOTOF)
  1185.       aptr->offset = -1L;
  1186.  
  1187. /*
  1188. errmsg("SLIPBACK=%d: offset=%ld iostat=%s (topoff=%ld, here=%ld, startoff=%ld)", inc, aptr->offset, io_tran(iostat), topoff, here, startoff);
  1189. */
  1190.  
  1191.    return(iostat);
  1192. }
  1193.  
  1194.  
  1195. /*
  1196. ** Assign section
  1197. */
  1198.  
  1199.  
  1200. void assign_IO_AD(dbnum)
  1201. int dbnum;
  1202. {
  1203.    Fntab[dbnum - 1][0]  = (int(*)())0; /* Empty */
  1204.    Fntab[dbnum - 1][1]  = i_init_file;
  1205.    Fntab[dbnum - 1][2]  = i_open_file;
  1206.    Fntab[dbnum - 1][3]  = i_close_file;
  1207.    Fntab[dbnum - 1][4]  = i_addrec;
  1208.    Fntab[dbnum - 1][5]  = i_delrec;
  1209.    Fntab[dbnum - 1][6]  = i_findkey;
  1210.    Fntab[dbnum - 1][7]  = i_firstkey;
  1211.    Fntab[dbnum - 1][8]  = i_lastkey;
  1212.    Fntab[dbnum - 1][9]  = i_lockrec;
  1213.    Fntab[dbnum - 1][10] = i_nextrec;
  1214.    Fntab[dbnum - 1][11] = i_prevrec;
  1215.    Fntab[dbnum - 1][12] = i_unlock_rec;
  1216.    Fntab[dbnum - 1][13] = i_updrec;
  1217.    Fntab[dbnum - 1][14] = i_commit;
  1218.    Fntab[dbnum - 1][15] = i_login;
  1219.    Fntab[dbnum - 1][16] = i_logoff;
  1220.    Fntab[dbnum - 1][17] = i_rollback;
  1221.    Fntab[dbnum - 1][18] = i_transact;
  1222.    Fntab[dbnum - 1][19] = i_selectinx;
  1223.    Fntab[dbnum - 1][20] = i_rereadrec;
  1224.    Fntab[dbnum - 1][21] = i_filename;
  1225. }
  1226.