home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / database / trl14db.zip / TRLSRC.EXE / TRLIB.C < prev    next >
C/C++ Source or Header  |  1990-10-22  |  17KB  |  799 lines

  1. /*
  2.  * trlib.c
  3.  *
  4.  * by Alastair Dallas, Ralph Davis, Tom Rettig, and Leonard Zerman
  5.  *
  6.  * Placed in the public domain by Tom Rettig Associates, 10/22/1990.
  7.  *
  8.  * This program sets up the Dbase interface for TRLIB functions.
  9.  *
  10.  */
  11.  
  12. #include "stdio.h"
  13. #include "trlib.h"
  14. #include "trdbase.h"
  15.  
  16. /*
  17.  * MINCONFIG is an example of how to configure trtable.h with
  18.  * a subset of the full Tom Rettig Library.  Define MINCONFIG to
  19.  * load only four functions: CMONTHN, ISPRINTER, RJUST, and TRVERS.
  20.  */
  21. /* #define MINCONFIG 1 */
  22.    
  23. #include "trtable.h"
  24.  
  25.  
  26. /*--------------------- external functions -------------------------*/
  27.  
  28. extern long atol();           /* Lattice ascii to long */
  29. extern int doit();            /* execute tr.lib function */
  30. extern int free();            /* Lattice level 3 memory deallocator */
  31. extern char *getvec();        /* fetch INT vector */
  32. extern char *malloc();        /* Lattice level 3 memory allocator */
  33. extern int pv_int();          /* service trpass interrupt */
  34. extern int rbrk();            /* Lattice level 1 memory release */
  35. extern int setvec();          /* set INT vector */
  36. extern int tr_int();          /* service trlib interrupt */
  37.  
  38. static char *oldvec1 = (char *)0;
  39. static char *oldvec2 = (char *)0;
  40.  
  41.  
  42. /*---------- parameter value array and index variable --------------*/
  43. struct {
  44.    char *p;
  45.    char typ;
  46.    } pstk[14];
  47. int pcount = 0;
  48.  
  49.  
  50. /*------------ return value array and index variable ---------------*/
  51. char *retv[4];
  52. int retp = 0;
  53.  
  54.  
  55. /*------------ Lattice environment control variables ---------------*/
  56. /* Override pre-defined variables in Lattice library */
  57. int  _stack = 8192;
  58. long _mneed = 4096;      /* minimum heap size */
  59.  
  60.  
  61. /*------------------------------ main ------------------------------*/
  62.  
  63. void main(argc, argv)
  64. int argc; 
  65. char *argv[];
  66. {
  67.    static char *database = "dBASE";
  68.    static char *prgfile  = "TRLIB";
  69.    static char *helpmsg  = 
  70. "\nUsage: TRLIB [-D<database software>] [-F] [-M<bytes>] [-P<program name>] [-S]\n";
  71.    char *p;
  72.    int silent = FALSE;
  73.    int floppy = FALSE;
  74.  
  75.    /* scan command line */
  76.    while (--argc > 0)
  77.       if (*argv[argc] == '-')
  78.          switch(toupper(argv[argc][1]))
  79.          {
  80.          case 'D':
  81.             database = &argv[argc][2];
  82.             toup(database);
  83.             break;
  84.  
  85.          case 'P':
  86.             prgfile = &argv[argc][2];
  87.             toup(prgfile);
  88.             break;
  89.  
  90.          case 'M':
  91.             p = argv[argc];
  92.             while (*p)
  93.                {
  94.                if (isdigit(*p))
  95.                   break;
  96.                p++;
  97.                }
  98.             _mneed += atol(p);       /* new heap size */
  99.             break;
  100.  
  101.          case 'S':
  102.             silent = TRUE;
  103.             break;
  104.  
  105.          case 'F':
  106.             floppy = TRUE;
  107.             break;
  108.  
  109.          default:
  110.             fputs(helpmsg,stderr);
  111.             _exit(1);
  112.             break;
  113.          }   /* switch */
  114.       else
  115.          {
  116.          fputs(helpmsg,stderr);
  117.          _exit(1);
  118.          }
  119.  
  120.    /* save old vectors, set new */
  121.    oldvec1 = getvec(TRINT);
  122.    oldvec2 = getvec(PVINT);
  123.    setvec(TRINT, &tr_int);
  124.    setvec(PVINT, &pv_int);
  125.    
  126.    if (!silent)
  127.       {
  128.       fputs("\nTom Rettig's Library: ",stdout);
  129.       puts(DBLIBVERS);
  130.       puts("Dbase Edition: Advanced Programmer's Library");
  131.       puts("\nPlaced in the Public Domain by Tom Rettig Associates, 10/22/1990.");
  132.       }
  133. /*
  134.  * Memory Allocation Note:
  135.  * When loaded, Lattice programs return all memory above the heap to DOS.
  136.  * The following call causes the heap to grow based on the contents of _mneed.
  137.  * dBASE will be loaded above the heap.
  138.  */
  139.    if (rbrk() == ERRORNEGL)      /* recalculate memory heap */
  140.       {
  141.       fputs("\n",stdout);
  142.       puts(_tr_errmsgs("main",E_HEAP));
  143.       goto error;
  144.       }
  145.  
  146.    if (floppy)
  147.      {
  148.      fputs("\nRemove your ",stdout);
  149.      fputs(prgfile,stdout);
  150.      fputs(" diskette and place your ", stdout);
  151.      fputs(database,stdout);
  152.      puts(" diskette in the same drive.");
  153.      puts("Press any key to continue...");
  154.      getch();
  155.      }
  156.  
  157.    if (!silent)
  158.       {
  159.       fputs("\nLoading ",stdout);
  160.       fputs(database,stdout);
  161.       puts(".  Please wait...");
  162.       }
  163.  
  164.    /* There is no way to disable the dBASE sign-on message */
  165.    if (forklp(database,"",prgfile,NULL))
  166.       {
  167.       fputs("\n",stdout);
  168.       fputs(_tr_errmsgs("main",E_EXEC),stdout);
  169.       puts(database);
  170.       goto error;
  171.       }
  172.    wait();      /* nop - may be useful for DOS 5.0 */
  173.    shutdown();
  174.    if (!silent)
  175.       puts("Tom Rettig's Library: Completion.");
  176.  
  177.    _exit(0);
  178.  
  179. error:
  180.    shutdown();
  181.    _exit(1);
  182.  
  183. }   /* main */
  184.  
  185.  
  186. shutdown()
  187. {
  188.    setvec(TRINT, oldvec1);     /* restore old vectors */
  189.    setvec(PVINT, oldvec2);
  190.    return(0);
  191. }
  192.  
  193.  
  194. /*------------------- interrupt service functions ------------------*/
  195.  
  196. /*
  197.  *   This function is called by the assembler routine
  198.  *   TR_INT, which fields the interrupt call from dBASE III.
  199.  */
  200.  
  201. callfunc(s)
  202. char *s;     /* String passed from dBASE III */
  203. {
  204.    register int i,j;
  205.    static char vartype[3] = " U";      /* must have leading space */
  206.  
  207.    toup(s);                                /* uppercase parameter */
  208.  
  209.    if ( s[1] == NULLC )       /* one character assumed to be type */
  210.       {
  211.       vartype[1] = s[0];        /* add leading space to parameter */
  212.       s = vartype;
  213.       }
  214.  
  215.    /* search the table for a match */
  216.    i = binary(s, tr_vectors, numvecs);
  217.    
  218.    if (i < 0)                            /* No such function name */
  219.       {
  220.       strcpy(retv[RV_CHAR], _tr_errmsgs("callfunc", E_FUNC) );
  221.       setpcount(0);
  222.       return(ERRORNEG); 
  223.       }
  224.  
  225.    if ( i > 3 )    /* not passing data type */
  226.       {
  227.       if (pcount != tr_vectors[i].num_parms) /* Invalid number of params */
  228.          {
  229.          strcpy(retv[RV_CHAR], _tr_errmsgs("callfunc", E_PARAM) );
  230.          setpcount(0);
  231.          return(-2);
  232.          }
  233.  
  234.       /* set undefined parameter type codes from table */
  235.       for (j=0; j<tr_vectors[i].num_parms; j++)
  236.          {
  237.          if (pstk[j].typ == UNDEF)
  238.             {
  239.             switch(tr_vectors[i].var_types[j])
  240.                {
  241.                case 'C':
  242.                   pstk[j].typ = CHARACTER;
  243.                   break;
  244.                case 'N':
  245.                   pstk[j].typ = NUMERIC;
  246.                   break;
  247.                case 'L':
  248.                   pstk[j].typ = LOGICAL;
  249.                   break;
  250.                case 'D':
  251.                   pstk[j].typ = DATE;
  252.                   break;
  253.                default:
  254.                   pstk[j].typ = UNDEF;
  255.                   break;
  256.                }   /* switch */
  257.             }   /* if undefined */
  258.          }   /* for each parm type */
  259.  
  260.       doit(tr_vectors[i].pfi);          /* execute trlib function */
  261.       setpcount(0);
  262.       }
  263.    else
  264.       {
  265.       if (pcount > 0)
  266.          {
  267.          /* passing data type: only place that does not reset pcount */
  268.          switch(i)
  269.             {
  270.             case 0:
  271.                pstk[pcount-1].typ = CHARACTER;
  272.                break;
  273.             case 1:
  274.                pstk[pcount-1].typ = DATE;
  275.                break;
  276.             case 2:
  277.                pstk[pcount-1].typ = LOGICAL;
  278.                break;
  279.             case 3:
  280.                pstk[pcount-1].typ = NUMERIC;
  281.                break;
  282.             }   /* switch */
  283.          }   /* endif pcount > 0 */
  284.       }   /* endif i > 3 */
  285.  
  286.    return (0);
  287. }  /* callfunc */
  288.  
  289.  
  290. int setpcount(cnt)
  291. int cnt;
  292. {
  293.    pcount = cnt;
  294.    return(0);
  295. }
  296.  
  297.  
  298. /*
  299.  *   The following functions are called by the assembler routine
  300.  *   PV_INT, which fields the interrupt calls from TRPASS.BIN and
  301.  *   TRRET.BIN.
  302.  */
  303.  
  304. void trpass(p)
  305. char *p;
  306. {
  307.    pstk[pcount].p = p;          /* place parameter var address in table */
  308.    pstk[pcount++].typ = UNDEF;  /* set type as undefined */
  309. }
  310.  
  311.  
  312. void trret(p)
  313. char *p;
  314. {
  315.    retv[retp++] = p;            /* place return var address in table */
  316. }
  317.  
  318.  
  319. /*--------------------- parameter-passing functions ----------------*/
  320. /*--------- compatible with Nantucket's Clipper Extend System --------*/
  321.  
  322. char *_parc(arg)
  323. int arg;
  324. {
  325.    if (arg > 0 && arg <= pcount)
  326.       return (pstk[arg-1].p);
  327.  
  328.    return ((char *)0);
  329. }
  330.  
  331.  
  332. char *_pards(arg)
  333. int arg;
  334. /* All date types are passed as char type date strings;
  335.  *    use DTOS.PRG to convert dates to date strings.
  336.  */ 
  337. {
  338.    if (arg > 0 && arg <= pcount)
  339.       return (pstk[arg-1].p);
  340.  
  341.    return ((char *)0);
  342. }
  343.  
  344.  
  345. int _parinfo(arg)
  346. int arg;
  347. {
  348.    if (arg == 0) return (pcount);
  349.  
  350.    if (arg <= pcount)
  351.       return ((int)pstk[arg-1].typ);
  352.    
  353.    return (0);
  354. }
  355.  
  356.  
  357. int _parl(arg)
  358. int arg;
  359. {
  360.    if (arg > 0 && arg <= pcount)
  361.       return (*(int *)pstk[arg-1].p);
  362.    
  363.    return (0);
  364. }
  365.  
  366.  
  367. double _parnd(arg)
  368. int arg;
  369. {
  370.    if (arg > 0 && arg <= pcount)
  371.       return (*(double *)pstk[arg-1].p);
  372.    
  373.    return (0.0);
  374. }
  375.  
  376.  
  377. int _parni(arg)
  378. int arg;
  379. {
  380.    double d;
  381.  
  382.    if (arg > 0 && arg <= pcount)
  383.       {
  384.       d = *(double *)pstk[arg-1].p;
  385.       return ((int)d);
  386.       }
  387.    
  388.    return (0);
  389. }
  390.  
  391.  
  392. long _parnl(arg)
  393. int arg;
  394. {
  395.    double d;
  396.  
  397.    if (arg > 0 && arg <= pcount)
  398.       {
  399.       d = *(double *)pstk[arg-1].p;
  400.       return ((long)d);
  401.       }
  402.    
  403.    return (0L);
  404. }
  405.  
  406.  
  407. char *_parptr(arg)
  408. int arg;
  409. {
  410.    if (arg > 0 && arg <= pcount)
  411.       return (pstk[arg-1].p);
  412.    
  413.    return ((char *)0);
  414. }
  415.  
  416.  
  417. /*----------------------- return value functions -------------------*/
  418. /*--------- compatible with Nantucket's Clipper Extend System --------*/
  419.  
  420.  
  421. int _ret()
  422. {
  423.    return(0);
  424. }
  425.  
  426.  
  427. int _retc(ptr)
  428. char *ptr;
  429. {
  430.    if (retv[RV_CHAR] != (char *)0)
  431.       strncpy(retv[RV_CHAR], ptr, 254);
  432.    return(0);
  433. }
  434.  
  435.  
  436. int _retds(ptr)
  437. char *ptr;
  438. /* All date types are passed as char type date strings;
  439.  *    use STOD.PRG to convert date string to date type.
  440.  */ 
  441. {
  442.    if (retv[RV_CHAR] != (char *)0)
  443.       strcpy(retv[RV_CHAR], ptr);
  444.    return(0);
  445. }
  446.  
  447.  
  448. int _retl(b)
  449. int b;
  450. {
  451.    if (retv[RV_LOGICAL] != (char *)0)
  452.       *(int *)retv[RV_LOGICAL] = b;
  453.    return(0);
  454. }
  455.  
  456.  
  457. int _retnd(d)
  458. double d;
  459. {
  460.    if (retv[RV_NUMBER] != (char *)0)
  461.       *(double *)retv[RV_NUMBER] = d;
  462.    return(0);
  463. }
  464.  
  465.  
  466. int _retni(i)
  467. int i;
  468. {
  469.    if (retv[RV_NUMBER] != (char *)0)
  470.       *(double *)retv[RV_NUMBER] = (double) i;
  471.    return(0);
  472. }
  473.  
  474.  
  475. int _retnl(l)
  476. long l;
  477. {
  478.    if (retv[RV_NUMBER] != (char *)0)
  479.       *(double *)retv[RV_NUMBER] = (double) l;
  480.    return(0);
  481. }
  482.  
  483.  
  484. /*--------------------------- memory functions -----------------------*/
  485. /*--------- compatible with Nantucket's Clipper Extend System --------*/
  486.  
  487.  
  488. char *_exmgrab(unsigned n)
  489. {
  490.    return( malloc(n) );
  491. }
  492.  
  493.  
  494. int _exmback(char *c, unsigned n)
  495. {
  496.    return( free(c) );
  497. }
  498.  
  499.  
  500.  
  501. /*----------------------- library glue functions -------------------*/
  502.  
  503. /*
  504.  * These functions are required because a few trlib functions
  505.  * get their parameters from the stack (C calling convention),
  506.  * rather than by calling the appropriate _par? functions.
  507.  *
  508.  */
  509.  
  510. int tr_cursor()
  511. {
  512.    cursor(_parc(1));
  513.    return(0);
  514. }
  515.  
  516.  
  517. int tr_dosfunc()
  518. {
  519.    dosfunc(_parc(1), _parptr(2));
  520.    return(0);
  521. }
  522.  
  523.  
  524. int tr_fileattr()
  525. {
  526.    fileattr(_parc(1), _parc(2));
  527.    return(0);
  528. }
  529.  
  530.  
  531. int tr_memdump()
  532. {
  533.    memdump(_parptr(1));
  534.    return(0);
  535. }
  536.  
  537.  
  538. int tr_offset()
  539. {
  540.    char *off;
  541.  
  542.    off = _tr_allocmem(5L);
  543.    if (off != (char *)0)
  544.       {
  545.       offset(_parptr(1), off);
  546.       off[4] = '\0';
  547.       _retc(off);
  548.       _tr_freemem(off);
  549.       }
  550.    else
  551.       _retc(_tr_errmsgs("offset",E_ALLOC));
  552.  
  553.    return(0);
  554. }
  555.  
  556.  
  557. int tr_rombios()
  558. {
  559.    double n;
  560.    n = _parnd(1);
  561.  
  562.    /* wants pass by reference rather than value */
  563.    rombios(&n, _parc(2), _parptr(3));
  564.  
  565.    return(0);
  566. }
  567.  
  568.  
  569. int tr_scroll()
  570. {
  571.    double tr, tc, br, bc, sr;
  572.  
  573.    tr = _parnd(1);
  574.    tc = _parnd(2);
  575.    br = _parnd(3);
  576.    bc = _parnd(4);
  577.    sr = _parnd(5);
  578.  
  579.    /* wants pass by reference rather than value */
  580.    scroll(&tr, &tc, &br, &bc, &sr, _parc(6));
  581.  
  582.    return(0);
  583. }
  584.  
  585.  
  586. int tr_segment()
  587. {
  588.    char *seg;
  589.  
  590.    seg = _tr_allocmem(5L);
  591.    if (seg != (char *)0)
  592.       {
  593.       segment(_parptr(1), seg);
  594.       seg[4] = '\0';
  595.       _retc(seg);
  596.       _tr_freemem(seg);
  597.       }
  598.    else
  599.       _retc(_tr_errmsgs("segment",E_ALLOC));
  600.  
  601.    return(0);
  602. }
  603.  
  604.  
  605. /*----------------------- library overrides ---------------------*/
  606.  
  607. /*
  608.  * Memory allocation note.
  609.  * 
  610.  * These functions use Lattice level 3 functions to allocate
  611.  * and free memory from the memory heap that was reserved 
  612.  * in main when first booting this program.
  613.  *
  614.  */
  615.  
  616.  
  617. char *_tr_allocmem(n)
  618. long n;
  619. {
  620.    return( malloc(n) );
  621. }
  622.  
  623.  
  624. int _tr_freemem(c)
  625. char *c;
  626. {
  627.    return( free(c) );
  628. }
  629.  
  630.  
  631. int allocate()
  632. {
  633.    extern char *_tr_hexasm();
  634.    char *address;
  635.  
  636.    address = _tr_allocmem( _parnl(1) );
  637.  
  638.    if (address)
  639.       _retc( _tr_hexasm( *(long *)&address ) );
  640.    else
  641.       _retc(NULLS);
  642.  
  643.    return(0);
  644. }
  645.  
  646.  
  647. int dealloc()
  648. {
  649.    extern long _tr_htol();
  650.  
  651.    /* _tr_freemem() returns 0 for success -1 for error */
  652.    _retl( !(_tr_freemem( _tr_htol(_parc(1)) )) );
  653.  
  654.    return(0);
  655. }
  656.  
  657.  
  658. int _tr_vers()
  659. {
  660.    _retc( TRLIBVERS ) ;         /* #defined in trlib.h */
  661.    return(0);
  662. }
  663.  
  664.  
  665. char *_tr_errmsgs( funcname, message )
  666. char *funcname;
  667. int message;
  668. {
  669.    static char *errmsg[] =
  670.                  { "TRLIB ERROR: ",     /* prefix to all other errors */
  671.                    " SYNTAX",
  672.                    " ALLOCATING MEMORY",
  673.                    " OPENING FILE",
  674.                    " SEEKING FILE POSITION",
  675.                    " READING FILE",
  676.                    " WRITING FILE",
  677.                    " CLOSING FILE",
  678.                    " ALLOCATING MEMORY HEAP",
  679.                    " EXECUTING ",             /* keep trailing space */
  680.                    " FUNCTION NAME NOT FOUND",
  681.                    " INVALID NUMBER OF PARAMETERS"
  682.                  };
  683.    static char tempbuff[64] = " "; /* max error msg len is 63 including funcname */
  684.    char *tp;
  685.  
  686.    tp = tempbuff;
  687.    tp = _tr_strcpy( tp, errmsg[E_PREFIX] );
  688.    tp = _tr_strcat( tp, funcname );
  689.    return( _tr_strcat(tp,errmsg[message]) );
  690. }
  691.  
  692.  
  693.  
  694. /*---------------------------- Subroutines --------------------------*/
  695.  
  696.  
  697. static int binary(word, tab, n)
  698. char *word;
  699. struct tr_dt tab[];
  700. int n;
  701. /* Binary search algorithm, Kernighan & Ritchie p.125 */
  702. {
  703.    int low, high, cond, mid;
  704.  
  705.    low = 0;
  706.    high = n - 1;
  707.    while (low <= high)
  708.       {
  709.       mid = low + high;
  710.       mid = (mid >> 1);
  711.       cond = strcmp(word, tab[mid].function);
  712.       if (cond < 0)
  713.          high = mid - 1;
  714.       else if (cond > 0)
  715.          low = mid + 1;
  716.       else
  717.          return(mid);     /* found */
  718.       }
  719.    return(ERRORNEG);      /* not found */
  720. }
  721.  
  722.  
  723. static int toup(s)
  724. char *s;
  725. /* toupper a string in place */
  726. {
  727.    while (*s)
  728.       {
  729.       *s = toupper(*s);
  730.       s++;
  731.       }
  732.    return(0);
  733. }
  734.  
  735.  
  736. /* converts numeric to ascii, used by tomoney() */
  737. void _ntoa(n, inmax, decmax, ostr)
  738. double n;
  739. int inmax;    /* ignored */
  740. int decmax;
  741. char *ostr;
  742. {
  743.    extern char *fcvt(double, int, int *, int *);  /* Lattice function */
  744.    char *string;
  745.    int decx, sign;
  746.    int leadg, i;
  747.  
  748.    string = fcvt(n, decmax, &decx, &sign);
  749.  
  750.    i = 0;
  751.    leadg = 0;
  752.    if (sign)
  753.       ostr[i++] = '-';
  754.    if (decx < 0)
  755.       {
  756.       leadg = decx * -1;
  757.       ostr[i++] = '.';
  758.       }
  759.  
  760.    while (leadg--)
  761.       ostr[i++] = '0';        /* leading zeros */
  762.  
  763.    while (*string)
  764.       {
  765.       if (decx-- == 0)
  766.          ostr[i++] = '.';
  767.       ostr[i++] = *string++;
  768.       }
  769.  
  770.    ostr[i] = '\0';
  771. }     /* _ntoa */
  772.  
  773.  
  774. int retc()
  775. /* used to write to tr_retc from dBASE so as not to alter tr_retc length */
  776. {
  777.    _retc(_parc(1));
  778.    return(0);
  779. }
  780.  
  781. int separate()
  782. /* separate long address into hex segment and decimal offset */
  783. {
  784.    char *s, ret[5];
  785.    int i;
  786.  
  787.    s = _parc(1);
  788.    _retni( _tr_htoi(&s[4]) );   /* return offset in tr_retn */
  789.  
  790.    for (i=0; i<4; i++)
  791.       ret[i] = *s++;            /* put segment in return buffer */
  792.    ret[4] = NULLC;              /* add null terminator */
  793.    _retc( ret );                /* return segment in tr_retc */
  794.  
  795.    return(0);
  796. }
  797.  
  798. /* eof */
  799.