home *** CD-ROM | disk | FTP | other *** search
-
- ; 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
-