Previous Next Contents

5. System RPL Specifications

This section is designed for System RPL programmers who wish to use FNT1 and/or FNT2 in their own applications. If you just need the UFL for an application you want to use, you don't have to read this section.

In order to use System RPL or HP48 machine language you need a compiler/assembler such as Jazz or GNU-Tools. See the HP48 FAQ for more information on how to get started programming in System RPL.

5.1 Programmer's Interface

The programmers' interface to the UFL has been designed to simplify checking existence of fonts as well as allowing for future expansion if necessary.

Due to the requirements of the Font Maintenance Package (FMnt) we had to go with fixed XLIBs for each font. However, we tried to do this in a way that didn't restrict further growth of the UFL, while at the same time minimizing overhead. This is the result we came up with:

ROMPTR 101 0    xFNT            ( user-accessible )
ROMPTR 101 1    Font
ROMPTR 101 2    Font?
ROMPTR 101 3    FNT1
ROMPTR 101 4    FNT2

ROMPTR 101 5 and on are for future expansion if necessary.

Notice that once the checking for fonts has been done, there is no performance loss imposed by using the UFL because the application using the fonts can call the appropriate XLIBs directly.

Libraries that do not have FNT1 or FNT2 respectively will still have the XLIBs in the above order, however if you try to recall the font that doesn't exist you will get an error. See the next section for more information.

5.2 Behaviour of each XLIB

Since there is more than one UFL library, the behaviour of the XLIBs in each library must be consistently defined. The following standard is defined:

xFNT (ROMPTR 101 0)

This is a user-accessible XLIB that accepts either a real or system binary and recalls the specified font if it exists. Otherwise it issues the error "Font not Found" and leaves the original argument on the stack.

Font (ROMPTR 101 1)

This is a nullnamed equivalent to xFNT that only accepts a system binary. It either recalls the specified font or issues the error "Font not Found" and drops the system binary.

Font? (ROMPTR 101 2)

Accepts a system binary and returns TRUE or FALSE depending on whether the font number specified exists or not.

FNT1 (ROMPTR 101 3)

Either returns FNT1 directly as a Library Data object or issues the error "Font not Found" if you neglected to check if FNT1 actually exists with Font or Font? first.

FNT2 (ROMPTR 101 4)

Either returns FNT2 directly as a Library Data object or issues the error "Font not Found" if you neglected to check if FNT2 actually exists with Font or Font? first.

5.3 Coding Standards

With font standards come coding standards. We recommend you create a file called ufl.h containing the following defines:

DEFINE  xFNTSTR         $ "FNT"
DEFINE  xFNT            ROMPTR 101 0
DEFINE  Font            ROMPTR 101 1
DEFINE  Font?           ROMPTR 101 2
DEFINE  FNT1            ROMPTR 101 3
DEFINE  FNT2            ROMPTR 101 4

You should then include this at the start of your program with:

        INCLUDE ufl.h

Furthermore, the check for existence of the UFL has been standardized with the following code, which will return TRUE or FALSE depending on whether the UFL library exists or not:

NULLNAME UFL?
::
 xFNTSTR palparse DROP ' xFNT EQUAL
;

You should check this at the start of your program. If it returns FALSE you should generate the error "UFL not Found".

The only exception to the above check should be if you need to check for the UFL in a library config routine. In that case the above code will not work because palparse is not valid at config time. If this is the case, you will have to use the following, inferior check:

NULLNAME UFL?
::
 ' Font ROMPTR@ NOTcaseFALSE DROPTRUE
;

Once again, do not use this alternative method if you do not have to! The only case where there should be a need for this check is in replacement stack programs such as Java.

For the font checks themselves, you do not have to provide the error message yourself. Instead, you can take advantage of the fact that the UFL will generate an error for you. See the Examples section for details.

5.4 Summary of Usage

Named XLIBs:

Nullnamed XLIBs:

5.5 Examples

Let's say someone wants to write a library that only needs FNT1. The simplest way to use the UFL would be something like:

xNAME   UFLTEST
::
 CK0
 FNT1 DROP                      ( Two possible errors - see below )
 ...
 FNT1
 ...
;

Notice that FNT1 (or ONE Font) will provide an appropriate error message "Font not Found" for you if the font you want doesn't exist. Another possibility is that the UFL library doesn't exist at all, in which case the above example will cause Error: Undefined XLIB Name.

This error isn't very informative, so if possible you should use the UFL? check given earlier to generate the standard error "UFL not Found". If you are making a library you should add this error to your message table. With these changes the improved code segment becomes something like:

ASSEMBLE
=xxMESSAGE
RPL
ARRY
[
 "UFL not Found"
]

DEFINE  UFLErr  #xxxxx

xNAME   MYLIB
::
 CK0
 UFL? NOTcase :: UFLErr ERROROUT ;
 FNT1 DROP
 ...
 FNT1
 ...
;

NULLNAME UFL?
::
 xFNTSTR palparse DROP ' xFNT EQUAL
;

The UFL? check does not necessarily have to be its own nullnamed XLIB, but it is handier that way if you have more than one place to check it in. Alternatively, for the above example we could use the following method that does everything in one place and is slightly smaller:

NULLNAME UFL?DoErr
::
 xFNTSTR palparse DROP ' xFNT EQUALNOTcase :: UFLErr ERROROUT ;
 FNT1 DROP
;

This checks both for the existence of the UFL and errors if FNT1 does not exist. This way, each user accessible XLIB only needs to call UFL?DoErr once. After it has passed the checks you are free to use FNT1 directly. These methods also have the benefit that they allow error trapping for your routines when called by external programs.

Of course, everything above applies to FNT2 as well, you would just replace all references to ONE with TWO and FNT1 calls with FNT2. If you need both then you would just use an appropriate combination of FNT1, FNT2, Font, and/or Font? calls that check both.

5.6 Conversion of Existing Programs to the UFL

Conversion of existing programs that have their own copies of FNT1 or FNT2 should be relatively straightforward. The two steps are:

5.7 Stack Access and Purging

One gotcha when using the UFL is the fact that if your program allows access to the stack, the user might actually purge the UFL while you are using it! This also applies if you are writing some sort of file browser that allows people to purge files. In Java we deal with this by simply binding a LAM to something small in the UFL to prevent purging. For example:

::
 ... Check existence of UFL as above ...
 ' Font? ROMPTR@ DROP { LAM #whatever } BIND
 ...
 ABND
;

If the user tries to purge the UFL with the above LAM bound, they will get Error: Object in Use.


Previous Next Contents