Jaap's Psion II Page

                                CHAPTER 13

                                 _________
                                 UTILITIES



The operating  system  includes  several  utility  routines  likely  to  be
required by the general user.

The greatest care has gone into making these highly efficient,  since  they
are expected to be used frequently.

The majority of these routines are concerned with buffer handling,  integer
arithmetic and display handling.



      _______________________________
13.1  BUFFER HANDLING SYSTEM SERVICES

        _______
13.1.1  UT$CPYB

VECTOR NUMBER:          109
INPUT PARAMETERS:       X register - Address of source buffer.
                        D register - Address of destination buffer.
                        UTW_S0     - Number of bytes to be copied.
OUTPUT VALUES:          None.

DESCRIPTION

    Copies the buffer of length UTW_S0 at X to the buffer at D.

    The two buffers can overlap in any way required.  There may seem to  be
    a difficulty when they overlap, since simply copying in ascending order
    could then result in some source bytes being over-written before  being
    copied.   To  deal with this, if the source address is greater than the
    destination address the  bytes  are  copied  in  ascending  order,  and
    otherwise in descending order.

    The rate of copying large blocks of data is 81K per second.

    If UTW_S0=0 or if X=D, the routine does nothing.

EXAMPLE:

    Copies 1000 bytes from address SOURCE to address DESTINATION.

        LDD     #1000
        STD     UTW_S0:
        LDX     #SOURCE
        LDD     #DESTINATION
        OS      UT$CPYB

ERRORS:                None.



        _______
13.1.2  UT$ICPB

VECTOR NUMBER:          114
INPUT PARAMETERS:       X register - Address of one string.
                        UTW_S0     - Address of other string.
                        A register - length of string at X.
                        B register - length of string at UTW_S0.
OUTPUT VALUES:          B register -  0 : matched and same length.
                                    < 0 : string at X first alphabetically.
                                    > 0 : string at UTW_S0 is first
                                          alphabetically.
                        Z flag     - according to B register.
                        N flag     - according to B register.
REGISTERS PRESERVED:    X

DESCRIPTION

    Case independent buffer compare.  The bytes are compared  from  low  to
    high  memory.   If  the strings match but are of different lengths, the
    shorter string precedes the other alphabetically.

    So,
        "ABCD" precedes "bcd",
        "abcd" precedes "BCD",
        "A" precedes "AA",
        "ABCD","abcd" and "AbcD" are all equal.

EXAMPLE:

    Compares BUF1, length LENBUF1, with BUF2, length LENBUF2, branching
    according to the return value.

        LDX     #BUF1           ; point to buffer BUF1
        LDD     #BUF2
        STD     UTW_S0:         ; point to buffer BUF2
        LDA     A,#LENBUF1
        LDA     B,#LENBUF2
        OS      UT$ICPB
        BEQ     MATCHED         ; branch to code for matched strings
        BMI     BUF1FIRST       ; branch to code for BUF1 first
BUF2FIRST:                      ; here if BUF2 first

ERRORS:                None.



        _______
13.1.3  UT$FILL

VECTOR NUMBER:          113
INPUT PARAMETERS:       X register - Address of buffer to be filled.
                        A register - The buffer is filled with this byte.
                        B register - Number of bytes to be filled.
OUTPUT VALUES:          None.

DESCRIPTION

    Fills a buffer of the given length with the specified byte, filling two
    bytes  at  a  time  for  efficiency.  Nothing is done if the B register
    input equals 0.

    Because of the 110 microsecond overhead of  the  SWI  instruction  when
    calling this service, the following code would be faster for filling up
    to 13 characters:-

        LDA     B,NUMCHARS
LOOP:   STA     A,0,X           ; Store the fill character
        INX                     ; Point to the next byte
        DEC     B               ; Decrement the counter
        BNE     LOOP            ; Branch back up if the counter is not 0

EXAMPLES:

    Fill 100 bytes of buffer at address BUF1 with 0.

        LDX     #BUF1
        CLR     A
        LDA     B,#100
        OS      UT$FILL

    Fill 4 bytes of buffer at address BUF2 with spaces.

        LDX     #BUF2
        LDA     A,#^A/ /        ; ASCII space character specified
        LDA     B,#4
        OS      UT$FILL

