Metropoli BBS
VIEWER: rpl48.doc MODE: TEXT (CP437)
                          Magic48ges presents:


                     █████  █████  █       █   ███
                      █   █  █   █ █      ██  █   █
                      █   █  █   █ █     █ █  █   █
                      ████   ████  █    █  █   ███
                      █ █    █     █    █████ █   █
                      █  █   █     █       █  █   █
                      █   █  █     ████    █   ███



             A SYSTEM-RPL DEVELOPMENT TOOLKIT FOR THE HP48


                              Version 2.02


       (c) 1993 by Detlef Mueller & Raymond Hellstern, Magic48ges


CONTENTS
════════


1. Introduction
    1.1 Copyrights & Acknowledgements
    1.2 The RPL48 Toolkit
    1.3 Requirements & Installation Instructions
    1.4 Abbreviations

2. <-RPL-> Library
    2.1	Overview
    2.2	The System-RPL Compiler/Decompiler
    2.3	The Saturn Assembler/Disassembler
	2.3.1 The Assembler Parameter Field Parser
    2.4	The Reference Table
    2.5	Command Reference
    2.6	Hooks
    2.7	Things to Notice

3. <-LIB-> Library
    3.1 Overview
    3.2 Control Variables
    3.3 Command Reference
    3.4 Things to Notice

Appendix A - Quick Reference Guides
    A.1 <-RPL->
	A.1.1 Commands
	A.1.2 Flag Usage
	A.1.3 Error Messages
    A.2 <-LIB->
	A.2.1 Commands
	A.2.2 Flag Usage
	A.2.3 Error Messages

Appendix B - A ->COD Example

Appendix C - Ordering Information


1. Introduction
═══════════════


1.1 Copyrights & Acknowledgements
─────────────────────────────────

All files of the RPL48 toolkit are copyrighted (c) by Detlef Mueller and
Raymond Hellstern - Magic48ges, 1991-1993 - unless otherwise noted.

The RPL48 package is distributed in the hope that it will be useful, but
RPL48 is provided 'as is,' and is subject to change without notice.
D. Mueller and R. Hellstern make no warranty of any kind with regard to
the software or documentation, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose.
D. Mueller and R.Hellstern shall not be liable for any error or for
incidental or consequential damages in connection with the furnishing,
performance, or use of this software and documentation.

This version of RPL48 is a GiftWare release. You may use it as long as you
like without registration, but only for developing non-commercial software.

Permission to copy the whole, unmodified RPL48 package is granted provided
that the copies are not made or distributed for resale (excepting nominal
copying fees). If you want to get your own, brand new version, and for further
information, please refer to Appendix C.

It should be impossible to crash your '48 by using RPL48, but be warned:
no software is bug free !

We would like to thank the following people for their support:

  Wlodek Mier-Jedrzejowicz	for presenting RPL48 to the world.
  Rick Grevelle			for the HACKIT library, the ->DIR command of
                                <-LIB->, the base of the sys-stack, many
                                suggestions, exiting talks and for sending
                                us an HP48GX.
  Mika Heiskanen		for beta testing, lots of suggestions, MKROM,
                                DEBUG, and for a great performance enhancement
                                of the D->LIB and L->DIR commands.
  Douglas R. Cannon		for beta testing, lots of suggestions, and
  				for reviewing this document.
  Joseph K. Horn		for beta testing and suggestions, the `HP 48
                                Resource Allocation Guideline; Library ID's`,
                                SORTLS and for maintaining the '48 GDs.
  Carlos Ferraro		for beta testing and his friendship.
  Simone Rapisarda		for beta testing and many suggestions.
  Fatri Mohamed,
  Romain Desplats,
  Georg Hoppen			for suggestions and beta testing.
  James H. Cloos,
  Steve VanDevender,
  Chris Maksymiak		for suggestions.
  Jeoff Krontz,			for suggestions, beta testing, getting another
  				GX for Raymond, exiting talks, and..
  Chris Spell			..for maintaining the '48 archive at
                                seq.uncwil.edu and for moderating
                                comp.sources.hp48.
  Dennis York			for the kindly permission to publish the BNF
                                parser generator example.
  W.C.Wickes & HP Corvallis	for the '48 and the RPL tools.


1.2 The RPL48 Toolkit
─────────────────────

The RPL48 Toolkit provides more than 50 powerful commands to aid system RPL
and assembler programming and library development on a HP48. It consists of
three parts:

	* library 1234, <-RPL->:5.00 - contains a sys-RPL compiler/decompiler
	  and Saturn assembler/disassembler.

	* library 1221, <-LIB->:2.0 - contains a library creator/splitter and
	  many commands for handling libraries and un-/supported objects.

	* a reference table which contains address/name pairs of ROM entry
	  points.

The main commands of RPL48 are modeled after the MesS-DOS programs RPLCOMP.
EXE, SASM.EXE and USRLIB.EXE which are provided by HP in the self extracting
archive TOOLS.EXE (available on several ftp sites and GD#4). This document
describes the interface to RPL48; it is not a sys-RPL or Saturn assembler
manual. Please refer to RPLMAN.DOC, RPLCOMP.DOC, USRLIB.DOC and SASM.DOC
(all contained in TOOLS.EXE) for learning and/or reference purposes.

We assume that you are familar with the fundamentals of sys-RPL, Saturn
assembly and libraries.


1.3 Requirements & Installation Instructions
────────────────────────────────────────────

RPL48 should work on ROM versions A-M HP48 - it's tested on rev A, E, L, M
machines by the authors, and it's reported to run also on rev D and J.

The <-RPL-> library is compiled to a fixed address; it MUST be stored in an
independent (FREEd) port (ie. it only works on a SX or GX), on a SX this can
be either port 1 or 2, on a GX this must be port 1 !

Because the whole RPL48 kit requires ~60kb of memory (including a reference
table made from the latest entries released by HP) it is recommended to store
it into a 128k RAM card. The <-LIB-> library was developed using the standard
methods, it can be stored and used in port 0 on any HP48; on a GX it's
limited to the ports 0 and 1, and must not be installed in the ports 2-33.

For a complete installation of RPL48 it is neccessary that you have plugged
in a 128k RAM card (which must have ~60kb free space) in either port 1 or 2
of your SX, port 1 of your GX; the card must be set to R/W. Proceed as
follows:

    a) remove all files of an earlier version

    b) merge the port

    c) set up RPL.TAB on your computer by renaming one of the two shipped
       reference tables or by creating an own one (see section '2.4 The
       Reference Table')

    d) download RPL.TAB, LIB.LIB and RPL.LIB

    e) recall RPL.TAB to the stack, purge RPL.TAB and store it as a backup
       object named RPL.TAB (case sensitive !) into port 0 (:0:RPL.TAB STO)

    f) recall the two libraries, purge the variables containing the original
       copies and store the libraries into port 0 (two times 0 STO)

    g) free the port, make sure that :0:1234 is the 1st entry of the list
       in level 2 for the FREE command ! (you can use 0 PVARS DROP to
       generate the base list)

    h) warmstart the '48 (power cycle it, or press [ON]-[C])

As mentioned, <-RPL-> is compiled to an absolute address. Its config code
takes care of the address the library is stored at. On an SX, if neccessary,
the base addresses of the ports are swapped and an additional warmstart
is initiated automatically while executing the first warmstart after
installation. If the config code recognizes that it is impossible to change
to the correct address (ie. the library is stored in port 0, not the 1st
object of port 1 or 2 on a SX, or not the 1st object of port 1 on a GX), the
autoattach to the home directory is supressed and no (c)-message and no beeps
are generated. If the library did not attach itself, make sure it becomes the
1st object of the desired port and execute a warmstart again.

