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

  1. /* ==( io/src/iparadox.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   06-Apr-90  See comments below    */
  11. /* ----------------------------------------------- */
  12. /* %W%  (%H% %T%) */
  13.  
  14. /*
  15.  *  Modifications
  16.  *
  17.  *  06-Apr-90  VvA - make internal fieldname buffer long enough
  18.  *  28-Mar-90  VvA - adjustments for locking modes, transactions
  19.  *  01-Feb-90  VvA - fld_cnt now in iogen.c, fd[] struct
  20.  *  01-Feb-90  VvA - Enabled openmode in open_file()
  21.  *  15-Dec-89  VvA - V.2 modifications
  22.  *  01-Dec-89  VvA - Adapted for Paradox
  23. */
  24.  
  25. /*  PARADOX specific calls to general IOGEN.C interface  */
  26.  
  27. /*
  28. 1.  Paradox Engine requires that the primary key be or start at the first
  29.     field of the record.  If a compound key, the fields must be contiguous.
  30.     This is not enforced by PRO-C, thus the user must be made aware of this.
  31.     If a compound key, the user should ensure the required fields making it
  32.     up are the first ones in the table, in order, even though the specifi-
  33.     cation will be made in a SegKey record in TABMOD.  A Unique key should 
  34.     not be specified on the first field, since this module would pick that
  35.     up instead, which is not the intention when specifying a compound key.
  36.  
  37. 2.  To use this interface on a network, the call to PCNetInit in the open
  38.     function, and the body of the lock/unlock functions, should be enabled 
  39.     and the library remade.  PCNetInit requires parameters not generated 
  40.     by PRO-C, thus some code customization will be needed to pass the 
  41.     network information needed.
  42.  
  43. 3.  Paradox restricts field lengths to 255 characters.  A MEMTYP field is
  44.     truncated within this module to 255 characters, and returned as a 255
  45.     character string.
  46. */
  47.  
  48.  
  49.  
  50. # include <iodef.h>
  51. # include <iomsg.h>
  52. # include <proc.io>
  53. # include <bench.h>
  54. # include <iosup.h>
  55. # include <pxengine.h>
  56.  
  57. # define SAVE_IMMEDIATE  FALSE             /* FALSE : buffered I/O (faster) */
  58.  
  59. /* Function prototypes */
  60. # ifdef ANSI
  61. static int i_addrec(int, char *);
  62. static int i_close_file(int, char *);
  63. static int i_commit(int, char *);
  64. static int i_delrec(int, char *);
  65. static int i_filename(int, char *);
  66. static int i_findkey(int, char *);
  67. static int i_firstkey(int, char *);
  68. static int i_init_file(int, char *);
  69. static int i_lastkey(int, char *);
  70. static int i_lockrec(int, char *);
  71. static int i_login(int, char *);
  72. static int i_logoff(int, char *);
  73. static int i_nextrec(int, char *);
  74. static int i_open_file(int, char *);
  75. static int i_prevrec(int, char *);
  76. static int i_rereadrec(int, char *);
  77. static int i_rollback(int, char *);
  78. static int i_selectinx(int, char *);
  79. static int i_transact(int, char *);
  80. static int i_unlock_rec(int, char *);
  81. static int i_updrec(int, char *);
  82. static int create_file(int);
  83. static int load_keys(int, int);
  84. static int field_handles(int);
  85. static int setupkey(int, char *);
  86. static int get_record(int, char *);
  87. static int put_record(int, char *);
  88. static int io_xlate(int, int, char *);
  89. # else
  90. static int i_addrec();
  91. static int i_close_file();
  92. static int i_commit();
  93. static int i_delrec();
  94. static int i_filename();
  95. static int i_findkey();
  96. static int i_firstkey();
  97. static int i_init_file();
  98. static int i_lastkey();
  99. static int i_lockrec();
  100. static int i_login();
  101. static int i_logoff();
  102. static int i_nextrec();
  103. static int i_open_file();
  104. static int i_prevrec();
  105. static int i_rereadrec();
  106. static int i_rollback();
  107. static int i_selectinx();
  108. static int i_transact();
  109. static int i_unlock_rec();
  110. static int i_updrec();
  111. static int create_file();
  112. static int load_keys();
  113. static int field_handles();
  114. static int setupkey();
  115. static int get_record();
  116. static int put_record();
  117. static int io_xlate();
  118. # endif
  119.  
  120.  
  121. struct ixinfo
  122. {
  123.    TABLEHANDLE fd_key;               /* Paradox table handle for this index */
  124.    FIELDHANDLE khdl[MAX_SEGS];
  125. };
  126.  
  127. struct pdx_def
  128. {
  129.    TABLEHANDLE fd_hdl;                              /* Paradox table handle */
  130.    RECORDHANDLE rec_hdl;
  131.    LOCKHANDLE lck_hdl;
  132.    FIELDHANDLE fhdl[MAX_FLDS];
  133.    struct ixinfo fdkey[MAX_KEYS];
  134. };
  135.  
  136.  
  137. static struct pdx_def fpx[MAX_FILES];
  138.  
  139. static char tempbuff[MAX_RECLEN];
  140. static char oldkey[MAX_FLDLEN * MAX_SEGS];
  141. static char newkey[MAX_FLDLEN * MAX_SEGS];
  142. static int zerokey;                  /* set if blank field is search target */
  143. int pxErr;
  144.  
  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.    char *f1;
  162.  
  163.    f1 = buffer;         /* strip file extension if any; default .DB assumed */
  164.    for( ; *f1 != '.' && *f1 != NULL; f1++)
  165.       ;
  166.    *f1 = NULL;
  167.  
  168.    return(IOGOOD);
  169. }
  170.  
  171. /*
  172.  *  File initialization
  173. */
  174. static int i_init_file(fd_sys, buffer)
  175. int fd_sys;
  176. char *buffer;
  177. {
  178.    if ((pxErr = PXSetDefaults(DEFSWAPSIZE, 8, DEFRECORDHANDLES, DEFLOCKHANDLES, DEFFILEHANDLES, SortOrderAscii)) != IOGOOD)
  179.       return(io_xlate(-1, pxErr, "PDX INIT1"));
  180. /*
  181.  * IF RUNNING ON A NETWORK: REPLACE PXInit() CALL WITH
  182.  *    if ((pxErr = PXNetInit(param1, param2, param3)) != IOGOOD)
  183.  * WHERE:
  184.  *    param1 = location of PARADOX.NET file
  185.  *    param2 = type of network (see Paradox Engine manual for codes)
  186.  *    param3 = network user name from PARADOX.NET
  187. */
  188.    if ((pxErr = PXInit()) != IOGOOD)
  189.       return(io_xlate(-1, pxErr, "PDX INIT2"));
  190.  
  191.    return(IOGOOD);
  192. }
  193.  
  194. /*
  195.  *  File open function
  196. */
  197. static int i_open_file(fd_sys, buffer)
  198. int fd_sys;
  199. char *buffer;
  200. {
  201.    int tbex = FALSE;                          /* flag for table's existence */
  202.    int i = 0, fid;
  203.    struct fd_def *fptr = &fd[fd_sys];
  204.    struct pdx_def *pptr = &fpx[fd_sys];
  205.    TABLEHANDLE tblptr;
  206.    RECORDHANDLE recptr;
  207.  
  208.    if ((pxErr = PXTblExist(fptr->filname, &tbex)) != IOGOOD)
  209.       return(io_xlate(fd_sys, pxErr, "PDX TEST"));  /* test table existence */
  210.  
  211.    if (!tbex || (fptr->openmode & OUTPUT_FLAG))
  212.    {                                      /* OUTPUT mode or table not found */
  213.       if (fptr->openmode & INPUT_FLAG)
  214.          return(IONOFILE);               /* no create attempt for read only */
  215.       if (create_file(fd_sys) != IOGOOD)               /* also creates keys */
  216.          return(IOERROR);
  217.    }
  218.                                                /* table exists, now open it */
  219.    if ((pxErr = PXTblOpen(fptr->filname, &tblptr, 0, SAVE_IMMEDIATE)) != IOGOOD) 
  220.       return(io_xlate(fd_sys, pxErr, "PDX OPEN1"));
  221.    pptr->fd_hdl = tblptr;                          /* save the table handle */
  222.  
  223.    if (load_keys(fd_sys, FALSE) <= 0)                           /* key info */
  224.       return(IOERROR);
  225.  
  226.    pptr->fdkey[0].fd_key = pptr->fd_hdl;              /* primary key handle */
  227.  
  228.    for (i = 1; i < fptr->key_cnt; i++)        /* handles for secondary keys */
  229.    {
  230.       fid = pptr->fdkey[i].khdl[0];
  231.       if (fid)
  232.       {
  233.          if ((pxErr = PXTblOpen(fptr->filname, &tblptr, fid, SAVE_IMMEDIATE)) != IOGOOD) 
  234.             return(io_xlate(fd_sys, pxErr, "PDX OPEN2"));
  235.          pptr->fdkey[i].fd_key = tblptr;
  236.       }
  237.       else   /* does not attempt open on sec keys that could not be created */
  238.          pptr->fdkey[i].fd_key = 999;             /* arbitrarily high value */
  239.    }
  240.  
  241.    if ((pxErr = PXRecBufOpen(pptr->fd_hdl, &recptr)) != IOGOOD) 
  242.       return(io_xlate(fd_sys, pxErr, "PDX OPEN3"));
  243.    pptr->rec_hdl = recptr;                  /* save the local record buffer */
  244.  
  245.    return(IOGOOD);
  246. }
  247.  
  248. /*
  249.  *  Create files
  250. */
  251. static int create_file(fd_sys)
  252. int fd_sys;
  253. {
  254.    int j, sl;
  255.    char *rfields[MAX_FLDS];
  256.    char *rtypes[MAX_FLDS];
  257.    struct fd_def *fptr = &fd[fd_sys];
  258.    struct pdx_def *pptr = &fpx[fd_sys];
  259.  
  260.    for (j = 0; j < fptr->fld_cnt; j++)           /* info arrays for Paradox */
  261.    {
  262.       rfields[j] = alloc(FLDNAME_LEN+1);
  263.       strcpy(rfields[j], fptr->flds[j].fldname);
  264.       rtypes[j] = alloc(10);
  265.         sl = fptr->flds[j].fldlen;
  266.       switch(fptr->flds[j].fldtype)
  267.       {
  268.          case (MEMTYP) :
  269.                 sl = 255;    /* Paradox restricts field length to 255, no memos */
  270.          case (CHRTYP) :
  271.             sprintf(rtypes[j], "A%d", sl);
  272.             break;
  273.          case (INTTYP) :
  274.             strcpy(rtypes[j], "S");
  275.             break;
  276.          case (LNGTYP) :
  277.          case (FLTTYP) :
  278.          case (DBLTYP) :
  279.             strcpy(rtypes[j], "N");
  280.             break;
  281.          case (DATTYP) :
  282.                 if (sl == 6)
  283.                 strcpy(rtypes[j], "D");
  284.                 else
  285.                     strcpy(rtypes[j], "N");
  286.             break;
  287.       } 
  288.    }
  289.  
  290.    pxErr = PXTblCreate(fptr->filname, fptr->fld_cnt, rfields, rtypes);
  291.  
  292.    for (j = 0; j < fptr->fld_cnt; j++)
  293.    {
  294.       free(rfields[j]);
  295.       free(rtypes[j]);
  296.    }
  297.  
  298.    if (pxErr != IOGOOD)
  299.       return(io_xlate(fd_sys, pxErr, "PDX CREAT"));
  300.  
  301.    if (load_keys(fd_sys, TRUE) > 0)                       /* create indexes */
  302.       return(IOGOOD);   
  303.    else
  304.       return(IOERROR);
  305. }
  306.  
  307. /*
  308.  *  Load keys and and set up indexes
  309.  *  This routine will open table temporarily to get field handles, if 
  310.  *     creatix TRUE; else it should be called with table already open
  311.  *  PARADOX LIMITATION:  the first field(s) in the record must be used
  312.  *    for the primary index, and if more than one, must be contiguous
  313.  *    (a warning is issued if the PRO-C spec does not provide for this)
  314. */
  315. static int load_keys(fd_sys, creatix)
  316. int fd_sys, creatix;
  317. {
  318.    int nkeys = 0, nsegs = 0, fix, n;
  319.    struct fd_def *fptr = &fd[fd_sys];
  320.    struct pdx_def *pptr = &fpx[fd_sys];
  321.    TABLEHANDLE tblptr;
  322.  
  323.    if (creatix)
  324.    {
  325.       if ((pxErr = PXTblOpen(fptr->filname, &tblptr, 0, SAVE_IMMEDIATE)) != IOGOOD) 
  326.          return(io_xlate(fd_sys, pxErr, "PDX KEYS1"));
  327.       pptr->fd_hdl = tblptr;
  328.    }
  329.  
  330.    n = field_handles(fd_sys);
  331.    if (creatix)                      /* table is closed if creating indexes */
  332.       PXTblClose(pptr->fd_hdl);
  333.    if (n != IOGOOD)                      /* failure to assign field handles */
  334.       return(IOERROR);
  335.  
  336.    while (fptr->keys[nkeys].segcount != -1)
  337.    {
  338.       for (nsegs = 0; nsegs < fptr->keys[nkeys].segcount; nsegs++)
  339.       {
  340.          if ((nkeys == 0) || (fptr->keys[nkeys].segcount == 1))
  341.          {
  342.             fix = fptr->keys[nkeys].fldindex[nsegs];
  343.             pptr->fdkey[nkeys].khdl[nsegs] = pptr->fhdl[fix];
  344.          }
  345.          else             /* blocks out unsupported secondary compound keys */
  346.             pptr->fdkey[nkeys].khdl[nsegs] = 0;
  347.       }
  348.       nkeys++;                                    /* & increment key number */
  349.    }
  350.  
  351.    if (creatix)
  352.    {                                          /* first set up primary index */
  353.       if ((fptr->keys[0].keytype == KEY_UNIQUE) &&
  354.           (pptr->fdkey[0].khdl[0] == pptr->fhdl[0]))
  355.       {
  356.          nsegs = fptr->keys[0].segcount;
  357.          if ((pxErr = PXKeyAdd(fptr->filname, nsegs, pptr->fdkey[0].khdl, PRIMARY)) != IOGOOD)
  358.             return(io_xlate(fd_sys, pxErr, "PDX KEYS2"));
  359.       }
  360.       else
  361.       {
  362.          errmsg(FileFirstKeyFld_s, fptr->filname);
  363.          return(IOERROR);
  364.       }
  365.  
  366.       for (n = 1; n < nkeys; n++)          /* now pick up any other indexes */
  367.       {
  368.          if (fptr->keys[n].segcount > 1)     /* no seg keys on secondary ix */
  369.          {
  370.             errmsg("Paradox does not support secondary compound keys");
  371.             pptr->fdkey[n].khdl[0] = 0;
  372.          }
  373.          else if ((pxErr = PXKeyAdd(fptr->filname, 1, pptr->fdkey[n].khdl, INCSECONDARY)) != IOGOOD)
  374.             return(io_xlate(fd_sys, pxErr, "PDX KEYS3"));
  375.       }
  376.    }
  377.  
  378.    fptr->key_cnt = nkeys;
  379.    return(nkeys);
  380. }
  381.  
  382. /*
  383.  *  Assign Paradox field handles
  384. */
  385. static int field_handles(fd_sys)
  386. int fd_sys;
  387. {
  388.    int j;
  389.  
  390.    for (j = 0; j < fd[fd_sys].fld_cnt; j++)
  391.       if ((pxErr = PXFldHandle(fpx[fd_sys].fd_hdl, fd[fd_sys].flds[j].fldname, &fpx[fd_sys].fhdl[j])) != IOGOOD)
  392.          return(io_xlate(fd_sys, pxErr, "FLDS"));
  393.  
  394.    return(IOGOOD);
  395. }
  396.  
  397.  
  398. /*
  399.  *  File close function
  400.  *  - All table handles for all indexes in each table are closed; 
  401.  *  - PXExit is called when no more files are marked active.
  402. */
  403. static int i_close_file(fd_sys, buffer)
  404. int fd_sys;
  405. char *buffer;
  406. {
  407.    int j, opnfils = 0;
  408.  
  409.    for (j = 0; j < fd[fd_sys].key_cnt; j++)
  410.    {
  411.       if (fpx[fd_sys].fdkey[j].fd_key < 999)
  412.          if ((pxErr = PXTblClose(fpx[fd_sys].fdkey[j].fd_key)) != IOGOOD)
  413.             return(io_xlate(fd_sys, pxErr, "PDX CLOSE"));
  414.    }
  415.  
  416.    fd[fd_sys].active = FALSE;
  417.  
  418.    for (j = 0; j < MAX_FILES; j++)
  419.       if (fd[j].active == TRUE)
  420.          opnfils++;
  421.  
  422.    if (!opnfils)           /* exit Paradox Engine if all files now inactive */
  423.       PXExit();
  424.  
  425.    return(IOGOOD);
  426. }
  427.  
  428.  
  429. /*
  430.  *  Select an index to perform processing on - already done in IOGEN.C
  431.  *  - if unsupported key chosen, default to primary key
  432. */
  433. static int i_selectinx(fd_sys, buffer)
  434. int fd_sys;
  435. char *buffer;
  436. {
  437.    if (fpx[fd_sys].fdkey[fd[fd_sys].cur_key].fd_key == 999)
  438.       fd[fd_sys].cur_key = 0;            /* represents unsupported key type */
  439.  
  440.    fpx[fd_sys].fd_hdl = fpx[fd_sys].fdkey[fd[fd_sys].cur_key].fd_key;
  441.  
  442.    return(IOGOOD);
  443. }
  444.  
  445.  
  446. /*
  447.  *  Find a record by key value
  448.  *  - To do a partial match on a blank or zero field, firstkey() is used.
  449.  *    Otherwise partial match is enabled by the CLOSESTRECORD parameter in
  450.  *    the calls to Paradox search functions.  In order to handle a partial
  451.  *    search that goes beyond the last record, old and new key values are
  452.  *    compared:  if new key is less than old, the record pointer location
  453.  *    returned is meaningless and this function returns IOEOF.
  454. */
  455. static int i_findkey(fd_sys, buffer)
  456. int fd_sys;
  457. char *buffer;
  458. {
  459.    int ck, stat, klen;
  460.    struct fd_def *fptr = &fd[fd_sys];
  461.    struct pdx_def *pptr = &fpx[fd_sys];
  462.  
  463.    if ((stat = setupkey(fd_sys, buffer)) != IOGOOD)
  464.       return(stat);
  465.  
  466.    ck = fptr->cur_key;
  467.    PXNetTblRefresh(pptr->fd_hdl);
  468.  
  469.    if (fptr->exact)
  470.    {
  471.       if (ck == 0)                      /* search on 1st seg of primary key */
  472.          pxErr = PXSrchKey(pptr->fd_hdl, pptr->rec_hdl, 1, SEARCHFIRST);
  473.       else
  474.          pxErr = PXSrchFld(pptr->fd_hdl, pptr->rec_hdl, pptr->fdkey[ck].khdl[0], SEARCHFIRST);
  475.  
  476.       if (pxErr != IOGOOD)
  477.          return(io_xlate(fd_sys, pxErr, "PDX EXACT"));
  478.    }
  479.    else
  480.    {
  481.       klen = extract_key(fd_sys, buffer, oldkey);       /* retain key value */
  482.       if (zerokey)            /* if key is blank or zero, go to top of file */
  483.          return(i_firstkey(fd_sys, buffer));
  484.       if (ck == 0)                      /* search on 1st seg of primary key */
  485.          pxErr = PXSrchKey(pptr->fd_hdl, pptr->rec_hdl, 1, SEARCHFIRST | CLOSESTRECORD);
  486.       else
  487.          pxErr = PXSrchFld(pptr->fd_hdl, pptr->rec_hdl, pptr->fdkey[ck].khdl[0], SEARCHFIRST | CLOSESTRECORD);
  488.  
  489.       if ((pxErr != IOGOOD) && (pxErr != PXERR_RECNOTFOUND))
  490.          return(io_xlate(fd_sys, pxErr, "PDX PART"));
  491.    }
  492.  
  493.    stat = get_record(fd_sys, buffer);
  494.  
  495.    if (!fptr->exact)
  496.    {
  497.       klen = extract_key(fd_sys, buffer, newkey);
  498.       if (memcmp(oldkey, newkey, klen) > 0)       /* no higher keyval found */
  499.       {                               /* so new record position meaningless */
  500.          i_unlock_rec(fd_sys, buffer);
  501.          zerorec(buffer, fptr->rec_len);
  502.          return(IOEOF);
  503.       }
  504.    }
  505.    return(stat);
  506. }
  507.  
  508. /*
  509.  *  This routine sets up fields for current key in Paradox buffer
  510. */
  511. static int setupkey(fd_sys, buffer)
  512. int fd_sys;
  513. char *buffer;
  514. {
  515.    int ck, n, so, sl, fix, ty, tm, td;
  516.    short itmp;
  517.    long ltmp;
  518.    float ftmp;
  519.    double dtmp;
  520.    char tstr[MAX_FLDLEN], nstr[4];
  521.    struct fd_def *fptr = &fd[fd_sys];
  522.    struct pdx_def *pptr = &fpx[fd_sys];
  523.  
  524.    zerokey = FALSE;
  525.    ck = fptr->cur_key;
  526.  
  527.    if ((pxErr = PXRecBufEmpty(pptr->rec_hdl)) != IOGOOD)
  528.       return(io_xlate(fd_sys, pxErr, "PDX KEYSETUP1"));
  529.  
  530.    for (n = 0; n < fptr->keys[ck].segcount; n++)
  531.    {
  532.       so = fptr->keys[ck].segstart[n];
  533.       sl = fptr->keys[ck].seglen[n];
  534.       fix = fptr->keys[ck].fldindex[n];
  535.  
  536.       switch(fptr->flds[fix].fldtype)
  537.       {
  538.          case CHRTYP :
  539.             strncpy(tstr, &buffer[so], sl); tstr[sl] = '\0';
  540.             pxErr = PXPutAlpha(pptr->rec_hdl, pptr->fdkey[ck].khdl[n], tstr);
  541.             zerokey = (tstr[0] ? FALSE : TRUE);
  542.             break;
  543.             case DATTYP :
  544.                 if (fptr->flds[fix].fldlen == 6)
  545.                 {
  546.                 strncpy(tstr, &buffer[so], sl); tstr[sl] = '\0';
  547.                     zerokey = FALSE;
  548.                 if (!tstr[0])
  549.                     {
  550.                    strcpy(tstr, "000101");
  551.                         zerokey = TRUE;
  552.                     }
  553.                 nstr[2] = '\0';
  554.                 strncpy(nstr, tstr, 2);
  555.                 ty = atoi(nstr) + 1900;
  556.                 strncpy(nstr, &tstr[2], 2);
  557.                 tm = atoi(nstr);
  558.                 strncpy(nstr, &tstr[4], 2);
  559.                 td = atoi(nstr);
  560.                 if ((pxErr = PXDateEncode(tm, td, ty, <mp)) == IOGOOD)
  561.                        pxErr = PXPutDate(pptr->rec_hdl, pptr->fdkey[ck].khdl[n], ltmp);
  562.                 break;
  563.                 }                   /* fall through to LNGTYP for long int date */
  564.          case LNGTYP :                                   /* don't move this */
  565.             memcpy((char *)<mp, &buffer[so], sl); 
  566.             pxErr = PXPutLong(pptr->rec_hdl, pptr->fdkey[ck].khdl[n], ltmp);
  567.             zerokey = (ltmp == 0L);
  568.             break;
  569.          case INTTYP :
  570.             memcpy((char *)&itmp, &buffer[so], sl); 
  571.             pxErr = PXPutShort(pptr->rec_hdl, pptr->fdkey[ck].khdl[n], itmp);
  572.             zerokey = (itmp ? FALSE : TRUE);
  573.             break;
  574.          case FLTTYP :
  575.             memcpy((char *)&ftmp, &buffer[so], sl); 
  576.             dtmp = (double)ftmp;
  577.             pxErr = PXPutDoub(pptr->rec_hdl, pptr->fdkey[ck].khdl[n], dtmp);
  578.             zerokey = ((int)dtmp == 0);
  579.             break;
  580.          case DBLTYP :
  581.             memcpy((char *)&dtmp, &buffer[so], sl); 
  582.             pxErr = PXPutDoub(pptr->rec_hdl, pptr->fdkey[ck].khdl[n], dtmp);
  583.             zerokey = ((int)dtmp == 0);
  584.             break;
  585.       }
  586.    }
  587.    if (pxErr != IOGOOD)
  588.       return(io_xlate(fd_sys, pxErr, "PDX KEYSETUP2"));
  589.  
  590.    return(IOGOOD);
  591. }
  592.  
  593. /*
  594.  *  Find first record in the file
  595. */
  596. static int i_firstkey(fd_sys, buffer)
  597. int fd_sys;
  598. char *buffer;
  599. {
  600.    fd[fd_sys].exact = 0;
  601.    PXNetTblRefresh(fpx[fd_sys].fd_hdl);
  602.  
  603.    if ((pxErr = PXRecFirst(fpx[fd_sys].fd_hdl)) != IOGOOD)
  604.       return(io_xlate(fd_sys, pxErr, "PDX FIRST"));
  605.  
  606.    return(get_record(fd_sys, buffer));
  607. }
  608.  
  609. /*
  610.  *  Find last physical record in the file
  611. */
  612. static int i_lastkey(fd_sys, buffer)
  613. int fd_sys;
  614. char *buffer;
  615. {
  616.    fd[fd_sys].exact = 0;
  617.    PXNetTblRefresh(fpx[fd_sys].fd_hdl);
  618.  
  619.    if ((pxErr = PXRecLast(fpx[fd_sys].fd_hdl)) != IOGOOD)
  620.       return(io_xlate(fd_sys, pxErr, "PDX LAST"));
  621.  
  622.    return(get_record(fd_sys, buffer));
  623. }
  624.  
  625. /*
  626.  *  Find next record in the file
  627. */
  628. static int i_nextrec(fd_sys, buffer)
  629. int fd_sys;
  630. char *buffer;
  631. {
  632.    i_unlock_rec(fd_sys, buffer);
  633.    PXNetTblRefresh(fpx[fd_sys].fd_hdl);
  634.  
  635.    if ((pxErr = PXRecNext(fpx[fd_sys].fd_hdl)) != IOGOOD)
  636.       return(io_xlate(fd_sys, pxErr, "NEXT"));
  637.  
  638.    return(get_record(fd_sys, buffer));
  639. }
  640.  
  641. /*
  642.  *  Find previous record in the file
  643. */
  644. static int i_prevrec(fd_sys, buffer)
  645. int fd_sys;
  646. char *buffer;
  647. {
  648.    i_unlock_rec(fd_sys, buffer);
  649.    PXNetTblRefresh(fpx[fd_sys].fd_hdl);
  650.  
  651.    if ((pxErr = PXRecPrev(fpx[fd_sys].fd_hdl)) != IOGOOD)
  652.       return(io_xlate(fd_sys, pxErr, "PREV"));
  653.  
  654.    return(get_record(fd_sys, buffer));
  655. }
  656.  
  657. /*
  658.  *  This routine retrieves the current record from Paradox file and 
  659.  *    converts fields to PRO-C buffer form
  660.  *  - This routine locks the record before retrieving and returns with
  661.  *    the record still locked if operations successful - inquire mode
  662.  *    in PRO-C applications will issue the unlock call
  663. */
  664. static int get_record(fd_sys, buffer)
  665. int fd_sys;
  666. char *buffer;
  667. {
  668.    int n, so, sl, ty, tm, td, stat;
  669.    short itmp;
  670.    long ltmp;
  671.    float ftmp;
  672.    double dtmp;
  673.    char tstr[MAX_FLDLEN];
  674.    struct fd_def *fptr = &fd[fd_sys];
  675.    struct pdx_def *pptr = &fpx[fd_sys];
  676.  
  677.    if ((pxErr = PXRecBufEmpty(pptr->rec_hdl)) != IOGOOD)
  678.       return(io_xlate(fd_sys, pxErr, "PDX GETREC1"));
  679.  
  680.    if (stat = i_lockrec(fd_sys, buffer))   /* lock record before retrieving */
  681.       return(stat);
  682.  
  683.    if ((pxErr = PXRecGet(pptr->fd_hdl, pptr->rec_hdl)) != IOGOOD)
  684.    {
  685.       i_unlock_rec(fd_sys, buffer);
  686.       return(io_xlate(fd_sys, pxErr, "PDX GETREC2"));
  687.    }
  688.  
  689.    zerorec(buffer, fptr->rec_len);
  690.  
  691.    for (n = 0; n < fptr->fld_cnt; n++)         /* now convert to PRO-C form */
  692.    {
  693.       so = fptr->flds[n].fldstart;
  694.       sl = fptr->flds[n].fldlen;
  695.  
  696.       switch(fptr->flds[n].fldtype)
  697.       {
  698.          case MEMTYP :
  699.                 sl = 255;
  700.          case CHRTYP :
  701.             pxErr = PXGetAlpha(pptr->rec_hdl, pptr->fhdl[n], sl+1, tstr);
  702.             strncpy(&buffer[so], tstr, sl);
  703.             break;
  704.          case INTTYP :
  705.             pxErr = PXGetShort(pptr->rec_hdl, pptr->fhdl[n], &itmp);
  706.             memcpy(&buffer[so], (char *)&itmp, sl); 
  707.             break;
  708.          case LNGTYP :
  709.             pxErr = PXGetLong(pptr->rec_hdl, pptr->fhdl[n], <mp);
  710.             memcpy(&buffer[so], (char *)<mp, sl); 
  711.             break;
  712.          case FLTTYP :
  713.             pxErr = PXGetDoub(pptr->rec_hdl, pptr->fhdl[n], &dtmp);
  714.             ftmp = (float)dtmp;
  715.             memcpy(&buffer[so], (char *)&ftmp, sl); 
  716.             break;
  717.          case DBLTYP :
  718.             pxErr = PXGetDoub(pptr->rec_hdl, pptr->fhdl[n], &dtmp);
  719.             memcpy(&buffer[so], (char *)&dtmp, sl); 
  720.             break;
  721.          case DATTYP :
  722.                 if (sl == 6)
  723.                 {
  724.                 if ((pxErr = PXGetDate(pptr->rec_hdl, pptr->fhdl[n], <mp)) == IOGOOD)
  725.                 {
  726.                        pxErr = PXDateDecode(ltmp, &tm, &td, &ty);
  727.                        if ((ty >= 1900) && (ty < 2000))
  728.                       ty -= 1900;
  729.                    sprintf(tstr, "%02d%02d%02d", ty, tm, td);
  730.                      memcpy(&buffer[so], tstr, sl);
  731.                     }
  732.             }
  733.                 else
  734.                 {
  735.                 pxErr = PXGetLong(pptr->rec_hdl, pptr->fhdl[n], <mp);
  736.                 memcpy(&buffer[so], (char *)<mp, sl); 
  737.                 }
  738.             break;
  739.       }
  740.    }
  741.  
  742.    if (pxErr != IOGOOD)
  743.    {
  744.       i_unlock_rec(fd_sys, buffer);
  745.       zerorec(buffer, fptr->rec_len);
  746.       return(io_xlate(fd_sys, pxErr, "PDX GETREC3"));
  747.    }
  748.  
  749.    return(IOGOOD);
  750. }
  751.  
  752. /*
  753.  *  Re-read/reposition record pointer function - if required
  754. */
  755. static int i_rereadrec(fd_sys, buffer)
  756. int fd_sys;
  757. char *buffer;
  758. {
  759.    return(i_findkey(fd_sys, buffer));
  760. }
  761.  
  762.  
  763. /*
  764.  *  Add a new record.
  765. */
  766. static int i_addrec(fd_sys, buffer)
  767. int fd_sys;
  768. char *buffer;
  769. {
  770.    if (put_record(fd_sys, buffer) != IOGOOD)
  771.       return(IOERROR);
  772.  
  773.    if ((pxErr = PXRecAppend(fpx[fd_sys].fd_hdl, fpx[fd_sys].rec_hdl)) != IOGOOD)
  774.       return(io_xlate(fd_sys, pxErr, "PDX ADD"));
  775.  
  776.    return(IOGOOD);
  777. }
  778.  
  779. /*
  780.  *  Update the current record.
  781. */
  782. static int i_updrec(fd_sys, buffer)
  783. int fd_sys;
  784. char *buffer;
  785. {
  786.    if (put_record(fd_sys, buffer) != IOGOOD)
  787.       return(IOERROR);
  788.  
  789.    if ((pxErr = PXRecUpdate(fpx[fd_sys].fd_hdl, fpx[fd_sys].rec_hdl)) != IOGOOD)
  790.       return(io_xlate(fd_sys, pxErr, "PDX UPD"));
  791.  
  792.    return(IOGOOD);
  793. }
  794.  
  795. /*
  796.  *  Delete the current record.
  797. */
  798. static int i_delrec(fd_sys, buffer)
  799. int fd_sys;
  800. char *buffer;
  801. {
  802.    if ((pxErr = PXRecDelete(fpx[fd_sys].fd_hdl)) != IOGOOD)
  803.       return(io_xlate(fd_sys, pxErr, "PDX DEL"));
  804.  
  805.    return(IOGOOD);
  806. }
  807.  
  808.  
  809. /*
  810.  *  Sets up a Paradox record from PRO-C buffer
  811. */
  812. static int put_record(fd_sys, buffer)
  813. int fd_sys;
  814. char *buffer;
  815. {
  816.    int n, so, sl, ty, tm, td;
  817.    short itmp;
  818.    long ltmp;
  819.    float ftmp;
  820.    double dtmp;
  821.    char tstr[MAX_FLDLEN], stmp[20];
  822.    struct fd_def *fptr = &fd[fd_sys];
  823.    struct pdx_def *pptr = &fpx[fd_sys];
  824.  
  825.    if ((pxErr = PXRecBufEmpty(pptr->rec_hdl)) != IOGOOD)
  826.       return(io_xlate(fd_sys, pxErr, "PDX PUTREC1"));
  827.  
  828.    for (n = 0; n < fptr->fld_cnt; n++)
  829.    {
  830.       so = fptr->flds[n].fldstart;
  831.       sl = fptr->flds[n].fldlen;
  832.  
  833.       switch(fptr->flds[n].fldtype)
  834.       {
  835.          case MEMTYP :
  836.                 sl = 255;
  837.          case CHRTYP :
  838.             strncpy(tstr, &buffer[so], sl); tstr[sl] = '\0';
  839.             pxErr = PXPutAlpha(pptr->rec_hdl, pptr->fhdl[n], tstr);
  840.             break;
  841.          case INTTYP :
  842.             memcpy((char *)&itmp, &buffer[so], sl); 
  843.             pxErr = PXPutShort(pptr->rec_hdl, pptr->fhdl[n], itmp);
  844.             break;
  845.          case LNGTYP :
  846.             memcpy((char *)<mp, &buffer[so], sl); 
  847.             pxErr = PXPutLong(pptr->rec_hdl, pptr->fhdl[n], ltmp);
  848.             break;
  849.          case FLTTYP :
  850.             memcpy((char *)&ftmp, &buffer[so], sl); 
  851.             dtmp = (double)ftmp;
  852.             pxErr = PXPutDoub(pptr->rec_hdl, pptr->fhdl[n], dtmp);
  853.             break;
  854.          case DBLTYP :
  855.             memcpy((char *)&dtmp, &buffer[so], sl); 
  856.             pxErr = PXPutDoub(pptr->rec_hdl, pptr->fhdl[n], dtmp);
  857.             break;
  858.          case DATTYP :
  859.             if (sl == 6)                 /* date stored as character string */
  860.                 {
  861.                strncpy(stmp, &buffer[so], 6);
  862.                 if (!stmp[0])
  863.                    strcpy(stmp, "000101");
  864.                 tstr[2] = '\0';
  865.                 strncpy(tstr, stmp, 2);
  866.                 ty = atoi(tstr) + 1900;
  867.                 strncpy(tstr, &stmp[2], 2);
  868.                 tm = atoi(tstr);
  869.                 strncpy(tstr, &stmp[4], 2);
  870.                 td = atoi(tstr);
  871.                 if ((pxErr = PXDateEncode(tm, td, ty, <mp)) == IOGOOD)
  872.                    pxErr = PXPutDate(pptr->rec_hdl, pptr->fhdl[n], ltmp);
  873.                 }
  874.                 else
  875.                 {
  876.                 memcpy((char *)<mp, &buffer[so], sl); 
  877.                 pxErr = PXPutLong(pptr->rec_hdl, pptr->fhdl[n], ltmp);
  878.                 }
  879.             break;
  880.       }
  881.       if (pxErr != IOGOOD)
  882.          break;
  883.    }
  884.    if (pxErr != IOGOOD)
  885.       return(io_xlate(fd_sys, pxErr, "PDX PUTREC2"));
  886.  
  887.    return(IOGOOD);
  888. }
  889.  
  890.  
  891. /*
  892.  *  Lock Record
  893. */  
  894. static int i_lockrec(fd_sys, buffer)
  895. int fd_sys;
  896. char *buffer;
  897. {
  898.    int tpxErr;
  899.  
  900.    if (fd[fd_sys].lockmode == NOLOCK)
  901.       return(IOGOOD);
  902.  
  903.    if ((tpxErr = PXNetRecLock(fpx[fd_sys].rec_hdl, &fpx[fd_sys].lck_hdl)) != IOGOOD)
  904.       return(io_xlate(fd_sys, tpxErr, "LOCK"));
  905.  
  906.    return(IOGOOD);
  907. }
  908.  
  909. /*
  910.  *  Unlock Record
  911. */
  912. static int i_unlock_rec(fd_sys, buffer)
  913. int fd_sys;
  914. char *buffer;
  915. {
  916.    int tpxErr;
  917.  
  918.    if (fd[fd_sys].lockmode == NOLOCK)
  919.       return(IOGOOD);
  920.  
  921.    if ((tpxErr = PXNetRecUnlock(fpx[fd_sys].rec_hdl, fpx[fd_sys].lck_hdl)) != IOGOOD)
  922.       return(io_xlate(fd_sys, tpxErr, "UNLOCK"));
  923.  
  924.    return(IOGOOD);
  925. }
  926.  
  927.  
  928. /*
  929.  *  Login
  930. */
  931. static int i_login(fd_sys, buffer)
  932. int fd_sys;
  933. char *buffer;
  934. {
  935.    return(IOGOOD);
  936. }
  937.  
  938. /*
  939.  *  Logoff
  940. */
  941. static int i_logoff(fd_sys, buffer)
  942. int fd_sys;
  943. char *buffer;
  944. {
  945.    return(IOGOOD);
  946. }
  947.  
  948. /*
  949.  *  End (Commit) transaction 
  950. */
  951. static int i_commit(fd_sys, buffer)
  952. int fd_sys;
  953. char *buffer;
  954. {
  955.    return(IOGOOD);
  956. }
  957.  
  958. /*
  959.  *  Rollback transaction
  960. */
  961. static int i_rollback(fd_sys, buffer)
  962. int fd_sys;
  963. char *buffer;
  964. {
  965.    return(IOGOOD);
  966. }
  967.  
  968. /*
  969.  *  Start transaction
  970. */
  971. static int i_transact(fd_sys, buffer)
  972. int fd_sys;
  973. char *buffer;
  974. {
  975.    return(IOGOOD);
  976. }
  977.  
  978.  
  979. /*
  980.  *  This routine translates Paradox Engine error codes into PRO-C codes.
  981.  *  If no PRO-C equivalent, displays the error number.
  982. */
  983. static int io_xlate(fd_sys, ernum, rtnname)
  984. int fd_sys;
  985. int ernum;
  986. char *rtnname;
  987. {
  988.    switch(ernum)
  989.    {
  990.       case PXERR_TABLEOPEN     :
  991.          return IOBADOPEN;
  992.       case PXERR_RECNOTFOUND   :
  993.          return IONOKEY;
  994.       case PXERR_ENDOFTABLE    :
  995.       case PXERR_TABLEEMPTY    :
  996.          return IOEOF;
  997.       case PXERR_STARTOFTABLE  :
  998.          return IOTOF;
  999.       case PXERR_INVTABLENAME  :
  1000.       case PXERR_TABLENOTFOUND :
  1001.          return IONOFILE;
  1002.       case PXERR_TABLELOCKED   :
  1003.       case PXERR_TABLEBUSY     :
  1004.       case PXERR_RECLOCKED     :
  1005.          return IOLOCKED;
  1006.       case PXERR_NONETINIT     :      /* harmless return for nonnetwork use */
  1007.          return IOGOOD;
  1008.    }
  1009.  
  1010.    if (fd_sys >= 0)
  1011.       errmsg(FileDbgError_sdss, "Paradox Engine", ernum, fd[fd_sys].filname, rtnname);
  1012.    else
  1013.       errmsg(FileDbgError_sds, "Paradox Engine", ernum, rtnname);
  1014.    return(IOERROR);
  1015. }
  1016.  
  1017.  
  1018. /*
  1019.  * Assign section
  1020. */
  1021.  
  1022. void assign_IO_PX(dbnum)
  1023. int dbnum;
  1024. {
  1025.    Fntab[dbnum - 1][0]  = (int(*)())0; /* Empty */
  1026.    Fntab[dbnum - 1][1]  = i_init_file;
  1027.    Fntab[dbnum - 1][2]  = i_open_file;
  1028.    Fntab[dbnum - 1][3]  = i_close_file;
  1029.    Fntab[dbnum - 1][4]  = i_addrec;
  1030.    Fntab[dbnum - 1][5]  = i_delrec;
  1031.    Fntab[dbnum - 1][6]  = i_findkey;
  1032.    Fntab[dbnum - 1][7]  = i_firstkey;
  1033.    Fntab[dbnum - 1][8]  = i_lastkey;
  1034.    Fntab[dbnum - 1][9]  = i_lockrec;
  1035.    Fntab[dbnum - 1][10] = i_nextrec;
  1036.    Fntab[dbnum - 1][11] = i_prevrec;
  1037.    Fntab[dbnum - 1][12] = i_unlock_rec;
  1038.    Fntab[dbnum - 1][13] = i_updrec;
  1039.    Fntab[dbnum - 1][14] = i_commit;
  1040.    Fntab[dbnum - 1][15] = i_login;
  1041.    Fntab[dbnum - 1][16] = i_logoff;
  1042.    Fntab[dbnum - 1][17] = i_rollback;
  1043.    Fntab[dbnum - 1][18] = i_transact;
  1044.    Fntab[dbnum - 1][19] = i_selectinx;
  1045.    Fntab[dbnum - 1][20] = i_rereadrec;
  1046.    Fntab[dbnum - 1][21] = i_filename;
  1047. }
  1048.