ERRORS:                None.



        _______
13.1.4  UT$ISBF

VECTOR NUMBER:          115
INPUT PARAMETERS:       X register - Address of major buffer.
                        UTW_S0     - Address of minor buffer.
                        A register - Length of major buffer.
                        B register - Length of minor buffer.
OUTPUT VALUES:          B register - Position within major buffer,
                                     of found minor buffer, or length
                                     of major buffer if not found.

DESCRIPTION

    Finds the occurrence of the minor buffer at  UTW_S0  within  the  major
    buffer at X.

    If found, the return value is the index  within  the  major  buffer  at
    which the minor buffer occurs; otherwise the length of the major buffer
    is returned.  The index of the first letter of the major buffer is 0.

    For example, if the major buffer contains "APPLYING",
        1.  "PLYING" occurs at index 2
        2.  "APPLY" occurs at index 0
        3.  "APPLE" occurs at index 8 (the length of the "APPLYING")

EXAMPLE:

MAJOR_BUFFER:
        .ASCII  "APPLYING"      ; 8-character major buffer

MINOR_BUFFER:
        .ASCII  "PLYING"        ; this buffer's at index 2 in MAJOR_BUFFER

    The following finds and saves the index of MINOR_BUFFER within
    MAJOR_BUFFER, and then if found, makes the X register point to the
    found position in MAJOR_BUFFER.

        LDX     #MAJOR_BUFFER
        PSHX                    ; save address of MAJOR_BUFFER
        LDD     #MINOR_BUFFER   ; point to minor buffer
        STD     UTW_S0:
        LDD     #$0805          ; A=8, B=5
        OS      UT$ISBF
        PULX                    ; restore address of MAJOR_BUFFER
        STA     B,INDEX
        CMP     B,#8
        BEQ     NOT_FOUND
FOUND:                          ; here if found
        ABX                     ; X points to found position

ERRORS:                None.



        _______
13.1.5  UT$SPLT

VECTOR NUMBER:          119
INPUT PARAMETERS:       X register - Address of buffer to split field from.
                        UTW_S0     - Length of buffer.
                        A register - Field separator character.
                        B register - Field number to be split out.
OUTPUT VALUES:
                        If field was found then
                            X register - Address of field.
                            D register - Length of field.
                            C flag     - Clear.
                        else
                            UTW_S0     - Number of fields less than input
                                          specification, in the buffer.
                            C flag     - Set.

DESCRIPTION

    Finds the address and length of a field in a buffer  where  the  fields
    are  separated  by  the character specified.  No separator character is
    expected at the end of the last  field.   The  first  field  has  field
    number 0.

    If the field does not exist within the buffer, then 0  is  returned  in
    the  X  register,  and  UTW_S0  holds  the input field number minus the
    number of fields found in the buffer.  That is, if the sixth  field  is
    required and the buffer contains only two fields, 4 will be returned in
    UTW_S0.

EXAMPLE:

    Code to find address and length of the sixth field in a 500-byte
    buffer, with the separator character ':' between fields.

        LDX     #BUFFER
        LDD     #500                    ; length of BUFFER
        STD     UTW_S0:
        LDA     A,#^A/:/                ; separator is a colon
        LDA     B,#5                    ; 6th field has field number 5
        OS      UT$SPLT
        BCS     NOT_FOUND               ; C-flag set if not found
FOUND:  STD     FIELD_LENGTH
        STX     FIELD_ADDRESS

ERRORS:                None.



        _______
13.1.6  UT$UTOB

VECTOR NUMBER:          122
INPUT PARAMETERS:       X register - Address of destination buffer.
                        D register - Unsigned binary number for conversion.
OUTPUT VALUES:          B register - Length of converted ascii buffer.
REGISTERS PRESERVED:    X

DESCRIPTION

    Converts the unsigned binary number in D to ASCII decimal in the buffer
    at X, returning the length of the buffer in B.

