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

  1. /* ==( io/src/iembay.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   VvA  01-Nov-88  for v.1.3             */
  10. /* Modified  VvA  11-Apr-90  see comments below    */
  11. /* ----------------------------------------------- */
  12. /* %W%  (%H% %T%) */
  13.  
  14. /*
  15.  *  Modifications
  16.  *
  17.  *  11-Apr-90  VvA - adapted to V.2
  18. */
  19.  
  20. /*  Emerald Bay specific I/O calls via general IOGEN.C interface  */
  21.  
  22. # include <stdio.h>
  23. # include <iodef.h>
  24. # include <iomsg.h>
  25. # include <proc.io>
  26. # include <bench.h>
  27. # include <iosup.h>
  28. # include <eb.h>
  29.  
  30. /* Function prototypes */
  31. # ifdef ANSI
  32. static int i_addrec(int, char *);
  33. static int i_close_file(int, char *);
  34. static int i_commit(int, char *);
  35. static int i_delrec(int, char *);
  36. static int i_filename(int, char *);
  37. static int i_findkey(int, char *);
  38. static int i_firstkey(int, char *);
  39. static int i_init_file(int, char *);
  40. static int i_lastkey(int, char *);
  41. static int i_lockrec(int, char *);
  42. static int i_login(int, char *);
  43. static int i_logoff(int, char *);
  44. static int i_nextrec(int, char *);
  45. static int i_open_file(int, char *);
  46. static int i_prevrec(int, char *);
  47. static int i_rereadrec(int, char *);
  48. static int i_rollback(int, char *);
  49. static int i_selectinx(int, char *);
  50. static int i_transact(int, char *);
  51. static int i_unlock_rec(int, char *);
  52. static int i_updrec(int, char *);
  53. static int create_file(int);
  54. static int length_check(int);
  55. static int load_keys(int);
  56. static int buff2eb(int, char *);
  57. static int eb2buff(int, char *, char *);
  58. static int io_xlate(int, int, char *);
  59. static void setupkey(int, char *, char *, int *);
  60. # else
  61. static int i_addrec();
  62. static int i_close_file();
  63. static int i_commit();
  64. static int i_delrec();
  65. static int i_filename();
  66. static int i_findkey();
  67. static int i_firstkey();
  68. static int i_init_file();
  69. static int i_lastkey();
  70. static int i_lockrec();
  71. static int i_login();
  72. static int i_logoff();
  73. static int i_nextrec();
  74. static int i_open_file();
  75. static int i_prevrec();
  76. static int i_rereadrec();
  77. static int i_rollback();
  78. static int i_selectinx();
  79. static int i_transact();
  80. static int i_unlock_rec();
  81. static int i_updrec();
  82. static int create_file();
  83. static int length_check();
  84. static int load_keys();
  85. static int buff2eb();
  86. static int eb2buff();
  87. static int io_xlate();
  88. static void setupkey();
  89. # endif
  90.  
  91.  
  92. #define       EB_FLDLEN       512         /* Emerald Bay field length limit */
  93.  
  94.  
  95. /*
  96.  * structure for Emerald Bay specific values 
  97. */
  98. struct ixinfo
  99. {
  100.    int ix_num;                             /* index handle from Emerald Bay */
  101.    char ixname[FILENAME_LEN];
  102.    NDXARG *ndxdesc;
  103. };
  104.  
  105. struct emb_def
  106. {
  107.    FLDARG *flddesc;
  108.    TEXTOBJECT *txtfld[MAX_FLDS];      /* ptrs only, allocated if a memo fld */
  109.    struct ixinfo fdkey[MAX_KEYS+1];
  110. };
  111.  
  112. static struct emb_def efd[MAX_FILES];
  113.  
  114. static char usrname[21] = { "" };
  115. static char pasword[21] = { "" };
  116. static char keybuff[EB_FLDLEN * MAX_SEGS + MAX_SEGS];
  117. static int dberrno;                                    /* error code global */
  118. static int dbhdl;            /* global handle for Emerald Bay database file */
  119.  
  120. static int EB_OPENMODE;
  121. static int EB_SHAREMODE;
  122.  
  123.  
  124. /*
  125.  *
  126.  * Interface Functions
  127.  *
  128. */
  129.  
  130.  
  131. /*
  132.  *  Sets up File Name - Name is passed in buffer
  133. */
  134. static int i_filename(fd_sys, buffer)
  135. int fd_sys;
  136. char *buffer;
  137. {
  138.    for ( ; (*buffer != '.') && (*buffer != NULL); buffer++)
  139.       ;
  140.    *buffer = NULL;
  141.  
  142.    return(IOGOOD);
  143. }
  144.  
  145.  
  146. /*
  147.  *  Overall initialization
  148.  *  - called once only, each time set of files is opened
  149.  *  - overall database name is passed in buffer
  150. */
  151. static int i_init_file(fd_sys, buffer)
  152. int fd_sys;
  153. char *buffer;
  154. {
  155.    if (!*buffer || (buffer == NULL))           /* if no overall name passed */
  156.       strcpy(buffer, "PRO_C1");
  157.  
  158.    if ((dbhdl = DbLogin(buffer, pasword)) < 0)         /* open the database */
  159.    {
  160.       if (dbhdl != DBNODB)
  161.          return(io_xlate(fd_sys, dbhdl, "EB INIT1"));
  162.  
  163.       if (DbCreate(buffer, pasword) == -1)           /* or try to create it */
  164.       {
  165.          errmsg("Database file pair %s could not be created", buffer);
  166.          return(IOERROR);
  167.       }
  168.  
  169.       if ((dbhdl = DbLogin(buffer, pasword)) < 0)
  170.       {
  171.          errmsg("Database %s just created cannot be opened", buffer);
  172.          return(IOERROR);
  173.       }
  174.    }
  175.    return(IOGOOD);
  176. }
  177.  
  178.  
  179. /*
  180.  *  File open function - required parameters are in fd structure.
  181.  *  - dbhdl contains the overall database handle for all operations,
  182.  *    until the files are closed
  183. */
  184. static int i_open_file(fd_sys, buffer)
  185. int fd_sys;
  186. char *buffer;
  187. {
  188.    int tbhdl;
  189.    char tblname[FILENAME_LEN];
  190.    struct fd_def *fptr = &fd[fd_sys];
  191.  
  192.    strcpy(tblname, fptr->filname);                /* table name in database */
  193.  
  194.    if (fptr->openmode & OUTPUT_FLAG)       /* create call destroys old file */
  195.    {
  196.       if ((dberrno = DbDropTable(dbhdl, tblname)) < 0)
  197.          return(io_xlate(fd_sys, dberrno, "EB OUTP"));
  198.       create_file(fd_sys);
  199.    }
  200.  
  201.    if ((tbhdl = DbOpenTable(dbhdl, tblname)) < 0)
  202.    {
  203.       if (fptr->openmode & INPUT_FLAG)
  204.          return(io_xlate(fd_sys, tbhdl, "EB OPEN1"));
  205.       
  206.       if (create_file(fd_sys) != IOGOOD)
  207.          return(IOERROR);
  208.       free(efd[fd_sys].flddesc);         /* will be reloaded in lengthcheck */
  209.    }
  210.    else                     /* file & indexes have been opened successfully */
  211.       fptr->fd_num = tbhdl;
  212.  
  213.    EB_OPENMODE = (fptr->openmode & INPUT_FLAG) ? READONLY : READWRITE;
  214.    EB_SHAREMODE = (fptr->openmode & P_EXCLUSIVE) ? EXCLUSIVE : SHARE; 
  215.    dberrno = DbSetLockMode(fptr->fd_num, EB_OPENMODE, EB_SHAREMODE);
  216.       
  217.    if (dberrno < 0)
  218.       return(io_xlate(fd_sys, dberrno, "EB OPEN2"));
  219.  
  220.    if (length_check(fd_sys) != IOGOOD)
  221.    {
  222.       errmsg(FileRecLenChg_s, fptr->filname);
  223.       return(IOERROR);
  224.    }
  225.    
  226.    return(IOGOOD);
  227. }
  228.  
  229.  
  230. /*
  231.  *  Checks field count and char field lengths for changes since last use,
  232.  *  and loads the Emerald Bay field and index parameters.
  233.  *  - this is called even for a just-created database table
  234.  *  - Emerald Bay adds a rec_no field #0 to all tables, which has to be
  235.  *    taken into account in reloading established tables & indexes.  This
  236.  *    is taken into account for the length check.
  237.  */
  238. static int length_check(fd_sys)
  239. int fd_sys;
  240. {
  241.    int j, fcnt, kcnt, nsegs = 0, ix, tmperror;
  242.    char ndxname[FILENAME_LEN];
  243.    struct fd_def *fptr = &fd[fd_sys];
  244.    struct emb_def *eptr = &efd[fd_sys];
  245.  
  246.    if ((fcnt = DbGetNumberOfFields(fptr->fd_num)) < 0)
  247.       return(io_xlate(fd_sys, fcnt, "EB LCHK1"));
  248.    
  249.    if (fcnt != fptr->fld_cnt+1)                  /* field count has changed */
  250.       return(IOERROR);
  251.       
  252. /*
  253.  * Field reallocation and reloading takes into account the 0th field used by
  254.  * Emerald Bay for rec_no
  255. */
  256.    eptr->flddesc = (FLDARG *)alloc(sizeof(FLDARG) * (fcnt+1));
  257.  
  258.    if ((dberrno = DbGetNamedFieldInfo(fptr->fd_num, "rec_no", &(eptr->flddesc[0]))) < 0)
  259.       return(io_xlate(fd_sys, dberrno, "EB LCHK2A"));
  260.  
  261.    for (j = 1; j < fcnt; j++)           /* load and check field information */
  262.    {
  263.       if ((dberrno = DbGetNamedFieldInfo(fptr->fd_num, fptr->flds[j-1].fldname, &(eptr->flddesc[j]))) < 0)
  264.          return(io_xlate(fd_sys, dberrno, "EB LCHK2B"));
  265.  
  266.       tmperror = FALSE;
  267.       if (fptr->flds[j-1].fldlen != eptr->flddesc[j].fldlen)
  268.       {
  269.          tmperror = TRUE;
  270.          if ((fptr->flds[j-1].fldtype == FLTTYP) && (eptr->flddesc[j].fldlen == sizeof(double)))
  271.             tmperror = FALSE;
  272.          if ((fptr->flds[j-1].fldtype == LOGTYP) && (eptr->flddesc[j].fldlen == sizeof(int)))
  273.             tmperror = FALSE;
  274.          if ((fptr->flds[j-1].fldtype == DATTYP) && (eptr->flddesc[j].fldlen == sizeof(long)))
  275.             tmperror = FALSE;
  276.          if ((fptr->flds[j-1].fldtype == MEMTYP))
  277.             tmperror = FALSE;
  278.       }
  279.       if (tmperror)
  280.          return(IOERROR);
  281.    }
  282.  
  283. /*
  284.  * Note that the keyinfo structure index will be 1 less than the fdkey
  285.  *  structure index, to allow for Emerald Bay's reserved 0th rec_no index.
  286. */
  287.    strcpy(eptr->fdkey[0].ixname, "rec_no");         /* Emerald Bay reserved */
  288.  
  289.    strcpy(ndxname, fptr->filname);          /* index names match their file */
  290.    if ((ix = strlen(ndxname)) > 7)                 /* ix is index id offset */
  291.       ix = 7;
  292.    ndxname[ix] = '\0';
  293.    strcat(ndxname, "0");
  294.    
  295.    for (kcnt = 0; kcnt < fptr->key_cnt; kcnt++)
  296.    {
  297.       ndxname[ix] = (char)(kcnt + 49);            /* sequential index names */
  298.       strcpy(eptr->fdkey[kcnt+1].ixname, ndxname);
  299.    }
  300.  
  301. /*
  302.  * Note that this load counts one more than keyinfo structure's number of
  303.  *  keys to allow for the 0th rec_no index.
  304. */
  305.    for (j = 0; j <= fptr->key_cnt; j++)           /* load index information */
  306.    {
  307.       eptr->fdkey[j].ndxdesc = (NDXARG *)alloc(sizeof(NDXARG));
  308.  
  309.       if ((dberrno = DbGetNamedIndexInfo(fptr->fd_num, eptr->fdkey[j].ixname, eptr->fdkey[j].ndxdesc)) < 0)
  310.          return(io_xlate(fd_sys, dberrno, "EB LCHK3"));
  311.     
  312.       eptr->fdkey[j].ix_num = eptr->fdkey[j].ndxdesc->ndxid;  
  313.    }
  314.  
  315.    for (j = 0; j < fptr->fld_cnt; j++)   /* if a memo, allocate text object */
  316.       if (fptr->flds[j].fldtype == MEMTYP)
  317.          eptr->txtfld[j+1] = DbTextInit(fptr->fd_num, eptr->flddesc[j+1].fldid);
  318.  
  319.    return(IOGOOD);
  320. }
  321.  
  322.  
  323. /*
  324.  *  Creates a new table.
  325.  *  - at this point, PRO-C and Emerald Bay fields still have the same 
  326.  *    index into field information structure arrays.
  327. */
  328. static int create_file(fd_sys)
  329. int fd_sys;
  330. {
  331.    int j;
  332.    int tbhdl;
  333.    char dfname[FILENAME_LEN];
  334.    struct fd_def *fptr = &fd[fd_sys];
  335.    struct emb_def *eptr = &efd[fd_sys];
  336.  
  337.    strcpy(dfname, fptr->filname);
  338.    eptr->flddesc = (FLDARG *)alloc(sizeof(FLDARG) * (fptr->fld_cnt+2));
  339.  
  340.    for (j = 0; j < fptr->fld_cnt; j++)           /* load field descriptions */
  341.    {
  342.       strcpy(eptr->flddesc[j].fldname, fptr->flds[j].fldname);
  343.       switch(fptr->flds[j].fldtype)
  344.       {
  345.          case CHRTYP :
  346.             eptr->flddesc[j].fldtype = DTYPSTR;
  347.             eptr->flddesc[j].fldlen = fptr->flds[j].fldlen;
  348.             break;
  349.          case INTTYP :
  350.             eptr->flddesc[j].fldtype = DTYPINT;
  351.             break;
  352.          case LNGTYP :
  353.             eptr->flddesc[j].fldtype = DTYPLNG;
  354.             break;
  355.          case FLTTYP :
  356.          case DBLTYP :
  357.             eptr->flddesc[j].fldtype = DTYPDBL;
  358.             break;
  359.          case DATTYP :
  360.                 if (fptr->flds[j].fldlen == 6)
  361.                 eptr->flddesc[j].fldtype = DTYPDAT;
  362.                 else
  363.                     eptr->flddesc[j].fldtype = DTYPLNG;    
  364.             break;
  365.          case MEMTYP :
  366.             eptr->flddesc[j].fldtype = DTYPBIN;
  367.             break;
  368.          case LOGTYP :
  369.             eptr->flddesc[j].fldtype = DTYPLOG;
  370.             break;
  371.       }      
  372.       eptr->flddesc[j].fldrepl = 0;
  373.       eptr->flddesc[j].fldreq = FALSE;                /* is field required? */
  374.       eptr->flddesc[j].flddefflag = FALSE;          /* is default supplied? */
  375.    }
  376.    eptr->flddesc[j].fldname[0] = '\0';
  377.  
  378.    if ((tbhdl = DbMakeTable(dbhdl, dfname, eptr->flddesc)) < 0)
  379.       return(io_xlate(fd_sys, tbhdl, "EB CRT1"));
  380.  
  381.    if ((tbhdl = DbOpenTable(dbhdl, dfname)) < 0)
  382.       return(io_xlate(fd_sys, tbhdl, "EB CRT2"));
  383.       
  384.    fptr->fd_num = tbhdl;
  385.  
  386.    if ((dberrno = DbGetNamedFieldInfo(fptr->fd_num, "rec_no", &(eptr->flddesc[0]))) < 0)
  387.       return(io_xlate(fd_sys, dberrno, "EB CRT3A"));
  388.  
  389.    for (j = 1; j <= fptr->fld_cnt; j++)          /* complete the field info */
  390.    {
  391.       if ((dberrno = DbGetNamedFieldInfo(fptr->fd_num, fptr->flds[j-1].fldname, &(eptr->flddesc[j]))) < 0)
  392.          return(io_xlate(fd_sys, dberrno, "EB CRT3B"));
  393.    }
  394.  
  395.    if (load_keys(fd_sys) > 0)                             /* create indexes */
  396.    {
  397.       free(eptr->flddesc);               /* will be reloaded in lengthcheck */
  398.       return(IOGOOD);
  399.    }
  400.    else
  401.       return(IOERROR);
  402. }
  403.  
  404.  
  405. /*
  406.  *  Load key information.
  407.  *  - this is called only when the file is being created
  408.  *  - creation of indexes must be done in non-shared (personal engine) mode
  409.  *  - index names are created by adding sequential numbers to the name of 
  410.  *    the data table to which they refer.
  411.  *  - assignment of values to Emerald Bay information structures already 
  412.  *    takes into account the reserved field 0 for the record number, 
  413.  *    although this information is not yet used here
  414.  *  - this information is reloaded in length_check() after this function 
  415.  *    has been completed
  416. */
  417. static int load_keys(fd_sys)
  418. int fd_sys;
  419. {
  420.    int ndxid, kcnt, fx, j, nkeys = 0;
  421.    NDXARG *tndxdesc;
  422.    char ndxname[FILENAME_LEN];
  423.    struct fd_def *fptr = &fd[fd_sys];
  424.    struct emb_def *eptr = &efd[fd_sys];
  425.  
  426.    tndxdesc = (NDXARG *)alloc(sizeof(NDXARG));
  427.  
  428.    strcpy(ndxname, fptr->filname);          /* index names match their file */
  429.    if ((ndxid = strlen(ndxname)) > 7)           /* ndxid is index id offset */
  430.       ndxid = 7;
  431.    ndxname[ndxid] = '\0';
  432.    strcat(ndxname, "0");
  433.  
  434.    for (kcnt = 0; kcnt < fptr->key_cnt; kcnt++)
  435.    {
  436.       ndxname[ndxid] = (char)(nkeys + 49);        /* sequential index names */  
  437.       strcpy(tndxdesc->ndxname, ndxname);
  438.       tndxdesc->ndxcase = TRUE;              /* make the key case sensitive */
  439.       for (j = 0; j < MAXNDX; j++)
  440.          tndxdesc->ndxatr[j] = 0;
  441.       tndxdesc->ndxtype = (fptr->keys[kcnt].keytype == KEY_UNIQUE) ? TRUE : FALSE;
  442.  
  443.       for (j = 0; j < fptr->keys[kcnt].segcount; j++)
  444.       {
  445.          fx = fptr->keys[kcnt].fldindex[j];
  446.          tndxdesc->ndxatr[j] = eptr->flddesc[fx+1].fldid;
  447.       }
  448.  
  449.       if ((dberrno = DbMakeIndex(fptr->fd_num, tndxdesc)) < 0)
  450.       {
  451.          nkeys = -1;
  452.          free(tndxdesc);
  453.          io_xlate(fd_sys, dberrno, "EB ICRT");
  454.          break;
  455.       }
  456.       nkeys++;                                       /* increment key count */
  457.    }
  458.  
  459.    free(tndxdesc);
  460.    return(nkeys);
  461. }
  462.  
  463.  
  464. /*
  465.  *  File close function.
  466.  *  - DbCloseTable function closes all indexes associated with the table
  467.  *  - DbLogout and DbExit close the overall database after all the
  468.  *    individual tables are closed
  469. */
  470. static int i_close_file(fd_sys, buffer)
  471. int fd_sys;
  472. char *buffer;
  473. {
  474.    int i, j = 0;
  475.  
  476.    for (j = 0; j < fd[fd_sys].fld_cnt; j++)      /* deallocate memo buffers */
  477.       if (fd[fd_sys].flds[j].fldtype == MEMTYP)
  478.          DbTextClose(efd[fd_sys].txtfld[j+1]);
  479.  
  480.    if ((dberrno = DbCloseTable(fd[fd_sys].fd_num)) < 0)
  481.       return(io_xlate(fd_sys, dberrno, "EB CLOSE1"));
  482.    fd[fd_sys].active = NO;
  483.  
  484.    for (i = 0; i < MAX_FILES; i++)       /* how many tables are still open? */
  485.       if (fd[i].active == YES)
  486.          j++;
  487.  
  488.    if (!j)                   /* close database if all tables are now closed */
  489.    {
  490.       if ((dberrno = DbLogout(dbhdl)) < 0)
  491.       {
  492.          errmsg("Error closing Emerald Bay database file");
  493.          return(IOERROR);
  494.       }
  495.       DbExit();
  496.    }
  497.  
  498.    return(IOGOOD);
  499. }
  500.  
  501.  
  502. /*
  503.  *  Index is selected in IOGEN.
  504.  *  - fd[fd_sys].cur_key refers to the keyinfo structure for PRO-C
  505.  *  - when referring to fdkey structure, add 1 to the value to bring it 
  506.  *    into line with Emerald Bay's 0th rec_no index.
  507. */
  508. static int i_selectinx(fd_sys, buffer)
  509. int fd_sys;
  510. char *buffer;
  511. {
  512.    return(IOGOOD);
  513. }
  514.  
  515. /*
  516.  *  Find a record by key value
  517. */
  518. static int i_findkey(fd_sys, buffer)
  519. int fd_sys;
  520. char *buffer;
  521. {
  522.    int ck, klen;
  523.    struct fd_def *fptr = &fd[fd_sys];
  524.    struct emb_def *eptr = &efd[fd_sys];
  525.  
  526.    ck = fptr->cur_key;
  527.    setupkey(fd_sys, buffer, keybuff, &klen);
  528.  
  529.    if (fptr->exact)
  530.       dberrno = DbSearch(fptr->fd_num, eptr->fdkey[ck+1].ix_num, keybuff, klen, EQUAL);
  531.    else
  532.       dberrno = DbSearch(fptr->fd_num, eptr->fdkey[ck+1].ix_num, keybuff, klen, GREATEQ);
  533.    if (dberrno < 0)
  534.       return io_xlate(fd_sys, dberrno, "EB FIND1");
  535.  
  536.    if (i_lockrec(fd_sys, buffer) == IOGOOD)
  537.       return(eb2buff(fd_sys, buffer, "EB FIND2"));
  538.  
  539.    return(IOERROR);
  540. }
  541.  
  542. /*
  543.  *  Find first record in the file
  544. */
  545. static int i_firstkey(fd_sys, buffer)
  546. int fd_sys;
  547. char *buffer;
  548. {
  549.    int ck;
  550.  
  551.    fd[fd_sys].exact = 0;
  552.    ck = fd[fd_sys].cur_key;
  553.  
  554.    if ((dberrno = DbFirst(fd[fd_sys].fd_num, efd[fd_sys].fdkey[ck+1].ix_num)) < 0)
  555.       return(io_xlate(fd_sys, dberrno, "EB FRST1"));
  556.  
  557.    if (i_lockrec(fd_sys, buffer) == IOGOOD)
  558.       return(eb2buff(fd_sys, buffer, "EB FRST2"));
  559.  
  560.    return(IOERROR);
  561. }
  562.  
  563. /*
  564.  *  Find last physical record in the file
  565. */
  566. static int i_lastkey(fd_sys, buffer)
  567. int fd_sys;
  568. char *buffer;
  569. {
  570.    int ck;
  571.  
  572.    ck = fd[fd_sys].cur_key;
  573.  
  574.    if ((dberrno = DbLast(fd[fd_sys].fd_num, efd[fd_sys].fdkey[ck+1].ix_num)) < 0)
  575.    {
  576.       if (dberrno == -1)                   /* IOEOF return if file is empty */
  577.          return(IOEOF);
  578.       return(io_xlate(fd_sys, dberrno, "EB LAST1"));
  579.    }
  580.  
  581.    if (i_lockrec(fd_sys, buffer) == IOGOOD)
  582.       return(eb2buff(fd_sys, buffer, "EB LAST2"));
  583.  
  584.    return(IOERROR);
  585. }
  586.  
  587.  
  588. /*
  589.  *  Find next record in the file
  590.  *  - uses Emerald Bay's DbKeyCheck function in exact matches to determine
  591.  *    if the new key matches the retained earlier record's key
  592. */
  593. static int i_nextrec(fd_sys, buffer)
  594. int fd_sys;
  595. char *buffer;
  596. {
  597.    int ck, klen;
  598.    struct fd_def *fptr = &fd[fd_sys];
  599.    struct emb_def *eptr = &efd[fd_sys];
  600.  
  601.    i_unlock_rec(fd_sys, buffer);                   /* unlock current record */
  602.  
  603.    ck = fptr->cur_key;
  604.    setupkey(fd_sys, buffer, keybuff, &klen);        /* former key for check */
  605.  
  606.    if ((dberrno = DbNext(fptr->fd_num, eptr->fdkey[ck+1].ix_num)) < 0)
  607.    {
  608.       if (dberrno == -1)
  609.          return(IOEOF);
  610.       return(io_xlate(fd_sys, dberrno, "EB NEXT1"));
  611.    }
  612.  
  613.    if (fptr->exact && (DbKeyCheck(fptr->fd_num, eptr->fdkey[ck+1].ix_num, keybuff, klen) != 0))
  614.       return(IONONEXT);               /* next record does not match exactly */
  615.  
  616.    if (i_lockrec(fd_sys, buffer) == IOGOOD)
  617.       return(eb2buff(fd_sys, buffer, "EB NEXT2"));
  618.  
  619.    return(IOERROR);
  620. }
  621.  
  622.  
  623. /*
  624.  *  Find previous record in the file
  625.  *  - uses Emerald Bay's DbKeyCheck function in exact matches to determine
  626.  *    if the new key matches the retained earlier record's key
  627. */
  628. static int i_prevrec(fd_sys, buffer)
  629. int fd_sys;
  630. char *buffer;
  631. {
  632.    int ck, klen;
  633.    struct fd_def *fptr = &fd[fd_sys];
  634.    struct emb_def *eptr = &efd[fd_sys];
  635.  
  636.    i_unlock_rec(fd_sys, buffer);                   /* unlock current record */
  637.  
  638.    ck = fptr->cur_key;
  639.    setupkey(fd_sys, buffer, keybuff, &klen);        /* former key for check */
  640.  
  641.    if ((dberrno = DbPrev(fptr->fd_num, eptr->fdkey[ck+1].ix_num)) < 0)
  642.    {
  643.       if  (dberrno == -1)
  644.          return(IOTOF);
  645.       return(io_xlate(fd_sys, dberrno, "EB PREV1"));
  646.    }
  647.  
  648.    if (fptr->exact && (DbKeyCheck(fptr->fd_num, eptr->fdkey[ck+1].ix_num, keybuff, klen) != 0))
  649.       return(IONONEXT);               /* prev record does not match exactly */
  650.  
  651.    if (i_lockrec(fd_sys, buffer) == IOGOOD)
  652.       return(eb2buff(fd_sys, buffer, "EB PREV2"));
  653.  
  654.    return(IOERROR);
  655. }
  656.  
  657.  
  658. /*
  659.  *  Re-read/reposition record pointer function - if required
  660. */
  661. static int i_rereadrec(fd_sys, buffer)
  662. int fd_sys;
  663. char *buffer;
  664. {
  665.    return(IOGOOD);
  666. }
  667.  
  668.  
  669. /*
  670.  *  Sets up a key string for record retrieval on current index
  671.  *  - calls Emerald Bay's DbMakeSearchKey function to set up target keys
  672.  *    packed to match the index data storage; multiple segments are
  673.  *    incorporated into the function call, if applicable
  674.  *  - to accommodate different key types, an array of unions of the 
  675.  *    available field types is used, using NULL for unused key segments
  676.  *  - key pattern string also passed to DbMakeSearchKey sorts out the
  677.  *    arguments to this varargs function
  678.  *  - Emerald Bay allows up to six segments per key
  679. */
  680. static void setupkey(fd_sys, buff, kbuff, klen)
  681. int fd_sys;
  682. char *buff, *kbuff;
  683. int *klen;
  684. {
  685.    int j, ck, toff, tlen, fx, tkey;
  686.    float ftmp;
  687.    double dtmp;
  688.    char keypat[7];
  689.    struct fd_def *fptr = &fd[fd_sys];
  690.    union {
  691.          char *stmp;
  692.          int itmp;
  693.          long ltmp;
  694.          double dtmp;
  695.          }           v[MAXNDX];
  696.  
  697.    ck = fptr->cur_key;
  698.    keypat[0] = '\0';
  699.    
  700.    for (j = 0; j < MAXNDX; j++)      /* blank out longest union member type */
  701.       v[j].dtmp = (double)0;
  702.  
  703.    for (j = 0; j < fptr->keys[ck].segcount; j++)
  704.    {
  705.       toff = fptr->keys[ck].segstart[j];
  706.       tlen = fptr->keys[ck].seglen[j];
  707.       fx = fptr->keys[ck].fldindex[j];
  708.       tkey = fptr->flds[fx].fldtype;
  709.  
  710.       if (tkey == FLTTYP)
  711.       {
  712.          bytecpy(&ftmp, &buff[toff], tlen); 
  713.          dtmp = (double)ftmp;
  714.          tlen = sizeof(double);
  715.       }
  716.       if (tkey == DATTYP)               /* stored as julian date (long int) */
  717.          tlen = sizeof(long);
  718.  
  719.       switch(tkey)                      /* get key values from PRO-C buffer */
  720.       {
  721.          case CHRTYP :
  722.             v[j].stmp = alloc(tlen+1);
  723.             strncpy(v[j].stmp, &buff[toff], tlen);
  724.             v[j].stmp[tlen] = '\0';
  725.             strcat(keypat, "s");
  726.             break;
  727.          case INTTYP :
  728.             bytecpy(&v[j].itmp, &buff[toff], tlen); 
  729.             strcat(keypat, "i");
  730.             break;
  731.          case DATTYP :
  732.          case LNGTYP :
  733.             bytecpy(&v[j].ltmp, &buff[toff], tlen);
  734.             strcat(keypat, "l");
  735.             break;
  736.          case DBLTYP :
  737.             bytecpy(&dtmp, &buff[toff], tlen);
  738.          case FLTTYP :
  739.             v[j].dtmp = dtmp;
  740.             strcat(keypat, "d");
  741.             break;
  742.       }
  743.    }                             /* key components not used have NULL value */
  744.  
  745.    *klen = DbMakeSearchKey(kbuff, keypat, v[0], v[1], v[2], v[3], v[4], v[5]);
  746.  
  747.    for (j = 0; j < fptr->keys[ck].segcount; j++)
  748.    {
  749.       fx = fptr->keys[ck].fldindex[j];
  750.       tkey = fptr->flds[fx].fldtype;
  751.       if (tkey == CHRTYP)
  752.          if (v[j].stmp)
  753.             free(v[j].stmp);
  754.    }
  755. }
  756.  
  757.  
  758. /*
  759.  *  Stores Emerald Bay local buffer contents to PRO-C buffer
  760.  *  - EB array index is one higher than PRO-C's because 1st field is recno
  761.  *  - EB buffers are not visible to programmer but defined internally only
  762. */
  763. static int eb2buff(fd_sys, buff, emsg)
  764. int fd_sys;
  765. char *buff;
  766. char *emsg;
  767. {
  768.    char tbuff[EB_FLDLEN+1], ercode[14];
  769.    int tftyp, tfoff, tflen, i, len, k;
  770.    int dy, mo, yr;
  771.    int itmp;
  772.    long ltmp;
  773.    float ftmp;
  774.    double dtmp;
  775.    struct fd_def *fptr = &fd[fd_sys];
  776.    struct emb_def *eptr = &efd[fd_sys];
  777.  
  778.    strcpy(ercode, "GET/");
  779.    strcat(ercode, emsg);
  780.  
  781.    zerorec(buff, fptr->rec_len);
  782.  
  783.    for (i = 0; i < fptr->fld_cnt; i++)
  784.    {
  785.       tftyp = fptr->flds[i].fldtype;
  786.       tfoff = fptr->flds[i].fldstart;
  787.       tflen = fptr->flds[i].fldlen;
  788.  
  789.       zerorec(tbuff, EB_FLDLEN+1);
  790.  
  791.       if (tftyp == MEMTYP)
  792.       {
  793.          DbTextReset(eptr->txtfld[i+1]);
  794.          itmp = 0;
  795.          len = tflen;
  796.          while (itmp < tflen)
  797.          {
  798.             k = (len < EB_FLDLEN) ? len : EB_FLDLEN;
  799.             zerorec(tbuff, EB_FLDLEN+1);
  800.             DbTextRead(eptr->txtfld[i+1], tbuff, k);
  801.             strncpy(&buff[tfoff+itmp], tbuff, k);
  802.             itmp += k;
  803.             len -= EB_FLDLEN;
  804.          }
  805.          continue;
  806.       }
  807.  
  808.       if (tftyp == CHRTYP)
  809.          dberrno = DbFetchLtd(fptr->fd_num, eptr->flddesc[i+1].fldid, tbuff, tflen);
  810.       else
  811.          dberrno = DbFetchNum(fptr->fd_num, eptr->flddesc[i+1].fldid, tbuff);
  812.  
  813.       if (dberrno < 0)
  814.          return io_xlate(fd_sys, dberrno, ercode);
  815.  
  816.       if (tftyp == FLTTYP)
  817.       {
  818.          bytecpy(&dtmp, tbuff, sizeof(double));
  819.          ftmp = (float)dtmp;
  820.          bytecpy(&buff[tfoff], &ftmp, sizeof(float));
  821.       }
  822.       else if ((tftyp == DATTYP) && (tflen == 6))
  823.       {
  824.          bytecpy(<mp, tbuff, sizeof(long));
  825.          julcal(ltmp, &dy, &mo, &yr);
  826.          sprintf(tbuff, "%02d%02d%02d", yr-1900, mo, dy);
  827.          bytecpy(&buff[tfoff], tbuff, tflen);
  828.       }
  829.       else if (tftyp == LOGTYP)   /* more fully implemented once "official" */
  830.       {
  831.          bytecpy(&itmp, tbuff, sizeof(int));
  832.          buff[tfoff] = itmp ? 'y' : 'n';
  833.       }
  834.       else
  835.          bytecpy(&buff[tfoff], tbuff, tflen);
  836.    }
  837.  
  838.    return(IOGOOD);
  839. }
  840.  
  841.  
  842. /*
  843.  *  Add a new record.
  844.  *  - DbClearRecord function ensures that the new record goes into a 
  845.  *    cleared buffer, before values are stored
  846.  *  (Not sure if DbFirst needs to be called before starting the add process.)
  847. */
  848. static int i_addrec(fd_sys, buffer)
  849. int fd_sys;
  850. char *buffer;
  851. {
  852.    struct fd_def *fptr = &fd[fd_sys];
  853.    struct emb_def *eptr = &efd[fd_sys];
  854.  
  855.    if ((dberrno = DbFirst(fptr->fd_num, eptr->fdkey[0].ix_num)) < -1)
  856.       return(io_xlate(fd_sys, dberrno, "EB ADD0"));
  857.  
  858.    if ((dberrno = DbClearRecord(fptr->fd_num)) < 0)
  859.       return(io_xlate(fd_sys, dberrno, "EB ADD1"));
  860.  
  861.    if (buff2eb(fd_sys, buffer) != IOGOOD)
  862.       return(IOERROR);
  863.  
  864.    if ((dberrno = DbAdd(fptr->fd_num)) < 0)
  865.       return(io_xlate(fd_sys, dberrno, "EB ADD2"));
  866.  
  867.    return(IOGOOD);
  868. }
  869.  
  870.  
  871. /*
  872.  *  Update the current record.
  873.  *  - DbUpdate function will not work with Personal Engine if files 
  874.  *    are opened in SHARE mode
  875. */
  876. static int i_updrec(fd_sys, buffer)
  877. int fd_sys;
  878. char *buffer;
  879. {
  880.    if (buff2eb(fd_sys, buffer) != IOGOOD)  
  881.       return(IOERROR);
  882.    
  883.    if ((dberrno = DbUpdate(fd[fd_sys].fd_num)) < 0)
  884.       return(io_xlate(fd_sys, dberrno, "EB UPD"));
  885.  
  886.    return(IOGOOD);
  887. }
  888.  
  889.  
  890. /*
  891.  *  Stores PRO-C buffer contents to Emerald Bay local buffer
  892.  *  - EB array index is one higher than PRO-C's because 1st field is recno
  893.  *  - EB buffers are not visible to programmer but defined internally only
  894. */
  895. static int buff2eb(fd_sys, buff)
  896. int fd_sys;
  897. char *buff;
  898. {
  899.    int tftyp, tfoff, tflen, i, itmp, k, len;
  900.    int dy, mo, yr;
  901.    long ltmp;
  902.    float ftmp;
  903.    double dtmp;
  904.    char tbuff[EB_FLDLEN+1], tstr[3];
  905.    struct fd_def *fptr = &fd[fd_sys];
  906.    struct emb_def *eptr = &efd[fd_sys];
  907.  
  908.    for (i = 0; i < fptr->fld_cnt; i++)
  909.    {
  910.       tftyp = fptr->flds[i].fldtype;
  911.       tfoff = fptr->flds[i].fldstart;
  912.       tflen = fptr->flds[i].fldlen;
  913.  
  914.       zerorec(tbuff, 100);
  915.  
  916.       switch(tftyp)
  917.       {
  918.          case DATTYP :
  919.             if (tflen == 6)              /* date stored as character string */
  920.                 {
  921.                strncpy(tbuff, &buff[tfoff], tflen);
  922.                 if (!tbuff[0])
  923.                      strcpy(tbuff, "000101");
  924.                 tstr[2] = '\0';
  925.                 strncpy(tstr, tbuff, 2);  yr = atoi(tstr) + 1900;
  926.                 strncpy(tstr, &tbuff[2], 2);  mo = atoi(tstr);
  927.                 strncpy(tstr, &tbuff[4], 2);  dy = atoi(tstr);
  928.                 ltmp = caljul(dy, mo, yr);
  929.                 dberrno = DbStoreNum(fptr->fd_num, eptr->flddesc[i+1].fldid, ltmp);
  930.                 break;
  931.                 }              /* else fall through to LNGTYP for long int date */
  932.          case LNGTYP :                                   /* don't move this */
  933.             bytecpy(<mp, &buff[tfoff], tflen);
  934.             dberrno = DbStoreNum(fptr->fd_num, eptr->flddesc[i+1].fldid, ltmp);
  935.             break;
  936.          case CHRTYP :
  937.             bytecpy(tbuff, &buff[tfoff], tflen);
  938.             tbuff[tflen] = '\0';
  939.             dberrno = DbStore(fptr->fd_num, eptr->flddesc[i+1].fldid, tbuff);
  940.             break;
  941.          case INTTYP :
  942.             bytecpy(&itmp, &buff[tfoff], tflen);
  943.             dberrno = DbStoreNum(fptr->fd_num, eptr->flddesc[i+1].fldid, itmp);
  944.             break;
  945.          case FLTTYP :
  946.             bytecpy(&ftmp, &buff[tfoff], tflen);
  947.             dtmp = (double)ftmp;
  948.             dberrno = DbStoreNum(fptr->fd_num, eptr->flddesc[i+1].fldid, dtmp);
  949.             break;
  950.          case DBLTYP :
  951.             bytecpy(&dtmp, &buff[tfoff], tflen);
  952.             dberrno = DbStoreNum(fptr->fd_num, eptr->flddesc[i+1].fldid, dtmp);
  953.             break;
  954.          case MEMTYP :
  955.             DbTextReset(eptr->txtfld[i+1]);
  956.             itmp = 0;
  957.             len = tflen;
  958.             while (itmp < tflen)
  959.             {
  960.                k = (len < EB_FLDLEN) ? len : EB_FLDLEN;
  961.                zerorec(tbuff, EB_FLDLEN+1);
  962.                strncpy(tbuff, &buff[tfoff+itmp], k);
  963.                DbTextWrite(eptr->txtfld[i+1], tbuff);
  964.                itmp += k;
  965.                len -= EB_FLDLEN;
  966.             }
  967.             break;
  968.          case LOGTYP :            /* more fully implemented once "official" */
  969.             itmp = (buff[tfoff] == 'y') ? 1 : 0;
  970.             dberrno = DbStoreNum(fptr->fd_num, eptr->flddesc[i+1].fldid, itmp);
  971.             break;
  972.       }
  973.       
  974.       if (dberrno < 0)
  975.          return io_xlate(fd_sys, dberrno, "BUFF2EB");
  976.    }
  977.    return(IOGOOD);
  978. }
  979.  
  980.  
  981. /*
  982.  *  Delete the current record.
  983.  *  - DbDel function will not work with Personal Engine if files are 
  984.  *    opened in SHARE mode (error code -600, user is locked out)
  985. */
  986. static int i_delrec(fd_sys, buffer)
  987. int fd_sys;
  988. char *buffer;
  989. {
  990.    if (i_lockrec(fd_sys, buffer) == IOGOOD)
  991.       if ((dberrno = DbDelete(fd[fd_sys].fd_num)) < 0)
  992.          return(io_xlate(fd_sys, dberrno, "EB DEL"));
  993.  
  994.    return(IOGOOD);       
  995. }
  996.  
  997.   
  998. /*
  999.  * Lock Record (handled automatically by Emerald Bay)
  1000.  * - Calls to DbLock requesting EXCLUSIVE use, when open mode for tables
  1001.      is set to SHARE, return an error code of -1
  1002. */
  1003. static int i_lockrec(fd_sys, buffer)
  1004. int fd_sys;
  1005. char *buffer;
  1006. {
  1007.    if (fd[fd_sys].lockmode != NOLOCK)
  1008.       if ((dberrno = DbLock(fd[fd_sys].fd_num, EXCLUSIVE)) < 0)
  1009.          return(io_xlate(fd_sys, dberrno, "EB LOCK"));
  1010.  
  1011.    return(IOGOOD);
  1012. }
  1013.  
  1014.  
  1015. /*
  1016.  *  Unlock Record
  1017.  *  - unlocks are handled automatically by Emerald Bay when transaction is
  1018.  *    finished
  1019.  *  - this explicit unlock requires that no transaction be active
  1020. */
  1021. static int i_unlock_rec(fd_sys, buffer)
  1022. int fd_sys;
  1023. char *buffer;
  1024. {
  1025. /*
  1026.  * DbUnlockTable is described in the manual but DOES NOT exist in
  1027.  * the M5EBL.LIB library!  (unresolved extern on link)
  1028.  *
  1029.    if (fd[fd_sys].lockmode != NOLOCK)
  1030.       if ((dberrno = DbUnlockTable(fd[fd_sys].fd_num)) < 0)
  1031.          return(io_xlate(fd_sys, dberrno, "EB UNLOCK"));
  1032. */   
  1033.    return(IOGOOD);
  1034. }
  1035.  
  1036. /*
  1037.  *  Login
  1038.  *  - Emerald Bay DbInit function serves as an initial log-in and checks
  1039.  *    if the TSR Emerald Bay engine has been started
  1040. */
  1041. static int i_login(fd_sys, buffer)
  1042. int fd_sys;
  1043. char *buffer;
  1044. {
  1045.    if (!*buffer || (buffer == NULL))
  1046.       strcpy(usrname, "OWNER");
  1047.    else
  1048.    {
  1049.       strncpy(usrname, buffer, 20);
  1050.       strncpy(pasword, &buffer[20], 20);
  1051.    }
  1052.  
  1053.    if ((dberrno = DbInit(usrname)) <= 0)    /* check for Emerald Bay engine */
  1054.    {
  1055.       if (!dberrno)
  1056.       {
  1057.          errmsg("EMERALD BAY DATABASE MANAGER ENGINE NOT STARTED");
  1058.          return(IOERROR);
  1059.       }
  1060.       return(io_xlate(fd_sys, dberrno, "EB LOGIN"));
  1061.    }
  1062.    return(IOGOOD);
  1063. }
  1064.  
  1065.  
  1066. /*
  1067.  *  Logoff
  1068. */
  1069. static int i_logoff(fd_sys, buffer)
  1070. int fd_sys;
  1071. char *buffer;
  1072. {
  1073.    return(IOGOOD);
  1074. }
  1075.  
  1076. /*
  1077.  *  End (Commit) transaction 
  1078. */
  1079. static int i_commit(fd_sys, buffer)
  1080. int fd_sys;
  1081. char *buffer;
  1082. {
  1083.    int stat;
  1084.  
  1085.    if (stat = DbCommitTransaction())
  1086.    {
  1087.       errmsg(FileTrnsCommit);
  1088.       return(io_xlate(fd_sys, stat, "EB ETRN"));
  1089.    }
  1090.  
  1091.    return(IOGOOD);
  1092. }
  1093.  
  1094. /*
  1095.  *  Rollback transaction
  1096. */
  1097. static int i_rollback(fd_sys, buffer)
  1098. int fd_sys;
  1099. char *buffer;
  1100. {
  1101.    int stat;
  1102.  
  1103.    if (stat = DbAbortTransaction())
  1104.    {
  1105.       errmsg(FileTrnsRlback);
  1106.       return(io_xlate(fd_sys, stat, "EB ATRN"));
  1107.    }
  1108.  
  1109.    return(IOGOOD);
  1110. }
  1111.  
  1112. /*
  1113.  *  Start transaction
  1114. */
  1115. static int i_transact(fd_sys, buffer)
  1116. int fd_sys;
  1117. char *buffer;
  1118. {
  1119.    int stat;
  1120.  
  1121.    if (stat = DbBeginTransaction())
  1122.    {
  1123.       errmsg(FileTrnsBegin);
  1124.       return(io_xlate(fd_sys, stat, "EB BTRN"));
  1125.    }
  1126.  
  1127.    return(IOGOOD);
  1128. }
  1129.  
  1130.  
  1131. /*
  1132.  *  This routine translates Emerald Bay Error codes into PRO-C error codes.
  1133.  *  If no PRO-C equivalent, displays the error number.
  1134. */
  1135. static int io_xlate(fd_sys, ernum, rtnname)
  1136. int fd_sys;
  1137. int ernum;
  1138. char *rtnname;
  1139. {
  1140.    switch(ernum)
  1141.    {
  1142.       case  DBOPEN    :
  1143.          return IOBADOPEN;
  1144.       case  DBNODB    :
  1145.          return IONOFILE;
  1146.       case  -1        :
  1147.          return IONOKEY;
  1148.       case  DBNDXDUP  :
  1149.          return IODUP;
  1150.       case  DBLOCKOUT :
  1151.          return IOLOCKED;
  1152.       case  DBNOXACT  :
  1153.       case  DBACTIVE  :
  1154.          return IONOTRANS;
  1155.    }
  1156.  
  1157.    if (fd_sys >= 0)
  1158.       errmsg(FileDbgError_sdss, "Emerald Bay", ernum, fd[fd_sys].filname, rtnname);
  1159.    else      /* if routines called from generated apps without valid fd_sys */
  1160.       errmsg(FileDbgError_sds, "Emerald Bay", ernum, rtnname);
  1161.    return(IOERROR);
  1162. }
  1163.  
  1164.  
  1165. /*
  1166.  * Assign section
  1167. */
  1168. void assign_IO_EB(dbnum)
  1169. int dbnum;
  1170. {
  1171.    Fntab[dbnum - 1][0]  = (int(*)())0; /* Empty */
  1172.    Fntab[dbnum - 1][1]  = i_init_file;
  1173.    Fntab[dbnum - 1][2]  = i_open_file;
  1174.    Fntab[dbnum - 1][3]  = i_close_file;
  1175.    Fntab[dbnum - 1][4]  = i_addrec;
  1176.    Fntab[dbnum - 1][5]  = i_delrec;
  1177.    Fntab[dbnum - 1][6]  = i_findkey;
  1178.    Fntab[dbnum - 1][7]  = i_firstkey;
  1179.    Fntab[dbnum - 1][8]  = i_lastkey;
  1180.    Fntab[dbnum - 1][9]  = i_lockrec;
  1181.    Fntab[dbnum - 1][10] = i_nextrec;
  1182.    Fntab[dbnum - 1][11] = i_prevrec;
  1183.    Fntab[dbnum - 1][12] = i_unlock_rec;
  1184.    Fntab[dbnum - 1][13] = i_updrec;
  1185.    Fntab[dbnum - 1][14] = i_commit;
  1186.    Fntab[dbnum - 1][15] = i_login;
  1187.    Fntab[dbnum - 1][16] = i_logoff;
  1188.    Fntab[dbnum - 1][17] = i_rollback;
  1189.    Fntab[dbnum - 1][18] = i_transact;
  1190.    Fntab[dbnum - 1][19] = i_selectinx;
  1191.    Fntab[dbnum - 1][20] = i_rereadrec;
  1192.    Fntab[dbnum - 1][21] = i_filename;
  1193. }
  1194.  
  1195.