home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
database
/
trl14db.zip
/
TRLSRC.EXE
/
TRLIB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-22
|
17KB
|
799 lines
/*
* trlib.c
*
* by Alastair Dallas, Ralph Davis, Tom Rettig, and Leonard Zerman
*
* Placed in the public domain by Tom Rettig Associates, 10/22/1990.
*
* This program sets up the Dbase interface for TRLIB functions.
*
*/
#include "stdio.h"
#include "trlib.h"
#include "trdbase.h"
/*
* MINCONFIG is an example of how to configure trtable.h with
* a subset of the full Tom Rettig Library. Define MINCONFIG to
* load only four functions: CMONTHN, ISPRINTER, RJUST, and TRVERS.
*/
/* #define MINCONFIG 1 */
#include "trtable.h"
/*--------------------- external functions -------------------------*/
extern long atol(); /* Lattice ascii to long */
extern int doit(); /* execute tr.lib function */
extern int free(); /* Lattice level 3 memory deallocator */
extern char *getvec(); /* fetch INT vector */
extern char *malloc(); /* Lattice level 3 memory allocator */
extern int pv_int(); /* service trpass interrupt */
extern int rbrk(); /* Lattice level 1 memory release */
extern int setvec(); /* set INT vector */
extern int tr_int(); /* service trlib interrupt */
static char *oldvec1 = (char *)0;
static char *oldvec2 = (char *)0;
/*---------- parameter value array and index variable --------------*/
struct {
char *p;
char typ;
} pstk[14];
int pcount = 0;
/*------------ return value array and index variable ---------------*/
char *retv[4];
int retp = 0;
/*------------ Lattice environment control variables ---------------*/
/* Override pre-defined variables in Lattice library */
int _stack = 8192;
long _mneed = 4096; /* minimum heap size */
/*------------------------------ main ------------------------------*/
void main(argc, argv)
int argc;
char *argv[];
{
static char *database = "dBASE";
static char *prgfile = "TRLIB";
static char *helpmsg =
"\nUsage: TRLIB [-D<database software>] [-F] [-M<bytes>] [-P<program name>] [-S]\n";
char *p;
int silent = FALSE;
int floppy = FALSE;
/* scan command line */
while (--argc > 0)
if (*argv[argc] == '-')
switch(toupper(argv[argc][1]))
{
case 'D':
database = &argv[argc][2];
toup(database);
break;
case 'P':
prgfile = &argv[argc][2];
toup(prgfile);
break;
case 'M':
p = argv[argc];
while (*p)
{
if (isdigit(*p))
break;
p++;
}
_mneed += atol(p); /* new heap size */
break;
case 'S':
silent = TRUE;
break;
case 'F':
floppy = TRUE;
break;
default:
fputs(helpmsg,stderr);
_exit(1);
break;
} /* switch */
else
{
fputs(helpmsg,stderr);
_exit(1);
}
/* save old vectors, set new */
oldvec1 = getvec(TRINT);
oldvec2 = getvec(PVINT);
setvec(TRINT, &tr_int);
setvec(PVINT, &pv_int);
if (!silent)
{
fputs("\nTom Rettig's Library: ",stdout);
puts(DBLIBVERS);
puts("Dbase Edition: Advanced Programmer's Library");
puts("\nPlaced in the Public Domain by Tom Rettig Associates, 10/22/1990.");
}
/*
* Memory Allocation Note:
* When loaded, Lattice programs return all memory above the heap to DOS.
* The following call causes the heap to grow based on the contents of _mneed.
* dBASE will be loaded above the heap.
*/
if (rbrk() == ERRORNEGL) /* recalculate memory heap */
{
fputs("\n",stdout);
puts(_tr_errmsgs("main",E_HEAP));
goto error;
}
if (floppy)
{
fputs("\nRemove your ",stdout);
fputs(prgfile,stdout);
fputs(" diskette and place your ", stdout);
fputs(database,stdout);
puts(" diskette in the same drive.");
puts("Press any key to continue...");
getch();
}
if (!silent)
{
fputs("\nLoading ",stdout);
fputs(database,stdout);
puts(". Please wait...");
}
/* There is no way to disable the dBASE sign-on message */
if (forklp(database,"",prgfile,NULL))
{
fputs("\n",stdout);
fputs(_tr_errmsgs("main",E_EXEC),stdout);
puts(database);
goto error;
}
wait(); /* nop - may be useful for DOS 5.0 */
shutdown();
if (!silent)
puts("Tom Rettig's Library: Completion.");
_exit(0);
error:
shutdown();
_exit(1);
} /* main */
shutdown()
{
setvec(TRINT, oldvec1); /* restore old vectors */
setvec(PVINT, oldvec2);
return(0);
}
/*------------------- interrupt service functions ------------------*/
/*
* This function is called by the assembler routine
* TR_INT, which fields the interrupt call from dBASE III.
*/
callfunc(s)
char *s; /* String passed from dBASE III */
{
register int i,j;
static char vartype[3] = " U"; /* must have leading space */
toup(s); /* uppercase parameter */
if ( s[1] == NULLC ) /* one character assumed to be type */
{
vartype[1] = s[0]; /* add leading space to parameter */
s = vartype;
}
/* search the table for a match */
i = binary(s, tr_vectors, numvecs);
if (i < 0) /* No such function name */
{
strcpy(retv[RV_CHAR], _tr_errmsgs("callfunc", E_FUNC) );
setpcount(0);
return(ERRORNEG);
}
if ( i > 3 ) /* not passing data type */
{
if (pcount != tr_vectors[i].num_parms) /* Invalid number of params */
{
strcpy(retv[RV_CHAR], _tr_errmsgs("callfunc", E_PARAM) );
setpcount(0);
return(-2);
}
/* set undefined parameter type codes from table */
for (j=0; j<tr_vectors[i].num_parms; j++)
{
if (pstk[j].typ == UNDEF)
{
switch(tr_vectors[i].var_types[j])
{
case 'C':
pstk[j].typ = CHARACTER;
break;
case 'N':
pstk[j].typ = NUMERIC;
break;
case 'L':
pstk[j].typ = LOGICAL;
break;
case 'D':
pstk[j].typ = DATE;
break;
default:
pstk[j].typ = UNDEF;
break;
} /* switch */
} /* if undefined */
} /* for each parm type */
doit(tr_vectors[i].pfi); /* execute trlib function */
setpcount(0);
}
else
{
if (pcount > 0)
{
/* passing data type: only place that does not reset pcount */
switch(i)
{
case 0:
pstk[pcount-1].typ = CHARACTER;
break;
case 1:
pstk[pcount-1].typ = DATE;
break;
case 2:
pstk[pcount-1].typ = LOGICAL;
break;
case 3:
pstk[pcount-1].typ = NUMERIC;
break;
} /* switch */
} /* endif pcount > 0 */
} /* endif i > 3 */
return (0);
} /* callfunc */
int setpcount(cnt)
int cnt;
{
pcount = cnt;
return(0);
}
/*
* The following functions are called by the assembler routine
* PV_INT, which fields the interrupt calls from TRPASS.BIN and
* TRRET.BIN.
*/
void trpass(p)
char *p;
{
pstk[pcount].p = p; /* place parameter var address in table */
pstk[pcount++].typ = UNDEF; /* set type as undefined */
}
void trret(p)
char *p;
{
retv[retp++] = p; /* place return var address in table */
}
/*--------------------- parameter-passing functions ----------------*/
/*--------- compatible with Nantucket's Clipper Extend System --------*/
char *_parc(arg)
int arg;
{
if (arg > 0 && arg <= pcount)
return (pstk[arg-1].p);
return ((char *)0);
}
char *_pards(arg)
int arg;
/* All date types are passed as char type date strings;
* use DTOS.PRG to convert dates to date strings.
*/
{
if (arg > 0 && arg <= pcount)
return (pstk[arg-1].p);
return ((char *)0);
}
int _parinfo(arg)
int arg;
{
if (arg == 0) return (pcount);
if (arg <= pcount)
return ((int)pstk[arg-1].typ);
return (0);
}
int _parl(arg)
int arg;
{
if (arg > 0 && arg <= pcount)
return (*(int *)pstk[arg-1].p);
return (0);
}
double _parnd(arg)
int arg;
{
if (arg > 0 && arg <= pcount)
return (*(double *)pstk[arg-1].p);
return (0.0);
}
int _parni(arg)
int arg;
{
double d;
if (arg > 0 && arg <= pcount)
{
d = *(double *)pstk[arg-1].p;
return ((int)d);
}
return (0);
}
long _parnl(arg)
int arg;
{
double d;
if (arg > 0 && arg <= pcount)
{
d = *(double *)pstk[arg-1].p;
return ((long)d);
}
return (0L);
}
char *_parptr(arg)
int arg;
{
if (arg > 0 && arg <= pcount)
return (pstk[arg-1].p);
return ((char *)0);
}
/*----------------------- return value functions -------------------*/
/*--------- compatible with Nantucket's Clipper Extend System --------*/
int _ret()
{
return(0);
}
int _retc(ptr)
char *ptr;
{
if (retv[RV_CHAR] != (char *)0)
strncpy(retv[RV_CHAR], ptr, 254);
return(0);
}
int _retds(ptr)
char *ptr;
/* All date types are passed as char type date strings;
* use STOD.PRG to convert date string to date type.
*/
{
if (retv[RV_CHAR] != (char *)0)
strcpy(retv[RV_CHAR], ptr);
return(0);
}
int _retl(b)
int b;
{
if (retv[RV_LOGICAL] != (char *)0)
*(int *)retv[RV_LOGICAL] = b;
return(0);
}
int _retnd(d)
double d;
{
if (retv[RV_NUMBER] != (char *)0)
*(double *)retv[RV_NUMBER] = d;
return(0);
}
int _retni(i)
int i;
{
if (retv[RV_NUMBER] != (char *)0)
*(double *)retv[RV_NUMBER] = (double) i;
return(0);
}
int _retnl(l)
long l;
{
if (retv[RV_NUMBER] != (char *)0)
*(double *)retv[RV_NUMBER] = (double) l;
return(0);
}
/*--------------------------- memory functions -----------------------*/
/*--------- compatible with Nantucket's Clipper Extend System --------*/
char *_exmgrab(unsigned n)
{
return( malloc(n) );
}
int _exmback(char *c, unsigned n)
{
return( free(c) );
}
/*----------------------- library glue functions -------------------*/
/*
* These functions are required because a few trlib functions
* get their parameters from the stack (C calling convention),
* rather than by calling the appropriate _par? functions.
*
*/
int tr_cursor()
{
cursor(_parc(1));
return(0);
}
int tr_dosfunc()
{
dosfunc(_parc(1), _parptr(2));
return(0);
}
int tr_fileattr()
{
fileattr(_parc(1), _parc(2));
return(0);
}
int tr_memdump()
{
memdump(_parptr(1));
return(0);
}
int tr_offset()
{
char *off;
off = _tr_allocmem(5L);
if (off != (char *)0)
{
offset(_parptr(1), off);
off[4] = '\0';
_retc(off);
_tr_freemem(off);
}
else
_retc(_tr_errmsgs("offset",E_ALLOC));
return(0);
}
int tr_rombios()
{
double n;
n = _parnd(1);
/* wants pass by reference rather than value */
rombios(&n, _parc(2), _parptr(3));
return(0);
}
int tr_scroll()
{
double tr, tc, br, bc, sr;
tr = _parnd(1);
tc = _parnd(2);
br = _parnd(3);
bc = _parnd(4);
sr = _parnd(5);
/* wants pass by reference rather than value */
scroll(&tr, &tc, &br, &bc, &sr, _parc(6));
return(0);
}
int tr_segment()
{
char *seg;
seg = _tr_allocmem(5L);
if (seg != (char *)0)
{
segment(_parptr(1), seg);
seg[4] = '\0';
_retc(seg);
_tr_freemem(seg);
}
else
_retc(_tr_errmsgs("segment",E_ALLOC));
return(0);
}
/*----------------------- library overrides ---------------------*/
/*
* Memory allocation note.
*
* These functions use Lattice level 3 functions to allocate
* and free memory from the memory heap that was reserved
* in main when first booting this program.
*
*/
char *_tr_allocmem(n)
long n;
{
return( malloc(n) );
}
int _tr_freemem(c)
char *c;
{
return( free(c) );
}
int allocate()
{
extern char *_tr_hexasm();
char *address;
address = _tr_allocmem( _parnl(1) );
if (address)
_retc( _tr_hexasm( *(long *)&address ) );
else
_retc(NULLS);
return(0);
}
int dealloc()
{
extern long _tr_htol();
/* _tr_freemem() returns 0 for success -1 for error */
_retl( !(_tr_freemem( _tr_htol(_parc(1)) )) );
return(0);
}
int _tr_vers()
{
_retc( TRLIBVERS ) ; /* #defined in trlib.h */
return(0);
}
char *_tr_errmsgs( funcname, message )
char *funcname;
int message;
{
static char *errmsg[] =
{ "TRLIB ERROR: ", /* prefix to all other errors */
" SYNTAX",
" ALLOCATING MEMORY",
" OPENING FILE",
" SEEKING FILE POSITION",
" READING FILE",
" WRITING FILE",
" CLOSING FILE",
" ALLOCATING MEMORY HEAP",
" EXECUTING ", /* keep trailing space */
" FUNCTION NAME NOT FOUND",
" INVALID NUMBER OF PARAMETERS"
};
static char tempbuff[64] = " "; /* max error msg len is 63 including funcname */
char *tp;
tp = tempbuff;
tp = _tr_strcpy( tp, errmsg[E_PREFIX] );
tp = _tr_strcat( tp, funcname );
return( _tr_strcat(tp,errmsg[message]) );
}
/*---------------------------- Subroutines --------------------------*/
static int binary(word, tab, n)
char *word;
struct tr_dt tab[];
int n;
/* Binary search algorithm, Kernighan & Ritchie p.125 */
{
int low, high, cond, mid;
low = 0;
high = n - 1;
while (low <= high)
{
mid = low + high;
mid = (mid >> 1);
cond = strcmp(word, tab[mid].function);
if (cond < 0)
high = mid - 1;
else if (cond > 0)
low = mid + 1;
else
return(mid); /* found */
}
return(ERRORNEG); /* not found */
}
static int toup(s)
char *s;
/* toupper a string in place */
{
while (*s)
{
*s = toupper(*s);
s++;
}
return(0);
}
/* converts numeric to ascii, used by tomoney() */
void _ntoa(n, inmax, decmax, ostr)
double n;
int inmax; /* ignored */
int decmax;
char *ostr;
{
extern char *fcvt(double, int, int *, int *); /* Lattice function */
char *string;
int decx, sign;
int leadg, i;
string = fcvt(n, decmax, &decx, &sign);
i = 0;
leadg = 0;
if (sign)
ostr[i++] = '-';
if (decx < 0)
{
leadg = decx * -1;
ostr[i++] = '.';
}
while (leadg--)
ostr[i++] = '0'; /* leading zeros */
while (*string)
{
if (decx-- == 0)
ostr[i++] = '.';
ostr[i++] = *string++;
}
ostr[i] = '\0';
} /* _ntoa */
int retc()
/* used to write to tr_retc from dBASE so as not to alter tr_retc length */
{
_retc(_parc(1));
return(0);
}
int separate()
/* separate long address into hex segment and decimal offset */
{
char *s, ret[5];
int i;
s = _parc(1);
_retni( _tr_htoi(&s[4]) ); /* return offset in tr_retn */
for (i=0; i<4; i++)
ret[i] = *s++; /* put segment in return buffer */
ret[4] = NULLC; /* add null terminator */
_retc( ret ); /* return segment in tr_retc */
return(0);
}
/* eof */