EXAMPLE:

    Convert $ffff to count-preceded ASCII decimal buffer.
    Resulting bytes are: 5,'6','5','5','3','5' at BUFFER-1.

        LDX     #BUFFER
        LDD     #$FFFF          ; $FFFF = 65535 decimal
        OS      UT$UTOB         ; preserves X
        DEX                     ; point one before BUFFER
        STA     B,0,X           ; length into count-byte

ERRORS:                None.



        _______
13.1.7  UT$XTOB

VECTOR NUMBER:          124
INPUT PARAMETERS:       X register - Address of destination buffer.
                        D register - Unsigned binary number for conversion.
OUTPUT VALUES:          B register - Length of converted ascii buffer.
REGISTERS PRESERVED:    X

DESCRIPTION

    Converts the unsigned binary number in D to ASCII  hexadecimal  in  the
    buffer at X, returning the length of the buffer in B.

EXAMPLE:

    Convert 2475 to count-preceded ASCII hexadecimal buffer.
    Resulting bytes are: 3,'9','A','B' at BUFFER-1.

        LDX     #BUFFER
        LDD     #2475           ; 2475 decimal = $9AB
        OS      UT$UTOB         ; preserves X
        DEX                     ; point one before BUFFER
        STA     B,0,X           ; length into count-byte

ERRORS:                None.



      ________________________________
13.2  DISPLAY HANDLING SYSTEM SERVICES

These services provide complex display handling,  displaying  any  required
parameters  according to the format control string parameter.  Display will
start at the cursor position.

_________________________
THE FORMAT CONTROL STRING
Format descriptors interspersed between literal text in the format control
string, allow the display of variables formatted in the specified way. In
the simplest case, these descriptors are prefixed by a '%' character
followed by the type-specifier, in which case the text is displayed left
justified at the cursor position.
      __________                ____________________
      descriptor                type to be displayed
        %a              ASCII coded character
        %i              signed integer word value
        %j              signed integer byte value
        %u              unsigned integer word value
        %v              unsigned integer byte value
        %x              unsigned integer word value in HEX
        %y              unsigned integer byte value in HEX
        %s              string that has a leading byte count
        %b              text buffer (address and length byte given)
        %f              fill field (for this type a field width
                        must be included; see below)

Optionally, the programmer can justify the text within a field of chosen
width, where the field is filled with a specified character. A number
after the '%' signifies the field width within which the text is to be
left justified with the SPACE fill character. Instead of '%', '+' can be
used for left and '-' for right justification, followed by the mandatory
fill character and field width.

The maximum field width is 99 and vertical scrolling will begin after the
text fills the whole LCD display. If the field is not wide enough, the text
is truncated on the side opposite to the justification specified (e.g. right
justification causes truncation on the left).

For convenience, '}' has been defined as equivalent to the commonly used
descriptor "-02v".

The required format for a descriptor field is therefore
        %[<field width>]<type specifier>
or
        +<fill character><field width><type specifier>
or
        -<fill character><field width><type specifier>.

Some examples:
        "%x"    - left justified HEX representation of word integer.
        "%6x"   - left justified HEX representation of word integer,
                  filling to the right with spaces in field width of 6.
        "-06x"  - right justified HEX representation of word integer,
                  filling to the left with zeroes.
        "-*14i" - right justification of a signed word integer parameter
                  in a 14-byte field, filled to the left with stars.
        "%18f"  - 18 spaces.
        "+*18f" - 18 stars ('+' needed only to specify the star).

All display is done through the service routine DP$EMIT (see section
8.3.4), so that control characters (such as 16 for beep) can be used in the
format control string.

The characters '%', '+', '-' and '}' themselves can be displayed by
preceding them by an extra '%' character.
        ________________________        ________ ______ _______ ______
E.g.     Sequence to be displayed        Required format control string
        70% + 3% - 1%                   "70%% %+ 3%% %- 1%%"
        %%                              "%%%%"
        ++                              "%+%+"
        --                              "%-%-"
        {2/{3*4}}                       "{2/{3*4%}%}"

_______________________________
PASSING THE VARIABLE PARAMETERS
Variable parameters must be pushed onto the machine stack in reverse order
to that in which they will be displayed. For a buffer parameter, the length
byte must be pushed before the address.

