c-isam - BASIC to C-ISAM interface


rem $include: í/usr/include/basic/isam.incí

call ibuild(isfd, filename$, recordlength, keydesc(), mode)
call iopen(isfd, filename$, mode)
call iclose(isfd)
call iaddindex(isfd, keydesc())
call idelindex(isfd, keydesc())
call istart(isfd, keydesc(), length, record$, mode)
call iread(isfd, record$, mode)
call iwrite(isfd, record$)
call irewrite(isfd, record$)
call iwrcurr(isfd, record$)
call irewcurr(isfd, record$)
call idelete(isfd, record$)
call idelcurr(isfd)
call iuniqueid(isfd, idhi, idlo)
call iindexinfo(isfd, buffer(), number)
call iaudit(isfd, filename$, mode)
call ierase(filename$)
call ilock(isfd)
call iunlock(isfd)
call irelease(isfd)
call irename(oldname$, newname$)
call ikeydesc(keydesc(), keyflags, keynparts
[, keypart.start, keypart.leng, keypart.type] . . .  )
call ildint(record$, offset, i%)
call istint(record$, offset, i%)
call ildflt(record$, offset, f!)
call istflt(record$, offset, f!)
call ilddbl(record$, offset, d#)
call istdbl(record$, offset, d#)


The include file and subprogram calls listed above constitute the interface from BASIC to the C-ISAM library.  C-ISAM is provided by, is documented by and is a trademark of Informix, Inc.  That documentation is sufficient and necessary for the use of C-ISAM and this interface, except as noted below and except that Basmark Corporation can not guarantee the appropriateness of C-ISAM.  Please refer to that documentation for further information and note the exceptions below. 

For convenience, the include file is provided so that symbolic names may be used instead of magic numbers.  This file is analogous to isam.h in C-ISAM. 

To load programs that use these subprogram calls, the interface file "isam.o" and the C-ISAM library must be specified on the command line, as demonstrated in the example below. 

Routine Names
The is prefix of the C-ISAM routine names is changed to i except that ldint, stint, ldfloat, stfloat, lddbl and stdbl become ildint, istint, ildflt, istflt, ilddbl and istdbl

Except where types are given explicitly, routine parameters are BASIC integers.  The type of every argument must be appropriate: the compiler cannot check argument types and mismatches are disasterous.  Ibuild and iopen have an extra, first argument where the routineís return value (the file descriptor) is stored. 

Key Description
The keydesc structure in C-ISAM is implemented as an array of integers: the first element of the array is the flags field, the second element is the nparts field.  The third, fourth and fifth elements are the start, length and type fields for the first key part.  The sixth, seventh and eighth elements are for the second key part, etc

To ease the production of key description arrays in BASIC, a special routine, ikeydesc has been implemented the arguments to which are an integer array of adequate length followed by a list of integers to be stored in the array (in order).  That is, the array, the flag field, the nparts field followed by "npart" triples of start, length and type fields. 

The iindexinfo routine may also return a structure, dictinfo, which is implemented as an array of seven integers: nkeys, record size, index record size fields followed by four values which represent the nrecords field, lowest order value first.  The four values comprise four base 256 digits.  The array must be of adequate length. 

A number of functions use record buffers.  These are implemented as BASIC strings of adequate length which are overwritten (when appropriate) by the C-ISAM function.  The easiest way to ensure that record$ has adequate length length is: "record$ = space$(length)."

Load and Store functions
The arguments to the load and store functions (ildint, etc.) are of the form: record string, offset and value.  The offset is an addition to the C-ISAM functions because computing offsets within strings in BASIC is very inefficient (compared with C).  The location within the record is offset bytes from the beginning of the record.  The value is either loaded or stored (from the point of view of the value) as appropriate. 

Unique ID
The unique ID function returns the long integer as two BASIC integers. 

If an error is detected by an C-ISAM routine, a BASIC run-time error is generated and the BASIC variable "err" is set to the value of the C-ISAM variable "iserrno."


Suppose we have a BASIC source file "bmake.b" that sorts <name, phone number> records from standard input:
	' $include: '/usr/include/basic/'
	defint a-z
	dim keydesc(10)
	on error goto recovery
	call ikeydesc(keydesc(), 0, 1, 0, 32, CHARTYPE)
	call ibuild(fd,"database",64,keydesc(),ISEXCLLOCK or ISINOUT)
	record$ = space$(64)
	name$ = space$(32)
	phone$ = space$(32)
	while 1
10		line input a$
		lset name$ = a$
		line input a$
		lset phone$ = a$
		call iwrite(fd, name$ + phone$)
	call iclose(fd)
	call iopen(fd, "database", ISEXCLLOCK or ISINOUT)
	call istart(fd, keydesc(), 0, record$, ISFIRST)
	while 1
20		call iread(fd, record$, ISNEXT)
		print record$
	call iclose(fd)
	call ierase("database")
	if erl = 10 then resume donewrite
	if erl = 20 then resume doneread
	print "Error #" err ", line " erl
	on error goto 0
The program can be compiled with a command of the form:
	$ basic -v -s -o bmake -C -K bmake.b isam.o /lib/libisam.a
The program could have as easily been coded in a C source file "cmake.c":
#include <stdio.h>
#include <isam.h>

	struct keydesc keydesc;
	int fd, i;
	char buf[100], name[100], phone[100], *gets();

	keydesc.k_flags = 0;
	keydesc.k_nparts = 1;
	keydesc.k_part[0].kp_start = 0;
	keydesc.k_part[0].kp_leng = 32;
	keydesc.k_part[0].kp_type = CHARTYPE;
	fd = isbuild("database", 64, &keydesc, ISEXCLLOCK|ISINOUT))
	if (fd == -1)
		fprintf(stderr, "Isbuild error\n"), exit(1);
	while (gets(name)) {
		if (!gets(phone))
			fprintf(stderr, "Gets error\n"), exit(1);
		for (i = 0; i < 64; i++)
			buf[i] = ' ';
		for (i = 0; i < 32 && name[i]; i++)
			buf[i] = name[i];
		for (i = 0; i < 32 && phone[i]; i++)
			buf[i + 32] = phone[i];
		if (iswrite(fd, buf))
			fprintf(stderr, "Iswrite error\n"), exit(1);
	if (isclose(fd))
		fprintf(stderr, "Isclose error\n"), exit(1);
	if ((fd = isopen("database", ISEXCLLOCK|ISINOUT)) == -1)
		fprintf(stderr, "Isopen error\n"), exit(1);
	if (isstart(fd, &keydesc, 0, 0, ISFIRST))
		fprintf(stderr, "Isstart error\n"), exit(1);
	while (!isread(fd, buf, ISNEXT))
		printf("%64.64s\n", buf);
	if (isclose(fd))
		fprintf(stderr, "Isclose error\n"), exit(1);
	if (iserase("database"))
		fprintf(stderr, "Iserase error\n"), exit(1);
This C program may be compiled with a command of the form:
$ cc -s -o cmake -O cmake.c /lib/libisam.a




Traditionally, the C environment is harsh compared to that of BASIC and this interface cannot attempt to provide protection.  Basmark Corporation has no way of knowing how C-ISAM will behave if misused and this interface has no way of checking on its own.  So be more careful than you would with ordinary BASIC programming and when you finish, be more impressed with yourself. 

from The Basmark QuickBASIC Programmerís Manual by Lawrence Leinweber