Interfaces
There are three language interfaces for the DATAdesign engine. You should
only read about those interfaces that you are going to use. However it may
sometimes be interesting to read about the other interfaces as well, as this
may give you some additional information (especilly for assembler programmers).
The source code
for the C interface is provided on disk, so that may also be interesting to
have a look at, and this for both C and Assembler programmers.
The commands are all treated together, explaining what they do, and giving the
specific details for each of the interfaces.
Actually, there isn't much which has to be mentioned before listing all the
commands. You just interface through the Sbasic commands. But you have to know
some details.
All routines which need a buffer- or indexid have an optional
parameter at the start. If you explicitly specify this buffer- or indexid,
then it has to be preceeded by a hash (#). This is similar to the passing
of channel ids to the i/o commands like print. If you don't pass a buffer-
or indexid, then the default bufferid and/or indexid will be used.
You also have to know how errors are dealt with. All of the routines will
only interupt the program in either of two occasions, that is if the DATAdesign
engine is not initialised, or when a bad parameter
is encountered. Parameters
can only be bad when the type of the parameter is completely wrong, or in the
case of a fieldid, when it is passed as the fieldname and no field with the
given name exists. Do note that fieldnames are case dependant.
In all other cases that errors are encountered, they will be
returned in a special variable called dd_err. Three important remarks
have to be made about this.
- This variable has to be spelled exactly like that, in lowercase.
- This variable has to be initialised, preferable before any
call to the DATAdesign engine, i.e. at the start of the program.
- The fact that this variable is set at each call to any of the
routines in the DATAdesign engine Sbasic interface is a
side-effect. So the line
PRINT dd_err, recordID
will print the error generated by the call to recordID and its
return value, and NOT the value dd_err had before the
line was executed.
The Sbasic interface allows for some parameters to be left out, or just
not specified, or to have several types. If there are default values for a
parameter, then the default will be mentioned after the name in square
brackets. If there is no default, but the parameter doesn't have to be
specified, then the type will be put in square brackets. The possible
parameter types are :
- bufferid
- always has to be a float. Can be left out (like with
channel id's). If not stated the default will be used.
- indexid
- always has to be a float. Can be left out (like with
channel id's). If not stated the default index of the default
buffer will be used. If the given id was actually a bufferid, then the
default index for that buffer will be used.
- field
- This parameter can be specified either as the fieldid,
or as the fieldname. Fieldnames are case relevant. An error will be
reported if the fieldname does not exist. The fieldid can be passed as
an integer or as a float. If no value is given for this field, then the
default will be used.
- compare
- This parameter can be passed either as an integer or float,
or as a string. When passed as a numerical value, you have to add the
values you want together. When passed as a string you just combine the
specific characters. So "-C" or 48 would give the same result : reverse
order and case dependant.
- string
- This parameter always has to be specified between quotes.
If no string is specified, than a NULL string (that is "", the
empty string) will be used.
- short
- This parameter can always be specified either as an integer
or as a float. If this parameter is not optional and is not specified,
then an error will be reported.
- long
- This parameter can only be passed as a float. If this parameter
is not optional and is not specified, then an error will be reported.
- char
- This parameter is always specified as a string. The first
character in the given string is the passed character.
- float
- This parameter has to be passed as a float, and will
internally be converted to an IEEE double.
- double
- This parameter is passed as a pointer to 8 bytes in memory
which should contain an IEEE double.
- pointer
- This is a parameter, passed in a float, which has to point
to a piece of memory which can be written into, i.e. a piece of memory
which was allocated with a call to ALCHP or RESPR
or similar.
- special
- There is also a parameter which can have any of the types
string, long, short, char, float. The actual type is then dependant
on some other part of the parameter parsing, or some internal structures
of the DATAdesign engine. Parsing these parameters will cause an error
when the wrong type is used (not in dd_err), so you should be carefull.
- pointer to special
- This parameter is passed as a pointer to 8 bytes
in memory which should contain either 8 characters (each in one
byte, value 0 used for filling when less than 8 chars used), a long (in
the first four bytes), a short (in the first 2 bytes), a char (also the
second byte, first byte 0), or an IEEE double (conversion of
a float to a double can be done with the SETfloat and
GETdouble commands on a field in an empty record) (all eight
bytes).
If a parameter is followed with updated, then the value of the parameter
will be changed according to the command. If the parameter is not passed as
a variable, and is not a pointer, then nothing is updated.
The entire DATAdesign engine is provided as an extension thing, and so you
can hardly discuss an assembler interface. All the actual interfacing can be
done with the standard thing system. If you want more information about this,
you should buy "QDOS Reference Manual", available from Jochen Merz (and
probably some others as well).
But we have also provided a few routines which are actually very similar to
the access routines for the Menu Extension (also from Jochen Merz;
also an extension thing). These routines are used to call and release
one specific extension at a time. It is however adviceable to keep one of the
extensions "in use" during the execution of your program, as this prevents
your buffer(s) from getting lost during execution of your program (this
can only happen if someone gets the stupid idea to either remove the
DATAdesign files job or DATAdesign.engine thing). You could use the
"INFO" extension for this. This is an empty extension, which only contains
some data which is used by the engine itself, and which is always the first
extension in the list. Never actually call this extension !
So here are the access routines:
Use DATAdesign engine DDE_USE
entry exit
d0 return
d2.l extension id
a1 address of thing extension
error return:
-thing not implemented
-engine not found
-any other error
Free DATAdesign engine DDE_FREE
no parameters, no return
Call DATAdesign engine extension jsr $18(a1)
entry exit
d0 return
a0 address of thing extension
a1 ptr to parameter list
The address of thing extension is the return value of the call to
DDE_USE and can also be placed in any other address register.
These routines can be found in the library file engine_lib.
Naturally, it is also possible to use the C-interface directly from assembler
if you prefer to do so.
The standard extension thing protocol is used.
- bufferid
- always passed in two long words. The second long word is
the actual bufferid. If the MS (most significant) word of
the first long word is zero, then the default buffer will be used, and
the second long word becomes irrelevant.
- indexid
- always passed in two long words. The second long word is
the indexid. If the MS word of the first long word is zero, then the
default index of the default buffer will be used, and the second long
word becomes irrelevant. If the given id was actually a bufferid, then
the default index for that buffer will be used.
The engine will automatically recognise whether the given parameter was
an indexid or a bufferid.
- field
- always passed as a long word. Only the LS word is important.
If the value -1 is passed then the default field will be used.
- string
- strings are always passed as two long words. There are two
possibilities. If you want to pass a standard QL string, then the MS
word of the first long word has to be $0100, and the second long word
is the pointer to the string. If you want to pass a
substring (just a series of chars),
then the MS word of the first long word has to be
$0200, and the LS word has to be the length. The second long
word contains the pointer to the substring.
- short
- this parameter is passed in a long word. The value is in the
LS word.
- long
- this parameter is passed in a long word.
- char
- this parameter is passed as the LS byte of a long word.
- double
- this parameter is passed as an 8 bytes IEEE double.
- return/update string
- the returned string can be either a QL string,
or a C string (null terminated). The C string is treated as return
substring. The parameter is passed as two long words. The second long
word is a pointer to the place where the string must be filled in. The
first long word contains the type in the MS word, $a100 for QL string,
$a200 for substring, and the maximum number of characters in the LS word.
- return/update xxx
- passed as two long words. The MS word of the first
long word is $a000, the second long word must be a pointer to the place
where the return value must be filled in, or where the value can be
read and written after processing. If the update parameter doesn't have
to be passed, and you don't want it updated, you should clear the
first long word.
- special
- there is also a parameter which can have any of the types
string, long, short, char, double. The actual type is then dependant
on some other part of the parameter parsing. It is passed in two long
words, and the value is left justified. Char is then considered as a
unsigned word. A string is max 8 chars, unused bytes must be zero.
- pointer to special
- this parameter is passed as a pointer to 8 bytes
in memory which should contain either 8 characters (each in one
byte, value 0 used for filling when less than 8 chars used), a long (in
the first four bytes), a short (in the first 2 bytes), a char (also the
second byte, first byte 0), or an IEEE double (all eight bytes). It is
passed as two long words, the pointer has to be in the second long word.
There isn't much which has to be said about the C interface except all the
commands. But before any of the commands can be called, you have to initialise
the DATAdesign variable which contains the address of the DATAdesign.engine
thing and which is used by all the other commands and macros. This can be done
with the DDinit() routine. This also makes sure that your job uses
the DATAdesign.engine thing. The thing can also be released with a call to
DDfree().
To be able to use the C interface in your C program files you have to include
the "DATAdesign.h" file.
You will also have to link the DATAdesign_lib
file with your own source code files.
All parameters are of a standard C data-type. There is however one exception.
Some routines require a pointer to a special 8 byte parameter. This parameter
can be considered as a union like this:
union special {
char string_par[8];
long long_par;
short short_par;
short char_par;
double double_par;
};
It may also be interesting to have a look at the special data type in
the Assembler interface, and at the source of the C interface.
Furthermore, bufferid and indexid parameters are passed as a long. If a zero
is passed, then the default buffer- or indexid will be used.
All C interface functions return the error which occurs during the execution
of the engine.
PROGS, Professional & Graphical Software
last edited September 6, 1996