________
WARNINGS
    The variable parameters must correspond in number and in type to the
    specification of the format control string.

    The type-specifiers must be in lower-case.



        _______
13.2.1  UT$DISP

VECTOR NUMBER:          111
INPUT PARAMETERS:       On machine stack - variables to display.
OUTPUT VALUES:          None.

DESCRIPTION

    Displays literal text and variables according  to  the  format  control
    string  which  is  inserted in-line directly after the operating system
    call to UT$DISP.  The LCD display  is  not  cleared  and  the  text  is
    displayed from the current cursor position.

    See the general discussion for this section for details of  the  format
    control string and the passing of parameters on the stack.

EXAMPLES:

    To display "A simple string" after clearing the screen.

        OS      UT$DISP
        .BYTE   D_FF            ; clear display - control character 12
        .ASCIZ  "A simple string"

    To display an unsigned word variable. If WORD_VAR contains 43210
    for instance, "WORD_VAR=43210" will be displayed.

        LDX     WORD_VAR
        PSHX                    ; push word variable value
        OS      UT$DISP
        .ASCIZ  "WORD_VAR=%u"   ; the format control string

    To display a signed word variable, right justified in a field width of
    9. If WORD_VAR contains -3210 for instance, "WORD_VAR=    -3210" will
    be displayed.

        LDX     WORD_VAR
        PSHX                    ; push word variable value
        OS      UT$DISP
        .ASCIZ  "WORD_VAR=- 9i"

    To display the date and time in the form
                ------------------
                |TUE 18 NOV 1986 |
                |    17:40:35    |
                ------------------
    where the order of the system variables in memory are:
        TMB_YEAR,TMB_MONS,TMB_DAYS,TMB_HOUR,TMB_MINS,TMB_SECS

MONTH_NAME_TABLE:
        .ASCII  "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"

DISPLAY_DATE_TIME:
        LDX     #TMB_YEAR       ; point to 6-byte date/time buffer
        LDD     4,X             ; minutes into A, seconds into B
        PSH     B
        PSH     A
        LDA     A,3,X           ; hour into A
        PSH     A
        LDD     0,X             ; year into A, month into B
        PSH     A
        LDA     A,#3            ; month names are 3 characters long
        PSH     A               ; buffer length pushed before address
        MUL                     ; multiply index into table by 3
        LDX     #MONTH_NAME_TABLE
        ABX                     ; point to month name
        PSHX                    ; push address of month buffer
        LDX     #TMB_YEAR
        LDA     A,2,X           ; day of month into A
        INC     A               ; day 0 means 1st of month
        PSH     A
        LDA     A,#3
        PSH     A               ; day (of week) name length
                                ; X still points to 6-byte date buffer
        OS      TM$DAYV         ; puts address of day name into X
        PSHX
        OS      UT$DISP
        .BYTE   D_HM            ; HOME the cursor - control character 11
        .ASCII  "%b - 2v %b 19}"
        .ASCIZ  "%5f}:}:}%4f"   ; must fill display as not cleared
        RTS

ERRORS:                None.



        _______
13.2.2  UT$DDSP

VECTOR NUMBER:          110
INPUT PARAMETERS:       D register - address of format control string.
                        On machine stack - variables to be displayed.
OUTPUT VALUES:          None.

DESCRIPTION

    Displays literal text and variables according  to  the  format  control
    string  the  address of which is in the D register.  The LCD display is
    not cleared and the text is displayed from the current cursor position.

    This is identical to UT$DISP except that the format control  string  is
    not inserted in-line.

    See the general discussion for this section for details of  the  format
    control string and the passing of parameters on the stack.

EXAMPLE:

    To clear the display and then display "A simple string".

CONTROL_STRING:
        .BYTE   D_FF            ; clear display - control character 12
        .ASCIZ  "A simple string"

DISP:   LDD     #CONTROL_STRING  ; D points to format control string
        OS      UT$DDSP

    See UT$DISP for further relevant examples, where the only difference is
    that in that routine the format control string is inserted in-line.

ERRORS:                None.



      __________________________________
13.3  INTEGER ARITHMETIC SYSTEM SERVICES

        _______
13.3.1  UT$SDIV

