        TITLE   'For - RxDOS Command Shell For Function'
        PAGE 59, 132
        .LALL

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Command Shell For                                      ;
        ;...............................................................;

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Real Time Dos                                                ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  This material  was created as a published version  of a DOS  ;
        ;  equivalent product.   This program  logically  functions in  ;
        ;  the same way as  MSDOS functions and it  is  internal  data  ;
        ;  structure compliant with MSDOS 6.0                           ;
        ;                                                               ;
        ;  This product is distributed  AS IS and contains no warranty  ;
        ;  whatsoever,   including  warranty  of   merchantability  or  ;
        ;  fitness for a particular purpose.                            ;
        ;                                                               ;
        ;                                                               ;
        ;  (c) Copyright 1990, 1997. Api Software and Mike Podanoffsky  ;
        ;      All Rights Reserved Worldwide.                           ;
        ;                                                               ;
        ;  This product is protected under copyright laws and  may not  ;
        ;  be reproduced  in whole  or in part, in any form  or media,  ;
        ;  included but not limited to source listing, facsimile, data  ;
        ;  transmission, cd-rom, or  floppy disk without the expressed  ;
        ;  written consent of the author.                               ;
        ;                                                               ;
        ;  License  for  distribution  for commercial  use  or  resale  ;
        ;  required from:                                               ;
        ;                                                               ;
        ;  Api Software                                                 ;
        ;  12 South Walker Street                                       ;
        ;  Lowell,  MA   01851                                          ;
        ;                                                               ;
        ;  internet: mikep@world.std.com                                ;
        ;                                                               ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;  Compile with MASM 5.1                                        ;
        ;...............................................................;

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Command Shell                                          ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Programmer's Notes:                                          ;
        ;                                                               ;
        ;  Command Shell consists of  two parts bound  together into a  ;
        ;  single executable load.  There  exists  a  single  resident  ;
        ;  command shell which is accessible by an Int 2Eh.             ;
        ;                                                               ;
        ;...............................................................;

        include rxdosmac.asm
        include rxdosdef.asm
        include rxdoscin.asm

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Command Shell                                          ;
        ;...............................................................;

RxDOSCMD SEGMENT PUBLIC 'CODE'
         assume cs:RxDOSCMD, ds:RxDOSCMD, es:RxDOSCMD, ss:RxDOSCMD

        public _For

        extrn CheckOptOneArg                            : near
        extrn CountArgs                                 : near
        extrn CmndLookup                                : near
        extrn CmndError_SyntaxError                     : near
        extrn CRLF                                      : near
        extrn DisplayErrorMessage                       : near
        extrn DisplayLine                               : near
        extrn DisplayPrompt                             : near
        extrn _CopyString                               : near
        extrn ReplaceForVariables                       : near
        extrn _CommandParser                            : far

        extrn RxDOS_ForArgs                             : near
        extrn _lowerCase                                : near
        extrn _lowerCaseString                          : near

        extrn _computeLength                            : near
        extrn _Seeif_WildCharacter                      : near

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  FOR %variable IN (set) DO command [command-parameters]       ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Replace %var in command.                                     ;
        ;                                                               ;
        ;...............................................................;

_For:

        Entry
        def __argarray, di
        def __arg
        def __cmdline
        def __endrepeatArg

        def _letter
        def _length
        def _WildChars
        ddef _CurrentDTA, 0000, 0000

        defbytes _DTA, sizeFINDENTRY
        defbytes _commandLine, 128
        defbytes _replacement, 128

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  get variable arg letter 
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        call CountArgs                                  ; must have min of 8 args
        cmp ax, 8                                       ; min args 
        jge _For_08                                     ; if at leats 8 -->
        jmp _ForError                                   ; else if less, syntax error -->

