home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
tasm
/
iparam.asm
< prev
next >
Wrap
Assembly Source File
|
1988-08-28
|
13KB
|
357 lines
; FILENAME: IPARAM.ASM
;
; Copyright (c) 1988 by Borland International
;
; DESCRIPTION: This module implements two routines that manage the
; command line parameters passed to the program. The routine ParamCount
; returns the number of parameters passed to the program while the
; routine ParamString returns a pointer to the referenced parameter
; string. This module uses ideal mode syntax.
;
; ASSEMBLY INSTRUCTIONS: To assemble this module use the following
; TASM command line.
;
; TASM /dMDL=memorymodel iparam
;
; 'memorymodel' in the above command line may be replaced by TINY, SMALL,
; MEDIUM, COMPACT, LARGE or HUGE. If assembling this module to run on
; a 286/386 machine, turn on the P286 directive in order to take advantage of
; 286/386 specific instructions. I.E.
;
; TASM /dMDL=memorymodel /jP286 iparam
;
; NOTE: This module requires that the main program declare and initialize
; the global variable PspAddress.
%tabsize 4
ifndef MDL
display "Error: This module requires that you provide a memory model"
display " definition on the command line. I.E. /dMDL=SMALL."
err ; Force a fatal error
else
ideal ; Use TASM's Ideal mode
model MDL ; Define the memory model
include "dos.inc"
include "idos.inc"
include "kbd.inc"
NotCalled equ 0FFh ; ParamCount was already called once
if @DataSize eq 0 ; Declare the appropriate type of data
dataseg ; segment depending on the memory model.
else
far_data
endif
; Declare variables to store the parsed parameters and parameter
; count.
ParmCount DB NotCalled ; ParamCount initializes this variable
; the first time it is called.
ParmList DB 7Fh DUP (?) ; Allocate enough space for a 127
; character command line
global PspAddress:word ; Define extrn variable
codeseg
global ParamCount:proc ; Public procs
global ParamString:proc
global LocateString:proc ; Declare external procs
global FindBytePos:proc
global FindAndReplace:proc
global ByteCopy:proc
global SkipSpaces:proc
proc ParamCount
; This routine returns the number of command line parameters passed to
; the program. Parameters are delimited by spaces or tabs. Double or
; single quotes can enclose parameters that include spaces or tabs
; inside them.
;
; While the function is parsing the command line it stores copies of
; each of the parameters in the modules data segment. The strings are
; stored in Turbo Pascal format. That is they are stored with a
; preceeding length byte. The first time the routine is called it also
; stores the result in the variable ParmCount in the modules data
; segment. Any subsequent calls simply return the contents of
; ParmCount.
;
; Input
; none
; Output
; al - Number of parameters
; Calling conventions
; NA
; Registers modified
; ax, bx, cx, DX, di, si, es, Flags
local SearchChar:byte=LocalSymbolSize ; Declare local variables
push bp ; Set up stack
mov bp, sp
sub sp, LocalSymbolSize ; Make room for local variables
; Point es:di to location where the parsed parameters will be stored
if @DataSize eq 0
mov ax, @data ; Using near data model
else
mov ax, @fardata ; Using far data model
endif
mov es, ax
; Check if the function was called previously. If it was we
; don't want to parse the command line again.
cmp [es:ParmCount], NotCalled
je FirstCall
jmp AlreadyCalled
FirstCall:
mov di, offset ParmList ; es:di now points to modules storage
push ds
; Note that we don't actually allocate any memory to store the
; DOS Psp. We simply use the STRUC declaration to determine
; the offsets of the fields in the memory allocated by DOS.
mov ds, [PspAddress] ; Load the segment address of the Psp
mov si, offset (Psp).CommandTail + 1
xor cx, cx ; Initialize cx
xor bx, bx ; Store # of parameters in bx
; Get the length of the DOS command line from the Psp.
mov cl, [ds:Psp.CommandTail.LengthByte]
; Check if the command line is empty and leave if it is.
cmp cl, 0
jne short ReplaceTabs
jmp InitParmCount
ReplaceTabs:
; Convert any tabs in the command line to spaces in order to
; make the parsing simpler.
push cx ; Store value of cx & es:di because call to
push es ; FindAndReplace modifies them.
push di
; Push the address of the DOS command line
push ds
if (@Cpu and 100b) eq 100b
push offset (Psp).CommandTail + 1
else
mov ax, offset (Psp).CommandTail + 1
push ax
endif
; Define the bytes to search/replace
mov ax, (SPACE shl 8) + TAB
call FindAndReplace ; Replace all tabs with spaces
pop di
pop es ; Restore previous values of cx & es:di
pop cx
; Skip any spaces at the beginning of the parameter list.
push es ; Save registers that will be modified
push di
push ds ; Pass the address of the string
push si
call SkipSpaces
pop si ; Update ds:si with start of next
pop ds ; parameter
pop di ; Restore es:di to point to location
pop es ; to store the next parameter
; Now parse the command line. Note that after each iteration of
; this loop ds:si points to the beginning of the next parameter
; and es:di points to location in the modules data segment where
; the next parameter will be stored.
ParseCmdLine:
inc bx ; Increment the parameter count
cmp [byte si], """" ; Check if current character is a "
je short DoubleQuote ; If it is use it as the delimiter
cmp [byte si], "'" ; Check if current character is a '
je short SingleQuote ; If it is use it as the delimiter
jmp short WhiteSpace
DoubleQuote:
mov [SearchChar], """"
inc si ; Point to the next character in the parameter list
dec cx ; Adjust number of bytes left to check
jmp short FindDelimiter
SingleQuote:
mov [SearchChar], "'"
inc si ; Point to the next character in the parameter list
dec cx ; Adjust number of bytes left to check
jmp short FindDelimiter
WhiteSpace:
mov [SearchChar], SPACE ; Use space, tab or eoln as delimiter
FindDelimiter:
mov al, [SearchChar] ; Store the character to search for
push bx ; Store bx, es:di
push es
push di
; Push the address of the start of the next parameter for the call
; to FindBytePos
push ds
push si
; Find the end of the parameter. After the call to FindBytePos
; ax = the number of bytes searched and es:di is pointing to
; the byte after the last one checked. cx=# of bytes left to
; check in the command line string.
call FindBytePos
push es ; Move the pointer returned by
pop ds ; FindBytePos into ds:si
mov si, di
pop di ; Restore es:di, bx
pop es
pop bx
; Now copy the parameter into its storage location
CopyParameter:
mov dx, si ; Calculate the offset of the source
sub dx, ax ; string
dec dx
push cx ; Save the values of registers
push bx ; modified by the call to ByteCopy
push es
push si
push di
cmp cx, 0
jne short StoreLength
inc al
StoreLength:
mov [byte es:di], al ; Store length of parameter in
inc di ; the length byte
push ds ; Push segment of source string
push dx ; Push offset of source string
push es ; Push segment of destination
push di ; Push offset of destination
call ByteCopy ; Copy the array of characters
pop di ; Restore the previous values of the
pop si ; registers modified by ByteCopy
pop es
pop bx
pop cx
add di, ax ; Move pointer past end of parameter
inc di
cmp [byte ds:si], SPACE
jne short NoWhiteSpace
; Now find the first character of the next parameter.
push es ; Save registers that will be modified
push di
push ds ; Pass the address of the string
push si
call SkipSpaces
pop si ; Update ds:si with start of next
pop ds ; parameter
pop di ; Restore es:di to point to location
pop es ; to store the next parameter
NoWhiteSpace:
jcxz short InitParmCount
jmp ParseCmdLine ; Get the next parameter on the
; command line.
InitParmCount:
; Initialize ParmCount so the routine doesn't have to parse the
; command line more than once.
mov [byte es:ParmCount], bl
pop ds ; Restore the programs data segment
AlreadyCalled:
mov al, [byte es:ParmCount] ; Return the previously determined
add sp, LocalSymbolSize ; value
pop bp
ret
endp ParamCount
proc ParamString
; This routine returns a far pointer to the parameter referenced in
; al. Before looking for the parameter, the function calls ParamCount
; to assure that the parameter exists. This has the side-affect of
; assuring that ParamCount parses and copies the parameters into the
; modules data segment.
;
; Input
; al - Parameter to return
; Output
; al = Desired Parameter
; es:di - Far pointer to parameter
; al = 0 - Parameter doesn't exist
; Calling conventions
; NA
; Registers modified
; ax, bx, cx, di, si, es, Flags
push bp ; Set up stack
mov bp, sp
; First check if the parameter exists
push ax ; Save index to desired parameter
call ParamCount
pop bx ; Restore index to desired parameter
cmp bl, al ; Check if the parameter exists
jg short InvalidParameter
mov al, bl ; Pass parameter index in al
; Point to modules data segment
if @DataSize eq 0
mov bx, @data ; Using near data model
else
mov bx, @fardata ; Using far data model
endif
mov es, bx ; Make es:si point to the data area
mov di, offset ParmList
call LocateString ; Determine the address of the string
jmp short Exit
InvalidParameter:
xor al, al
Exit:
pop bp
ret
endp ParamString
endif ; ifndef MDL
end