VECTOR NUMBER:          117
INPUT PARAMETERS:       X register - Numerator.
                        D register - Denominator.
OUTPUT VALUES:          X register - Quotient.

DESCRIPTION

    2-byte by 2-byte signed integer division  routine.   Divides  X  by  D,
    putting the result into X.

EXAMPLE:

        LDD     SIGNED_DENOMINATOR
        BEQ     ERROR           ; divide by zero not checked for in UT$SDIV
        LDX     SIGNED_NUMERATOR
        OS      UT$SDIV
        INX                     ; test X
        DEX
        BMI     NEGATIVE_QUOTIENT

ERRORS:                None.

BUGS

    Does not check for division by zero, which will cause an infinite loop.



        _______
13.3.2  UT$SMUL

VECTOR NUMBER:          118
INPUT PARAMETERS:       X register - Signed integer.
                        D register - Signed integer.
OUTPUT VALUES:          X register - Less significant word of product.
                        D register - More significant word of product.

DESCRIPTION

    2-byte by 2-byte signed integer multiply routine.  Multiplies  D  by  X
    putting  the  product  back into D and X.  The more significant word of
    the product goes into D.

EXAMPLE:
        LDX     SIGNED_MULTIPLIER
        LDD     SIGNED_MULTIPLICAND
        OS      UT$SMUL
        TST     A                       ; test the most significant byte
        BMI     NEGATIVE_PRODUCT



        _______
13.3.3  UT$UDIV

VECTOR NUMBER:          120
INPUT PARAMETERS:       X register - Numerator.
                        D register - Denominator.
OUTPUT VALUES:          X register - Quotient.
                        D register - Remainder.
                        UTW_S2     - Quotient (a copy of X).

DESCRIPTION

    2-byte by 2-byte unsigned integer division routine.  Divides  X  by  D,
    putting  the  quotient into X and also into UTW_S2, and X modulo D into
    D.

EXAMPLE:
        LDD     UNSIGNED_DENOMINATOR
        BEQ     ERROR           ; divide by zero not checked for in UT$SDIV
        LDX     UNSIGNED_NUMERATOR
        OS      UT$UDIV
        STX     QUOTIENT
        STD     REMAINDER

ERRORS:                None.

BUGS

    Does not check for division by zero, which will cause an infinite loop.



        _______
13.3.4  UT$UMUL

VECTOR NUMBER:          121
INPUT PARAMETERS:       D register - unsigned integer.
                        X register - unsigned integer.
OUTPUT VALUES:          D register - More significant word of product.
                        X register - Less significant word of product.
                        UTW_S1     - More significant word of product.
                        UTW_S2     - Less significant word of product.

DESCRIPTION

    2-byte by 2-byte unsigned integer multiply routine.  Multiplies D by  X
    putting  the  product  back  into  D  and  X, (and also into UTW_S1 and
    UTW_S2).  The more significant word of the product  goes  into  D  (and
    into UTW_S1).

EXAMPLE:
        LDX     UNSIGNED_MULTIPLIER
        LDD     UNSIGNED_MULTIPLICAND
        OS      UT$UMUL

ERRORS:                None.



      _____________________________
13.4  MISCELLANEOUS SYSTEM SERVICES

        _______
13.4.1  UT$ENTR

VECTOR NUMBER:          112
INPUT PARAMETERS:       X register - Address of routine to be entered.
                        D register - Parameter to be passed to the routine.
OUTPUT VALUES:          B register - Code number (generally an error code).
                        C-flag     - Clear if B register is zero, else set.

