home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
USCX
/
BATPGMS.ZIP
/
PARSER.INC
< prev
next >
Wrap
Text File
|
1983-08-14
|
10KB
|
215 lines
;
; parser.inc
;
;
; This INCLUDE file implements a PSP command line parser of
; the following command line syntax:
;
; <byte count> [leading delims][ / [cmd1 [cmd2 cmd3] / ][ <string> ]
;
; where:
;
; <byte count> is a mandatory one-byte count of the rest of
; the characters in the command line.
; The byte count may be zero (null cmd line).
;
; leading delims are leading blanks or tabs before the first
; slash or the first non-blank character of
; <string>.
;
; cmdi is the ith one-character command code following
; the first "/" encountered on the line. These
; commands are executed as they are encountered
; during the left-to-right parsing of the line.
;
; <string> all characters, including any blanks or tabs,
; that follow the second slash if present; or
; all characters that follow leading blanks or
; tabs, if no slashes are present.
;
;
; on entry, this code expects the following register values:
;
; SI = offset of the byte count (the first byte of the line)
;
; this code trashes the following registers:
;
; AX, BX, CX, DX, possibly BP
;
; this parser discards any leading delimiters up to the first optional
; slash. It then decodes and executes any valid one-character commands
; found between the first and second slash encountered. The definition
; and execution of the commands is table driven, a table interface is
; provided by the host program that INCLUDEs this code. When the second
; slash is encountered, parsing is done. The CX register contains the
; number of string characters left after the second slash (including
; delimiters) or, if no slashes are encountered before the first non-
; delimiter, the number of string characters starting at the first non-
; delimiter. The BX register points to the corresponding character,
; relative to [SI].
;
; examples:
;
; null string parser finds no cmds CX = 0
; BX undefined
;
; <space><tab><space> parser finds no cmds CX = 0
; BX undefined
;
; / cmd1 parser executes cmd1 CX = 0
; BX undefined
;
; /<string> parser executes any valid CX = 0
; command characters found BX undefined
; in string
;
; /cmd1 cmd2/<tab><string> parser executes cmd1 and CX = count of
; cmd2. string +
; tab char
; BX points at tab
;
; <space><space><string> parser finds no commands CX = count of
; string only
; BX points at
; first char of
; string.
;
; This code expects the following table interface to be defined in the
; host code.
;
; CMD_TOTAL DW n ;total number of commands defined
;
; CMD_LETTERS DB 'cmd1','CMD1' ;two characters each of which
; . ; signify a command
; .
; DB 'cmdn','CMDn' ;(typically lower and upper case
; ; of one letter)
;
; CMD_OFFSETS DW offset_proc1 ;the corresponding procedure for
; . ;the command defined above
; .
; DW offset_procn ;(NEAR procedures in host code)
;
; symbols defined within the INCLUDE code will have a leading "_"
;
; equates
;
_TAB EQU 9 ;ascii TAB code
_BLANK EQU ' ' ;ascii BLANK code
_SLASH EQU '/' ;ascii '/' code
;
; start the parse
;
; if command line is empty, skip parsing, report back that CX = 0
;
;
_START_PARSE: SUB CX,CX ;zero CX
MOV CL,[SI] ;get char count from 1st byte
OR CL,CL ;is it zero?
JZ _PARSE_DONE ;done if yes, CX = 0
;
; cmd line is not null
;
; set up loop indices: CX = number of chars left in string
; BX = index relative to [SI] of the
; next character to be tested
;
SUB BX,BX ;initialize index (first iter
; of loop will increment BX
;
; parse leading blanks and tabs until either a "/" is found or else
; all leading blanks and tabs are discarded
;
_PARSE_BLANKS: INC BX ;point to next character in line
MOV AL,[SI][BX] ;next character into AL
CMP AL,_BLANK ;is it blank?
JZ _LOOP_BLANK ;keep parsing if yes
CMP AL,_TAB ;is it tab?
JZ _LOOP_BLANK ;keep parsing if yes
CMP AL,_SLASH ;is it first slash?
JZ _NEXT_CMD ;jump if yes, start decoding
; commands between slashes
JMP _PARSE_DONE ;else first non-blank non-tab
;delimiter.
;
; leading blank or tab found, continue looking for leading delimiters
;
_LOOP_BLANK: LOOP _PARSE_BLANKS
JMP _PARSE_DONE
;
; parse next character after first slash
;
_CMD_PARSE: MOV AL,[SI][BX] ;get next char in cmd line
CMP AL,_SLASH ;is it second slash?
JNE _CHECK_TABLES ;if not, go to tables to find
;the command.
;
; second slash found. parsing is done. point BX to next character and
; decrement CX so it equals characters left after second slash
;
INC BX ;leave BX pointing to next char
DEC CX ;leave CX as count of all chars
; after the second slash.
JMP _PARSE_DONE ;and exit this parser code
;
; set up inner loop to search through CMD_LETTERS table for a match of
; command characters with char in AL. If not in table, ignore character
; in AL and parse next character in cmd line.
;
_CHECK_TABLES: PUSH BX ;save outer loop context
PUSH CX
MOV CX,CMD_TOTAL ;table length for inner loop
SUB BX,BX ;clear index
;
; for each CMD_LETTERS 2-byte entry, check both characters for a match
;
_TABLE_LOOP: CMP AL,CMD_LETTERS[BX] ;does left byte match?
JE _DO_CMD ;jump if yes, do command
CMP AL,CMD_LETTERS[BX+1] ;else does right match?
JNE _MORE_TABLE
;
; command "letter" matches AL. After saving context, enter host-
; supplied procedure indirectly through corresponding entry in
; CMD_OFFSETS table.
;
_DO_CMD: PUSH AX ;save context
PUSH BX
PUSH CX
PUSH SI
CALL CMD_OFFSETS[BX] ;call indirect through table
POP SI
POP CX
POP BX
POP AX ;restore context
JMP _MORE_PARSE ;parse next char
;
; else haven't matched AL yet, so look at next table entry in inner loop
;
_MORE_TABLE: INC BX ;point to next word
INC BX
LOOP _TABLE_LOOP ;and loop on table length
;
; command definition table exhausted (so ignore this character) or
; character command was found in table and executed.
;
; restore outer loop context and parse the next character in line
;
_MORE_PARSE: POP CX ;restore outer loop context
POP BX
_NEXT_CMD: INC BX ;point to next char in cmd line
LOOP _CMD_PARSE ;parse until 2nd slash or CX=0
;
; CX is characters left after second slash
; or, characters left after leading delimiters if no slashes
; or, zero if no characters at all
; or, zero if no slashes and no non-blank or non-tab characters
; or, zero if no characters at all after second slash
;
; BX is pointing to corresponding character in string if CX > 0
; or, undefined if CX = 0
;
_PARSE_DONE LABEL NEAR ;done
;
; ------------ end of parser.inc ------------
;