Filters

Filters, as provided on the Z88, are a fairly general means of achieving simple context-independent transformations in a character sequence. Their anticipated use is in simple text processing, but they may potentially be used for more complex tasks. The calls for handling filters are:

GN_Flo      open a filter, returning a filter handle
GN_Flw      write a character to a filter
GN_Flr      read a character from a filter
GN_Fpb      push a character back into the filter
GN_Flf      flush the filter
GN_Flc      close the filter

To use a filter, the programmer must first set up a 'Filter Definition Table' (FDT), which determines the operation of the filter. The filter must then be opened with GN_Flo with the programmer giving the address of the FDT and setting various input parameters. GN_Flo returns a filter handle which the other filter routines takes as input. Once open the filter can be written to a byte at a time using GN_Flw and read from (again a byte at a time) using GN_Flr. The bytes read out of the filter will be the processed form of the input; if processing has occurred on a particular character this is indicated ny Fz = 1 on return from GN_Flr. While the filter is open, it can be flushed, ie. all the characters written to it, but not read out, can be discarded. It is also possible to push one character back into the filter, before a subsequent filter read takes place. Finally the filter is closed using GN_Flc, which apart from freeing the handle and buffers associated with the filter also returns information as to how many characters have been written to and read from the filter.

Note that filters can be used with a number of GN calls, in place of a source or destination which is in memory or a stream. Calls which can operate with filter are:

GN_Fcm      compress a filename
GN_Fex      expand a filename
GN_Gdn      convert ASCII decimal string to integer
GN_Pdn      convert integer to ASCII decimal string
GN_Gtm      convert ASCII string to internal time
GN_Ptm      convert internal time to ASCII string
GN_Pdt      convert internal date to ASCII string
GN_Gdt      convert ASCII string to internal date
GN_Skc      skip character
GN_Skd      skip to delimiter
GN_Skt      skip to value

How the filter works 

The filter definition table provides a list of strings to be searched for in the input sequence, and when one is found it will replace the found string with a replacement string also specified in the table. The table might contain the contain the following pairs of strings:

            Search      Replace
            Monday      Mon
            Tuesday     Tue
            Wednesday   Wed
            Thursday    Thu
            Friday      Fri
            Saturday    Sat
            Sunday      Sun

If the characters M,o,n,d,a,y - were pushed into the filter, then the characters pulled from the other end (via GN_Flr) would be: M,o,n - and then and 'End of file' return code, RC_EOF ($09), would be encountered. Thus the filter provides a convenient means of performing simple text processing.

Because the filter can only search for strings to substitute amongst characters which are 'in' the filter, the normal use is to push in the entire input string and pull out the entire result, each in one go. Also note that the filter routine will select the first successful match in the FST, so if one of the search strings is an extension of another, the longer should come first if the obvious substitution is required. For instance:

            Mon         Lundi
            Monday      Lundi

would result in the transformation of "Monday" into "Lundiday"; probably not what was intended. 
 

Filter Definition Table

2 bytes     Size of FDT in bytes
1 byte      Options for left-hand strings
1 byte      Options for right-hand strings

The options for the strings may be made up of some combination of the following bit settings:

            128         Table has top bit set characters (ISO standard)
            64          Table has numeric data
            32          Table has alphabetic data
            16          Table has punctation characters

Then come the entries, with the following format:

1 byte      1+m
m bytes     search string
1 byte      1+n
n bytes     replacement string

The 'length bytes are actually a displacement to the character beyond the next string, hence they are one greater than the length of the string.

RESTRICTIONS: The FDT must not span a 16K boundary, and due to a software bug, the FDT must be addressed in segment 1.

The filter calls are fully specified in System Calls Reference
 

Example
include "memory.def"                ; memory call definitions
include "stdio.def"                 ; standard I/O definitions
 
; it is assumed that this code would be running in segment 3 
; - it finds out which bank it is running in and binds this bank to segment 1 
; Note that the binding of segment 3 does not change 
; 
; the routine assumes the address of the string is held at 
; the static address 'input_string' 
; 
; the effect of the routine is to abbreviate full day names 
; to the 3 character day names 

.abbreviate ld   c, MS_S3           ; assumes table is in segment 3
            oz   OS_Mgb             ; get binding of segment 3
            ld   c, MS_S1
            oz   OS_Mpb             ; bind table into segment 1. Note bank
                                    ; is still bound to segment 3
            ld   hl, fdt_Table      ; start address of table
            ld   a,h
            and  @00111111          ; mask out segment bits (15, 14)
            or   MM_S1              ; merge memory mask for segment 1
            ld   h,a                ; HL now addresses segment 1

            ld   a, 4               ; buffer size in B
            ld   b, 30              ; buffer size
            oz   GN_Flo             ; open filter
            ret  c                  ; exit if error

            ld   hl, (input_string) ; address of string to process
.loop       ld   a,(hl)
            cp   0
            jr   z, end_loop
            oz   GN_FPW             ; write character to filter
            inc  hl
            jr   loop

.end_loop   oz   GN_Flr             ; pull character from filter
            jr   c, finished        ; exit if last one or error
            oz   OS_Out             ; write converted char to std. output
            jr   end_loop

.finished   oz   GN_Flc             ; close the filter
            oz   GN_Nln             ; new line
            ret

.fdt_start  defw fdt_end-fdt_start  ; length of FDT
            defb 32                 ; search string alphabetic
            defb 32                 ; replace string alphabetic

            defm 7, "Monday"        ; abbreviate Monday
            defm 4, "Mon"

            defm 8, "Tuesday"       ; abbreviate Tuesday
            defm 4, "Tue"

            defm 10, "Wednesday"    ; abbreviate Wednesday
            defm 4,  "Wed"

            defm 9, "Thursday"      ; abbreviate Thursday
            defm 4, "Thu"

            defm 7, "Friday"        ; abbreviate Friday
            defm 4, "fri"

            defm 9, "Saturday"      ; abbreviate Saturday
            defm 4, "Sat"

            defm 7, "Sunday"        ; abbreviate Sunday
            defm 4, "Sun"

.fdt_end                            ; end of table