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

  1. /* ==( io/src/idbc3.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   NA   24-Feb-88                        */
  10. /* Modified  VV   12-Apr-90  See comments below    */
  11. /* ----------------------------------------------- */
  12. /* %W%  (%H% %T%) */
  13.  
  14. /*
  15.  *  Modifications
  16.  *
  17.  *  12-Apr-90  VvA - corrections to next/prev fn for EOF/TOF 
  18.  *  28-Mar-90  VvA - adjustments for locking modes, transactions
  19.  *  14-Mar-90  VvA - fixed blank dBASE field bug
  20.  *  01-Feb-90  VvA - fld_cnt now in iogen.c, fd[] struct
  21.  *  01-Feb-90  VvA - Enabled openmode in open_file()
  22.  *  14-Dec-89  VvA - V.2 modifications
  23.  *  01-Sep_89  VvA - Modified for generic I/O interface
  24.  *  01-Sep_88  VvA - Adapted from existing IO modules
  25. */
  26.  
  27. /*  dBC III+ I/O calls via general IOGEN.C interface  */
  28.  
  29.  
  30. # include <stdio.h>
  31. # include <dbc3plus.h>
  32. # include <iodef.h>
  33. # include <iomsg.h>
  34. # include <proc.io>
  35. # include <bench.h>
  36. # include <iosup.h>
  37.  
  38.  
  39. /* Function prototypes */
  40. # ifdef ANSI
  41. static int i_addrec(int, char *);
  42. static int i_close_file(int, char *);
  43. static int i_commit(int, char *);
  44. static int i_delrec(int, char *);
  45. static int i_filename(int, char *);
  46. static int i_findkey(int, char *);
  47. static int i_firstkey(int, char *);
  48. static int i_init_file(int, char *);
  49. static int i_lastkey(int, char *);
  50. static int i_lockrec(int, char *);
  51. static int i_login(int, char *);
  52. static int i_logoff(int, char *);
  53. static int i_nextrec(int, char *);
  54. static int i_open_file(int, char *);
  55. static int i_prevrec(int, char *);
  56. static int i_rereadrec(int, char *);
  57. static int i_rollback(int, char *);
  58. static int i_selectinx(int, char *);
  59. static int i_transact(int, char *);
  60. static int i_unlock_rec(int, char *);
  61. static int i_updrec(int, char *);
  62. static int  create_file(int, char *);
  63. static int  load_memos(int, int);
  64. static int  load_keys(int, int);
  65. static int  length_check(int);
  66. static int  get_record(int, char *, int);
  67. static int  update_keys(int, char *, int);
  68. static int  lock_sizebyte(int, char *);
  69. static int  lock_ndx(int);
  70. static int  unlock_ndx(int, char *);
  71. static int  lock_mem(int);
  72. static int  io_xlate(int, int, char *);
  73. static void unlock_mem(int);
  74. static void unlock_sizebyte(int);
  75. static void setupkey(int, char *, char *);
  76. static void buff2db(int, char *, char *);
  77. static void db2buff(int, char *, char *);
  78. # else
  79. static int i_addrec();
  80. static int i_close_file();
  81. static int i_commit();
  82. static int i_delrec();
  83. static int i_filename();
  84. static int i_findkey();
  85. static int i_firstkey();
  86. static int i_init_file();
  87. static int i_lastkey();
  88. static int i_lockrec();
  89. static int i_login();
  90. static int i_logoff();
  91. static int i_nextrec();
  92. static int i_open_file();
  93. static int i_prevrec();
  94. static int i_rereadrec();
  95. static int i_rollback();
  96. static int i_selectinx();
  97. static int i_transact();
  98. static int i_unlock_rec();
  99. static int i_updrec();
  100. static int  create_file();
  101. static int  load_memos();
  102. static int  load_keys();
  103. static int  length_check();
  104. static int  get_record();
  105. static int  update_keys();
  106. static int  lock_sizebyte();
  107. static int  lock_ndx();
  108. static int  unlock_ndx();
  109. static int  lock_mem();
  110. static int  io_xlate();
  111. static void unlock_mem();
  112. static void unlock_sizebyte();
  113. static void setupkey();
  114. static void buff2db();
  115. static void db2buff();
  116. # endif
  117.  
  118.  
  119. extern RECNUM _appnded;          /* allows use of APPEND in dBputr function */
  120. extern int _dlock;
  121.  
  122.  
  123. /*
  124.  * structure for dBC III+ specific values 
  125. */
  126. struct dbc_def
  127. {
  128.    char *dbf_num;                                   /* data file descriptor */
  129.    char *mm_num;                                    /* memo file descriptor */
  130.    char *ix_num[MAX_KEYS];                        /* index file descriptors */
  131.    int dbrec_len;                         /* record length seen by dBC file */
  132. };
  133.  
  134. static struct dbc_def fdbf[MAX_FILES];
  135.  
  136. static char keybuff[MAX_FLDLEN * MAX_SEGS + MAX_SEGS];
  137. static char xkeybuff[MAX_FLDLEN * MAX_SEGS + MAX_SEGS];
  138. static char oldbuff[MAX_RECLEN];
  139. static char storbuff[MAX_RECLEN];
  140. static char memobuff[5000];
  141.  
  142. static int dberrno;                                   /* dBC III error code */
  143. static RECNUM recnum;                      /* record number in dBC III form */
  144. static int DBCMODE;                  /* file open mode, shared or exclusive */
  145.  
  146.  
  147. /*
  148.  *
  149.  * Interface Functions
  150.  *
  151. */
  152.  
  153.  
  154. /*
  155.  *  Sets up File Name extension.
  156. */
  157. static int i_filename(fd_sys, buffer)
  158. int fd_sys;
  159. char *buffer;
  160. {
  161.    for ( ; (*buffer != '.') && (*buffer != NULL); buffer++)
  162.       ;
  163.    *buffer = NULL;
  164.  
  165.    return(IOGOOD);
  166. }
  167.  
  168. /*
  169.  *  File initialization
  170. */
  171. static int i_init_file(fd_sys, buffer)
  172. int fd_sys;
  173. char *buffer;
  174. {
  175.    return(IOGOOD);
  176. }
  177.  
  178. /*
  179.  *  File open function
  180. */
  181. static int i_open_file(fd_sys, buffer)
  182. int fd_sys;
  183. char *buffer;
  184. {
  185.    int n;
  186.    char *dbfdesc;
  187.    char dbfname[FILENAME_LEN];
  188.    struct fd_def *fptr = &fd[fd_sys];
  189.    struct dbc_def *dptr = &fdbf[fd_sys];
  190.  
  191.    strcpy(dbfname, fptr->filname);
  192.    strcat(dbfname, ".DBF");         /* dBASE III type filename from filname */
  193.  
  194.    dptr->mm_num = NULL;
  195.  
  196.    _dlock = d_TLOCK;                               /* dBC3+ no-wait locking */
  197.  
  198.    if (fptr->openmode & OUTPUT_FLAG)
  199.       create_file(fd_sys, dbfname);     /* if OUTPUT, delete existing files */
  200.  
  201.    DBCMODE = (fptr->openmode & P_SHARED) ? d_SHARED : d_SINGLE;
  202.  
  203.    if ((dberrno = dBopen(dbfname, DBCMODE | d_MINBUF, &dbfdesc)) != SUCCESS)
  204.    {
  205.       if ((DBCMODE == d_SHARED) && (dberrno == d_LOCKED))
  206.       {
  207.          errmsg(FileShareReqd);      /* unconditional exit if SHARE not run */
  208.          return(IOERROR);
  209.       }
  210.                           /* exit if file to be read-only OR already exists */
  211.       if ((fptr->openmode & INPUT_FLAG) || !access(dbfname, 00))
  212.          return(io_xlate(fd_sys, dberrno, "dBC OPEN1"));
  213.  
  214.       if (create_file(fd_sys, dbfname) != IOGOOD)
  215.          return(IOERROR);
  216.  
  217.       if ((dberrno = dBopen(dbfname, DBCMODE | d_MINBUF, &dbfdesc)) != SUCCESS)
  218.          return(io_xlate(fd_sys, dberrno, "dBC OPEN2"));
  219.    }
  220.                                        /* file has been opened successfully */
  221.    dptr->dbf_num = dbfdesc; 
  222.  
  223.    if (length_check(fd_sys) != IOGOOD)
  224.    {
  225.       i_close_file(fd_sys, buffer);
  226.       return(IOERROR);
  227.    }
  228.  
  229.    return(IOGOOD);
  230. }
  231.  
  232. /*
  233.  *  dBC III+ create file function - file will be opened by the create call
  234. */
  235. static int create_file(fd_sys, dfname)
  236. int fd_sys;                                          /* index into fd table */
  237. char *dfname;
  238. {
  239.    int j;
  240.    struct fd_def *fptr = &fd[fd_sys];
  241.    struct dbc_def *dptr = &fdbf[fd_sys];
  242.    dBFIELD *fldtmp;
  243.  
  244.    fldtmp = (dBFIELD *)alloc(sizeof(dBFIELD) * fptr->fld_cnt);
  245.  
  246.    for (j = 0; j < fptr->fld_cnt; j++)           /* load field descriptions */
  247.    {
  248.       strcpy(fldtmp[j].fieldnm, cvt_upper(fptr->flds[j].fldname));
  249.       fldtmp[j].dec   = (FLDDEC)0;
  250.       switch(fptr->flds[j].fldtype)
  251.       {
  252.          case CHRTYP :
  253.             fldtmp[j].type  = 'C';
  254.             fldtmp[j].width = (FLDWIDTH)fptr->flds[j].fldlen;
  255.             break;
  256.          case INTTYP :
  257.          case LNGTYP :
  258.          case FLTTYP :
  259.          case DBLTYP :
  260.             fldtmp[j].type  = 'N';
  261.             fldtmp[j].width = (FLDWIDTH)nummasklen(fptr->flds[j].fldmask);
  262.             fldtmp[j].dec   = (FLDDEC)decmasklen(fptr->flds[j].fldmask);
  263.             break;
  264.          case DATTYP :
  265.                 if (fptr->flds[j].fldlen == 6)
  266.                 {
  267.                 fldtmp[j].type  = 'D';
  268.                 fldtmp[j].width = (FLDWIDTH)8;
  269.                 }
  270.                 else
  271.                 {
  272.                     fldtmp[j].type = 'N';
  273.                     fldtmp[j].width = (FLDWIDTH)10;
  274.                     fldtmp[j].dec = (FLDDEC)0;
  275.                 }
  276.             break;
  277.          case LOGTYP :
  278.             fldtmp[j].type  = 'L';
  279.             fldtmp[j].width = (FLDWIDTH)1;
  280.             break;
  281.          case MEMTYP :
  282.             fldtmp[j].type  = 'M';
  283.             fldtmp[j].width = (FLDWIDTH)10;
  284.             break;
  285.       }      
  286.    }
  287.  
  288.    if ((dberrno = dBcreat(dfname, (FLDNUM)fptr->fld_cnt, fldtmp)) != SUCCESS)
  289.    {
  290.       free(fldtmp);
  291.       return(io_xlate(fd_sys, dberrno, "dBC CRT"));
  292.    }
  293.    free(fldtmp);
  294.  
  295.    if (load_memos(fd_sys, TRUE) != IOGOOD)
  296.       return(IOERROR);
  297.  
  298.    return((load_keys(fd_sys, TRUE) > 0) ? IOGOOD : IOERROR);
  299. }
  300.  
  301. /*
  302.  *  dBC III+ memo load function - creates or opens memo files 
  303.  *  - if creatmemo is TRUE, file will be created, otherwise it is opened
  304.  *  - one memo file will do for all memo fields
  305. */
  306. static int load_memos(fd_sys, creatmemo)
  307. int fd_sys, creatmemo;
  308. {
  309.    int j;
  310.    char *memdesc, memname[FILENAME_LEN];
  311.    struct fd_def *fptr = &fd[fd_sys];
  312.    struct dbc_def *dptr = &fdbf[fd_sys];
  313.  
  314.    strcpy(memname, fptr->filname);     /* memo names match their file names */
  315.    strcat(memname, ".DBT");
  316.  
  317.    for (j = 0; j < fptr->fld_cnt; j++)           /* load field descriptions */
  318.       if (fptr->flds[j].fldtype == MEMTYP)
  319.       {
  320.          if (creatmemo)
  321.          {
  322.             if ((dberrno = dBmcreat(memname)) != SUCCESS)
  323.                return(io_xlate(fd_sys, dberrno, "dBC MEMCRTE"));
  324.          }
  325.  
  326.          if ((dberrno = dBmopen(memname, DBCMODE, &memdesc)) != SUCCESS)
  327.             return(io_xlate(fd_sys, dberrno, "dBC MEMOPEN"));
  328.  
  329.          fdbf[fd_sys].mm_num = memdesc;
  330.          break;
  331.       }
  332.  
  333.    return(IOGOOD);
  334. }
  335.  
  336. /*
  337.  *  dBC III+ key load function - creates or opens indexes for new files 
  338.  *  - if creatndx is TRUE, index will be created, otherwise it is opened
  339. */
  340. static int load_keys(fd_sys, creatndx)
  341. int fd_sys, creatndx;
  342. {
  343.    int ndxid, n, m, fx;
  344.    char keytype, *ndxdesc;
  345.    char ndxname[FILENAME_LEN], keyname[FLDNAME_LEN * MAX_SEGS * 3], fmtstr[12];
  346.    struct fd_def *fptr = &fd[fd_sys];
  347.    KEYLEN keylen;
  348.  
  349.    strcpy(ndxname, fptr->filname);    /* index names match their file names */
  350.    if ((ndxid = strlen(ndxname)) > 7)           /* ndxid is index id offset */
  351.       ndxid = 7;
  352.    ndxname[ndxid] = '\0';
  353.    strcat(ndxname, "0.NDX");
  354.  
  355.    n = 0;
  356.    while (fptr->keys[n].segcount != -1)
  357.    {
  358.       ndxname[ndxid] = (char)(n + 49);      /* sequential index name suffix */
  359.  
  360.       if (creatndx)                                   /* create the indexes */
  361.       {
  362.          keyname[0] = '\0';
  363.          keylen = (KEYLEN)0;
  364.          keytype = 'C';
  365.          for (m = 0; m < fptr->keys[n].segcount; m++)
  366.          {                  /* requires conversions for mixed type keys !!! */
  367.             fx = fptr->keys[n].fldindex[m];
  368.             if (m > 0)
  369.                strcat(keyname, "+");
  370.             if ((fptr->keys[n].segcount == 1) || (fptr->flds[fx].fldtype == CHRTYP))
  371.             {
  372.                if ((fptr->flds[fx].fldtype == CHRTYP) &&
  373.                    (fptr->flds[fx].fldlen != fptr->keys[n].seglen[m]))
  374.                {
  375.                   strcat(keyname, "SUBSTR(");
  376.                   strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
  377.                   zerorec(fmtstr, 12);
  378.                   sprintf(fmtstr, ",%d,%d)", 
  379.                      (fptr->keys[n].segstart[m]+1 - fptr->flds[fx].fldstart), 
  380.                      fptr->keys[n].seglen[m]);
  381.                   strcat(keyname, fmtstr);
  382.                }
  383.                else
  384.                   strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
  385.                keylen += (KEYLEN)fptr->keys[n].seglen[m];
  386.             }
  387.             else if (fptr->flds[fx].fldtype == DATTYP)
  388.             {
  389.                     if (fptr->flds[fx].fldlen == 6)
  390.                     {
  391.                    strcat(keyname, "DTOC(");
  392.                    strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
  393.                    strcat(keyname, ")");
  394.                    keylen += (KEYLEN)8;
  395.                     }
  396.                     else
  397.                     {
  398.                    strcat(keyname, "STR(");
  399.                    strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
  400.                    strcat(keyname, ",10,0)");
  401.                    keylen += (KEYLEN)10;
  402.                     }
  403.             }
  404.             else
  405.             {
  406.                zerorec(fmtstr, 12);
  407.                sprintf(fmtstr, ",%d,%d)", nummasklen(fptr->flds[fx].fldmask), decmasklen(fptr->flds[fx].fldmask));
  408.                strcat(keyname, "STR(");
  409.                strcat(keyname, cvt_upper(fptr->flds[fx].fldname));
  410.                strcat(keyname, fmtstr);
  411.                keylen += (KEYLEN)nummasklen(fptr->flds[fx].fldmask);
  412.             }
  413.          }
  414.  
  415.          if (fptr->keys[n].segcount == 1)     /* compound keys all type 'C' */
  416.          {
  417.             fx = fptr->keys[n].fldindex[0];
  418.             switch(fptr->flds[fx].fldtype)
  419.             {
  420.                case CHRTYP :
  421.                   keytype = 'C';
  422.                   break;
  423.                case DATTYP :
  424.                         if (fptr->flds[fx].fldlen == 6)
  425.                         {
  426.                       keytype = 'D';
  427.                       break;
  428.                         }              /* long int dates fall through to 'N' type */
  429.                case INTTYP :
  430.                case LNGTYP :
  431.                case FLTTYP :
  432.                case DBLTYP :
  433.                   keytype = 'N';
  434.                   break;
  435.             }
  436.          }
  437.          if ((dberrno = dBicreat(ndxname, keyname, keylen, keytype)) != SUCCESS)
  438.             return(io_xlate(fd_sys, dberrno, "dBC IXCRTE"));
  439.       }
  440.       else                                         /* just open the indexes */
  441.       {
  442.          if ((dberrno = dBiopen(ndxname, DBCMODE, &ndxdesc)) != SUCCESS)
  443.             return(io_xlate(fd_sys, dberrno, "dBC IXOPEN"));
  444.  
  445.          fdbf[fd_sys].ix_num[n] = ndxdesc;
  446.       }
  447.       n++;
  448.    }
  449.    return(n);                       /* value returned is the number of keys */
  450. }
  451.  
  452. /*
  453.  *  Length check function
  454.  *  - checks record length against that expected by PRO-C
  455. */
  456. static int length_check(fd_sys)
  457. int fd_sys;
  458. {
  459.    int i;
  460.    RECLEN chkreclen;
  461.    FLDNUM chkfldcnt;
  462.    char cm, cd, cy;
  463.    struct fd_def *fptr = &fd[fd_sys];
  464.    struct dbc_def *dptr = &fdbf[fd_sys];
  465.    dBFIELD *flds;
  466.    
  467.    flds = (dBFIELD *)alloc(sizeof(dBFIELD) * fptr->fld_cnt);
  468.  
  469.    dptr->dbrec_len = 0;        /* what PRO-C thinks DBF record length is... */
  470.  
  471.    for (i = 0; i < fptr->fld_cnt; i++)
  472.    {
  473.       switch (fptr->flds[i].fldtype)
  474.       {
  475.          case DATTYP :
  476.                 if (fptr->flds[i].fldlen == 6)
  477.                 dptr->dbrec_len += 8;
  478.                 else
  479.                     dptr->dbrec_len += 10;
  480.             break;
  481.          case INTTYP :
  482.          case LNGTYP :
  483.          case FLTTYP :
  484.          case DBLTYP :
  485.             dptr->dbrec_len += nummasklen(fptr->flds[i].fldmask);
  486.             break;
  487.          case CHRTYP :
  488.             dptr->dbrec_len += fptr->flds[i].fldlen;
  489.             break;
  490.          case LOGTYP :
  491.             dptr->dbrec_len += 1;
  492.             break;
  493.          case MEMTYP :
  494.             dptr->dbrec_len += 10;
  495.             break;
  496.       }
  497.    }                 /* dbrec_len is field length as defined in application */
  498.  
  499.    if ((dberrno = dBgetf(dptr->dbf_num, &chkreclen, &cm, &cd, &cy, &chkfldcnt, flds)) != SUCCESS)
  500.    {
  501.       free(flds);
  502.       return(io_xlate(fd_sys, dberrno, "dBC LCHK"));
  503.    }
  504.  
  505.    free(flds);
  506.  
  507.    if (dptr->dbrec_len != (int)chkreclen)
  508.    {                                  /* if file length has been changed... */
  509.       errmsg(FileRecLenChg_s, fptr->filname);
  510.       return(IOERROR);
  511.    }
  512.  
  513.    if (load_memos(fd_sys, FALSE) != IOGOOD)
  514.       return(IOERROR);
  515.  
  516.    return((load_keys(fd_sys, FALSE) > 0) ? IOGOOD : IOERROR);
  517. }
  518.  
  519. /*
  520.  *  File close function - including index files
  521.  *  - with manual locking, files must be locked, flushed and unlocked
  522.  *    before closing
  523. */
  524. static int i_close_file(fd_sys, buffer)
  525. int fd_sys;
  526. char *buffer;
  527. {
  528.    int n;
  529.    struct dbc_def *dptr = &fdbf[fd_sys];
  530.  
  531.    n = 0;
  532.    while (fd[fd_sys].keys[n].segcount != -1)
  533.    {
  534.       if ((dberrno = dBiclose(dptr->ix_num[n])) != SUCCESS)
  535.          io_xlate(fd_sys, dberrno, "dBC ICLS");
  536.       n++;
  537.    }
  538.  
  539.    if (dptr->mm_num)                                 /* close the memo file */
  540.       if ((dberrno = dBmclose(dptr->mm_num)) != SUCCESS)
  541.          io_xlate(fd_sys, dberrno, "dBC MCLS");
  542.  
  543.    if ((dberrno = dBclose(dptr->dbf_num)) != SUCCESS)
  544.       return(io_xlate(fd_sys, dberrno, "dBC DCLS"));
  545.  
  546.    fd[fd_sys].active = NO;
  547.    return(IOGOOD);
  548. }
  549.  
  550. /*
  551.  *  Select an index to perform processing on - already done in IOGEN.C
  552. */
  553. static int i_selectinx(fd_sys, buffer)
  554. int fd_sys;
  555. char *buffer;
  556. {
  557.    return(IOGOOD);
  558. }
  559.  
  560.  
  561. /*
  562.  *  Find a record by key value
  563. */
  564. static int i_findkey(fd_sys, buffer)
  565. int fd_sys;
  566. char *buffer;
  567. {
  568.    int errcode;
  569.    struct fd_def *fptr = &fd[fd_sys];
  570.    struct dbc_def *dptr = &fdbf[fd_sys];
  571.  
  572.    setupkey(fd_sys, buffer, keybuff);
  573.  
  574.    dberrno = dBtkey(dptr->ix_num[fptr->cur_key], keybuff, &recnum);
  575.    if ((dberrno != SUCCESS) && (fptr->exact || (dberrno != d_MAYBE)))
  576.       return(io_xlate(fd_sys, dberrno, "dBC FIND"));
  577.  
  578.    errcode = get_record(fd_sys, buffer, NEXT);
  579.    return((fptr->exact && (errcode == IOEOF)) ? IONOKEY : errcode);
  580. }
  581.  
  582. /*
  583.  *  Find first record in the file
  584. */
  585. static int i_firstkey(fd_sys, buffer)
  586. int fd_sys;
  587. char *buffer;
  588. {
  589.    struct fd_def *fptr = &fd[fd_sys];
  590.    struct dbc_def *dptr = &fdbf[fd_sys];
  591.  
  592.    if ((dberrno = dBrewind(dptr->ix_num[fptr->cur_key])) != SUCCESS)
  593.       return(io_xlate(fd_sys, dberrno, "dBC FRST1"));
  594.  
  595.    if ((dberrno = dBnkey(dptr->ix_num[fptr->cur_key], keybuff, &recnum)) != SUCCESS)
  596.       return(io_xlate(fd_sys, dberrno, "dBC FRST2"));
  597.  
  598.    return(get_record(fd_sys, buffer, NEXT));
  599. }
  600.  
  601. /*
  602.  *  Find last physical record in the file
  603. */
  604. static int i_lastkey(fd_sys, buffer)
  605. int fd_sys;
  606. char *buffer;
  607. {
  608.    struct fd_def *fptr = &fd[fd_sys];
  609.    struct dbc_def *dptr = &fdbf[fd_sys];
  610.  
  611.    if ((dberrno = dBfwd(dptr->ix_num[fptr->cur_key])) != SUCCESS)
  612.       return(io_xlate(fd_sys, dberrno, "dBC LAST1"));
  613.  
  614.    if ((dberrno = dBpkey(dptr->ix_num[fptr->cur_key], keybuff, &recnum)) != SUCCESS)
  615.    {
  616.       if ((dberrno == d_NOKEY) || (dberrno == d_TOPKEY))
  617.          return(IOEOF);
  618.       return(io_xlate(fd_sys, dberrno, "dBC LAST2"));
  619.    }
  620.  
  621.    return(get_record(fd_sys, buffer, PREV));
  622. }
  623.  
  624. /*
  625.  *  Find next record in the file
  626. */
  627. static int i_nextrec(fd_sys, buffer)
  628. int fd_sys;
  629. char *buffer;
  630. {
  631.    struct fd_def *fptr = &fd[fd_sys];
  632.    struct dbc_def *dptr = &fdbf[fd_sys];
  633.     
  634.    i_unlock_rec(fd_sys, buffer);   /* unlock current rec before proceeding */
  635.  
  636.    if ((dberrno = dBnkey(dptr->ix_num[fptr->cur_key], xkeybuff, &recnum)) != SUCCESS)
  637.    {
  638.       if (dberrno == d_ENDKEY)
  639.          return(IOEOF);
  640.       return(io_xlate(fd_sys, dberrno, "dBC NEXT"));
  641.    }
  642.  
  643.    return(get_record(fd_sys, buffer, NEXT));
  644. }
  645.  
  646. /*
  647.  *  Find previous record in the file
  648. */
  649. static int i_prevrec(fd_sys, buffer)
  650. int fd_sys;
  651. char *buffer;
  652. {
  653.    struct fd_def *fptr = &fd[fd_sys];
  654.    struct dbc_def *dptr = &fdbf[fd_sys];
  655.  
  656.    i_unlock_rec(fd_sys, buffer);   /* unlock current rec before proceeding */
  657.  
  658.    if ((dberrno = dBpkey(dptr->ix_num[fptr->cur_key], xkeybuff, &recnum)) != SUCCESS)
  659.    {
  660.       if (dberrno == d_TOPKEY)
  661.          return(IOTOF);
  662.       return(io_xlate(fd_sys, dberrno, "dBC PREV"));
  663.    }
  664.  
  665.    return(get_record(fd_sys, buffer, PREV));
  666. }
  667.  
  668. /*
  669.  *  Retrieve a record
  670.  *  - record locking is taken care of here
  671.  *  - if nextone is TRUE, will try next record when passing over a deleted
  672.  *    record; otherwise will try previous record
  673. */
  674. static int get_record(fd_sys, buffer, nextone)
  675. int fd_sys, nextone;
  676. char *buffer;
  677. {
  678.    char stat;
  679.    struct dbc_def *dptr = &fdbf[fd_sys];
  680.  
  681.    if (i_lockrec(fd_sys, buffer) != IOGOOD)
  682.       return(IOERROR);
  683.  
  684.    if ((dberrno = dBflush(dptr->dbf_num)) != SUCCESS)
  685.    {
  686.       i_unlock_rec(fd_sys, buffer);
  687.       return(io_xlate(fd_sys, dberrno, "dBC GETREC1"));
  688.    }
  689.    if ((dberrno = dBgetr(dptr->dbf_num, recnum, storbuff, &stat)) != SUCCESS)
  690.    {
  691.       i_unlock_rec(fd_sys, buffer);
  692.       return(io_xlate(fd_sys, dberrno, "dBC GETREC2"));
  693.    }
  694.  
  695.    if (stat == INACTIVE)          /* skip over record if flagged as deleted */
  696.       return(nextone ? i_nextrec(fd_sys, buffer) : i_prevrec(fd_sys, buffer));
  697.  
  698.    db2buff(fd_sys, storbuff, buffer);                 /* back to PRO-C form */
  699.    bytecpy(oldbuff, buffer, fd[fd_sys].rec_len);       /* copy original rec */
  700.    return(IOGOOD);
  701. }
  702.  
  703. /*
  704.  *  Re-read/reposition record pointer function - if required
  705. */
  706. static int i_rereadrec(fd_sys, buffer)
  707. int fd_sys;
  708. char *buffer;
  709. {
  710.    return(i_findkey(fd_sys, buffer));
  711. }
  712.  
  713.  
  714. /*
  715.  *  Add a new record.
  716. */
  717. static int i_addrec(fd_sys, buffer)
  718. int fd_sys;
  719. char *buffer;
  720. {
  721.    struct dbc_def *dptr = &fdbf[fd_sys];
  722.  
  723.    buff2db(fd_sys, buffer, storbuff);
  724.  
  725.    if (!lock_sizebyte(fd_sys, buffer))    /* append only if sizebyte locked */
  726.       return(IOERROR);
  727.    if (!lock_ndx(fd_sys))                             /* index lock failure */
  728.    {
  729.       unlock_sizebyte(fd_sys);
  730.       return(IOERROR);
  731.    }
  732.    if (!lock_mem(fd_sys))
  733.    {
  734.       unlock_sizebyte(fd_sys);
  735.       unlock_ndx(fd_sys, buffer);
  736.       return(IOERROR);
  737.    }
  738.  
  739.    if ((dberrno = dBputr(dptr->dbf_num, APPEND, storbuff)) != SUCCESS)
  740.    {
  741.       unlock_sizebyte(fd_sys);
  742.       unlock_ndx(fd_sys, buffer);                    /* also unlocks record */
  743.       return(io_xlate(fd_sys, dberrno, "dBC ADD1"));
  744.    }
  745.    if ((dberrno = dBflush(dptr->dbf_num)) != SUCCESS)
  746.    {
  747.       unlock_sizebyte(fd_sys);
  748.       unlock_ndx(fd_sys, buffer);
  749.       return(io_xlate(fd_sys, dberrno, "dBC ADD2"));
  750.    }
  751.    unlock_sizebyte(fd_sys);
  752.    recnum = _appnded;                   /* external dBC variable rec number */
  753.  
  754.    return(update_keys(fd_sys, buffer, FALSE));    /* now add key to indexes */
  755. }
  756.  
  757. /*
  758.  *  Update the current record.
  759. */
  760. static int i_updrec(fd_sys, buffer)
  761. int fd_sys;
  762. char *buffer;
  763. {
  764.    struct fd_def *fptr = &fd[fd_sys];
  765.    struct dbc_def *dptr = &fdbf[fd_sys];
  766.  
  767.    if (i_lockrec(fd_sys, buffer) == IOGOOD)
  768.    {
  769.       if ((dberrno = dBckey(dptr->ix_num[fptr->cur_key], xkeybuff, &recnum)) != SUCCESS)
  770.       {
  771.          i_unlock_rec(fd_sys, buffer);
  772.          return(io_xlate(fd_sys, dberrno, "dBC UPD1"));
  773.       }
  774.  
  775.       if (!lock_ndx(fd_sys))                         /* index lock failure */
  776.          i_unlock_rec(fd_sys, buffer);
  777.       else                   /* update only if indexes locked successfully */
  778.       {    
  779.          if (!lock_mem(fd_sys))
  780.          {
  781.             unlock_ndx(fd_sys, buffer);
  782.             return(IOERROR);
  783.          }
  784.  
  785.          buff2db(fd_sys, buffer, storbuff);
  786.  
  787.          if ((dberrno = dBupdr(dptr->dbf_num, recnum, storbuff)) != SUCCESS)
  788.          {
  789.             unlock_ndx(fd_sys, buffer);              /* also unlocks record */
  790.             return(io_xlate(fd_sys, dberrno, "dBC UPD2"));
  791.          }
  792.          if ((dberrno = dBflush(dptr->dbf_num)) != SUCCESS)
  793.          {
  794.             unlock_ndx(fd_sys, buffer);
  795.             return(io_xlate(fd_sys, dberrno, "dBC UPD3"));
  796.          }
  797.  
  798.          return(update_keys(fd_sys, buffer, TRUE));   /* now update indexes */
  799.       }
  800.    }
  801.    return(IOERROR);
  802. }
  803.  
  804. /*
  805.  *  Index key update function
  806.  *  - if updating argument = TRUE, old key occurrences are removed first
  807. */
  808. static int update_keys(fd_sys, buffer, updating)
  809. int fd_sys, updating;
  810. char *buffer;
  811. {
  812.    int ck, j = 0, result = IOGOOD;
  813.    struct dbc_def *dptr = &fdbf[fd_sys];
  814.  
  815.    ck = fd[fd_sys].cur_key;
  816.  
  817.    while (fd[fd_sys].keys[j].segcount != -1)
  818.    {
  819.       fd[fd_sys].cur_key = j;
  820.  
  821.       if (updating)              /* removes old key values from the indexes */
  822.       {
  823.          setupkey(fd_sys, oldbuff, xkeybuff);           /* old key value */
  824.          if ((dberrno = dBrmvkey(dptr->ix_num[j], xkeybuff, recnum)) != SUCCESS)
  825.          {
  826.             result = io_xlate(fd_sys, dberrno, "dBC KEYRMV");
  827.             break;
  828.          }
  829.       }
  830.  
  831.       setupkey(fd_sys, buffer, keybuff);                /* new key value */
  832.       if ((dberrno = dBakey(dptr->ix_num[j], keybuff, recnum)) != SUCCESS)
  833.       {
  834.          result = io_xlate(fd_sys, dberrno, "dBC KEYADD1");
  835.          break;
  836.       }
  837.       if ((dberrno = dBiflsh(dptr->ix_num[j])) != SUCCESS)
  838.       {
  839.          result = io_xlate(fd_sys, dberrno, "dBC KEYADD2");
  840.          break;
  841.       }
  842.       j++;
  843.    }
  844.  
  845.    unlock_ndx(fd_sys, buffer);                  /* also unlocks data record */
  846.    fd[fd_sys].cur_key = ck;
  847.    return(result);
  848. }
  849.  
  850.  
  851. /*
  852.  *  dBC III delete record function
  853.  *  - this only marks records inactive; no PACK is available with dBC III+
  854.  *  - indexes are not changed; relies on detection of inactive flag to skip
  855.  *    deleted records in retrievals
  856. */
  857. static int i_delrec(fd_sys, buffer)
  858. int fd_sys;
  859. char *buffer;
  860. {
  861.    struct fd_def *fptr = &fd[fd_sys];
  862.    struct dbc_def *dptr = &fdbf[fd_sys];
  863.  
  864.    if (i_lockrec(fd_sys, buffer) != IOGOOD)
  865.       return(IOERROR);
  866.    
  867.    if ((dberrno = dBckey(dptr->ix_num[fptr->cur_key], keybuff, &recnum)) != SUCCESS)
  868.    {
  869.       i_unlock_rec(fd_sys, buffer);
  870.       return(io_xlate(fd_sys, dberrno, "dBC DEL1"));
  871.    }
  872.  
  873.    if ((dBdelete(dptr->dbf_num, recnum)) != SUCCESS)
  874.    {
  875.       i_unlock_rec(fd_sys, buffer);
  876.       return(io_xlate(fd_sys, dberrno, "dBC DEL2"));
  877.    }
  878.       
  879.    if ((dberrno = dBflush(dptr->dbf_num)) != SUCCESS)
  880.    {
  881.       i_unlock_rec(fd_sys, buffer);
  882.       return(io_xlate(fd_sys, dberrno, "dBC DEL3"));
  883.    }
  884.  
  885.    i_unlock_rec(fd_sys, buffer);
  886.    return(IOGOOD);
  887. }
  888.  
  889.  
  890. /*
  891.  *  Lock Record - gets number of current record first
  892. */  
  893. static int i_lockrec(fd_sys, buffer)
  894. int fd_sys;
  895. char *buffer;
  896. {
  897.    struct fd_def *fptr = &fd[fd_sys];
  898.    struct dbc_def *dptr = &fdbf[fd_sys];
  899.  
  900.    if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
  901.       return(IOGOOD);
  902.  
  903.    if ((dberrno = dBckey(dptr->ix_num[fptr->cur_key], xkeybuff, &recnum)) != SUCCESS)
  904.    {
  905.       if ((dberrno == d_TOPKEY) || (dberrno == d_ENDKEY))
  906.          return(IOGOOD);                   /* bypass retry count if EOF/TOF */
  907.       return(io_xlate(fd_sys, dberrno, "dBC LOCK1"));
  908.    }
  909.       
  910.    dberrno = dBlockr(dptr->dbf_num, recnum, (RECNUM)1, d_TLOCK);
  911.    if ((dberrno != SUCCESS) && (dberrno != d_SELFLK))
  912.       return(io_xlate(fd_sys, dberrno, "dBC LOCK2"));
  913.  
  914.    return(IOGOOD);
  915. }
  916.  
  917. /*
  918.  *  Unlock Record
  919. */
  920. static int i_unlock_rec(fd_sys, buffer)
  921. int fd_sys;
  922. char *buffer;
  923. {
  924.    if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
  925.       return(IOGOOD);
  926.  
  927.    dberrno = dBlockr(fdbf[fd_sys].dbf_num, recnum, (RECNUM)1, d_TEST);
  928.    if (dberrno == d_FREE)
  929.       return(IOGOOD);
  930.  
  931.    dberrno = dBlockr(fdbf[fd_sys].dbf_num, recnum, (RECNUM)1, d_ULOCK);
  932.    if ((dberrno != SUCCESS) && (dberrno != d_FREE))
  933.       return(io_xlate(fd_sys, dberrno, "dBC ULOCK"));
  934.  
  935.    return(IOGOOD);
  936. }
  937.  
  938. /*
  939.  * Lock Size Bytes of .DBF file for record append
  940. */
  941. static int lock_sizebyte(fd_sys, buffer)
  942. int fd_sys;
  943. char *buffer;
  944. {    
  945.    int timeout;
  946.  
  947.    if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
  948.       return(TRUE);
  949.  
  950.    timeout = fd[fd_sys].lockmode;
  951.    do
  952.    {
  953.       dberrno = dBlocksz(fdbf[fd_sys].dbf_num, d_TLOCK);
  954.       if ((dberrno == SUCCESS) || (dberrno == d_SELFLK))
  955.          return(TRUE);
  956.    }
  957.    while (--timeout > 0);
  958.    
  959.    i_unlock_rec(fd_sys, buffer);         /* no add if sizebyte unavailable */
  960.    io_xlate(fd_sys, dberrno, "dBC LCKSIZ");
  961.    return(FALSE);
  962. }
  963.  
  964. /*
  965.  * Unlock Size Bytes of .DBF file for record append
  966. */
  967. static void unlock_sizebyte(fd_sys)
  968. int fd_sys;
  969. {    
  970.    if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
  971.       return;
  972.  
  973.    dberrno = dBlocksz(fdbf[fd_sys].dbf_num, d_TEST);
  974.    if (dberrno == d_FREE)
  975.       return;
  976.  
  977.    dberrno = dBlocksz(fdbf[fd_sys].dbf_num, d_ULOCK);
  978.    if ((dberrno != SUCCESS) && (dberrno != d_FREE))
  979.       io_xlate(fd_sys, dberrno, "dBC ULCKSIZ");
  980. }
  981.  
  982. /*
  983.  * Lock all indexes associated with a file for append/update
  984. */
  985. static int lock_ndx(fd_sys)
  986. int fd_sys;
  987. {
  988.    int j = 0, k, timeout;
  989.    struct dbc_def *dptr = &fdbf[fd_sys];
  990.     
  991.    if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
  992.       return(TRUE);
  993.  
  994.    while (fd[fd_sys].keys[j].segcount != -1)
  995.    {
  996.       timeout = fd[fd_sys].lockmode;
  997.       do
  998.       {
  999.          dberrno = dBlocki(dptr->ix_num[j], d_TLOCK);
  1000.          if ((dberrno == SUCCESS) || (dberrno == d_SELFLK))
  1001.             break;
  1002.       }
  1003.       while (--timeout > 0);
  1004.  
  1005.       if ((dberrno != SUCCESS) && (dberrno != d_SELFLK))
  1006.       {
  1007.          io_xlate(fd_sys, dberrno, "dBC LCKNDX");
  1008.          for (k = 0; k < j; k++)               /* unlock any already locked */
  1009.             dBlocki(dptr->ix_num[k], d_ULOCK);
  1010.          return(FALSE);
  1011.       }
  1012.       j++;
  1013.    }
  1014.    return(TRUE);
  1015. }
  1016.  
  1017. /*
  1018.  *  Unlock all index files associated with a datafile
  1019.  *  - calls record unlock function afterwards
  1020. */
  1021. static int unlock_ndx(fd_sys, buffer)
  1022. int fd_sys;
  1023. char *buffer;
  1024. {
  1025.    int j = 0;
  1026.  
  1027.    if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
  1028.       return(IOGOOD);
  1029.     
  1030.    while (fd[fd_sys].keys[j].segcount != -1)
  1031.    {
  1032.       dberrno = dBlocki(fdbf[fd_sys].ix_num[j], d_TEST);
  1033.       if (dberrno != d_FREE)
  1034.       {
  1035.          dberrno = dBlocki(fdbf[fd_sys].ix_num[j], d_ULOCK);
  1036.          if ((dberrno != SUCCESS) && (dberrno != d_FREE))
  1037.             io_xlate(fd_sys, dberrno, "dBC ULCKNDX");
  1038.       }
  1039.       j++;
  1040.    }
  1041.    unlock_mem(fd_sys);
  1042.    return(i_unlock_rec(fd_sys, buffer));
  1043. }
  1044.  
  1045. /*
  1046.  * Lock memo file associated with a file for append/update
  1047. */
  1048. static int lock_mem(fd_sys)
  1049. int fd_sys;
  1050. {
  1051.    int timeout;
  1052.    struct dbc_def *dptr = &fdbf[fd_sys];
  1053.     
  1054.    if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
  1055.       return(TRUE);
  1056.  
  1057.    if (!dptr->mm_num)                                           /* no memos */
  1058.       return(TRUE);
  1059.  
  1060.    timeout = fd[fd_sys].lockmode;
  1061.    do
  1062.    {
  1063.       dberrno = dBlockm(dptr->mm_num, d_TLOCK);
  1064.       if ((dberrno == SUCCESS) || (dberrno == d_SELFLK))
  1065.          break;
  1066.    }
  1067.    while (--timeout > 0);
  1068.  
  1069.    if ((dberrno != SUCCESS) && (dberrno != d_SELFLK))
  1070.    {
  1071.       io_xlate(fd_sys, dberrno, "dBC LCKMEM");
  1072.       return(FALSE);
  1073.    }
  1074.    return(TRUE);
  1075. }
  1076.  
  1077. /*
  1078.  *  Unlock memo file associated with a datafile
  1079. */
  1080. static void unlock_mem(fd_sys)
  1081. int fd_sys;
  1082. {
  1083.    if ((DBCMODE == d_SINGLE) || (fd[fd_sys].lockmode == NOLOCK))
  1084.       return;
  1085.  
  1086.    if (!fdbf[fd_sys].mm_num)
  1087.       return;
  1088.  
  1089.    dberrno = dBlockm(fdbf[fd_sys].mm_num, d_TEST);
  1090.    if (dberrno == d_FREE)
  1091.       return;
  1092.  
  1093.    dberrno = dBlockm(fdbf[fd_sys].mm_num, d_ULOCK);
  1094.    if ((dberrno != SUCCESS) && (dberrno != d_FREE))
  1095.       io_xlate(fd_sys, dberrno, "dBC ULCKMEM");
  1096. }
  1097.  
  1098.  
  1099. /*
  1100.  *  Set up target key 
  1101.  *  - sets up a key string for record retrieval on current index
  1102.  *  - compound keys allowed only for character field types, so numerical
  1103.  *    segments are converted to strings and set up according to fmt mask
  1104. */
  1105. static void setupkey(fd_sys, recbuf, keybuf)
  1106. int fd_sys;
  1107. char *recbuf, *keybuf;
  1108. {
  1109.    int i, ofs, tlen, len, fx, so = 0, nnum, ndec;
  1110.    int itmp;
  1111.    long ltmp;
  1112.    float ftmp;
  1113.    double dtmp;
  1114.    char tbuff[MAX_FLDLEN], *tptr;
  1115.    struct fd_def *fptr = &fd[fd_sys];
  1116.    struct keyinfo *kptr = &fd[fd_sys].keys[fd[fd_sys].cur_key];
  1117.  
  1118.    memset(keybuf, (int)' ', MAX_FLDLEN * MAX_SEGS);
  1119.    keybuf[0] = '\0';
  1120.  
  1121.    for (i = 0; i < kptr->segcount; i++)
  1122.    {
  1123.       ofs = kptr->segstart[i];
  1124.       tlen = kptr->seglen[i];
  1125.       fx = kptr->fldindex[i];
  1126.  
  1127.       if (fptr->flds[fx].fldtype == CHRTYP)
  1128.       {
  1129.          dBstrcpy(&keybuf[so], 'L', tlen, &recbuf[ofs]);
  1130.          so += tlen;
  1131.       }
  1132.       else                             /* numerical or date keys conversion */
  1133.       {
  1134.          zerorec(tbuff, MAX_FLDLEN);
  1135.          keybuf[so] = 'N';
  1136.          switch(fptr->flds[fx].fldtype)
  1137.          {
  1138.             case DATTYP :
  1139.                if (tlen == 6)
  1140.                {
  1141.                   strncpy(tbuff, "19", 2);
  1142.                   strncpy(&tbuff[2], &recbuf[ofs], tlen);
  1143.                         keybuf[so] = 'D';
  1144.                         break;
  1145.                }           /* else fall through to LNGTYP for long int dates */
  1146.             case LNGTYP :                                 /* don't move this */
  1147.                bytecpy(<mp, &recbuf[ofs], tlen); 
  1148.                ltoa(ltmp, tbuff, 10);
  1149.                strcat(tbuff,".");
  1150.                break;
  1151.                 case INTTYP :
  1152.                bytecpy(&itmp, &recbuf[ofs], tlen); 
  1153.                itoa(itmp, tbuff, 10);
  1154.                break;
  1155.             case FLTTYP:
  1156.                bytecpy(&ftmp, &recbuf[ofs], tlen); 
  1157.                gcvt((double)ftmp, 15, tbuff);
  1158.                break;
  1159.             case DBLTYP :
  1160.                bytecpy(&dtmp, &recbuf[ofs], tlen); 
  1161.                gcvt(dtmp, 15, tbuff);
  1162.                break;
  1163.          }
  1164.          if (kptr->segcount == 1)
  1165.          {
  1166.             dBatokey(tbuff, &keybuf[so]);
  1167.             so += 8;
  1168.          }
  1169.          else               /* part of compound key, so keep in string form */
  1170.          {
  1171.             if ((fptr->flds[fx].fldtype == DATTYP) && (fptr->flds[fx].fldlen == 6))
  1172.             {
  1173.                dBstrcpy(&keybuf[so], 'L', 8, tbuff);
  1174.                so += 8;
  1175.             }
  1176.             else     /* store value as ASCII using length/decimals of field */
  1177.             {
  1178.                     if (fptr->flds[fx].fldtype == DATTYP)       /* long int date */
  1179.                     {
  1180.                         nnum = 10;
  1181.                         ndec = 0;
  1182.                     }
  1183.                     else
  1184.                     {
  1185.                    nnum = nummasklen(fptr->flds[fx].fldmask);
  1186.                    ndec = decmasklen(fptr->flds[fx].fldmask);
  1187.                     }
  1188.  
  1189.                              /* now format number string using mask lengths */
  1190.                if ((tptr = strchr(tbuff, (int)'.')) == NULL)
  1191.                {
  1192.                   strcat(tbuff, ".00000");
  1193.                   tptr = strchr(tbuff, (int)'.');
  1194.                }
  1195.                len = strlen(tbuff) - strlen(tptr);
  1196.                if (ndec > 0)
  1197.                   tbuff[len + ndec + 1] = '\0';
  1198.                else
  1199.                   tbuff[len] = '\0';
  1200.  
  1201.                memset(&keybuf[so], (int)' ', nnum);
  1202.                if (nnum >= strlen(tbuff))
  1203.                {
  1204.                   so += nnum - strlen(tbuff);
  1205.                   bytecpy(&keybuf[so], tbuff, strlen(tbuff));
  1206.                   so += strlen(tbuff);
  1207.                }
  1208.                else
  1209.                   so += nnum;        /* if reaches this, does not store key */
  1210.             }
  1211.          }
  1212.       }
  1213.    }
  1214. }
  1215.  
  1216.  
  1217. /*
  1218.  *  Convert record to dBC III+ form from PRO-C buffer format before storing
  1219. */
  1220. static void buff2db(fd_sys, P_buff, DB_buff)
  1221. int fd_sys;
  1222. char *P_buff, *DB_buff;
  1223. {
  1224.    int ofst, ftyp, flen, lnum, ldec, i, so = 0, k = 0;
  1225.    int itmp;
  1226.    long ltmp;
  1227.    float ftmp;
  1228.    double dtmp;
  1229.    char tstr[50];
  1230.    struct fd_def *fptr = &fd[fd_sys];
  1231.  
  1232.    memset(DB_buff, (int)' ', fdbf[fd_sys].dbrec_len);
  1233.    
  1234.    for (i = 0; i < fd[fd_sys].fld_cnt; i++)
  1235.    {
  1236.       ftyp = fptr->flds[i].fldtype;
  1237.       ofst = fptr->flds[i].fldstart;
  1238.       flen = fptr->flds[i].fldlen;
  1239.       lnum = nummasklen(fptr->flds[i].fldmask);
  1240.       ldec = decmasklen(fptr->flds[i].fldmask);
  1241.  
  1242.       if (ftyp == CHRTYP)
  1243.       {
  1244.          dBstrcpy(&DB_buff[so], 'L', flen, &P_buff[ofst]);
  1245.          so += flen;                               /* offset for next field */
  1246.       }
  1247.       else if ((ftyp == DATTYP) && (flen == 6))
  1248.       {
  1249.             strncpy(&DB_buff[so], "19", 2);               /* dBASE date format */
  1250.              so += 2;
  1251.              dBstrcpy(&DB_buff[so], 'L', flen, &P_buff[ofst]);
  1252.              so += flen;                               /* offset for next field */
  1253.       }
  1254.       else if (ftyp == LOGTYP)
  1255.       {
  1256.          DB_buff[so] = P_buff[ofst];
  1257.          so++;
  1258.       }
  1259.       else if (ftyp == MEMTYP)
  1260.       {
  1261.          if (P_buff[ofst])                 /* write memo only if one exists */
  1262.          {
  1263.             zerorec(memobuff, 5000);
  1264.             strncpy(memobuff, &P_buff[ofst], flen);
  1265.             if (dBputm(fdbf[fd_sys].mm_num, memobuff, &DB_buff[so]) != SUCCESS)
  1266.                errmsg(FileMemoNoWrite_ss, fptr->flds[i].fldname, fptr->filname);
  1267.          }
  1268.          k++;                    /* uses memo files in original field order */
  1269.          so += 10;
  1270.       }
  1271.       else
  1272.       {
  1273.          switch(ftyp)
  1274.          {
  1275.             case INTTYP :
  1276.                bytecpy(&itmp, &P_buff[ofst], flen);
  1277.                itoa(itmp, tstr, 10);
  1278.                strcat(tstr,".");
  1279.                break;
  1280.                 case DATTYP :                             /* long int date type */
  1281.                     lnum = 10;
  1282.                     ldec = 0;
  1283.             case LNGTYP :     /* don't move this - long int date falls thru */
  1284.                bytecpy(<mp, &P_buff[ofst], flen); 
  1285.                ltoa(ltmp, tstr, 10);
  1286.                strcat(tstr,".");
  1287.                break;
  1288.             case FLTTYP :
  1289.                bytecpy(&ftmp, &P_buff[ofst], flen);
  1290.                gcvt((double)ftmp, lnum, tstr);
  1291.                break;
  1292.             case DBLTYP :
  1293.                bytecpy(&dtmp, &P_buff[ofst], flen);
  1294.                gcvt(dtmp, lnum, tstr);
  1295.                break;
  1296.          }
  1297.          dBatofld(tstr, lnum, ldec, &DB_buff[so]);
  1298.          so += lnum;
  1299.       }
  1300.    }
  1301. }
  1302.  
  1303. /*
  1304.  *  Convert record to PRO-C buffer format from dBC III+ form before returning
  1305. */
  1306. static void db2buff(fd_sys, DB_buff, P_buff)
  1307. int fd_sys;
  1308. char *DB_buff, *P_buff;
  1309. {
  1310.    int ftyp, ofst, flen, lnum, i, so = 0, k = 0;
  1311.    int itmp;
  1312.    long ltmp;
  1313.    float ftmp;
  1314.    double dtmp;
  1315.    char tstr[50];
  1316.    struct fd_def *fptr = &fd[fd_sys];
  1317.  
  1318.    zerorec(P_buff, fptr->rec_len);
  1319.    
  1320.    for (i = 0; i < fd[fd_sys].fld_cnt; i++)
  1321.    {
  1322.       ftyp = fptr->flds[i].fldtype;
  1323.       ofst = fptr->flds[i].fldstart;
  1324.       flen = fptr->flds[i].fldlen;
  1325.       lnum = nummasklen(fptr->flds[i].fldmask);
  1326.  
  1327.       if (ftyp == CHRTYP)
  1328.       {
  1329.          strncpy(&P_buff[ofst], &DB_buff[so], flen);
  1330.          stripright(&P_buff[ofst], flen);
  1331.          so += flen;                               /* offset for next field */
  1332.       }
  1333.       else if ((ftyp == DATTYP) && (flen == 6))
  1334.       {
  1335.          so += 2;                            /* ignore the "19" in the date */
  1336.          strncpy(&P_buff[ofst], &DB_buff[so], flen);
  1337.          stripright(&P_buff[ofst], flen);
  1338.          so += flen;                               /* offset for next field */
  1339.       }
  1340.       else if (ftyp == LOGTYP)
  1341.       {
  1342.          P_buff[ofst] = DB_buff[so];
  1343.          so++;
  1344.       }
  1345.       else if (ftyp == MEMTYP)
  1346.       {
  1347.          zerorec(memobuff, 5000);
  1348.          if (dBgetm(fdbf[fd_sys].mm_num, &DB_buff[so], memobuff) != SUCCESS)
  1349.             errmsg(FileMemoNoRead_ss, fptr->flds[i].fldname, fptr->filname);
  1350.          strncpy(&P_buff[ofst], memobuff, flen);
  1351.          k++;
  1352.          so += 10;
  1353.       }
  1354.       else
  1355.       {
  1356.             if (ftyp == DATTYP)        /* special case for long int date type */
  1357.                 lnum = 10;
  1358.          zerorec(tstr, 50);
  1359.          dBfldtoa(&DB_buff[so], lnum, tstr);
  1360.          switch(ftyp)
  1361.          {
  1362.             case INTTYP :
  1363.                itmp = atoi(tstr);
  1364.                bytecpy(&P_buff[ofst], &itmp, flen);
  1365.                break;
  1366.                 case DATTYP :
  1367.             case LNGTYP :
  1368.                ltmp = atol(tstr);
  1369.                bytecpy(&P_buff[ofst], <mp, flen);
  1370.                break;
  1371.             case FLTTYP :
  1372.                ftmp = (float)atof(tstr);
  1373.                bytecpy(&P_buff[ofst], &ftmp, flen);
  1374.                break;
  1375.             case DBLTYP :
  1376.                dtmp = atof(tstr);
  1377.                bytecpy(&P_buff[ofst], &dtmp, flen);
  1378.                break;
  1379.          }
  1380.          so += lnum;
  1381.       }
  1382.    }
  1383. }
  1384.  
  1385.  
  1386.  
  1387. /*
  1388.  *  Login
  1389. */
  1390. static int i_login(fd_sys, buffer)
  1391. int fd_sys;
  1392. char *buffer;
  1393. {
  1394.    return(IOGOOD);
  1395. }
  1396.  
  1397. /*
  1398.  *  Logoff
  1399. */
  1400. static int i_logoff(fd_sys, buffer)
  1401. int fd_sys;
  1402. char *buffer;
  1403. {
  1404.    return(IOGOOD);
  1405. }
  1406.  
  1407. /*
  1408.  *  End (Commit) transaction 
  1409. */
  1410. static int i_commit(fd_sys, buffer)
  1411. int fd_sys;
  1412. char *buffer;
  1413. {
  1414.    return(IOGOOD);
  1415. }
  1416.  
  1417. /*
  1418.  *  Rollback transaction
  1419. */
  1420. static int i_rollback(fd_sys, buffer)
  1421. int fd_sys;
  1422. char *buffer;
  1423. {
  1424.    return(IOGOOD);
  1425. }
  1426.  
  1427. /*
  1428.  *  Start transaction
  1429. */
  1430. static int i_transact(fd_sys, buffer)
  1431. int fd_sys;
  1432. char *buffer;
  1433. {
  1434.    return(IOGOOD);
  1435. }
  1436.  
  1437.  
  1438. /*
  1439.  *  This routine translates dBC III+ Error codes into PRO-C error codes.
  1440.  *  If no PRO-C equivalent, displays the error number.
  1441. */
  1442. static int io_xlate(fd_sys, ernum, rtnname)
  1443. int fd_sys;
  1444. int ernum;
  1445. char *rtnname;
  1446. {
  1447.    switch(ernum)
  1448.    {
  1449.       case  d_WTFAIL  :
  1450.          return IOBADOPEN;
  1451.       case  d_NODBF   :
  1452.       case  d_NONDX   :
  1453.          return IONOFILE;
  1454.       case  d_MAYBE   :
  1455.       case  d_NOTFND  :
  1456.       case  d_TOPKEY  :
  1457.       case  d_ENDKEY  :
  1458.       case  d_NOKEY   :
  1459.          return IONOKEY;
  1460.       case  d_LOCKED  :
  1461.          return IOLOCKED;
  1462.       case  d_FREE    :
  1463.          return IONOLOCK;
  1464.    }
  1465.  
  1466.    if (fd_sys >= 0)
  1467.       errmsg(FileDbgError_sdss, "dBC III Plus", ernum, fd[fd_sys].filname, rtnname);
  1468.    else      /* if routines called from generated apps without valid fd_sys */
  1469.       errmsg(FileDbgError_sds, "dBC III Plus", ernum, rtnname);
  1470.    errmsg(FileDbgError_sds, "dBC III Internal", _dbcerr, rtnname);
  1471.  
  1472.    return(IOERROR);
  1473. }
  1474.  
  1475.  
  1476. /*
  1477.  * Assign section
  1478. */
  1479.  
  1480. void assign_IO_DB(dbnum)
  1481. int dbnum;
  1482. {
  1483.    Fntab[dbnum - 1][0]  = (int(*)())0; /* Empty */
  1484.    Fntab[dbnum - 1][1]  = i_init_file;
  1485.    Fntab[dbnum - 1][2]  = i_open_file;
  1486.    Fntab[dbnum - 1][3]  = i_close_file;
  1487.    Fntab[dbnum - 1][4]  = i_addrec;
  1488.    Fntab[dbnum - 1][5]  = i_delrec;
  1489.    Fntab[dbnum - 1][6]  = i_findkey;
  1490.    Fntab[dbnum - 1][7]  = i_firstkey;
  1491.    Fntab[dbnum - 1][8]  = i_lastkey;
  1492.    Fntab[dbnum - 1][9]  = i_lockrec;
  1493.    Fntab[dbnum - 1][10] = i_nextrec;
  1494.    Fntab[dbnum - 1][11] = i_prevrec;
  1495.    Fntab[dbnum - 1][12] = i_unlock_rec;
  1496.    Fntab[dbnum - 1][13] = i_updrec;
  1497.    Fntab[dbnum - 1][14] = i_commit;
  1498.    Fntab[dbnum - 1][15] = i_login;
  1499.    Fntab[dbnum - 1][16] = i_logoff;
  1500.    Fntab[dbnum - 1][17] = i_rollback;
  1501.    Fntab[dbnum - 1][18] = i_transact;
  1502.    Fntab[dbnum - 1][19] = i_selectinx;
  1503.    Fntab[dbnum - 1][20] = i_rereadrec;
  1504.    Fntab[dbnum - 1][21] = i_filename;
  1505. }
  1506.