home *** CD-ROM | disk | FTP | other *** search
- 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