DESCRIPTION

    Allows a routine at X to be called in such a way that it may be  exited
    from  any  of  the  routines  nested  within it.  The parameter in D is
    passed to the routine at X.

    The most important use for UT$ENTR (together with UT$LEAV) is for error
    handling:  they can mimic the ON ERROR and RAISE facilities in OPL.

    UT$ENTR establishes a new  control  region,  meaning  that  an  entered
    routine  can be terminated early by a call to UT$LEAV.  That is, any of
    the routines (to any depth) used within the entered  routine  can  call
    UT$LEAV  which  will  cause 'immediate' return to the instruction after
    the call to UT$ENTR.  The B register will then contain the value passed
    to UT$LEAV.

    So, in the same way that an 'RTS' instruction causes control to  return
    from  a  normal  subroutine to the calling routine, the call to UT$LEAV
    causes control to return from within UT$ENTR to the routine that called
    UT$ENTR.  In both cases the stack is adjusted appropriately for return.

    Calls to UT$ENTR can be nested to any depth, with a control region  for
    each  call.  UT$LEAV dis-establishes only the most recently established
    region, returning to the instruction after the last UT$ENTR call.

    Note that a new control  region  is  disestablished  either  by  normal
    return  from  UT$ENTR,  or  by  a call to UT$LEAV within the new region
    (unless called within a nested control region).

    The entered routine must return an appropriate code number (generally 0
    to indicate non-error) in the B register.

    The locations UTW_S1 through UTW_S5 may be used for passing  parameters
    to the entered routine.  UTW_S0 is corrupted prior to entry, however.

    See UT$LEAV in section 13.4.2.

    This routine is best illustrated by the examples.

EXAMPLES:

    To enter ROUTINE_1, which calls other routines, any of which may call
    UT$LEAV on error. Pass the value 1 to ROUTINE_1.

ENTER_ROUTINE_1:
        LDX     #ROUTINE_1      ; UT$ENTR calls the routine at address X
        LDD     #1              ; Set parameter for ROUTINE_1
        OS      UT$ENTR         ; Establish new control region
; Region now dis-established
        BCS     ERROR           ; On error, B set to error code, C-flag set
        RTS

ROUTINE_1:
        STD     ROUTINE_1_PARAMETER
        BCC     NO_ERROR_1
        LDA     B,#ERROR_CODE_1
        OS      UT$LEAV ; return B to ENTER_ROUTINE_1, setting C-flag
NO_ERROR_1:
        JSR     ROUTINE_2       ; if either of these 2 routines call
        JSR     ROUTINE_3       ;   UT$LEAV, control doesn't return to
                                ;   this routine
        CLR     B               ; B must be cleared to indicate non-error
        RTS

ROUTINE_2:
        .
        .
        BCC     NO_ERROR_2
        LDA     B,#ERROR_CODE_2
        OS      UT$LEAV ; return B to ENTER_ROUTINE_1, setting C-flag
NO_ERROR_2:
        RTS                     ; no need to clear B here as not called
                                ; directly by UT$ENTR


    The following example establishes nested control regions,
    clarifying where control continues after calling UT$LEAV. (In this
    example, 0 in the B register is used to signify non-error return from
    UT$ENTR).

MAIN:
        .
        .
        LDX     #REGION_1
        LDD     P1              ; set D to parameter for REGION_1
        OS      UT$ENTR         ; Establish a new control region
; REGION_1 now dis-established
        BCS     ERROR           ; On error, B set to error code, C-flag set
        RTS

REGION_1:
        STD     PARAMETER_1
        .
        .
        BCC     NO_ERROR_1
        LDA     B,#CODE1
        OS      UT$LEAV         ; return B register to MAIN, setting C-flag
NO_ERROR_1:
        JSR     RTN1            ; if RTN1 calls UT$LEAV,
        .                       ;    control returns to MAIN
        .
        LDX     #REGION_2
        LDD     P2              ; set D to parameter for REGION_2
        OS      UT$ENTR         ; Establish a new control region
; REGION_2 now dis-established
        BCS     ERROR           ; On error, B set to error code, C-flag set
        CLR     B               ; B must be cleared for normal return
        RTS

REGION_2:
        STD     PARAMETER_2
        .
        .
        BCC     NO_ERROR_2
        LDA     B,#CODE2
        OS      UT$LEAV         ; return to REGION_1, setting C-flag
NO_ERROR_2:
        JSR     RTN2            ; if RTN2 calls UT$LEAV,
                                ;    control returns to REGION_1
        .
        .
        LDX     #REGION_3
        LDD     P3              ; set D to parameter for REGION_3
        OS      UT$ENTR         ; Establish a new control region
; REGION_3 now dis-established
        BCS     ERROR           ; On error, B set to error code, C-flag set
        CLR     B               ; B must be cleared for normal return
        RTS