If you have installed an HP41 emulator card, <-RPL-> does not install because
the emulator uses a similar sheme to install itself to the same address (it
is also an absolute library) -- just remove the card.

The <-RPL-> and the <-LIB-> libraries are not self-modifing - you can write
protect the card containing the libraries.


1.4 Abbreviations
─────────────────

LID   - library id; a number in the range 0..2047, part of any library, It
	is used by the HP firmware to identify libraries while resolving
	commands, messages etc.
|     - used in stack diagrams for 'or'

Abbreviations denoting objects:

ob	object of any type
xlib	named or unnamed library command
:x:y	tagged object - tag x, ob y
prg	program (secondary)
bak	backup
dir	directory
alg	algebraic
lib	library
libdta	library data
meta(t)	meta object, obn .. ob1 %n, all ob's are of the same type t

All other abbreviations are defined in RPLMAN.DOC (like %, # etc.).


2. <-RPL-> Library
══════════════════


2.1 Overview
────────────

<-RPL-> contains 17 commands, including a sys-RPL compiler (->RPL), a sys-RPL
decompiler (RPL->), a Saturn assembler (->COD), a Saturn disassembler (COD->)
a RPL.TAB browser (EC) and a medium font sys-stack environment (4/5/7).


2.2 The System-RPL Compiler/Decompiler
──────────────────────────────────────

The compiler is a simple token based one pass LR compiler and implements a
grammatical subset of RPLCOMP.EXE. It accepts string objects containing a
token sequence, seperated by whitespace (NL,CR,Space,TAB etc.), as input.

The output of the decompiler can be used as input for the compiler or (with
minor modifications) as input for RPLCOMP.EXE.

While ->RPL is compiling a string, it recognizes certain words and generates
appropriate code for them. All other words are assumed to be the labels of
objects in the runstream and are emitted simply as 5-nibble constants - the
reference table (see below) and the assembler symbol table are searched to
resolve the appropriate 5-nibble addresses. If an entry can't be found in one
of the tables and its 1st chararcter is a 'x', then ->RPL will try to resolve
the word without the leading 'x' as a built-in word (e.g. for 'xDROP' the
address #1FBD8 would be generated).

If the currently processed token isn't resolvable by ->RPL as an object,
entry, or built-in word, it is passed to the user-RPL compiler, palparse.
If the result is an ID or prg, an error will be generated. If the token is
parsed to a %, it will be converted to a # (eg. "12345" ->RPL --> <3039h>
(negative values are mapped to 0 and fractional parts are ignored)); any
other valid object is simply added to the runstream (eg. [[1,2][3,4]] (F(.))
inserts a 2*2 array of %).

The following words are recognized by ->RPL or generated by RPL->:

LAM <id>                                (1)
    DOLAM object whose name is specified by <id>.

ID <id>                                 (1)
    DOIDNT object whose name is specified by <id>. 0-IDs aren't supported by
    ->RPL.

TAG <id> <ob>
    DOTAG object whose tag is specified by <id> and whose object is given
    by <ob>.

$ "string"                              (1)
    DOCSTR object with the contents contained between the quotes.

CHR <char>                              (1)
    DOCHAR object with the specified character.

# <hex>					(3)
#<hex>					(3)
    DOBINT object whose body is the number specified in hex.

% <real>
    DOREAL object with the specified floating-point number.

%% <extended real>
    DOEREL object with the specified floating-point number. The number is
    parsed with % resolution.

C% <real> <real>
    DOCMP object with the specified floating-point numbers.

C%% <extended real> <extended real>
    DOECMP object with the specified floating-point numbers. The numbers are
    parsed with % resolution.

PTR <address in hex>			(2,5)
    Inserts the specified address as a runstream pointer-obj.

ROMPTR <LID> <rom word>
    DOROMP obj whose body will contain the two 3-digit hex numbers.

HXS <length in hex> <hstring>
GROB <length in hex> <hstring>
CODE <length in hex> <hstring>		(2)
ARRY <length in hex> <hstring>		(2)
LNKARRY <length in hex> <hstring>	(2)
LIBRARY <length in hex> <hstring>	(2)
BACKUP <length in hex> <hstring>	(2)
LIBDAT <length in hex> <hstring>	(2)
EXT1 <length in hex> <hstring>		(2,4)
EXT2 <length in hex> <hstring>		(2)
EXT3 <length in hex> <hstring>		(2)
EXT4 <length in hex> <hstring>		(2)
    Specified object whose body is made from the specified hex-string.
    Zero-length obj's aren't supported by ->RPL.

ACPTR <data address> <access routine address>	(2,4)
    DOACPTR object, whose data and access routine addresses are built from
    the two specified hex numbers.

NIBB <length in hex> <hstring>		(2)
    Adds the binary form of the specified hex string to the runstream, eg.
    NIBB 7 84E2000 creates a 0-ID.

CODE <assembler source ..> ENDCODE
    CODE object, the assembler is called to assemble the body.

ASSEMBLE <assembler source ..> RPL
    The assembler is called to assemble the inline code.

INCLUDE <name>
    The accessable path is searched for a variable with the name <name>. Its
    contents must be a compilable string and may contain further INCLUDE
    statements. The resulting code is inserted at the position of the INCLUDE
    statement.

INCLOB <name>				(2)
    The accessable path is searched for a variable with the name <name>. Its
    recalled contents are inserted at the position of the INCLOB statement.


The following words create runstream pointer obj's:

UNIT	DOEXT  - Unit start
SYMBOL	02AB8  - Symbolic start
::	DOCOL  - Program start
{	DOLIST - List start
}	SEMI   - List terminator
;	SEMI   - Program, UNIT or SYMBOL terminator


Text surrounded by ' (' and ') ' is ignored by ->RPL.


Before you start compiling your own objects, play with the decompiler to
get some examples of the syntax definitions, eg. try { + } 1 GET RPL-> to
decompile 'x+'.

->RPL will automatically add SEMIs at the end of a compiled object to close
any open composite object, ie. compiling ":: 1" will create :: ONE ;

Note (1)
    Character substitution is supported via '\xxx' in strings, IDs, LAMs and
    CHRs using the internal routine which does the tranlsation for TRANSIO,
    code 3 (see the '48 manual for a complete description). You must use
    '\034' to insert doublequotes (") into strings.
    RPL-> generates (") within strings, not \034.

Note (2)
    These statements are not supported by RPLCOMP.EXE.

Note (3)
    ->RPL accepts BINTS in one of the following form:
	# xxx - allways compiled to BINT objects
	#xxx  - searches the ROM for a BINT with the appropriate value, if
		found a pointer to it is generated instead of a BINT object
	xxx   - real numbers are COERCED and then handled like #xxx

Note (4)
    ACPTR and EXT1 obj's do have the same prologue addresses but are defined
    differently, the former is a GX only obj, the latter an SX only obj.
    ->RPL won't allow you to compile a EXT1 obj on a GX and vice versa. RPL->
    can only handle ACPTR !

Note (5)
    If you want to recompile a source generated by RPL->, you must manually
    replace all PTR 12345 statements by

        ASSEMBLE
            CON(5)	#12345
        RPL


2.3 The Saturn Assembler/Disassembler
─────────────────────────────────────

The assembler defines a subset of SASM.EXE written by Nathan Zelle. You can
use it 'stand-alone' or in conjunction with the RPL compiler ->RPL. It's a
2-pass assembler.

The input string should be plain ASCII (with blanks and/or TAB's) generated
on a PC or the '48 itself.

It is 'free format' which means that no column counting is required, except
that labels MUST begin in the first coloumn of a line.

If a line consists only of a comment, an '*' MUST be in column 1. Empty lines
are ignored.

The general line structure is: "<label> [<mnemonic> [<parameter>] [<comment>]]"
or "* <comment>"; the fields are seperated by blanks or TABs.

Most parameters can be symbolic (eg. " GOVLNG (=SAVPTR)+45*3" is valid).

The assembler supports conditional assembling as well as defining equates via
"Label  EQU  expression". Please refer to SASM.DOC for more details.

You can call global entry points if a reference table is installed.

A predefined standard macro named LOOP is also included. If entered in the
mnemonic field it will be assembled to " GOVLNG  =Loop", an address which
simply does

=Loop A=DAT0  A
      D0=D0+  5
      PC=(A)

If the assembler source don't contain any code, the 2nd pass is skiped to
speed up RPL define like constructs - eg. a directory may hold along with
the source strings a variable HEADER:

(HEADER)
ASSEMBLE
@a EQU =1GETLAM
!a EQU =1PUTLAM
@b EQU =2GETLAM
!b EQU =2GETLAM
nr EQU =TWO
RPL

which may be included by a source like:

(xyz - just a program)
INCLUDE HEADER
::
  CKN
  DUP nr #<> case SETSIZEERR

  ' NULLLAM nr NDUPN {}N BIND

  @a @b 2DUP EQUAL ?SWAP
  !b !a
	(...etc...)
  ABND
;


2.3.1 The Assembler Parameter Field Parser
──────────────────────────────────────────

Parameter fields are parsed by an expression parser that is defined as
follows:

    expr : expr op1 term | term
    term : term op2 fact | fact
    fact : '(' expr ')' | op3 fact | '(' '=' entry ')' | '(' symbol ')' | num

    op1  : '+' | '-' | '!' | '|' | '^'
    op2  : '*' | '/' | ':'
    op3  : '-' | '"'

    num  : real-number | '#' hxs-number

    entry  : label of RPL.TAB
    symbol : label of the assembler symbol table

    op  action
    ──  ──────
    *   multiply
    /   divide
    :   modulo
    "   ones complement
    -   subtract / twos complement
    +   add
    !   bit AND
    |   bit OR
    ^   bit XOR

A complete expr must not contain whitespace chars. If an expression consists
only of a '#' number, an entry or a symbol, the parenteses aren't neccessary
(eg. @n EQU =1GETLAM ). Real numbers are converted internally to HXS numbers,
the accuracy is 64 bit. Parsing real numbers and hex numbers is done by the
'48 internal real/hex parser. The expr/term/fact parser uses the solver
token type table.

Expressions of EQU parameter fields must resolve to the requested number
during the 1st assembler pass; they are ignored in the 2nd pass.


2.4 The Reference Table
───────────────────────

RPL->, ->RPL, COD->, ->COD, EC, E<->A and 4/5/7 are looking for a reference
table named RPL.TAB which is used to resolve names and addresses of ROM
entry points. It may be stored in a variable, as a backup object in any port
or as a library command. If RPL.TAB exists, its recalled contents will be
evaluated and if the result is a string starting with '\000\010' it will be
used as a reference table. It is recommended to use one of the two tables
shipped with RPL48; they are made using the latest entries lists released by
HP as database - double named entries are removed and a few user-RPL names
are added to avoid conflicts when de/compiling different '->', '>>', 'END'
(user-RPL) words.

For generating your own tables, use GENTAB.C, also shipped with RPL48.

The following example (HP terminology) outlines the structure of a reference
table:

ASSEMBLE
	CON(5)  =DOCSTR		String prologue
	REL(5)  TabEnd          Length field
	NIBASC  '\00\n'		Reference table identifier
*				A hash table, for each char from ' ' - DEL
*				a 5-nib offset into the table
	CON(5)	0		' ' entry, empty
	REL(5)	_!_		relativ offset to words starting with '!'
	CON(5)	0		'"' entry, empty
*   	...			'#' - 'C'
	REL(5)	_D_		'D' entry
*   	...			'E' - '}'
	CON(5)	0		'~' entry, empty
	CON(5)	TabEnd		DEL entry, always TabEnd

_!_
	CON(6)	#9623A0
	NIBASC	`!!append$`
*	...
_D_
*                ┌─────── Length of the label in bytes.
*                │        A label can't be > 15 chars in size.
*                │┌┬┬┬┬── Address associated to the label, here 074E4
*                ││││││
	CON(6)  #6074E4		Address/length field of the following
	NIBASC  'DOBIND'	Label

TabEnd
RPL


2.5 Command Reference
─────────────────────

RPL->		( ob			--> $				)

    Decompiles an object into a string. The string can be used as input for
    ->RPL without modifications (most times).


->RPL		( $			--> ob				)

    Compiles the input string to an object.


DCADR		( hxs[adr]		--> $ hxs[adr]'			)

    Decompiles the object referenced by the address adr to a string in
    level 2 and increment the address by the object size.


COD->		( code			--> $				)

    Disassembles a code object, generates HP styled mnemonics. The reference
    table is searched for addresses of GO and Dx=(5) mnemonics. The string
    can be used as input for ->COD without modifications (most times).


->COD		( $			--> code LibDat			)

    Assembles a code object. LibDat is the compressed form of a cross
    reference listing, use SYM-> (see below) for decompression.


->OB		( hxs[adr]		--> ob				)
		( #adr			--> ob				)
		( XLIB			--> ob				)
		( ob			--> ob'				)

    Input	Action
    ─────       ──────
    hxs		Build a pointer, pointing to the address given by the value
		of hxs[adr].
    #		Same as for hxs, except if the value of # points to a valid
		ob in the hidden ROM; in this case the object is copied into
		TEMPOB. Eg. "# 72000" ->RPL ->OB returns the message table
		of the internal library 0.
		On a GX, passing a # is the same as passing a HXS.
    XLIB	Does a rompointer recall.
    ob		Unconditionally TOTEMPOB.


DAN		( hxs[adr] %n		--> $1 .. $n hxs[adr]'		)

    Disassembles n instructions starting at address hxs[adr].


DA1		( hxs[adr]		--> $ hxs[adr]'			)

    Disassembles the instruction at address hxs[adr].


DAXY		( hxs[start] hxs[end]	--> $				)

    Disassembles until the actual adr. is > hxs[end], starting at address
    hxs[start].


SYM->		( LibDat		--> $				)

    Converts the cross reference table produced by ->COD into a string.


$->		( $			--> ob				)

    Converts a hex-dump to an object.


->$		( ob			--> $				)

    Generates a hex-dump of an object.


EC		(			--> ?				)

    Entries Catalog - the reference table browser. Errors if no RPL.TAB
    can be found.

    When starting EC the first time, it'll create the variable ECpar in
    the HOME directory. It contains a HXS that is used by EC as a lookup
    table into RPL.TAB; you may store the variable into a port (like
    RPL.TAB). Any time you install a new reference table it is neccessary
    to purge ECpar !

    The main display of EC shows eight entries, one per line. Each line shows
    the name and the addresses of an entry, a 'm' behind the address marks non
    RPL entries (ie. ML entries). These words are probably for use within
    assembly only. One line is inversed, showing the current position of
    the cursor bar which can be moved by the UP/DOWN arrows.

    Active keys in the main display of EC:

      Unshifted:
	UP    - move scroll bar up one word
	DOWN  - move scroll bar down one word
	ENTER - push highlighted word as $ onto the stack. If EC is launched
		from a command/edit line, ENTER coppies the word into the
		editline starting at the current cursor position
	NXT   - scan for next occurence of the SCAN word.
	ON    - exit EC or cancel sub-action

      Rightshifted:
	ENTER - in case no editline exists, the current word is copied into a
		newly opened editline
	UP    - move to first entry
	ON    - turn off

      Menu keys:
	PG|^  - page up
	PG|v  - page down
	SCAN  - prompts for a $ to search, ENTER starts searching. If EC is
		launched from a command/edit line, the prompt looks a bit
		suspicious, but its functionality is the same
	A-Z   - try it
	A->ST - push the address of the current word onto the stack. If EC
		is launched from a command/edit line, the A->ST key changes
		to the ABOUT key.
	HELP  - provides two pages of help on keys

    For use of EC within a normal edit line, append the following list to
    your CST variable and launch EC with CST EC:
	{ $ "EC" :: TakeOver ROMPTR 4D2 C (EC) ; }


E<->A		( hxs[adr] | $name	--> $name | hxs[adr]		)

    Searches the reference table for a name or address of a given address or
    name. Errors if the label or address can't be resolved.


RPLtab		(			--> $				)

    Tries to recall the ref. table via RPL.TAB. If no table is found, a
    zero-length string is returned.


4/5/7		(			-->				)

    Starts the medium font sys-stack display in five line mode. Pressing
    4/5/7 in five line mode switches to seven line mode, in seven line mode
    the sys-stack is canceled.

    If you have flag 61 set, the commandline changes to sys-RPL mode, and
    the i-stack allows you to edit objects in sys-RPL syntax when pressing
    the EDIT menu key.

    The following keys are redefined while the 5/7 stack is active:
      - pressing the up arrow without an active edit/commandline starts a
	5/7 level interactive sys-RPL stack
      - pressing the down arrow without an active edit/commandline starts
	editing the object of stack level one in sys-RPL syntax, if flag
	61 is set.
      - pressing ENTER to terminate a command line compiles it using the
	internal ->RPL, if flag 61 is set.

	YOU MUST NOT MOVE THE <-RPL-> LIBRARY WHILE 4/5/7 IS ACTIVE !!
    (ie. DON'T MERGE THE PORT WHERE <-RPL-> IS STORED WITH AN ACTIVE 4/5/7 !!)

    Clear flag 62 to quit 4/5/7 if you wan't to purge/move <-RPL->.


CC		(			--> ?				)

    Character set Catalog. CC displays a map of 128 characters in the small
    font along with some more information for the highlighted char. You can
    move through the map using the cursor keys. If you hold down one of the
    cursor keys, it will repeat until you release. The ON-key exits the
    program, RIGHT-ON turns the calc off and ENTER fetches the char number
    (tagged with the char) to the stack.

    There are three menu keys available:
      SWAP - swaps between the upper/lower half of the char set
      BIN  - toggles the char code display from real/hex to binary and back
      EXIT - leaves CC

    If you launch CC within an active editline (eg. via the CST menu), ENTER
    will copy the highlighted character into the editline to the current
    cursor position. For use of CC within a normal edit line, append the
    following list to your CST variable and launch CC with CST CC:
	{ $ "CC" :: TakeOver ROMPTR 4D2 10 (CC) ; }


2.7 Hooks
─────────

There are a few user hooks in <-RPL->, each an unnamed ROMPTR:

ROMPTR 4D2 13	(			-->				)

    Switches to ADISP and displays a 5/7 level sys-RPL stack.


ROMPTR 4D2 14	(			-->				)

    Errors if <-RPL-> isn't ATTACHed to the HOME directory.


ROMPTR 4D2 15	( ob			--> $				)

    Decompiles an object in quiet mode, eg. for editing.


ROMPTR 4D2 16	( $			-->				)

    Compiles a string in quiet mode, eg. after editing.


Note: no stack checks are done by these routines !


2.7 Things to Notice
────────────────────

->RPL maintains a global assembler symbol table while compiling an object,
ie. it is possible to jump backward from a code object to a previous one:

::
  CODE
Lp LOOP
  ENDCODE
  CODE
   GOTO lp
  ENDCODE
;

(Note: in the current version of <-RPL-> this seems not to work, I'm bug
 hunting... Detlef)

->RPL tries to resolve a token in the following order:
    1. check for atomic object (eg. %, # et c.)
    2. search reference table
    3. search symbol table
    4. check for #<hex-no>
    5. check for user-RPL word
    6. check for user-RPL object

The search of the symbol table enables the programmer to use DEFINE like
constructs:

::
  ASSEMBLE
@val EQU =1GETLAM
!val EQU =1PUTLAM
  RPL

  ONE 1LAMBIND
  @val #1+ !val
  1GETABND
;


3. <-LIB->
══════════


3.1 Overview
────────────

<-LIB-> contains 39 commands, including a library maker (D->LIB), a library
splitter (L->DIR), commands to handle any sort of composite objects and
commands to manage libraries.

Libraries are very useful objects to extend the command set of a '48 in a
'native' manner, but unfortunately library creation is not supported by the
'48 firmware. The HP tools package contains the program USRLIB.EXE, which
provides library creation on a PC; if you want to move your most often used
programs into a library (because of easier handling and to keep your VARs
area clean), you have to collect them into a subdirectory, add a few control
variables, transfer the directory in binary form to a PC, run USRLIB.EXE on
it, and transfer the created library back to your '48, where you can install
and test the library.

<-LIB-> provides the command D->LIB that works on the currently active
directory, allowing you to create a library from this directory on the '48
itself - no transfers, no PC, and no USRLIB.EXE are required.

The input directory stucture of D->LIB is very similar to the directory
structure required by USRLIB.EXE, thus existing USRLIB.EXE input can be
used for a library creation with minor changes (the difference is the
format of the $MESSAGE control variable, see below).


3.2 Control Variables
─────────────────────

The library creation process is controlled by some variables with reserved
names and only the current directory is searched for their presence (note:
multiple occurences of these names are ignored, only the contents of the
first one found in the current directory is used for the library creation
process):

$ROMID
    Must contain a real or binary number representing the LID that is to
    be given to the library. The LID must be in the range 0..2047. Negative
    real numbers are mapped to 0.
    This is the only control variable that MUST exist in the current
    directory !

$TITLE
    Should contain a character string to be used as the name of the library
    (note: any other object is converted to a string). The first few
    characters of the name are displayed in the LIBRARY menu label
    associated to the library, the first 22 characters are displayed by
    pressing REVIEW in the LIBRARY menu. If $TITLE is absent or contains an
    empty string, no title is generated and the resulting library doesn't
    have a menu label in the LIBRARY menu (note: you can switch to the
    library's command menu by executing %LID MENU, even if the library
    doesn't have a name or is not attached).

$CONFIG
    Must contain a program to be executed at configuration time.
    The configuration code can generally NOT be written in user-RPL, but
    simple programs such as \<< 123 ATTACH \>> are Ok - more complicated
    programs should take care to leave the stack unchanged, and be sure
    NOT TO ERROR ! An error in a configuration program will cause a warmstart;
    the configuration code is called again during the startup process,
    producing a new error etc. If you are accidentally trapped by this, you
    must clear your memory to remove the faulty library !

$MESSAGE
    Must contain a list of strings to be combined into a message table (note:
    any other objects are converted to strings). The message numbers
    correspond to the list positions. In user-RPL you can generate errors
    with your own messages in the following manner:
	    #32001h DOERR
             │││││
             │││└┴── Message number     (here 1)
             └┴┴──── LID                (here #320h = 800)
    In sys-RPL you can use
	    # 32001 ERROROUT

    In this example an error is generated, using the first message from the
    message table of a library with the LID 800.

    Note: The message list structure is NOT compatible to USRLIB.EXE.

$VISIBLE
    Must contain a list of names of variables to be converted to user-
    accessible, named library commands. By default, all variables will be
    translated to named library commands. When the $VISIBLE list is present,
    only the names in this list are included in the library hash table. An
    empty list is Ok, meaning that no hash table is generated.

$HIDDEN
    Must contain a list of names of variables that are to be converted to
    unnamed objects in the library. When the $HIDDEN list is present, those
    names listed are not entered in the library hash table. If both $VISIBLE
    and $HIDDEN are present, only $HIDDEN will be used.

    Note: all visible commands appear as labeled softkeys in the menu
    associated to the library, all hidden commands are not, and there is no
    way to access them from user scope.

$VARS
    Must contain a list of variables that should remain RAM-based - i.e. the
    objects of the variables listed in $VARS are not included in the library
    and no XLIB pointers are made to substitute their names. All other
    variables of the current directory are included in the library.

    Note: You should add all subdirectory names of the current directory to
    the list.

$ROMID must exist in the current directory, all other control variables are
optional - eg. you can generate libraries containing only a configuration
program or a message table. All control variables are internally handled by
D->LIB to be $VARS and can't be accessed from within the library commands.


3.4 Command Reference
─────────────────────

D->LIB		(			--> lib				)

    Dir to lib; assembles a library from the objects of the current directory.
    The creation process is controlled by a few variables with reserved names
    (see '3.3 Control Variables').
    If you set flag -13 before running D->LIB, it will switch off the screen
    while working (for saving time and batteries).


L->DIR		( %LID			--> dir				)
		( xlib			--> ob				)

    Lib to dir; if the argument is a LID then L->DIR assembles a directory
    containing all commands of this library as variables. The neccessary
    control variables (see 3.3) are also generated. D->LIB may be used to
    recreate the library.
    If the argument is an XLIB, then L->DIR recalls its object from the
    associated library onto the stack.
    If you set flag -13 before running L->DIR on a library, it will switch
    off the screen while working.

    Note: You cannot use L->DIR to split <-LIB->, this should prevent users
    from a memory lost. If you are familiar with the internals of your '48,
    use 'ROMPTR@' (or ->OB of <-RPL->) to extract single routines from
    <-LIB->, but beware of starting the routines in RAM, most of them will
    crash your calc when running alone !


MCFG		(			-->				)

    Make config; stores a configuration program into a variable named
    '$CONFIG' into the current directory. This configuration program will
    attach the generated library to the home directory at warmstarts (ON-C
    etc.).
    '$ROMID' must exist in the current directory.


ML->D		(			--> prg				)

    Generates a program with the following interface:

		( {}			--> libdta			)

    The list can contain anything. The program checks for argument count and
    type and may error with:
	#201 - To Few Arguments  - nothing on the stack
	#202 - Bad Argument Type - not a list on the stack

    '$ROMID' must exist in the current directory.


MD->L		(			--> prg				)

    Generates a program with the following interface:

		( libdta		--> {}				)

    The program checks for argument count, type and correct LID and may error
    with:
	#201 - To Few Arguments   - nothing on the stack
	#202 - Bad Argument Type  - no library data on the stack
	#203 - Bad Argument Value - the libdta wasn't created by this lib

    '$ROMID' must exist in the current directory.

  Note: Store the programs generated by ML->D and MD->L into variables in
  your source directory and use them as an interface to generate/resolve
  data associated to the resulting library.


OB->		( prg			--> ob1 .. obn %n		)
		( xlib			--> %LID %objno			)
		( arry			--> ob1 .. obn { %di .. %d1 }	)
		( alg			--> ob1 .. obn %n		)
		( dir			--> ob1 id .. obn id %n		)
		( id			--> $				)
		( libdta		--> {} %LID			)
		( bak			--> ob id			)
		( id			--> $				)
		( ob			--> dispatch to OBJ->		)

    OB-> is an extension to the built-in OBJ->, supporting system level
    objects.


->DIR		( ob1 id1 .. obn idn %n	--> dir				)
->PRG		( ob1 .. obn %n		--> prg				)
->XLIB		( %LID %cmdno		--> xlib			)
		( #LID #cmdno		--> xlib			)
->ARR		( ob1 .. obn %n		--> arry			)
		( ob1 .. obn { %di .. %d1 } --> arry			)
->ALG		( ob1 .. obn %n		--> prg				)
->LD		( {} %LID		--> libdta			)
->BAK		( ob id			--> bak				)
->ID		( $			--> id				)

    Functions to reverse OB->.

    About ->ARR:
       Generates arrays of any type and any dimension (eg. a four dimensional
       array of libraries :-).
       %di * .. * %d1 must be = n, ob1 .. obn must be of the same type.
       All possible parameter errors are trapped.


ADRp		( ob			--> ob #addr			)

    Get address of ob.

    Note: The data stack is a stack of pointers to objects. ADRp simply
    returns the value from the top element (about the 'p', see 'LIBp' below).


$romid
$visible
$title
$config
$vars
$hidden
$message	(			--> '$XXX'			)

    These commands just put a control variable name onto the stack.


LBCRC		( lib			--> lib'			)
		( bak			--> bak'			)

    Recalculates the CRC of a library or backup, useful if you have patched
    it because modifying the body of a library or backup invalidates the CRC
    included at the end of the body.


RNLIB		( lib $			--> lib'			)

    Renames a library, ie. changes title.


CHLID		( lib %			--> lib'			)

    Change LID; this program allows you to change the LID of a library if
    it's not splittable.

    Note: Most time a LID is also hardcoded in the config code - this can
    generally not be changed by CHLID. You have to attach the library manually
    after a warmstart. Also any library has its LID coded in a field above
    any visible command (the error handling system identifies the command
    that caused an error using this field (the sys-RPL commands 'CKn' copies
    this values to the appropriate location)). These fields are not changed
    by CHLID (yet).


RHASH		( %LID			--> hxs				)

    Recall hash table; get a pointer to the hash table of a library.


RLINK		( %LID			--> hxs				)

    Recall link table; get a pointer to the link table of a library.


RCFG		( %LID			--> ob				)

    Recall config code; get a pointer to the config code of a library.


RMSG		( %LID			--> arry			)

    Recall message table; get a pointer to the message table of a library.

RTITLE		( %LID			--> $				)

    Recall title; get the name of a library.


    Note: RHASH, RLINK, RCFG, RMSG and RTITLE don't error if the library
    associated to %LID didn't contain the requested item, they leave the
    stack unchanged in that case.


RPORT		( %port			--> ob1 .. obn			)

    Recalls pointers to all objects of a given port (0/1/2 - 3-33 on a GX)
    onto the stack, ignoring the R/W status of that port.


RLIB		( :%port:%LID		--> lib				)
		( %LID			--> libn %portn ...		)

    Recall lib; the 1st case recalls a library from a given port, the 2nd
    case searches ports 0,1,2 (followed by ports 3-33 on a GX) for libraries
    with %LID, returning all found libraries and the port numbers where
    they're stored.

    Note: On a SX this command actually returns pointer to libraries (like
    RPORT), if you recall a lib and try to purge it while it's on the stack,
    you'll get a 'Object in use' error. Execute NEWOB or store it into a
    variable first.


PGLIB		( :%port:%LID		-->				)
		( %LID			-->				)

    Purge lib; the 1st case works like :%port:%LID PURGE, in the 2nd case the
    ports are searched in order 0,1,2 (followed by ports 3-33 on a GX) for an
    active library with %LID. The difference to PURGE: if the library is
    attached to the home directory, it's detached before purging. On a SX:
    Also if there is an inactive library with the same LID in any other port,
    it becomes active and is attached to the HOME directory (if flag 5 is
    set, its config code is executed - see STLIB below).


STLIB		( lib %port		-->				)

    Store lib into port; there're a few differences to STO:
	- The library is installed full; a warmstart isn't neccessary
	  and thus not initiated at the next power cycle. All warmstart
	  volatile variables (stack, PICT) remains intact.
	- The library last stored is visible to the '48 (in case of
	  having a library with the same LID installed in another port).
	- If flag 5 is clear, the library is attached simply to the
	  home directory.
	- If flag 5 is set, the config code of the library is executed
	  under warmstart conditions. Usefull for testing a config code.

    Note: This command is currently disabled on a GX !


ACLIB		( :%port:%LID		-->				)

    Activate library. You can install libraries with the same LID in different
    ports, but only one will be visible to the '48 at the time. During
    warmstarts the ports are searched in order 2,1,0 (most cases), ie. the
    library stored in the port with the highest number will be active.
    ACLIB allows you to switch to any other library with the same LID at
    runtime, the effect is immidiate. ACLIB 1st detaches the LID from HOME,
    sets the new priority and than a) attaches the LID to HOME again if flag
    5 is clear, or b) runs the library config code if flag 5 is set (see STLIB
    above).

    Note: This command is currently disabled on a GX !


LIBp		( %LID			--> $				)

    Returns a detailed layout of a library. The map starts with the title (if
    exist), followed by the 1st and last address of the lib and the LID. The
    remainder lists the contents of the lib, one line of information for each
    XLIB entry. Structure of a line:

	1st last  xn name  typ
        │││ ││││  ││ ││││  └┴┴─ Type of the object
        │││ ││││  ││ └┴┴┴────── Name of the object (if it's a visible cmd)
        │││ ││││  └┴─────────── XLIB number of the object
        │││ └┴┴┴─────────────── Last relative address of the object
        └┴┴──────────────────── Offset to startaddr. of the object

    The list is sorted by offset. Try 1221 LIBp or 2 LIBp.

    Note: If you find unexpected 'holes' between two XLIBs (> 10 nibbs) or
    XLIBs embedded in other XLIBS, the library wasn't generated using
    USRLIB.EXE or D->LIB; do not use D->LIB for recreating it because the
    'holes' can hold essential data..

    Note: This command is currently disabled on a GX !


INSTp		(			--> { %LIDn .. %LID1 }		)

    Returns a list of all libraries attached to the current directory, { } if
    none.

    Note: You can PURGE libraries even if they are attached to a subdirectory.
    INSTp can be used to find such zombie references.


LIBSp		(			--> { %LID1 .. %LIDn }		)

    Returns a list of all libraries currently installed on your '48.


  Note: We didn't use the '?' postfix because normally it marks a routine
  for returning a flag in RPL. The JARGON file, v2.9.9, 01 APR 1992 states:

    3. The `-P' convention: Turning a word into a question by
    appending the syllable `P'; from the LISP convention of appending
    the letter `P' to denote a predicate (a boolean-valued function).
    The question should expect a yes/no answer, though it needn't.

    At dinnertime:
       Q: "Foodp?"
       A: "Yeah, I'm pretty hungry." or "T!"

    At any time:
       Q: "State-of-the-world-P?"
       A: (Straight) "I'm about to go home."
       A: (Humorous) "Yes, the world has a state."

  so we used 'p' for marking routines returning information ;-)


fEVAL		( ob			--> ?				)

    Works like EVAL, but switches the display off first. Speeds up evaluation
    by ~11%. In case of an error or the ob has finished execution, the
    display is switched on again. Not very useful, if ob prompts for input..


3.5 Things to Notice
────────────────────

┌───────────────────────────────────────────────────┐
│ HP 48 Resource Allocation Guideline: Library ID's │
├───────────────────────────────────────────────────┤
│ 0000 - 0256  Take-over libraries; do not use!     │
│ 0257 - 0512  HP ROM-based libraries; do not use!  │
│ 0513 - 0768  HP RAM-based libraries; do not use!  │
│ 0769 - 1791  3rd Party (assigned by HP)           │
│ 1792 - 2047  Command-line; do not use!            │
└───────────────────────────────────────────────────┘

[This sure doesn't seem to leave many for us hackers to use, eh?  -jkh-]

*Don't use the following LIDs*, they're handled special by a '48SX (and
probably also by a GX):

LID		What's special ?
───             ────────────────
240-255		ROMPTR@ assumes that the associated library command is in the
		hidden ROM.
0-256,1792	The central routine to compile IDs (PTR 7BFD on a SX, PTR
		7C18 on a GX) returns pointer instead of XLIBs.

The library stucture is 'flat', so don't try to include subdirectories in a
library, it can end up in a memory lost.

Not all program objects that execute correctly from global variables are
directly convertable into libraries. Here are some pitfalls:

    - Since a library cannot be modified, no library command may be the
      target of a STO or PUT operation.
    - XLIB names are not usable in all contexts in which global names are
      valid arguments. This can cause constructs that reference a named
      object to fail. For example,
	'A' 5 GETI
      where A is a list will not work when A is converted to an XLIB name.
      Instead use
	    A 5 GETI
    - XLIB names are not valid as formal variables in algebraics, or as the
      independent variable for plotting or solving.
    - \->STR applied to a global name that is converted to a 'hidden' library
      command (see $HIDDEN) returns a null string.

If any visible command starts with the seqence '\<< \->' or '\->' it's marked
in the library as a valid command for algebraics. If you press its associated
softkey in ALG entry mode, you'll get 'name()'.

Multiple occurences of variable names results in an incorrect library because
only the contents of the first one is picked up.

D->LIB needs ~(1.2 * size_of_source_directory) bytes to be free to generate a
library.

The time D->LIB needs for doing a job depends mainly on the total number of
commands included in the resulting library. Eg. Raymond runs D->LIB on a
~60kb directory containing ~300 variables; D->LIB needs ~15min on a rev A
'48 to make the library (not in FAST-mode). Of course, this is quite faster
than using USRLIB.EXE !!!

Reassembling a split library may be dangerous if the original library was
not generated using USRLIB.EXE or D->LIB. There is no guarantee that the
result will work properly - even if no code changes are done.

USRLIB.EXE generates a link table entry for the configuration program; if you
split such a library with L->DIR, you'll get the configuration code twice,
the first one stored in $CONFIG, the second one stored in a variable of the
generated directory. Purge the variable before using D->LIB. You also can
use LIBp to see the second reference to the config code.


Appendix A - Quick Reference Guides
═══════════════════════════════════


A.1 <-RPL->
───────────


A.1.1 Commands
──────────────

Page 1234.1

    RPL->	( ob		--> $		)	decompile object
    ->RPL	( $		--> ob		)	compile object
    DCADR	( hxs		--> $ hxs'	)	decompile one word
    COD->	( code		--> $		)	disassemble CODE
    ->COD	( $		--> code libdat	)	assemble CODE
    ->OB	( ob		--> ob'		)	convert object

Page 1234.2

    DAN		( hxs %n	--> $1 .. $n hxs' )	disassemble n times
    DA1		( hxs		--> $ hxs'	)	disassemble one mnemo
    DAXY	( hxs hxs	--> $		)	disassemble block
    SYM->	( libdat	--> $		)	convert symbol table
    $->		( $		--> ob		)	hex-dump to object
    ->$		( ob		--> $		)	object to hex-dump

Page 1234.3

    EC		(		--> ?		)	entries catalog
    E<->A	( hxs | $name	--> $name | hxs	)	get name/address
    RPLtab	(		--> $		)	recall ref. table
    4/5/7	(		-->		)	sys-stack display
    CC		(		--> ?		)	character set catalog


A.1.2 Flag Usage
────────────────

General:

    Flag	Meaning
    ────        ───────
     -4		If set, RPL->/DCADR are using the disassembler to decompile
		code objects.
    -13		Quiet mode if set. The status report of RPL->, ->RPL, COD->
		and ->COD is suppressed.
     64		Reserved.
     63		Toggles sys-stack between 5/7 lines mode.
     62		Set by 4/5/7 to signal an active medium font display. Can
		be cleared to quit the sys-stack.
     61		Toggles the behaivior of the down arrow key during sys-stack
		display, the EDIT menu key during the sys-i-stack and the
		ENTER key when finishing a command line. If set, you can edit
		objects in sys-RPL syntax. A menu toggle for this flag can be
		found on the 3rd page of the i-stack menu (labeled S-ED).

DAN and DA1 are using the following flags:

    Flag (set)	Meaning
    ──────────  ───────
      1 	next instr is a GO/RET YES/NO
      2	 	last instr was RET...
      3 	last instr was GO C/NC/TO
      4 	last instr was relative GOSUB
      5 	last instr was absolute GO
      6 	last instr was PC manipulation
      7 	used internaly
      8 	last instr was absolute GO or Dx=(5)


A.1.3 Error Messages
────────────────────

General Errormessages:

    "Undefined XLIB Name"
	Requests to execute a command when the <-RPL-> library is not attached
	to the HOME directory will cause this error. See section 1.3.

    "Need Binary Number"
	The object passed to DCADR or DA1 isn't a binary number.

    "Need String"
	The object passed to ->RPL, ->COD or $-> isn't a string.

    "Data Modifies Stack"
	The object stored in RPL.TAB or ECpar doesn't add one item to the
	stack.

    "Where's your Program ?"
	The string passed to ->RPL results to nothing.

    "Primitive Code Object"
	The object passed to RPL-> or the address passed to DCADR points to
	a PCO.

    "Found ACPTR on a SX"
        RPL-> can't decompile ACPTR (ie. EXT1 objects) if <-RPL-> is installed
        on a '48SX.

->COD Errormessages:

    ->COD generates error messages of the following form:
	"->COD Error: x:yy
	 Message"
    where 'x' is the INCLUDE nesting depth and 'yy' is the character offset of
    the first character following the token that caused the error. 'Message'
    may be one of the following:

    "ENDIF Expected"		an IF isn't matched by an ENDIF
    "ENDIF w/o IF"		missplaced ENDIF
    "ELSE w/o IF"		missplaced ELSE
    "Invalid Parameter"		invalid parameter field
    "Inv. Expr: expr"		invalid parameter field expression <expr>
    "Invalid Mnemonic"		invalid menemonic
    "Duplicate Label"		double defined label
    "GOYES/RTNYES Expected"	comparisation without a following
				conditional jump
    "GOYES out of range"	jump destination is more than -128/+127
				nibbles away
    "Parameter Expected"	parameter of a mnemonic which expects
				one is missing
    "Unknown Symbol: symb"	unknown symbol <symb> in an expression
    "Inv. $: str"		invalid string <str> constant
    "No IF Nesting Yet"		nesting of conditional IF .. ELSE .. ENDIF
				structures is not allowed (yet)
    "Can't INCLUDE: nam"
	There's no variable with the name <nam>

->RPL Errormessages:

    ->RPL generates error messages of the following form:
	"->RPL Error: x:yy
	 Message"
    where 'x' is the INCLUDE nesting depth and 'yy' is the character offset of
    the first character following the token that caused the error. Note that
    if the error is generated by the asssembler (called by ->RPL to assemble
    inline code), 'yy' is the error position relative to the first char after
    the CODE or ASSEMBLE token. 'Message' may be one of the following
    (additional to the ones listed for ->COD):

    ") Expected"
	Missing a ) to terminate a comment

    "" Expected"
	Missing a " to terminate a string

    "ENDCODE Expected"
	Missing the token ENDCODE to terminate a CODE statement

    "RPL Expected"
	Missing the token RPL to terminate a ASSEMBLE statement

    "Misplaced ; or }"
	Found a ; or } without a opening ::, {, UNIT or SYMBOL

    "Suspect %"
    "Suspect %%"
	Parsing of a number results in an object of incorrect type

    "Body Len <> Datalen"
	The length field of a HXS-like styled statement is not equal to
	the data length

    "ACPTR is a G object"
	ACPTR can only be compiled, if <-RPL-> is installed on a GX

    "EXT1 is a S object"
	EXT1 can only be compiled, if <-RPL-> is installed on a SX

    "More Tokens Expected"
	The statement at the end of the input string is incomplete

    In the following messages 'ttt' represents the token that causes the
    error:

    "ROMP LibID >FFF: ttt"
    "ROMP ROMWD >FFF: ttt"
	The library ID part or the ROM word number part of a ROMPTR statement
	is > FFF

    "Suspect \ Seq: ttt"
	The escape sequence ttt in the string, ID or LAM is incomplete or
	invalid

    "Can't INCLUDE: ttt"
    "Can't INCLOB: ttt"
	There's no variable with the name ttt

    "Cont. no $: nam"
	The INCLUDEd variable <nam> doesn't contain a string

    "Inv. xxx: ttt"
	where 'xxx' is one of the following:

	"Tok"	- ttt is unresolvable
	"#"	- ttt is out of range or contains chars other than hex digits
	"$"	- ttt doesn't start with a "
	"%","%%"- ttt represents an invalid number
	"PTR"	- ttt is out of range or contains chars other than hex digits
	"CHR"	- ttt contains more than one char

	"Body Dat" - the data field of a HXS-like styled statement contains
		     chars other than hex digits
	"Body len" - the length field of a HXS-like styled statement contains
		     chars other than hex digits
	"RomWd"    - the ROM word number field of a ROMPTR is longer than 5
		     chars or contains chars other than hex digits
	"LibID"    - the library ID field of a ROMPTR is longer than 5 chars
		     or contains chars other than hex digits
	"APaa"     - the access address field of an ACPTR is longer than 5
		     chars or contains chars other than hex digits
	"APda"     - the data address field of an ACPTR is longer than 5
		     chars or contains chars other than hex digits


A.2 <-LIB->
═══════════


A.2.1 Commands
──────────────

Page 1221.1

    D->LIB	(		--> lib		)	build library
    L->DIR	( %		--> dir		)	split library
    MCFG	(		-->		)	make config program
    ML->D	(		--> prg		)	make libdat-> handler
    MD->L	(		--> prg		)	make ->libdat handler
    OB->	( ob		--> ?		)	split object

Page 1221.2

    ->DIR	( meta(ob,id)	--> dir		)	make directory
    ->PRG	( meta(ob)	--> prg		)	make program
    ->XLIB	( % % | # #	--> xlib	)	make XLIB
    ->ARR	( meta(ob)	--> arry	)	make array
    ->ALG	( meta(ob)	--> alg		)	make algebraics
    ->LD	( {} %		--> libdta	)	make library data

Page 1221.3

    ->BAK	( ob $		--> bak		)	make backup
    ->ID	( $		--> id		)	make identifier
    ADRp	( ob		--> ob #	)	get address of object
    $romid	(		--> id		)	get id '$ROMID'
    $visible	(		--> id		)	get id '$VISIBLE'
    $title	(		--> id		)	get id '$TITLE'

Page 1221.4

    $config	(		--> id		)	get id '$CONFIG'
    $vars	(		--> id		)	get id '$VARS'
    $hidden	(		--> id		)	get id '$HIDDEN'
    $message	(		--> id		)	get id '$MESSAGE'
    LBCRC	( lib | bak	--> lib' | bak'	)	recalculate CRC
    RNLIB	( lib $		--> lib'	)	rename library

Page 1221.5

    CHLID	( lib %		--> lib'	)	change LID
    RHASH	( %		--> C#		)	get hash table
    RLINK	( %		--> C#		)	get link table
    RCFG	( %		--> prg		)	get config code
    RMSG	( %		--> arry	)	get message table
    RTITLE	( %		--> $		)	get title

Page 1221.6

    RPORT	( %		--> ob ...	)	recall port
    RLIB	( %		--> lib % ...	)	recall library(s)
    PGLIB	( % | :%:%	-->		)	purge library
    STLIB	( lib %		-->		)	store library
    ACLIB	( :%:%		-->		)	activate library
    LIBp	( %		--> $		)	get library layout

Page 1221.7

    INSTp	(		--> {}		)	get installed LIDs
    LIBSp	(		--> {}		)	get all LIDs on 48
    fEVAL	( ob		--> ?		)	fast EVAL


A.2.2 Flag Usage
────────────────

5	Set:	STLIB executes config code of passed library after
		installation.
		ACLIB executes config code of activated library.
		<-LIB->s config code displays a (c) notice.
	Clear:	STLIB and ACLIB are simply attaching the handled library
		to the HOME directory.
		<-LIB->s config code doesn't display (c) notice.

6	Set:	L->DIR places the $control variables at the end of the
		generated directory.
	Clear:	L->DIR places the $control variables at the beginning of
		the generated directory.

7	Set:	L->DIR generates a $HIDDEN but no $VISIBLE variable.
	Clear:	L->DIR generates a $VISIBLE but no $HIDDEN variable.

-13	Set:	D->LIB/L->DIR switch the display off while processing
		a directory/library (fast mode).
	Clear:	D->LIB/L->DIR are leaving the display on while working.


A.2.3 Error Messages
────────────────────

"Missing $ROMID"
    $ROMID is not defined in the current directory

"$ROMID Not Real/Binary"
    $ROMID doesn't contain a % or HXS object

"$ROMID Out of Range"
    a) the value of $ROMID is > 2047
    b) a % > 2047 was passed to CHLID

"$CONFIG Not a Program"
    Because the stack must not change during warmstarts, $CONFIG must contain
    a program

    Note: Use 1 ->PRG to embedd CODE, IDs or XLIBs into a program.

"$HIDDEN Not a List"
"$VISIBLE Not a List"
"$VARS Not a List"
"$MESSAGE Not a List"
    $XXX must contain a list

"Found ID Name>16 Chars"
    D->LIB have found a visible command name which is > 16 chars in size

"Found 0-ID"
    D->LIB have found a visible command name with the size 0

"Won't work on a G"
    The initiated operation can't be executed on a '48G(X).


Appendix B - A ->COD Example
════════════════════════════


Key in the following text (including the string delimiters) on your '48 (you
may leave out the comments):

"       GOSBVL  =SAVPTR         ** Save RPL pointers in save locations
**				   P is 0 , HEX mode enabled
	LAHEX	123AFE		** Load HEX nibbles into A Register
**				   starting at P
	P=	5		**
	GOVLNG	=PUSHhxsLoop	** Push A[WP] onto Data stack
**				   and pass control to RPL
"

Store it in the variable SRC1. Recall the text to the stack, then press
[->COD]. The display will show 'ASSEMBLER PASS 1' on the bottom line. In the
upper part of the display 'Line  nnn' will appear, where <nnn> represents
the actual code line to be assembled (empty lines or comment lines are not
counted).

A second later the display will show 'ASSEMBLER PASS 2' on the bottom line
and 'Processing nnn Lines' in the message area. Another second later the
source will have been assembled and the the string will be replaced by a
'Code' object and a 'Library Data' object. The stack should look as follows:

┌─────────────────────┐
│                     │
├─────────────────────┤
│4:                   │
│3:                   │
│2:               Code│
│1:       Library Data│
│## ### ### ### ### ##│
└─────────────────────┘


The Library Data object contains all used local symbols (eg. labels). For the
above example, it is an empty string, as there are no local symbols. The Code
object represents the assembled source text. DROP the Library Data object and
store the Code object into 'XQ1', then press the menu key [XQ1] . The stack
now looks like:

┌─────────────────────┐
│                     │
├─────────────────────┤
│4:                   │
│3:                   │
│2:                   │
│1:          # 123AFEh│
│## ### ### ### ### ##│
└─────────────────────┘


Now lets change example 1 to make use of the symbolic facilities of SASM48.
First recall [SRC1] and edit the string:

"
hexdig	EQU	#123AFE
pHXS	EQU	5
	GOSBVL	=SAVPTR 	** Save RPL pointers in save locations
**				   P is 0 , HEX mode enabled
	LA(6)	hexdig		** Load 6 HEX nibbles (represented by hexdig)
**				   into A Register , starting at P
	P=	pHXS		** Set P to the value specified by pHXS
	GOVLNG	=PUSHhxsLoop	** Push A[WP] onto Data stack
**				   and pass control to RPL
"

Store the string in SRC2, recall it back to the stack, then press [->COD].
The result looks like the result of example 1 except that the Library Data
now contains the values of the defined labels. When the stack shows:

┌─────────────────────┐
│                     │
├─────────────────────┤
│4:                   │
│3:                   │
│2:               Code│
│1:       Library Data│
│## ### ### ### ### ##│
└─────────────────────┘

press [SYM->] (located on the second menu page). The display changes to:

┌─────────────────────┐
│                     │
├─────────────────────┤
│4:                   │
│3:                   │
│2:               Code│
│1: "hexdig  EQU   #..│
│## ### ### ### ### ##│
└─────────────────────┘


Press the down-arrow key:

┌─────────────────────┐
│                  prg│
├─────────────────────┤
│                     │
│                     │
│"hexdig  EQU   #123..│
│pHXS    EQU   #5     │
│## ### ### ### ### ##│
└─────────────────────┘

This is the symbol table for SRC2. Press ATTN to return to the stack. DROP
the string in level 1 and store the Code object into 'XQ2'. Press [XQ2]. You
will get the same result as in example 1 because it's the same machine
language program.

You could even use [COD->] to disassemble the Code object in level 1.


Appendix C - Ordering Information
═════════════════════════════════


The sources of the <-RPL-> and the <-LIB-> libraries consists of more than
18000 lines of RPL/assembler code (that's more than 300kb of text !) and we
have spent our free time for more than two years in writing RPL48, so we
decided to release this version as GiftWare - ie. you can use RPL48 as long
as you like but only for developing non-comercial software and only as a
private person.

If you think RPL48 is useful and that the authors deserve to be rewarded for
the time they have invested in developing this toolkit, feel free to send
one of us (or both ;-) any sort of gift (even only a postcard will be
welcome).

If your gift covers the expense sending you a disk via SnailMail (costs
are: the disk, an envelope, the stamp and our time -> ~$25 or something
equivalent), we will send you the latest *whole* version of RPL48 on a
MesS-DOS formatted disk (including the <-RPL-> library branded with your
name in the startup message). Don't forget to include your name, address
and the disk size you prefer.

Developping commercial software using RPL48 requires registration via the
GiftWare concept; companies must send us at least a $50-worth gift for
registration.

Planned for the future are:
    - better ARRY support in <-RPL->
    - maybe a DIR support in <-RPL->
    - a built-in system RPL debugger (hairy)
    - a string editor (hairy)
    - better GX port of <-LIB->

(all without guaranteeing the implementation)

Contact addresses:

	Detlef Mueller
	Bellerbek 33
	D-22559 Hamburg
	Germany

	Tel:	+49 40 811 92 80	8:00pm - 0:00am CET + 1h ds
	FAX:    +49 40 589 58 199
	e-mail:	detlef@dmhh.hanse.de


	Raymond Hellstern
	Liebigstr. 8
	D-30163 Hannover
	Germany

	Tel./FAX +49 511 66 10 11
[ RETURN TO DIRECTORY ]