;*********************************************************************
;
; System name:  Command Line Paramater Parsing
;
; Designation:  parm.asm
;
; Description:  This file contains source to command line parameter
;               parsing code.
;
; Return item:  none
;
; Rev History:  95/9/25     DA Puryear  Created
;
;*********************************************************************


    IDEAL
    DOSSEG
    MODEL   small

tail_len    EQU     0080h   ; offset of param len byte in DTA
cmd_tail    EQU     0081h   ; offset of parameters in DTA

    UDATASEG

parms       db      128 DUP (?) ; 128-byte block for strings
num_parms   dw      ?       ; number of parameters

    CODESEG

    PUBLIC  parm_init, parm_getone, parm_count

; parm_init         - initialize procedures
; parm_getone       - get a parameter
; parm_count        - return number of parameters

;
; Designation:  parm_init
;
; Description:  Setup the parameter code. Must be called first.
;
; Input parms:  ds = PSP (automatically in ds upon .exe startup)
;               es = data segment
;
; Return item:  ds = data segment
;               (parms contain ASCIIZ strings)
;

PROC        parm_init

    push    ax
    push    bx
    push    dx
    push    si
    push    di

    ; init counter (cx) and index (si, di)

    xor     ch, ch
    mov     cl, [ds:tail_len]   ; cx = length of parameters
    inc     cx                  ; include carriage return at end
    mov     si, cmd_tail        ; address parameters with si
    mov     di, OFFSET parms    ; address destination with di

    ; skip leading blanks and tabs

@@10:
    call    separators          ; check if character is whitespace
    jne     @@20                ; jump if not a blank or tab
    inc     si
    loop    @@10

    ; copy parameter string to global parms

@@20:
    push    cx                  ; save length for later
    jcxz    @@30                ; skip movsb if count = 0
    cld
    rep     movsb               ; copy cx bytes from ds:si to es:di

    ; convert blanks to nulls and set num_parms

@@30:
    push    es
    pop     ds                  ; ds = es
    pop     cx                  ; restore old length
    xor     bx, bx              ; init parm count
    jcxz    @@60                ; skip loop if count = 0
    mov     si, OFFSET parms    ; address parameters with si

@@40:
    call    separators          ; check if character is whitespace
    jne     @@50                ; nope
    mov     [BYTE PTR si], 0    ; change separator to null
    inc     bx

@@50:
    inc     si                  ; point to next character
    loop    @@40                ; loop until cx = 0

@@60:
    mov     [num_parms], bx     ; save number of parameters

    pop     di
    pop     si
    pop     dx
    pop     bx
    pop     ax

    ret

ENDP        parm_init

;
; Designation:  parm_getone
;
; Description:  Get one of the parameters.
;
; Input parms:  cx = parameter's number (0 = first)
;
; Return item:  di = offset of ASCIIZ string
;

PROC        parm_getone

    push    ax
    push    cx

    xor     al, al
    mov     di, OFFSET parms    ; address parameter strings
    jcxz    @@99                ; if cx = 0, already pointing at first
    cmp     cx, [num_parms]     ; compare number with max
    jae     @@99                ; exit if > max number
    cld

@@10:
    scasb                       ; scan for null
    jnz     @@10                ; repeat until found
    loop    @@10                ; repeat for count in cx

@@99:
    pop     cx
    pop     ax

    ret

ENDP        parm_getone

;
; Designation:  parm_count
;
; Description:  Return number of parameters
;
; Input parms:  none
;
; Return item:  dx = parameter count
;

PROC        parm_count

    mov     dx, [num_parms]
    ret

ENDP        parm_count

;
; PRIVATE
;

;
; Designation:  separator
;
; Description:  Check if character is whitespace.
;
; Input parms:  ds:si = character
;
; Return item:  zf = 1 (je) = character is whitespace
;               zf = 0 (jne) = ""       "" not whitespace
;

PROC        separators

    push    ax

    mov     al, [si]            ; get character at ds:si
    cmp     al, 020h            ; is it a blank?
    je      @@10
    cmp     al, 009h            ; is it a tab?
    je      @@10
    cmp     al, 00Dh            ; is it a cr?

@@10:
    pop     ax

    ret

ENDP        separators

    END