ERRORS:                None.



        _______
13.4.2  UT$LEAV

VECTOR NUMBER:          116
INPUT PARAMETERS:       B register - Code number to be returned by UT$ENTR.
OUTPUT VALUES:          B register - Code number to be returned by UT$ENTR.
                        C-flag     - Clear if B register is zero, else set.

DESCRIPTION

    SEE UT$ENTR for full description of control regions.

    Causes an exit from the control region established by the  most  recent
    UT$ENTR  call.   Execution resumes as if UT$ENTR had returned the value
    in the B register,  so  that  UT$LEAV  never  returns  to  the  calling
    routine.   Routines  to  any  depth  may be terminated early by calling
    UT$LEAV, provided that all are dynamic  descendants  of  at  least  one
    UT$ENTR call.

EXAMPLE:

    (SEE UT$ENTR for more examples).

    To restart a routine after each error message.

LOOP:
        LDX     #ERROR_PRONE_ROUTINE
        LDD     PARAMETER
        OS      UT$ENTR
        BCC     EXIT_LOOP
        JSR     DISPLAY_MESSAGE        ; display the message corresponding
                                        ;     to the value in B
        BRA     LOOP
EXIT_LOOP:

  (Then in any of ERROR_PRONE_ROUTINE's dynamic descendants UT$LEAV may
   be called with the appropriate error code in B.)

DYNAMIC_DESCENDANT:
        .
        .
        BCC     NO_ERROR
        LDA     B,#ERROR_CODE_1
        OS      UT$LEAV         ; cause UT$ENTR to return B, setting C-flag
NO_ERROR:

ERRORS:                None.



        _______
13.4.3  UT$XCAT

VECTOR NUMBER:          123
INPUT PARAMETERS:       UTW_S0     : record type of filename ($81 to $8F)
                                     - least significant byte only.
OUTPUT VALUES:          None.

DESCRIPTION

    See chapter 12 for description of OS file handling.

         Displays all filenames of the  given  record  type  (in  the  byte
    UTW_S0+1) on the current device.  A record type of $81 in UTW_S0+1 will
    do a directory of files, as in the OPL DIR$  function,  and  any  other
    value  up  to  $8F  inclusive will do a directory of block files of the
    given type.

    Waits for EXE or ON/CLEAR to be pressed after displaying each filename.
    If  EXE is pressed the next filename is displayed, while ON/CLEAR exits
    UT$XCAT.

    Displays "END OF PACK" message when no more filenames found,  and  then
    pressing EXE displays the first filename again, and ON/CLEAR exits.

    Other error messages possibly reported are for

    1.  no pak in slot

    2.  bad or damaged pak in slot

    3.  an invalid pak selected

    after any of which UT$XCAT is exited.

    See also sections 12.2.2 FL$BCAT, 12.1.3 block files, 12.1.2 files.

EXAMPLE:

    Display names of all diary files saved.

DIARY_DIRECTORY:
        LDA     A,#BDIATYP  ; BDIATYP ($82) is diary filename record type
        STA     A,UTW_S0+1: ; Store in LSB of UTW_S0
        OS      UT$XCAT

ERRORS:                None.



        _______
13.4.4  UT$YSNO

VECTOR NUMBER:          125
INPUT PARAMETERS:       None.
OUTPUT VALUES:          B register - The key pressed.
                        C-flag     - Set for 'Y' or 'y' pressed.
                                   - Clear for 'N', 'n' or ON/CLEAR.

DESCRIPTION

    Waits for 'Y', 'y', 'N', 'n' or ON/CLEAR to be pressed,  returning  the
    key  pressed  in B.  If 'Y' or 'y' pressed, return C-flag set.  If 'N',
    'n' or ON/CLEAR, return C-flag clear.

    UT$YSNO calls KB$STAT to set  the  keyboard  to  alpha  shift,  so  the
    previous keyboard status will be destroyed.

EXAMPLE:

    Display " Y/N" then call UT$YSNO.

        OS      UT$DISP
        .ASCIZ  " Y/N"
        OS      UT$YSNO

ERRORS:                None.