_For_08:
        mov si, word ptr [ forVarIdent ][ di ]          ; point to arg
        cmp byte ptr [ si ], '%'                        ; is arg a % variable ?
        ifnz _ForError                                  ; if not, then syntax error -->

        mov al, byte ptr [ si + 1 ]                     ; get letter
        call _lowerCase
        cbw
        storarg _letter, ax

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  check for 'in' argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        mov si, word ptr [ forInArg ][ di ]             ; point to next arg
        mov di, offset RxDOS_ForArgs
        call CmndLookup                                 ; lookup command
        ifc _ForError                                   ; if not, then syntax error -->

        cmp bx, _IN                                     ; 'in' returns a zero
        ifnz _ForError                                  ; if not 'in', then syntax error -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  check for ( argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        getarg di, __argarray
        add di, forInStartParen + 2
        mov si, word ptr [ di - 2 ]                     ; point to next arg
        cmp byte ptr [ si ], '('                        ; is arg a ( variable ?
        ifnz _ForError                                  ; if not, then syntax error -->

        storarg __arg, di                               ; di points to an argument

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  search for ) do ...
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dec di
        dec di

_ForSearchForParen:
        inc di
        inc di
        mov si, word ptr [ di ]                         ; point to next arg
        or si, si                                       ; end of args ?
        ifz _ForError                                   ; if not, then syntax error -->

        cmp byte ptr [ si ], ')'                        ; is arg a ) variable ?
        jnz _ForSearchForParen                          ; keep looking -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  search for last ) in case ))) ...
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_ForSearchForDoLastParen:
        inc di
        inc di
        mov si, word ptr [ di ]                         ; point to next arg
        or si, si                                       ; end of args ?
        ifz _ForError                                   ; if not, then syntax error -->

        cmp byte ptr [ si ], ')'                        ; is arg a ) variable ?
        jz _ForSearchForDoLastParen                     ; keep looking -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  test for a 'do' argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_ForSearchForDo:
        push di
        mov di, offset RxDOS_ForArgs
        call CmndLookup                                 ; lookup command
        pop di                                          ; restore arg pointer
        ifc _ForError                                   ; if not legit, syntax error -->

        cmp bx, _DO                                     ; 'do' returns a 1
        ifnz _ForError                                  ; if not found -->

        inc di
        inc di
        storarg __cmdline, di                           ; where command line is

        sub di, 4
        storarg __endrepeatArg, di                      ; end repeat arg

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  get initial DTA address
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        Int21 GetDTA
        stordarg _CurrentDTA, es, bx

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  sequentially walk through each arg
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_ForNext:
        getarg bx, __arg                                ; point to arg list
        cmp bx, word ptr [ __endrepeatArg ][ bp ]       ; end repeat arg ?
        ifz _ForReturn                                  ; if at end, exit -->

        storarg _WildChars, 0000
        mov si, word ptr [ bx ]
        call _computeLength                             ; compute length
        storarg _length, cx                             ; save length

        call _Seeif_WildCharacter                       ; see if wild characters in name.
        jc _ForNext_30                                  ; if no -->

        lea di, offset _replacement [ bp ]              ; where to copy
        rep movsb                                       ; copy argument
        xor ax, ax                                      ; null terminate
        stosb                                           ; null terminate
        storarg _WildChars, -1                          ; wild characters used.

        lea dx, offset [ _DTA ][ bp ]
        Int21 SetDTA

        lea dx, offset _replacement [ bp ]              ; search for argument
        Int21 FindFirstFile                             ; any found ?
        jc _ForNext_36                                  ; if none -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  create replacement variable
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_ForNext_14:
        lea si, offset [ _DTA. findFileName ][ bp ]
        lea di, offset _replacement [ bp ]              ; search for argument
        call _CopyString                                ; get command line

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  build command line to execute
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_ForNext_30:
        getarg di, __cmdline                            ; ptr->arg array where command line begins
        mov si, word ptr [ di ]                         ; ptr-> text
        lea di, offset [ _commandLine + 1 ][ bp ]
        call _CopyString                                ; get command line

        mov al, byte ptr [ _letter ][ bp ]
        lea bx, offset [ _replacement ][ bp ]
        lea si, offset [ _commandLine + 1 ][ bp ]
        call ReplaceForVariables                        ; replace variable letter

        call DisplayPrompt                              ; display prompt

        lea dx, offset [ _commandLine + 1 ][ bp ]
        call DisplayLine                                ; echo line
        call CRLF

        push ds
        getdarg ds, dx, _CurrentDTA
        Int21 SetDTA                                    ; temp set DTA
        pop ds

        lea si, offset [ _commandLine ][ bp ]
        mov byte ptr [ si ], 128
        call _CommandParser                             ; reparse remainder of line

        cmp word ptr [ _WildChars ][ bp ], 0000         ; wild character search ?
        jz _ForNext_36                                  ; no, skip to next arg in set -->

        lea dx, offset [ _DTA ][ bp ]
        Int21 SetDTA

        Int21 FindNextFile                              ; search for next matching file
        jnc _ForNext_14                                 ; continue -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  get next argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_ForNext_36:
        mov di, word ptr [ __arg ][ bp ]                ; get current pointer to arg array
        mov dx, word ptr [ di ]                         ; get current reference
        add dx, word ptr [ _length ][ bp ]              ; offset to past current arg
        sub di, 2

_ForNext_38:
        add di, 2
        mov si, word ptr [ di ]                         ; get current reference
        cmp si, dx                                      ; beyond or equal to current ?
        jc _ForNext_38                                  ; not yet -->

        mov word ptr [ __arg ][ bp ], di                ; remember reference
        jmp _ForNext

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  error
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_ForError:
        mov dx, offset CmndError_SyntaxError
        call DisplayErrorMessage

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_ForReturn:
        cmp word ptr [ _CurrentDTA. _segment ][ bp ], 0000
        jz _ForReturn_08

        push ds
        getdarg ds, dx, _CurrentDTA
        Int21 SetDTA                                    ; temp set DTA
        pop ds

_ForReturn_08:
        Return

RxDOSCMD                        ENDS
                                END
