home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
utils
/
asmutl
/
zsm23.lbr
/
XLIB.DZC
/
XLIB.DOC
Wrap
Text File
|
1991-08-28
|
19KB
|
357 lines
This library uses the same parameter passing mechanism as lib.l: see lib.doc
for a discussion of this.
_crypt: c2 = _crypt(c1);
_setcr: _setcr(str);
_crypt and _setcr implement an encryption system: _setcr initiates the system,
and repeated calls to _crypt encrypt or decrypt the data. The string passed
to _setcr may be considered a password, this string is used to initiate the
crypt system. Once this has been done, each character of plain text is passed
to _crypt, which returns the encrypted result. It should be noted that the
action performed by _crypt is self inverting, so in a typical application, a
file might be processed byte by byte through _crypt, after a password had been
passed to _setcr. This would generate an encrypted version of the file, which
could be restored by repeating the process. NOTE: No guarantees are given as
to the security of this system: you use it at your own risk. In practice the
encryption process should deter casual perusal, although if the NSA were to
set a Cray 2 on this they might be able to break it.
_rnd: i = _rnd(n);
This returns a random number from 0 to n - 1 (unsigned); This routine uses
an algorithm based on multiply overflow, rather than remainder on division,
so there is no weighting problem with repeated calls doing _rnd(40000)
_rand: i = _rand()
This returns a random 16 bit quantity.
_srand: _srand(a, b);
In _rnd & _rand, certain values are used to seed the random number
generator, and while they may be different from one program to the next,
for successive runs of a given program they will be the same, hence causing
_rand to return the same sequence of numbers. _srand provides a means to
reseed the R.N.G., this can be done in one of four ways:
1. _srand(0) prints a "canned" string, and waits for the user to hit return.
While it's waiting, a counter is kept running, and the resulting value is
used to reseed the R.N.G.
2. _srand(1, str) prints str, and waits for any character to be typed, again
running the counter. Hwever it does not "eat" the character typed in the same
way as _srand(0) will: typical use might be the signon message printed by an
interactive program, and as soon as the user responds, the R.N.G. is reseeded,
and the program can carry on.
3. _srand(2) this one starts by reading the refresh register, then does some
disk i/o, then gets a second value from the refresh register. It then uses
the two 8 bit values as one 16 bit value to reseed the R.N.G.
4. _srand(3, n) simply uses n directly to reseed the R.N.G. Note that n is
used in combination with the current seed, so repeated _srand(3, n)'s with
the same value of n will keep reseeding the R.N.G. to different states.
Any other value given as the first argument is used directly, the only
reason that _srand(3, n) is present is to allow n to be 0, 1, 2 or 3.
_setlin: _setlin(x1, y1, x2, y2)
_point: i = _point(xp, yp)
_setlin and _point are a pair of routines that operate a straight line drawing
algorithm. To set up, _setlin is called with the two endpoints of the line in
x,y coordinates: drawing starts at x1,y1 and goes to x2,y2. _point gets the
next point on the line: xp and yp are the addresses of two integer variables
into which the coordinates are placed. The return value i will be true (non-
zero) while the values put in xp and yp lie between x1,y1 and x2,y2, but after
the last point (x2,y2) has been returned, _point starts returning false (zero)
although it will continue to return coordinate pairs that extend the line.
_assert: _assert(test, fmt, a1, a2, a3, ...)
_assert is used to check a condition while a program is running: it inspects
it's first argument, if true then _assert simply returns. If the first
argument is false (zero) then the format and arguments are processed as in
_printf producing an error message, after which the program aborts: control
is passed back to CP/M.
_initp ok = _initp(array, size, width)
_perm ok = _perm()
These two handle generation of all possible permutations of a given data
array. _initp is called to set the system up: array is the address of the
data that will be permuted, size is the number of elements in the array,
and width is the width of each one. Note that size must be between 1 and 16
inclusive, and width must be between 1 and 255 inclusive. If the call is
successful, ok is zero, if there is an error (size or width out of range)
ok gets -1. _perm is called to generate the next permutation: it moves
the data around within the array passed to _initp, so this area of memory
must remain useable throughout the operation. If _initp has not been called
or returned an error (-1) then _perm will also return -1, and take no
other action. If _initp was successful, then _perm will return 1 until it
generates the last permutation (i.e. the data in array is returned to it's
original state), at which point it returns 0 to show that this is the final
permutation. However, successive calls to _perm will continue to cycle
through the same sequence of permutations, returning 1 again until the data
returns to it's original order etc. etc.
_printf,
_sprintf,
_fprintf,
_xprintf: The arguments passed to these are exactly as in the _printf
family in LIB.L: however more options are available in the formatting. In all
cases a '-' immediately following the '%' that introduces a format specifier
indicates that the information should be left justified rather than the
default right justification. In addition for strings ('%s') a second number
can be given by preceding it with a period ('.'): the effect of this is to
specify a maximum field width: so if %.10s was given, then at most ten
characters from the string would be printed, the remainder would be discarded.
This can be used in conjunction with a minimum field width: for example assume
%12.10s was given. In this case there would always be at least two blanks on
the left, because the output must be at least 12 characters wide, but only a
maximum of 10 can be printed from the string. In addition two other numeric
output formats are recognised. %r %R: these print in roman numerals for
values between 1 and 4999 - %r uses lower case, and %R uses upper case. Zero
is printed as '0' and values greater than 4999, which cannot be represented
using the standard ASCII character set, are replaced by a number of '*'
characters to signify the error. %a %A: these print in 'alphabetic' notation:
zero is again printed as '0', but 1 becomes 'a' or 'A' (%a generates lower
case, and %A generates upper case), 2 becomes 'b', 3 - 'c', ... 25 - 'y',
26 - 'z', 27 - 'aa', 28 - 'ab' and so on. As with all numeric outputs, %r, %R,
%a and %A recognise a minimum field width before the format specifier, and
the '-' to force left justification. Finally %z causes a 'recursive' _printf
to occur. The argument is taken as the address of an array of integer words
which is assumed to be the following: the first word is the address of a
format string, and the second and subsequent words are the values to be
processed by the format.
_scanf,
_sscanf,
_fscanf,
_xscanf: These four routines form a set of routines for doing formatted
input, in a similar manner to _printf et al. The parameters are similar:
_scanf takes a format as it's first argument, followed by a series of pointers
to locations where the scanned values are returned. _scanf reads from standard
input (the keyboard, unless redirected - for an explanation of redirection
read ARX.DOC). _sscanf takes an additional parameter before the format which
is the address of a string (zero byte terminated) from which the scanning
will be done. _fscanf has a similar first parameter, but in this case it is
a file pointer such as _fopen would return (see LIB.DOC for an explanation
of _fopen and file pointers). _xscanf takes the address of a procedure that
can be called to get successive characters: this procedure must observe the
standard protocol (can destroy de and a, value returned in hl, bc, ix, iy
must be preserved). The format string is similar to that of _printf: to start
a conversion a '%' character is given, followed by an optional assignment
suppression character: '*', followed by an optional maximum field width given
as a number, followed by a format specifier. Format specifiers are just like
in _printf: 'd' for a number, 'u' for an unsigned number, 'o' for an octal
number, 'x' for a hexadecimal number, 'b' for a binary number, 's' for a
string, and 'c' for a character. Other characters in the format string must
match the input, if a mismatch occurs then scanning stops. Note that since
'%' has special meaning in the format string, if a '%' in the input is to be
matched, then '%%' should be given in the format string. White space in the
format string matches optional white space in the input stream, so it is a
good idea to place a space after every conversion specifier in the format
string to cause the input field delimiters to be consumed. In the simplest
case _scanf will parse a sequence of fields separated by white space. As an
example, if the format were:
'%d %x %s'
then:
'42 a3e hello '
would be suitable input. The arguments that should follow the above format
are two pointers to integers: these will receive 42 and 0xa3e respectively,
and the address of a character buffer that will receive the string 'hello'
complete with a zero byte to terminate it. In this case scanf would return
3: it's return value is the number of successfully converted and assigned
fields. Note that conversions that are not assigned because of a '*' are not
included in the return count. Note however, if the format were:
'%d %2x %s'
then the two integers would get 42 and 0xa3 (two characters maximum), and the
string would receive 'e' (first byte following the 'a3'). Assignemt supression
causes a field to be scanned, but it is then thrown away: so no argument
should be pushed onto the stack to receive the scanned value. Note that if
'%05s' is given as the format specifier, then normal white space supression
is ignored: this simply transferrs the next five characters verbatim to the
string buffer provided. There is a final conversion specifier that behaves
somewhat like 's': it allows recognition of strings of arbitrary length, but
delimited by non white space characters. If the format specifier is '[' then
characters upto a matching ']' are taken as a set that defines what the string
must be composed of. In cases where a range of characters (e.g. ABCDEFGHI)
needs to be given A-I will suffice. Note also that characters are converted
until one is found that is not in the range given in []: if the reverse is
required, i.e. conversion of all characters not specified, then by providing
a '^' as the first character, the sense of testing is reversed. Since ']',
'^' and '-' have special meaning, they can be escaped by being preceded with
a '\' (which can also escape itself). Note however, these significant
characters should not be used as part of a range specifier: for example if
the range 'WXYZ[\]' were being scanned, it would be necessary to do it as
'W-[\\\]' where the 'W-[' gives the first five, the '\\' gives a '\', and the
'\]' gives the ']'. Note also, because of the way ZSM works, when assembling
a string that contains a backslash it must itself be escaped to ZSM, so the
above format in a ZSM source would appear as 'W-[\\\\\\]', because each '\\'
pair in the ZSM db string source gets converted to a single '\' in the
program. To give some working examples: if a CP/M directory name were to
be converted to a drive, a filename, and an extension the following might
be useable:
'%c:%8[A-Z0-9].%3s'
where the '%c' would match the drive specifier and assign it into an integer
pointer. The ':' matches, then the %8[A-Z0-9] would match an alphanumeric
only string with a maximum length of 8 characters, followed by a '.' and
another string of up to 3 characters. In this case however, a filename such
as A:-HELP.TXT would fail as the '-' would not match. This can be better done
by:
'%c:%8[^.].%3s'
where the %8[^.] matches anything that is not a '.'. Of course in this case
spaces would be considered valid characters, however by adding suitable
characters to the group in the [], this problem could be avoided. One last
word of warning: in all cases except 's' and '[' the parameter given must
be a pointer to an integer, so that the value can be properly saved, and
's' and '[' require the address of a buffer big enough to take the string.
In the case of scanning from a file (_fscanf) or from standard input (_scanf),
-1 is returned if the first thing encountered in the input is an end of file.
This is different from a zero which means that input was read, but could not
be matched at all.
_qsort _qsort(array, size, width, test)
_qsort is used to sort an array in memory. It takes four parameters: the
first is the address of the array to be sorted, the second is the number
of elements in the array, the third is the width in bytes of each element,
and the fourth is a routine that will be used to test if one element is
smaller, equal to, or greater than a second. test will be called with the
addresses of two elements from the array on the stack: as an example if
the array contained integers, then the parameters given to test would be
pointers to two of these integers, or if the array contained pointers to
strings, test would receive pointers to pointer to strings. test should
compare the two elements given to it and return a negative number if the
first was smaller, zero if they were equal, and a positive number if the
first was greater. Note that the first argument is given in terms of
the standard calling order: test(arg1, arg2) - so in fact the first argument
would be the one pushed immediately prior to the call to test: on the
stack on entry to test would be:
second arg
first arg
return address to _qsort
stack pointer --->
Note that test must adhere to the standard calling convention: i.e. it can
destroy de and a, it's result is returned in hl; and bc, ix and iy cannot
be damaged.
_search pointer = _search(array, size, width, test, match)
_search scans a sorted array looking for a specific element. The first
four parameters are exactly as in _qsort, however the array must already
be sorted (i.e. by a call to _qsort). match is a pointer to an entry like
those in the array (e.g. if the aray contained integers, match would be
a pointer to an integer). _search returns the address in the array of the
first element in the array greater than or equal to the match element, or
NULL if all elements are less than match.
_exec _exec(program)
_execl _execl(program, arg1, arg2, ... argn, 0)
These two provide the means to chain from one program to another: in both
cases the first parameter is the address of a string containing the name
of the program to chain to. Note that the '.COM' extension is added by
the routines. _exec simply invokes the program with no arguments, setting
the command tail buffer at 0x0080 empty, and the default fcbs at 0x005c
empty as well. _execl allows one or more arguments to be given to the
program: arg1, arg2, etc. are pointers to strings containing the arguments:
they are terminated by a NULL (zero) pointer. These are placed into the
buffer at 0x0080, in the same manner as CCP does, in addition the default
fcbs at 0x005c and 0x006c are initialised.
_alloc memory = _alloc(size)
_alloc provides a more flexible memory allocation system than _sbrk in LIB.L:
in particular it is possible to return a block of memory to the system for
further use. _alloc is the basic memory allocation routine: it takes a size
and returns a pointer to a block of memory that many bytes big. NOTE: _alloc
places certain internal accounting information in the area just outside
the block returned, so when using this memory do not access areas anywhere
outside it. Also note that unlike _sbrk, _alloc does not return contiguous
memory. If there is insufficient memory available to fulfill the request,
_alloc returns NULL (zero) to signify the error.
_realloc newmem = _realloc(memory, size)
_realloc allows a block of memory handed out by _alloc to have it's size
changed after the fact. The first parameter should be a pointer previously
returned by _alloc, and the second should be the new size. _realloc returns
a pointer to the new area, which may not the at the same address. Note
however that if the new pointer is different, than _realloc will copy as
much of the original data as makes sense (i.e. the smaller of the original
and new sizes)
_free _free(memory)
_free returns a block of memory previously given out by _alloc or _realloc
to the system, for subsequent re-use. Note that the data contained in the
memory is not affected, but it's validity cannot be guaranteed: _alloc or
_realloc may hand portions of it out at any subsequent time.
_xfree _xfree(memory, size)
_xfree allows a piece of memory NOT given out by _alloc or _realloc to be
added to the system for subsequent use. The first parameter is the address
of the memory being handed to the _alloc system, and size should be it's
size in bytes. This might be used to allow _alloc to use a large data table
that was used once for initialisation, but would then remain idle.
Caveat: The above four routines require that strict discipline be maintained
regarding their usage: if a program writes outside the bounds of a memory
area given to it, or _free is handed an arbitrary pointer, then this may
well lead to a program crash.
_alloca memory = _alloca(size)
_alloca is similar to _alloc, but it allocates memory in the stack frame
of the procedure that called it. It allocates the memory by adjusting
the stack pointer to create a block on the stack, and then returning a
pointer to it. It is the responsibility of the calling procedure to reset
the stack pointer: if #csv and #cret are in use, then the jump to #cret
will clean up automatically, otherwise some other means must be found
to reset the stack pointer. Note that any values pushed onto the stack
before a call to _alloca cannot be subsequently popped off: they live above
the block, and the stack pointer points to the bottom.
The following is a list of further external labels that are reserved - these
are used by the above routines, and their names should not clash with any
external labels in the program being linked.
#addcom #alcb #alcp #argfcb #doexec
#doprnt #doscan #getmem #seed #setfcb
#testdh