home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / portfoli / bat2ex13 / bat2exe.asm next >
Encoding:
Assembly Source File  |  1991-08-21  |  116.7 KB  |  2,915 lines

  1.         page    66,132
  2. ;============================================================================
  3. ; BAT2EXEC.COM - a batch file compiler
  4. ;
  5. ; Syntax:
  6. ;    BAT2EXEC filename
  7. ;
  8. ; Revision History:
  9. ;
  10. ;    Version 1.0    Initial Release     PC Magazine Vol 9 Num 14
  11. ;    Version 1.1    Bug Fixes               July 19, 1990
  12. ;    Version 1.2    Bug Fixes               July 28, 1990
  13. ;                       Added ability to read large BAT files.
  14. ;       Version 1.3     PATH cmd fix.           Oct.  3, 1990
  15. ;             Echo cmd fix
  16. ;                       Other small bug fixes.
  17. ;
  18. ;============================================================================
  19.  
  20.         code    segment
  21.         assume    cs:code
  22.  
  23.         org    2ch
  24. local_environment    dw    ?            ;Word containing the segment
  25.                         ;  of the program's env. block.
  26.         org    80h
  27. command_tail    db    ?            ;Offset of the command tail.
  28.  
  29.         org    100h
  30.  
  31. main:        jmp    initialize
  32. program     db    13,10,"BAT2EXEC 1.3 "
  33. copyright    db    "(c) 1990 Ziff Communications Co.",10,13
  34. author        db    "PC Magazine ",254," Douglas Boling"
  35.         db    10,13,"$",1Ah
  36. ;----------------------------------------------------------------------------
  37. ;Equates used to find data offsets in the compiled program.
  38. ;----------------------------------------------------------------------------
  39. BUFF_SIZE        equ    255            ;Size of runtime buffers
  40.  
  41. std_data_size    equ    offset data_end - data_start
  42. code_start_ptr    equ    [bp + offset code_start - offset data_start]
  43. com_stack_ptr    equ    [bp + offset stack_ptr - offset data_start]
  44. com_prog_size    equ    [bp + offset prog_segsize - offset data_start]
  45. com_label_start equ    [bp + offset label_list_strt - offset data_start]
  46. parse_buff    equ    [bp + offset prse_buff_ptr - offset data_start]
  47. parse2_buff    equ    [bp + offset prs2_buff_ptr - offset data_start]
  48. exec_buff    equ    [bp + offset exec_buff_ptr - offset data_start]
  49. forloop_buff    equ    [bp + offset for_buff_ptr - offset data_start]
  50. forloop_ptr    equ    [bp + offset floop_ptr - offset data_start]
  51. stdout_hdl    equ    [bp + offset file_handle1 - offset data_start]
  52. outfile_hdl    equ    [bp + offset file_handle2 - offset data_start]
  53. stdin_hdl    equ    [bp + offset file_handle3 - offset data_start]
  54. infile_hdl    equ    [bp + offset file_handle4 - offset data_start]
  55. environment_seg equ    [bp + offset master_env - offset data_start]
  56. dos_version    equ    [bp + offset version_num - offset data_start]
  57. process_rc    equ    [bp + offset proc_rc - offset data_start]
  58. shift_count    equ    [bp + offset shift_cnt - offset data_start]
  59.  
  60. code_call_size    equ    offset code_call_end - offset code_call
  61. code_jmp_size    equ    offset code_jmp_end - offset code_jmp
  62. code_jc_size    equ    offset code_jc_end - offset code_jc
  63. code_jnc_size    equ    offset code_jnc_end - offset code_jnc
  64. code_jmpdis_size   equ       offset code_jmpdis_end - offset code_jmpdis
  65. code_leasi_size equ    offset code_leasi_end - offset code_leasi
  66. code_movsi_size equ    offset code_movsi_end - offset code_movsi
  67. code_movsiim_size equ    offset code_movsiim_end - offset code_movsiim
  68. code_leadi_size equ    offset code_leadi_end - offset code_leadi
  69. code_movdi_size equ    offset code_movdi_end - offset code_movdi
  70. code_movdiim_size equ    offset code_movdiim_end - offset code_movdiim
  71. ;============================================================================
  72. ;Compiler data
  73. ;============================================================================
  74. command_table    db    "IF",0                  ;Commands processed by
  75.         db    "REM",0                 ;  compiler
  76.         db    "FOR",0
  77.         db    "ECHO",0
  78.         db    "GOTO",0
  79.         db    "EXIT",0
  80.         db    "PAUSE",0
  81.         db    "SHIFT",0
  82.         db    "SET",0
  83.         db    "CALL",0
  84.         db    "PATH",0
  85.         db    "PROMPT",0
  86.         db    "CD",0                  ;DOS commands internal to
  87.         db    "MD",0                  ;  command.com.
  88.         db    "RD",0
  89.         db    "CLS",0
  90.         db    "DIR",0
  91.         db    "DEL",0
  92.         db    "REN",0
  93.         db    "VER",0
  94.         db    "VOL",0
  95.         db    "CTTY",0
  96.         db    "CHCP",0
  97.         db    "TYPE",0
  98.         db    "COPY",0
  99.         db    "DATE",0
  100.         db    "TIME",0
  101.         db    "ERASE",0
  102.         db    "CHDIR",0
  103.         db    "MKDIR",0
  104.         db    "RMDIR",0
  105.         db    "BREAK",0
  106.         db    "RENAME",0
  107.         db    "DELETE",0
  108.         db    "VERIFY",0
  109.         db    "COMMAND",0,0
  110.  
  111. batcmd_jmptbl    dw    if_cmd            ;if command
  112.         dw    rem_cmd         ;rem command
  113.         dw    for_cmd         ;for command
  114.         dw    echo_cmd        ;echo command
  115.         dw    goto_cmd        ;goto command
  116.         dw    rem_cmd         ;exit command
  117.         dw    pause_cmd        ;pause command
  118.         dw    shift_cmd        ;shift command
  119.         dw    set_cmd         ;set command
  120.  
  121.         dw    internal_cmd        ;call command
  122.         dw    path_cmd         ;Path command
  123.         dw    prompt_cmd         ;Prompt command
  124.         dw    internal_cmd        ;DOS internal command
  125.         dw    external_cmd        ;DOS program
  126.         dw    label_cmd        ;Process BAT label
  127. batcmd_jmptbl1    =    $
  128.  
  129. ifstr1        db    "ERRORLEVEL"
  130. ifstr2        db    "EXIST"
  131.  
  132. internal_cmdsw    db    "/C "                   ;Switch for transient commands
  133.  
  134. for_active_flag db    0            ;Set if parsing a FOR loop
  135. goto_active    db    0            ;Set if goto parsed
  136. goto_data_ptr    dw    0            ;Data offset of last goto    
  137.  
  138. temp1        dw    0            ;Temp data storage.
  139.  
  140. cmd_switches    db    ?            ;Used if command line/ä⇩⇧î③ê⇦ppî    Ç⇦⇩⇧î⇨Ç✓ë≥@rI≥rr@OנÇê✓    ê    ij≡p≡püÄ⇦⇧Ç⇦Ç⇧éêr    Çr✓êä✓⇧נéé⇧Ç     êê⇨ü≥@①Ä⇦⇧נîÇê    נäÇ⇧éêOÇ⇦✓✓⑦╱à{@ `╱Xï⇦⑤Ü">✓⇨    ⇨Σ③ΣÅΣΣΣÇ9①①⓪    ƒ⇨ƒ⑧⇧✓⇨    ⑧⇨ƒ⇨◆⓪ƒ⑧③⓪αβ⑧③⓪⑨①①⇨    Σ③③ΣÅΣΣΣǃƒ⇦⓪⓪ƒ①ƒ⇨◆⓪ƒ8  ƒ①⇦⇨⓪üαβαβ③⇨⑨①①✓⇨    ⇨Σ③ΣÇΣΣΣÇ9①①⓪    ƒ⇨ƒ◆⇨③ƒ⇨◆ jmp_disp_error    ;If none, report no filename
  141. init_1:
  142.         mov    al,[si]
  143.         cmp    amij①`&✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓קךYHəYê⑧ףף[X[Ö✓§ם]⑧ם⇨BéBZÖB\⑧\£ךWך\£¢ץâBéBXן[⇩[ןY⑧ÿ]⑨Ü[⑨BBNצןY✓ə[£]✓⓪ÉU✓⑨Ü[⑨CBéBZÿאZ¢\⑦ךə\ץ⑦ך\£¢ץâBéBZ¢\⇩\םץ¥✓⑧\£ךWןףYə[ÖWך[Ö⇨B£⑧\£ךWך\£¢ץÄâBéB[[§éY♪ךÖ£ך]✓⑨\£¢\ךכâBÜ¢\⑦ךə\ץ⑦ך\£¢ץÄâBéBZ¢\⇩Yə\ץ⑦ך\£¢ץâB£⑧\£ךWןףYə[ÖWך[ÖâBÄבBÄסףף\ə[⑨H⓪ÉU✓⑨Ü[⑨Hə[ÖH⑧ßHə[ÖKâBÄבBéB[[§é\םKə[ÿ¥YÖùץéBNקפHם[¥זזə[£]✓⓪ÉU✓⑨Ü[⑨CBéB[[§éYəK⑨⑧]⑧X¥YÖùץ§⑧\¥⇩Nע②Hם[¥זז⓪צצH⑨Ü[⑨H⑨⑧]⑧KâBéBXY⑨⇩YəK§⑨⑦ך⑧]⑧Wץם^ÖBNצXZךH¢ףףH⑨¢ץêstd data set.
  144. new_line:
  145.         inc    file_linecount        ;Inc line number
  146. new_line1:
  147.         xor    bl,bl            ;Look for 1st character
  148.         call    scan4char        ;If nothing on line, check
  149.         jc    comp_endcheck        ;  for EOF
  150.         call    redirect_check
  151.         cmp    byte ptr [si],'@'    ;See if non echo prefix
  152.         jne    comp_1
  153.         inc    si            ;Move past @
  154. comp_1:
  155.         call    parse            ;Parse 1st wp⇦ëנéנüâêOüéê@≡p≥rîO≥Ç◆Ç    é⇦◆Ç✓⇦äÇ⇦≥rpp≥rÇ◆≥⇦⇨Ç⇦üנÇê⇧éêppî◆Ç✓ëî⇨ê @≡p≥r ◆≥⇧IJהDrrr@⇦✓✓Oé✓נî⇦äÄ✓✓Oäê⇧Ç⇦ÇIJנé✓נäpp≥rêrê⇧éêrr@OנîüéÇ✓@≡p≥r ◆≥✓é⇧êCÄëü,13,"$",1Ah
  156. ;----------------------------------------------------------------------------
  157. ;Equates used to find data offsets in the compiled program.
  158. ;----------------------------------------------------------------------------
  159. BUFF_SIZE        equ    255            ;Size of runtime buffers
  160.  
  161. std_data_size    equ    offset data_end - data_start
  162. code_start_ptr    equ    [bp + offset code_start - offset data_start]
  163. com_stack_ptr    equ    [bp + offset stack_ptr - offset data_start]
  164. com_prog_size    equ    [bp + offset prog_segsize - offset data_start]
  165. com_label_start equ    [bp + offset label_list_strt - offset data_start]
  166. parse_buff    equ    [bp + offset prse_buff_ptr - offset data_start]
  167. parse2_buff    equ    [bp + offset prs2_buff_ptr - offset data_start]
  168. exec_buff    equ    [bp + offset exec_buff_ptr - offset data_start]
  169. forloop_buff    equ    [bp + offset for_buff_ptr - offset data_start]
  170. forloop_ptr    equ    [bp + offset floop_ptr - offset data_start]
  171. stdout_hdl    equ    [bp + offset file_handle1 - offset data_start]
  172. outfile_hdl    equ    [bp + offset file_handle2 - offset data_start]
  173. stdin_hdl    equ    [bp + offset file_handle3 - offset data_start]
  174. infile_hdl    equ    [bp + offset file_handle4 - offset data_start]
  175. environment_seg equ    [bp + offset master_env - offset data_start]
  176. dos_version    equ    [bp + offset version_num - offset data_start]
  177. process_rc    equ    [bp + offset proc_rc - offset data_start]
  178. shift_count    equ    [bp + offset shift_cnt - offset data_start]
  179.  
  180. code_call_size    equ    offset code_call_end - offset code_call
  181. code_jmp_size    equ    offset code_jmp_end - offset code_jmp
  182. code_jc_size    equ    offset code_jc_end - offset code_jc
  183. code_jnc_size    equ    offset code_jnc_end - offset code_jnc
  184. code_jmpdis_size   equ       offset code_jmpdis_end - offset code_jmpdis
  185. code_leasi_size equ    offset code_leasi_end - offset code_leasi
  186. code_movsi_size equ    offset code_movsi_end - offset code_movsi
  187. code_movsiim_size equ    offset code_movsiim_end - offset code_movsiim
  188. code_leadi_size equ    offset code_leadi_end - offset code_leadi
  189. code_movdi_size equ    offset code_movdi_end - offset code_movdi
  190. code_movdiim_size equ    offset code_movdiim_end - offset code_movdiim
  191. ;============================================================================
  192. ;Compiler data
  193. ;============================================================================
  194. command_table    db    "IF",0                  ;Commands processed by
  195.         db    "REM",0                 ;  compiler
  196.         db    "FOR",0
  197.         db    "ECHO",0
  198.         db    "GOTO",0
  199.         db    "EXIT",0
  200.         db    "PAUSE",0
  201.         db    "SHIFT",0
  202.         db    "SET",0
  203.         db    "CALL",0
  204.         db    "PATH",0
  205.         db    "PROMPT",0
  206.         db    "CD",0                  ;DOS commands internal to
  207.         db    "MD",0                  ;  command.com.
  208.         db    "RD",0
  209.         db    "CLS",0
  210.         db    "DIR",0
  211.         db    "DEL",0
  212.         db    "REN",0
  213.         db    "VER",0
  214.         db    "VOL",0
  215.         db    "CTTY",0
  216.         db    "CHCP",0
  217.         db    "TYPE",0
  218.         db    "COPY",0
  219.         db    "DATE",0
  220.         db    "TIME",0
  221.         db    "ERASE",0
  222.         db    "CHDIR",0
  223.         db    "MKDIR",0
  224.         db    "RMDIR",0
  225.         db    "BREAK",0
  226.         db    "RENAME",0
  227.         db    "DELETE",0
  228.         db    "VERIFY",0
  229.         db    "COMMAND",0,0
  230.  
  231. batcmd_jmptbl    dw    if_cmd            ;if command
  232.         dw    rem_cmd         ;rem command
  233.         dw    for_cmd         ;for command
  234.         dw    echo_cmd        ;echo command
  235.         dw    goto_cmd        ;goto command
  236.         dw    rem_cmd         ;exit command
  237.         dw    pause_cmd        ;pause command
  238.         dw    shift_cmd        ;shift command
  239.         dw    set_cmd         ;set command
  240.  
  241.         dw    internal_cmd        ;call command
  242.         dw    path_cmd         ;Path command
  243.         dw    prompt_cmd         ;Prompt command
  244.         dw    internal_cmd        ;DOS internal command
  245.         dw    external_cmd        ;DOS program
  246.         dw    label_cmd        ;Process BAT label
  247. batcmd_jmptbl1    =    $
  248.  
  249. ifstr1        db    "ERRORLEVEL"
  250. ifstr2        db    "EXIST"
  251.  
  252. internal_cmdsw    db    "/C "                   ;Switch for transient commands
  253.  
  254. for_active_flag db    0            ;Set if parsing a FOR loop
  255. goto_active    db    0            ;Set if goto parsed
  256. goto_data_ptr    dw    0            ;Data offset of last goto    
  257.  
  258. temp1        dw    0            ;Temp data storage.
  259.  
  260. cmd_switches    db    ?            ;Used if command line/ä⇩⇧î③ê⇦ppî    Ç⇦⇩⇧î⇨Ç✓ë≥@rI≥rr@OנÇê✓    ê    ij≡p≡püÄ⇦⇧Ç⇦Ç⇧éêr    Çr✓êä✓⇧נéé⇧Ç     êê⇨ü≥@①Ä⇦⇧נîÇê    נäÇ⇧éêOÇ⇦✓✓⑦╱à{@ `╱Xï⇦⑤Ü">✓⇨    ⇨Σ③ΣÅΣΣΣÇ9①①⓪    ƒ⇨ƒ⑧⇧✓⇨    ⑧⇨ƒ⇨◆⓪ƒ⑧③⓪αβ⑧③⓪⑨①①⇨    Σ③③ΣÅΣΣΣǃƒ⇦⓪⓪ƒ①ƒ⇨◆⓪ƒ8  ƒ①⇦⇨⓪üαβαβ③⇨⑨①①✓⇨    ⇨Σ③ΣÇΣΣΣÇ9①①⓪    ƒ⇨ƒ◆⇨③ƒ⇨◆try:  SI - Pointer to ASCII string to find.
  261. ;      DI - Pointer to list of ASCIIZ strings.
  262. ;      CX - Size of string
  263. ; Exit:   CF - Clear if string found
  264. ;      BX - If CF clear, index into list
  265. ;-----------------------------------------------------------------------------
  266. findstr     proc    near
  267.         push    cx
  268.         push    es
  269.         push    cs            ;Point ES:DI to table of
  270.         pop    es            ;  batch commands.
  271.         xor    dx,dx
  272.         or     dx,cx            ;Save length of string
  273.         je    finds_3
  274.         xor    bx,bx            ;Zero index counter
  275. finds_1:
  276.         push    si
  277.         mov    cx,dx            ;Restore command size
  278.         repe    cmpsb            ;Compare command
  279.         pop    si
  280.         je    string_found
  281.         inc    bx
  282.         xor    al,al
  283.         cmp    [di-1],al
  284.         jne    finds_2
  285.         dec    di
  286. finds_2:
  287.         mov    cx,10            ;Scan to next zero
  288.         repne    scasb
  289.         cmp    byte ptr [di],0     ;See if second zero. If so
  290.         jne    finds_1         ;  end of list.
  291. finds_3:
  292.         mov    bx,13
  293.         stc                ;Indicate string not found
  294. findstr_exit:
  295.         pop    es
  296.         pop    cx
  297.         ret
  298. string_found:
  299.         cmp    bx,12            ;If past the BAT commands,
  300.         jb    findstr_3        ;  then it is an internal cmd.
  301.         mov    bx,12
  302. findstr_3:
  303.         clc                ;Set string found flag
  304.         jmp    short findstr_exit
  305. findstr     endp
  306.  
  307. ;-----------------------------------------------------------------------------
  308. ; CAPSWORD capitalizes word pointed to by SI
  309. ; Entry:  SI - Pointer to ASCII word to capitalize
  310. ; Exit:   CX - Size of word
  311. ;-----------------------------------------------------------------------------
  312. capsalpha    proc near
  313.         assume    ds:nothing,es:nothing
  314.         push    ax
  315.         xor    ax,ax            ;Exit on non-alpha chars
  316.         jmp    short capsword_entry2
  317. capsalpha    endp
  318.  
  319. ;-----------------------------------------------------------------------------
  320. ; CAPSWORD capitalizes word pointed to by SI
  321. ; Entry:  SI - Pointer to ASCII word to capitalize
  322. ; Exit:   CX - Size of word
  323. ;-----------------------------------------------------------------------------
  324. capsword    proc near
  325.         assume    ds:nothing,es:nothing
  326.         push    ax
  327.         mov    ah,1            ;Ignore extra characters
  328. capsword_entry2:
  329.         push    di
  330.         push    si
  331.         push    es
  332.         push    ds            ;Set ES:DI = DS:SI
  333.         pop    es
  334.         mov    di,si
  335.         xor    cx,cx            ;Clear byte counter.
  336. caps_1:
  337.         lodsb                ;Get character
  338.         cmp    al," "                  ;Allow any non-space character
  339.         jbe    caps_exit
  340.         cmp    al,"a"                  ;If between a and z,
  341.         jb    caps_3           ;  capitalize it.
  342.         cmp    al,"z"
  343.         ja    caps_exit
  344.         and    al,0DFh
  345. caps_2:
  346.         stosb                ;Save character
  347.         inc    cx            ;Inc byte counter
  348.         jmp    short caps_1
  349. caps_3:
  350.         or    ah,ah            ;See if we should check 
  351.         jne    caps_2            ;  non-alpha chars.
  352.         cmp    al,'Z'
  353.         ja    caps_exit
  354.         cmp    al,'A'
  355.         jae    caps_2
  356. caps_exit:
  357.         pop    es
  358.         pop    si
  359.         pop    di
  360.         pop    ax
  361.         ret
  362. capsword    endp
  363.  
  364. ;-----------------------------------------------------------------------------
  365. ; REDIRECT CLOSE post process redirection commands
  366. ; Entry:  DI - Pointer to end of COM file data.
  367. ; Exit:   CF - Set if error.
  368. ;      Batch file line updated to remove any redirection symbols
  369. ;-----------------------------------------------------------------------------
  370. redirect_close    proc    near
  371.         assume    cs:code,ds:code
  372.         cmp    redirect_in,0        ;See if redirecton active
  373.         je    redirclose_1
  374.         mov    redirect_in,0
  375.         mov    bx,offset redirci_next    ;Append close redirect file
  376.         call    include_code        ;  routine to code.
  377.         xor    cx,cx
  378.         call    inline_code
  379. redirclose_1:
  380.         cmp    redirect_out,0        ;See if redirecton active
  381.         je    redirclose_2
  382.         mov    redirect_out,0
  383.         mov    bx,offset redirco_next    ;Append close redirect file
  384.         call    include_code        ;  routine to code.
  385.         xor    cx,cx
  386.         call    inline_code
  387. redirclose_2:
  388.         cmp    pipein_flag,0        ;See if in pipe curr active
  389.         je     redirclose_3
  390.         mov    dx,pipein_file        ;Get offset of input pipe file
  391.         mov    cx,1            ;Indicate parameter type
  392.         mov    bx,offset redirdel_next    ;Delete the piping file
  393.         call    include_code
  394.         call    inline_code        
  395.         mov    pipein_flag,0        ;Clear flag
  396. redirclose_3:
  397.         cmp    pipeout_flag,0        ;See if out pipe curr active
  398.         je     redirclose_exit
  399.         mov    dx,pipeout_file        ;Get offset of input pipe file
  400.         xor    bx,bx            ;Add output redirection code
  401.         xor    ax,ax            ;  to file.
  402.         call    redirect_openi
  403.         mov    pipein_flag,1        ;Set pipe input flag
  404.         mov    pipeout_flag,0        ;Clear pipe output flag
  405.         mov    pipein_file,dx        ;Copy pointer to filename
  406. redirclose_exit:
  407.         ret
  408. redirect_close    endp
  409.  
  410. ;-----------------------------------------------------------------------------
  411. ; REDIRECT CHECK process redirection commands
  412. ; Entry:  SI - Pointer to current BAT file line
  413. ;      DI - Pointer to end of COM file data.
  414. ; Exit:   CF - Set if error.
  415. ;      Batch file line updated to remove any redirection symbols
  416. ;-----------------------------------------------------------------------------
  417. redirect_check    proc    near
  418.         assume    cs:code,ds:code
  419.         push    si
  420.         call    redirect_close
  421.         mov    quote_flag,0
  422. redirect_1:
  423.         mov    bp,si            ;Save current position
  424.         lodsb
  425.         cmp    al,'"'                  ;See if quote
  426.         jne    redirect_2
  427.         not    quote_flag
  428. redirect_2:
  429.         cmp    quote_flag,0        ;Ignore characters in quotes
  430.         jne    redirect_1
  431. ;
  432. ; Check for piping
  433. ;
  434.         cmp    al,'|'                  ;Check for piping symbol
  435.         jne    redirect_5 
  436.         mov    byte ptr [si-1],13    ;Replace | with CR
  437.  
  438.         mov    bx,offset pipe1_file    ;Get offset of pipe file to
  439.         cmp    pipe_toggle,0        ;  use.  Alternate files so
  440.         jne    redirect_3         ;  that input and output files
  441.         mov    bx,offset pipe2_file    ;  don't get mixed up.
  442. redirect_3:
  443.         not    pipe_toggle
  444.         xor    dx,dx            ;If file not already used, 
  445.         or     dx,[bx]            ;  load the filename into 
  446.         jne    redirect_4         ;  the COM data buffer.
  447.         mov    dx,di
  448.         sub    dx,databuff_start    ;Compute offset of filename
  449.         mov    [bx],dx            ;Save pointer to filename
  450.         lea    si,[bx+2]        ;Get address of filename
  451.         mov    ah,1    
  452.         call    copy_string        ;Copy name to COM data buffer
  453.         xor    al,al            ;Terminate filename with zero
  454.         stosb
  455. redirect_4:
  456.         mov    pipeout_file,dx
  457.         mov    pipeout_flag,1
  458.         xor    bx,bx            ;Add output redirection code
  459.         xor    ax,ax            ;  to file.
  460.         call    redirect_openo
  461.         jmp    short redirect_exit    ;Terminate line scan.
  462. ;
  463. ; Check for output redirection
  464. ;
  465. redirect_5:
  466.         cmp    al,'>'                  ;Check for redirect out
  467.         jne    redirect_7
  468.         xor    bx,bx
  469.         cmp    byte ptr [si],'>'       ;Check for append redirect
  470.         jne    redirect_6
  471.         lodsb                ;Remove 2nd >
  472.         inc    bx
  473. redirect_6:
  474.         push    bx            ;Save append flag
  475.         xor    bl,bl
  476.         call    scan4char        ;Get filename
  477.         mov    dx,di
  478.         mov    ah,1            ;Copy only one word
  479.         call    copy_string
  480.         xor    al,al            ;Terminate name with zero
  481.         stosb
  482.         sub    dx,databuff_start    ;Compute offset of filename
  483.         pop    ax
  484.         call    redirect_openo
  485.         call    erase_redirect        ;Erase redirect from line.
  486.         jmp    short redirect_1
  487. redirect_7:
  488.         cmp    al,'<'                  ;Check for redirect in
  489.         jne    redirect_10
  490.         xor    bl,bl
  491.         call    scan4char        ;Get filename
  492.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@---------
  493. ; REDIRECT OPENI loads code to open a file for ynput redirection
  494. ; Entry:  DX - Offset from data buffer start oµ file name
  495. <rOנ£âנijOונÇÇOüäÄä⇧Ä⇧éנÇ✓נêé⇧êÄ✓@≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ppäê    é⇦ê ⇧Ç◆êér◆äÇ rê⇦≡p≥r⇦⇦✓r ⇦@î    êAëä@î    êpp≥r◆Ç⇦⇨≥⇦⇩pp≥r≥ ⇨IJהrrr@②ëé ⇧êOçÄ⇦Ä✓⇧ê⇦נüé◆êpp≥r⇦≥ âIJîâ≥rr@⇦✓✓Oé✓נêÇנÇÄ⇦נÇ⇦נî    נüéêpp≥rêr⇦ê    é⇦ê ⇧Ç⇩Frr@OנçÄ⇦Ç⇦@≡p≡p≥r≥ âIJÇ✓êä✓⇧נçäÇLyijץÇ⑥@;áIם;+í⇨{33¢+í⇨{1⇨úô♪s¢c♪ú(hPHK♪c`KKsc½#*√{#(HIך⇧⇨,dx            ;Restore command size
  496.         repe    cmpsb            ;Compare command
  497.         pop    si
  498.         je    string_found
  499.         inc    bx
  500.         xor    al,al
  501.         cmp    [di-1],al
  502.         jne    finds_2
  503.         dec    di
  504. finds_2:
  505.         mov    cx,10            ;Scan to next zero
  506.         repne    scasb
  507.         cmp    byte ptr [di],0     ;See if second zero. If so
  508.         jne    finds_1         ;  end of list.
  509. finds_3:
  510.         mov    bx,13
  511.         stc                ;Indicate string not found
  512. findstr_exit:
  513.         pop    es
  514.         pop    cx
  515.         ret
  516. string_found:
  517.         cmp    bx,12            ;If past the BAT commands,
  518.         jb    findstr_3        ;  then it is an internal cmd.
  519.         mov    bx,12
  520. findstr_3:
  521.         clc                ;Set string found flag
  522.         jmp    short findstr_exit
  523. findstr     endp
  524.  
  525. ;-----------------------------------------------------------------------------
  526. ; CAPSWORD capitalizes word pointed to by SI
  527. ; Entry:  SI - Pointer to ASCII word to capitalize
  528. ; Exit:   CX - Size of word
  529. ;-----------------------------------------------------------------------------
  530. capsalpha    proc near
  531.         assume    ds:nothing,es:nothing
  532.         push    ax
  533.         xor    ax,ax            ;Exit on non-alpha chars
  534.         jmp    short capsword_entry2
  535. capsalpha    endp
  536.  
  537. ;-----------------------------------------------------------------------------
  538. ; CAPSWORD capitalizes word pointed to by SI
  539. ; Entry:  SI - Pointer to ASCII word to capitalize
  540. ; Exit:   CX - Size of word
  541. ;-----------------------------------------------------------------------------
  542. capsword    proc near
  543.         assume    ds:nothing,es:nothing
  544.         push    ax
  545.         mov    ah,1            ;Ignore extra characters
  546. capsword_entry2:
  547.         push    di
  548.         push    si
  549.         push    es
  550.         push    ds            ;Set ES:DI = DS:SI
  551.         pop    es
  552.         mov    di,si
  553.         xor    cx,cx            ;Clear byte counter.
  554. caps_1:
  555.         lodsb                ;Get character
  556.         cmp    al," "                  ;Allow any non-space character
  557.         jbe    caps_exit
  558.         cmp    al,"a"                  ;If between a and z,
  559.         jb    caps_3           ;  capitalize it.
  560.         cmp    al,"z"
  561.         ja    caps_exit
  562.         and    al,0DFh
  563. caps_2:
  564.         stosb                ;Save character
  565.         inc    cx            ;Inc byte counter
  566.         jmp    short caps_1
  567. caps_3:
  568.         or    ah,ah            ;See if we should check 
  569.         jne    caps_2            ;  non-alpha chars.
  570.         cmp    al,'Z'
  571.         ja    caps_exit
  572.         cmp    al,'A'
  573.         jae    caps_2
  574. caps_exit:
  575.         pop    es
  576.         pop    si
  577.         pop    di
  578.         pop    ax
  579.         ret
  580. capsword    endp
  581.  
  582. ;-----------------------------------------------------------------------------
  583. ; REDIRECT CLOSE post process redirection commands
  584. ; Entry:  DI - Pointer to end of COM file data.
  585. ; Exit:   CF - Set if error.
  586. ;      Batch file line updated to remove any redirection symbols
  587. ;-----------------------------------------------------------------------------
  588. redirect_close    proc    near
  589.         assume    cs:code,ds:code
  590.         cmp    redirect_in,0        ;See if redirecton active
  591.         je    redirclose_1
  592.         mov    redirect_in,0
  593.         mov    bx,offset redirci_next    ;Append close redirect file
  594.         call    include_code        ;  routine to code.
  595.         xor    cx,cx
  596.         call    inline_code
  597. redirclose_1:
  598.         cmp    redirect_out,0        ;See if redirecton active
  599.         je    redirclose_2
  600.         mov    redirect_out,0
  601.         mov    bx,offset redirco_next    ;Append close redirect file
  602.         call    include_code        ;  routine to code.
  603.         xor    cx,cx
  604.         call    inline_code
  605. redirclose_2:
  606.         cmp    pipein_flag,0        ;See if in pipe curr active
  607.         je     redirclose_3
  608.         mov    dx,pipein_file        ;Get offset of input pipe file
  609.         mov    cx,1            ;Indicate parameter type
  610.         mov    bx,offset redirdel_next    ;Delete the piping file
  611.         call    include_code
  612.         call    inline_code        
  613.         mov    pipein_flag,0        ;Clear flag
  614. redirclose_3:
  615.         cmp    pipeout_flag,0        ;See if out pipe curr active
  616.         je     redirclose_exit
  617.         mov    dx,pipeout_file        ;Get offset of input pipe file
  618.         xor    bx,bx            ;Add output redirection code
  619.         xor    ax,ax            ;  to file.
  620.         call    redirect_openi
  621.         mov    pipein_flag,1        ;Set pipe input flag
  622.         mov    pipeout_flag,0        ;Clear pipe output flag
  623.         mov    pipein_file,dx        ;Copy pointer to filename
  624. redirclose_exit:
  625.         ret
  626. redirect_close    endp
  627.  
  628. ;-----------------------------------------------------------------------------
  629. ; REDIRECT CHECK process redirection commands
  630. ; Entry:  SI - Pointer to current BAT file line
  631. ;      DI - Pointer to end of COM file data.
  632. ; Exit:   CF - Set if error.
  633. ;      Batch file line updated to remove any redirection symbols
  634. ;-----------------------------------------------------------------------------
  635. redirect_check    proc    near
  636.         assume    cs:code,ds:code
  637.         push    si
  638.         call    redirect_close
  639.         mov    quote_flag,0
  640. redirect_1:
  641.         mov    bp,si            ;Save current position
  642.         lodsb
  643.         cmp    al,'"'                  ;See if quote
  644.         jne    redirect_2
  645.         not    quote_flag
  646. redirect_2:
  647.         cmp    quote_flag,0        ;Ignore characters in quotes
  648.         jne    redirect_1
  649. ;
  650. ; Check for piping
  651. ;
  652.         cmp    al,'|'                  ;Check for piping symbol
  653.         jne    redirect_5 
  654.         mov    byte ptr [si-1],13    ;Replace | with CR
  655.  
  656.         mov    bx,offset pipe1_file    ;Get offset of pipe file to
  657.         cmp    pipe_toggle,0        ;  use.  Alternate files so
  658.         jne    redirect_3         ;  that input and output files
  659.         mov    bx,offset pipe2_file    ;  don't get mixed up.
  660. redirect_3:
  661.         not    pipe_toggle
  662.         xor    dx,dx            ;If file not already used, 
  663.         or     dx,[bx]            ;  load the filename into 
  664.         jne    redirect_4         ;  the COM data buffer.
  665.         mov    dx,di
  666.         sub    dx,databuff_start    ;Compute offset of filename
  667.         mov    [bx],dx            ;Save pointer to filename
  668.         lea    si,[bx+2]        ;Get address of filename
  669.         mov    ah,1    
  670.         call    copy_string        ;Copy name to COM data buffer
  671.         xor    al,al            ;Terminate filename with zero
  672.         stosb
  673. redirect_4:
  674.         mov    pipeout_file,dx
  675.         mov    pipeout_flag,1
  676.         xor    bx,bx            ;Add output redirection code
  677.         xor    ax,ax            ;  to file.
  678.         call    redirect_openo
  679.         jmp    short redirect_exit    ;Terminate line scan.
  680. ;
  681. ; Check for output redirection
  682. ;
  683. redirect_5:
  684.         cmp    al,'>'                  ;Check for redirect out
  685.         jne    redirect_7
  686.         xor    bx,bx
  687.         cmp    byte ptr [si],'>'       ;Check for append redirect
  688.         jne    redirect_6
  689.         lodsb                ;Remove 2nd >
  690.         inc    bx
  691. redirect_6:
  692.         push    bx            ;Save append flag
  693.         xor    bl,bl
  694.         call    scan4char        ;Get filename
  695.         mov    dx,di
  696.         mov    ah,1            ;Copy only one word
  697.         call    copy_string
  698.         xor    al,al            ;Terminate name with zero
  699.         stosb
  700.         sub    dx,databuff_start    ;Compute offset of filename
  701.         pop    ax
  702.         call    redirect_openo
  703.         call    erase_redirect        ;Erase redirect from line.
  704.         jmp    short redirect_1
  705. redirect_7:
  706.         cmp    al,'<'                  ;Check for redirect in
  707.         jne    redirect_10
  708.         xor    bl,bl
  709.         call    scan4char        ;Get filename
  710.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@com file data area.  As always, if environment
  711. ;variables or command line parameters are in the data, insert a call to
  712. ;the translate routine before calli~g the for loop routine.
  713. ;
  714. for_cmd_1:
  715.         lodsb                ;Scan until '(' is found
  716.         cmp    al,13            ;  indicating the start of the
  717.         jne    for_cmd_2        ;  data set.
  718. jmp_for_syntax:
  719.         jmp    for_syntax
  720. for_cmd_2:
  721.         cmp    al,'('
  722.         jne    for_cmd_1
  723.         mov    ah,3            ;Copy until ')' found.
  724.         call    copy_string
  725.         xp⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩0´2É9´94Ã3É;œ´4⓪=2¨7ù╱à⇦䨴7¨õ╱à⇦äÀÆ⇦õ¶⑥⑧ÿœ╱,dx            ;Restore command size
  726.         repe    cmpsb            ;Compare command
  727.         pop    si
  728.         je    string_found
  729.         inc    bx
  730.         xor    al,al
  731.         cmp    [di-1],al
  732.         jne    finds_2
  733.         dec    di
  734. finds_2:
  735.         mov    cx,10            ;Scan to next zero
  736.         repne    scasb
  737.         cmp    byte ptr [di],0     ;See if second zero. If so
  738.         jne    finds_1         ;  end of list.
  739. finds_3:
  740.         mov    bx,13
  741.         stc                ;Indicate string not found
  742. findstr_exit:
  743.         pop    es
  744.         pop    cx
  745.         ret
  746. string_found:
  747.         cmp    bx,12            ;If past the BAT commands,
  748.         jb    findstr_3        ;  then it is an internal cmd.
  749.         mov    bx,12
  750. findstr_3:
  751.         clc                ;Set string found flag
  752.         jmp    short findstr_exit
  753. findstr     endp
  754.  
  755. ;-----------------------------------------------------------------------------
  756. ; CAPSWORD capitalizes word pointed to by SI
  757. ; Entry:  SI - Pointer to ASCII word to capitalize
  758. ; Exit:   CX - Size of word
  759. ;-----------------------------------------------------------------------------
  760. capsalpha    proc near
  761.         assume    ds:nothing,es:nothing
  762.         push    ax
  763.         xor    ax,ax            ;Exit on non-alpha chars
  764.         jmp    short capsword_entry2
  765. capsalpha    endp
  766.  
  767. ;-----------------------------------------------------------------------------
  768. ; CAPSWORD capitalizes word pointed to by SI
  769. ; Entry:  SI - Pointer to ASCII word to capitalize
  770. ; Exit:   CX - Size of word
  771. ;-----------------------------------------------------------------------------
  772. capsword    proc near
  773.         assume    ds:nothing,es:nothing
  774.         push    ax
  775.         mov    ah,1            ;Ignore extra characters
  776. capsword_entry2:
  777.         push    di
  778.         push    si
  779.         push    es
  780.         push    ds            ;Set ES:DI = DS:SI
  781.         pop    es
  782.         mov    di,si
  783.         xor    cx,cx            ;Clear byte counter.
  784. caps_1:
  785.         lodsb                ;Get character
  786.         cmp    al," "                  ;Allow any non-space character
  787.         jbe    caps_exit
  788.         cmp    al,"a"                  ;If between a and z,
  789.         jb    caps_3           ;  capitalize it.
  790.         cmp    al,"z"
  791.         ja    caps_exit
  792.         and    al,0DFh
  793. caps_2:
  794.         stosb                ;Save character
  795.         inc    cx            ;Inc byte counter
  796.         jmp    short caps_1
  797. caps_3:
  798.         or    ah,ah            ;See if we should check 
  799.         jne    caps_2            ;  non-alpha chars.
  800.         cmp    al,'Z'
  801.         ja    caps_exit
  802.         cmp    al,'A'
  803.         jae    caps_2
  804. caps_exit:
  805.         pop    es
  806.         pop    si
  807.         pop    di
  808.         pop    ax
  809.         ret
  810. capsword    endp
  811.  
  812. ;-----------------------------------------------------------------------------
  813. ; REDIRECT CLOSE post process redirection commands
  814. ; Entry:  DI - Pointer to end of COM file data.
  815. ; Exit:   CF - Set if error.
  816. ;      Batch file line updated to remove any redirection symbols
  817. ;-----------------------------------------------------------------------------
  818. redirect_close    proc    near
  819.         assume    cs:code,ds:code
  820.         cmp    redirect_in,0        ;See if redirecton active
  821.         je    redirclose_1
  822.         mov    redirect_in,0
  823.         mov    bx,offset redirci_next    ;Append close redirect file
  824.         call    include_code        ;  routine to code.
  825.         xor    cx,cx
  826.         call    inline_code
  827. redirclose_1:
  828.         cmp    redirect_out,0        ;See if redirecton active
  829.         je    redirclose_2
  830.         mov    redirect_out,0
  831.         mov    bx,offset redirco_next    ;Append close redirect file
  832.         call    include_code        ;  routine to code.
  833.         xor    cx,cx
  834.         call    inline_code
  835. redirclose_2:
  836.         cmp    pipein_flag,0        ;See if in pipe curr active
  837.         je     redirclose_3
  838.         mov    dx,pipein_file        ;Get offset of input pipe file
  839.         mov    cx,1            ;Indicate parameter type
  840.         mov    bx,offset redirdel_next    ;Delete the piping file
  841.         call    include_code
  842.         call    inline_code        
  843.         mov    pipein_flag,0        ;Clear flag
  844. redirclose_3:
  845.         cmp    pipeout_flag,0        ;See if out pipe curr active
  846.         je     redirclose_exit
  847.         mov    dx,pipeout_file        ;Get offset of input pipe file
  848.         xor    bx,bx            ;Add output redirection code
  849.         xor    ax,ax            ;  to file.
  850.         call    redirect_openi
  851.         mov    pipein_flag,1        ;Set pipe input flag
  852.         mov    pipeout_flag,0        ;Clear pipe output flag
  853.         mov    pipein_file,dx        ;Copy pointer to filename
  854. redirclose_exit:
  855.         ret
  856. redirect_close    endp
  857.  
  858. ;-----------------------------------------------------------------------------
  859. ; REDIRECT CHECK process redirection commands
  860. ; Entry:  SI - Pointer to current BAT file line
  861. ;      DI - Pointer to end of COM file data.
  862. ; Exit:   CF - Set if error.
  863. ;      Batch file line updated to remove any redirection symbols
  864. ;-----------------------------------------------------------------------------
  865. redirect_check    proc    near
  866.         assume    cs:code,ds:code
  867.         push    si
  868.         call    redirect_close
  869.         mov    quote_flag,0
  870. redirect_1:
  871.         mov    bp,si            ;Save current position
  872.         lodsb
  873.         cmp    al,'"'                  ;See if quote
  874.         jne    redirect_2
  875.         not    quote_flag
  876. redirect_2:
  877.         cmp    quote_flag,0        ;Ignore characters in quotes
  878.         jne    redirect_1
  879. ;
  880. ; Check for piping
  881. ;
  882.         cmp    al,'|'                  ;Check for piping symbol
  883.         jne    redirect_5 
  884.         mov    byte ptr [si-1],13    ;Replace | with CR
  885.  
  886.         mov    bx,offset pipe1_file    ;Get offset of pipe file to
  887.         cmp    pipe_toggle,0        ;  use.  Alternate files so
  888.         jne    redirect_3         ;  that input and output files
  889.         mov    bx,offset pipe2_file    ;  don't get mixed up.
  890. redirect_3:
  891.         not    pipe_toggle
  892.         xor    dx,dx            ;If file not already used, 
  893.         or     dx,[bx]            ;  load the filename into 
  894.         jne    redirect_4         ;  the COM data buffer.
  895.         mov    dx,di
  896.         sub    dx,databuff_start    ;Compute offset of filename
  897.         mov    [bx],dx            ;Save pointer to filename
  898.         lea    si,[bx+2]        ;Get address of filename
  899.         mov    ah,1    
  900.         call    copy_string        ;Copy name to COM data buffer
  901.         xor    al,al            ;Terminate filename with zero
  902.         stosb
  903. redirect_4:
  904.         mov    pipeout_file,dx
  905.         mov    pipeout_flag,1
  906.         xor    bx,bx            ;Add output redirection code
  907.         xor    ax,ax            ;  to file.
  908.         call    redirect_openo
  909.         jmp    short redirect_exit    ;Terminate line scan.
  910. ;
  911. ; Check for output redirection
  912. ;
  913. redirect_5:
  914.         cmp    al,'>'                  ;Check for redirect out
  915.         jne    redirect_7
  916.         xor    bx,bx
  917.         cmp    byte ptr [si],'>'       ;Check for append redirect
  918.         jne    redirect_6
  919.         lodsb                ;Remove 2nd >
  920.         inc    bx
  921. redirect_6:
  922.         push    bx            ;Save append flag
  923.         xor    bl,bl
  924.         call    scan4char        ;Get filename
  925.         mov    dx,di
  926.         mov    ah,1            ;Copy only one word
  927.         call    copy_string
  928.         xor    al,al            ;Terminate name with zero
  929.         stosb
  930.         sub    dx,databuff_start    ;Compute offset of filename
  931.         pop    ax
  932.         call    redirect_openo
  933.         call    erase_redirect        ;Erase redirect from line.
  934.         jmp    short redirect_1
  935. redirect_7:
  936.         cmp    al,'<'                  ;Check for redirect in
  937.         jne    redirect_10
  938.         xor    bl,bl
  939.         call    scan4char        ;Get filename
  940.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@osw                ;Clear end of list tag
  941.         stosw                ;Indicate unitialized label
  942.         mov    al,cl
  943.         stosb                ;Save length of label
  944.         rep    movsb            ;Copy label into data buffer
  945.         mov    ax,bp
  946.         sub    ax,bx            ;Compute offset to new label
  947.         mov    [bx],ax         ;Load offset in prev. label
  948.         mov    bx,bp            ;Get start of label entry
  949. getlabel_exit:
  950.         clc
  951.         ret
  952. getlabel    endp
  953.  
  954. ;-----------------------------------------------------------------------------
  955. ; EXTERNAL CMD compiles a routine to exexute a program.
  956. ; Entry:  SI - Pointer to character after the command
  957. ;      DI - Pointer to end of compiled data.
  958. ; Exit:   AL - Error code if CF set
  959. ;      CF - Set if error
  960. ;      SI,DI updated.
  961. ;-----------------------------------------------------------------------------
  962. external_cmd    proc    near
  963.         assume    cs:code,ds:code
  964.         mov    dx,di            ;Save ptr to filename
  965.         sub    dx,databuff_start    ;Compute offset.
  966.         mov    ah,1
  967.         call    copy_string        ;Copy filename to COM data.
  968.         mov    temp1,bx        ;Save translate flag
  969.         dec    si            ;Back up one char
  970.         xor    al,al            ;Terminate filename with zero
  971.         stosb
  972.         inc    di
  973.         push    di            ;Save ptr to command line tail
  974.         xor    ah,ah
  975.         call    c∩çé⇦⇧äéêrr@◆éOîëנüéêOüÄ⇩⇧ij≡p≥r≥⇨IJוווëâ≥r@◆çêëנ£⇦נÄëנÇê⇦Çpp≥r⇦⇧Ç⇦pp≥r◆Ç◆≥ ç≥rr@⇦êOüêê⇧âנÇ✓נî    נüéêOüÄ⇩⇧ij≡p≥r⇩îr ⇧≥rr@Oנß    ÇÇ⇦⇧נêÇ⇦נüâêO£⇦נä⇩î✓O≡p≥r≥ çijFAî⇧≥r@OנçäÇ ⇦⇧äנÇ⇩⇧üנÄ    ëנ£⇦ij:7É:42åà⇦䨴õ⇦õ8⑥20´0õ:ø3/¨´0¨:⇦¥É⓪1ôÃ:⑦⓪⓪"¶2õÉ897øÉ34¶2¨É╱à⇦äÕy╱⇧απ#⇧∙99 'τijIJIJ⇩'וτא@gijIJ⇦ x8y9⇩y╱AαהA∙99 ⇩⇦⇦'IJ⇦gijאGBוIJgה⇦ג'ijD⇦⇦ג⇦°8y9D9⇦⇧ijג⇩@Gה⇦ij#88`88`⇩⇦⇦'IJ⇦gij⇦'ijD⇦⇦τijאGBוIJg2
  976. capsalpha    endp
  977.  
  978. ;-----------------------------------------------------------------------------
  979. ; CAPSWORD capitalizes word pointed to by SI
  980. ; Entry:  SI - Pointer to ASCII word to capitalize
  981. ; Exit:   CX - Size of word
  982. ;-----------------------------------------------------------------------------
  983. capsword    proc near
  984.         assume    ds:nothing,es:nothing
  985.         push    ax
  986.         mov    ah,1            ;Ignore extra characters
  987. capsword_entry2:
  988.         push    di
  989.         push    si
  990.         push    es
  991.         push    ds            ;Set ES:DI = DS:SI
  992.         pop    es
  993.         mov    di,si
  994.         xor    cx,cx            ;Clear byte counter.
  995. caps_1:
  996.         lodsb                ;Get character
  997.         cmp    al," "                  ;Allow any non-space character
  998.         jbe    caps_exit
  999.         cmp    al,"a"                  ;If between a and z,
  1000.         jb    caps_3           ;  capitalize it.
  1001.         cmp    al,"z"
  1002.         ja    caps_exit
  1003.         and    al,0DFh
  1004. caps_2:
  1005.         stosb                ;Save character
  1006.         inc    cx            ;Inc byte counter
  1007.         jmp    short caps_1
  1008. caps_3:
  1009.         or    ah,ah            ;See if we should check 
  1010.         jne    caps_2            ;  non-alpha chars.
  1011.         cmp    al,'Z'
  1012.         ja    caps_exit
  1013.         cmp    al,'A'
  1014.         jae    caps_2
  1015. caps_exit:
  1016.         pop    es
  1017.         pop    si
  1018.         pop    di
  1019.         pop    ax
  1020.         ret
  1021. capsword    endp
  1022.  
  1023. ;-----------------------------------------------------------------------------
  1024. ; REDIRECT CLOSE post process redirection commands
  1025. ; Entry:  DI - Pointer to end of COM file data.
  1026. ; Exit:   CF - Set if error.
  1027. ;      Batch file line updated to remove any redirection symbols
  1028. ;-----------------------------------------------------------------------------
  1029. redirect_close    proc    near
  1030.         assume    cs:code,ds:code
  1031.         cmp    redirect_in,0        ;See if redirecton active
  1032.         je    redirclose_1
  1033.         mov    redirect_in,0
  1034.         mov    bx,offset redirci_next    ;Append close redirect file
  1035.         call    include_code        ;  routine to code.
  1036.         xor    cx,cx
  1037.         call    inline_code
  1038. redirclose_1:
  1039.         cmp    redirect_out,0        ;See if redirecton active
  1040.         je    redirclose_2
  1041.         mov    redirect_out,0
  1042.         mov    bx,offset redirco_next    ;Append close redirect file
  1043.         call    include_code        ;  routine to code.
  1044.         xor    cx,cx
  1045.         call    inline_code
  1046. redirclose_2:
  1047.         cmp    pipein_flag,0        ;See if in pipe curr active
  1048.         je     redirclose_3
  1049.         mov    dx,pipein_file        ;Get offset of input pipe file
  1050.         mov    cx,1            ;Indicate parameter type
  1051.         mov    bx,offset redirdel_next    ;Delete the piping file
  1052.         call    include_code
  1053.         call    inline_code        
  1054.         mov    pipein_flag,0        ;Clear flag
  1055. redirclose_3:
  1056.         cmp    pipeout_flag,0        ;See if out pipe curr active
  1057.         je     redirclose_exit
  1058.         mov    dx,pipeout_file        ;Get offset of input pipe file
  1059.         xor    bx,bx            ;Add output redirection code
  1060.         xor    ax,ax            ;  to file.
  1061.         call    redirect_openi
  1062.         mov    pipein_flag,1        ;Set pipe input flag
  1063.         mov    pipeout_flag,0        ;Clear pipe output flag
  1064.         mov    pipein_file,dx        ;Copy pointer to filename
  1065. redirclose_exit:
  1066.         ret
  1067. redirect_close    endp
  1068.  
  1069. ;-----------------------------------------------------------------------------
  1070. ; REDIRECT CHECK process redirection commands
  1071. ; Entry:  SI - Pointer to current BAT file line
  1072. ;      DI - Pointer to end of COM file data.
  1073. ; Exit:   CF - Set if error.
  1074. ;      Batch file line updated to remove any redirection symbols
  1075. ;-----------------------------------------------------------------------------
  1076. redirect_check    proc    near
  1077.         assume    cs:code,ds:code
  1078.         push    si
  1079.         call    redirect_close
  1080.         mov    quote_flag,0
  1081. redirect_1:
  1082.         mov    bp,si            ;Save current position
  1083.         lodsb
  1084.         cmp    al,'"'                  ;See if quote
  1085.         jne    redirect_2
  1086.         not    quote_flag
  1087. redirect_2:
  1088.         cmp    quote_flag,0        ;Ignore characters in quotes
  1089.         jne    redirect_1
  1090. ;
  1091. ; Check for piping
  1092. ;
  1093.         cmp    al,'|'                  ;Check for piping symbol
  1094.         jne    redirect_5 
  1095.         mov    byte ptr [si-1],13    ;Replace | with CR
  1096.  
  1097.         mov    bx,offset pipe1_file    ;Get offset of pipe file to
  1098.         cmp    pipe_toggle,0        ;  use.  Alternate files so
  1099.         jne    redirect_3         ;  that input and output files
  1100.         mov    bx,offset pipe2_file    ;  don't get mixed up.
  1101. redirect_3:
  1102.         not    pipe_toggle
  1103.         xor    dx,dx            ;If file not already used, 
  1104.         or     dx,[bx]            ;  load the filename into 
  1105.         jne    redirect_4         ;  the COM data buffer.
  1106.         mov    dx,di
  1107.         sub    dx,databuff_start    ;Compute offset of filename
  1108.         mov    [bx],dx            ;Save pointer to filename
  1109.         lea    si,[bx+2]        ;Get address of filename
  1110.         mov    ah,1    
  1111.         call    copy_string        ;Copy name to COM data buffer
  1112.         xor    al,al            ;Terminate filename with zero
  1113.         stosb
  1114. redirect_4:
  1115.         mov    pipeout_file,dx
  1116.         mov    pipeout_flag,1
  1117.         xor    bx,bx            ;Add output redirection code
  1118.         xor    ax,ax            ;  to file.
  1119.         call    redirect_openo
  1120.         jmp    short redirect_exit    ;Terminate line scan.
  1121. ;
  1122. ; Check for output redirection
  1123. ;
  1124. redirect_5:
  1125.         cmp    al,'>'                  ;Check for redirect out
  1126.         jne    redirect_7
  1127.         xor    bx,bx
  1128.         cmp    byte ptr [si],'>'       ;Check for append redirect
  1129.         jne    redirect_6
  1130.         lodsb                ;Remove 2nd >
  1131.         inc    bx
  1132. redirect_6:
  1133.         push    bx            ;Save append flag
  1134.         xor    bl,bl
  1135.         call    scan4char        ;Get filename
  1136.         mov    dx,di
  1137.         mov    ah,1            ;Copy only one word
  1138.         call    copy_string
  1139.         xor    al,al            ;Terminate name with zero
  1140.         stosb
  1141.         sub    dx,databuff_start    ;Compute offset of filename
  1142.         pop    ax
  1143.         call    redirect_openo
  1144.         call    erase_redirect        ;Erase redirect from line.
  1145.         jmp    short redirect_1
  1146. redirect_7:
  1147.         cmp    al,'<'                  ;Check for redirect in
  1148.         jne    redirect_10
  1149.         xor    bl,bl
  1150.         call    scan4char        ;Get filename
  1151.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Append runtime routines.
  1152.         sub    dx,databuff_start
  1153.         or    bx,bx            ;Check translate flag, if set
  1154.         je    echo_c21        ;  append translate code 1st.
  1155.         mov    bx,offset procstr_next    ;Append translate string
  1156.         call    include_code        ;  routine to code.
  1157.         mov    bx,offset prse_buff_ptr - offset data_start
  1158.         mov    cx,0021h        ;Indicate parameter type
  1159.         call    inline_code        ;Insert translate code.
  1160.         mov    dx,bx
  1161.         mov    cx,2            ;Use proper parameter type
  1162. echo_c21:
  1163.         mov    bx,offset echo_msg_next ;Append echo string
  1164.         call    include_code        ;  routine to code.
  1165. echo_c3:
  1166.         call    inline_code        ;Add code to COM file.
  1167. echo_cstatus:
  1168. echo_exit:
  1169.         clc
  1170. echo_cmd_exit:
  1171.         ret
  1172. echo_cmd    endp
  1173.  
  1174. ;-----------------------------------------------------------------------------
  1175. ; PAUSE CMD compiles a PAUSE command.
  1176. ; Entry:  SI - Pointer to character after the PAUSE command
  1177. ;      DI - Pointer to end of compiled data.
  1178. ; Exit:   AL - Error code if CF set
  1179. ;      CF - Set if error
  1180. ;      SI,DI updated.
  1181. ;-----------------------------------------------------------------------------
  1182. pause_cmd    proc    near
  1183.         assume    cs:code,ds:code
  1184. ;Append routine if necessary
  1185.         mov    bx,offset pause_next     ;Append PAUSE routine if
  1186.         call    include_code         ;  necessary.
  1187.  
  1188.         mov    cx,0            ;Add inline code with 0 params
  1189.         call    inline_code        ;  to call pause routine.
  1190.  
  1191.         mov    bl,2            ;Scan to end of line
  1192.         call    scan4char
  1193.         clc
  1194. pause_cmd_exit:
  1195.         ret
  1196. pause_cmd    endp
  1197.  
  1198. ;-----------------------------------------------------------------------------
  1199. ; SHIFT CMD compiles a SHIFT command.
  1200. ; Entry:  SI - Pointer to character after the SHIFT command
  1201. ;      DI - Pointer to end of compiled data.
  1202. ; Exit:   AL - Error code if CF set
  1203. ;      CF - Set if error
  1204. ;      SI,DI updated.
  1205. ;-----------------------------------------------------------------------------
  1206. shift_cmd    proc    near
  1207.         assume    cs:code,ds:cp    êpp≥r≥ âIJÇ✓êä✓⇧נä⇨é✓üÇê⇨ü≥Oij◆çêëנä⇨é✓üנäÇ⇧éêOé✓≡p≥r ⇧ü≥⇩î⇧Ç    ê     êrrOijOנÇê ✓⇦⇦⇦é@≡p≥r≥ ⇨IJו≥rr@    ëנéüéêOî    êOÇ⇩⇧âנונçÄ⇦Ä⇦pp≥r ⇧ü≥⇩üéê     êrr@OנüÇOî⇧üנçÄ⇦✓OäÇ⇧éê@≡p≥r⇧Æ⇦õ6⑥⑨⇦ää¥⌐õãÃ⓪:7É2d of line
  1208.         call    scan4char
  1209.         clc
  1210.         ret
  1211. shift_cmd    endp
  1212.  
  1213. ;-----------------------------------------------------------------------------
  1214. ; REM CMD  Processes remark lines in batch file.
  1215. ; Entry:  SI - pointer to line in BAT file
  1216. ;--------------------------------------------------------------------------.@Aå8£"¡Ç⇧Àש£@<$ ü¨òàז4($%àללרŒö%ìכΘì©æöõæכΘì©æö4($%æòî%לñ$$$ϕ    àì¼üרijüע¶üŒà¡öüלרחöü§öüæ©Õ¥ס4)חòŒ}îגΦÇ%õ©æלê$$$$∮ÇüŒÑלכüäüìàחחà¥öüחòערחÕÕ4($%ìŒij%àããדàá$$$ϕ1©©ijüר¨עÑãüò¨Éü©ÿüõѨöü©זüò¨É4($%⌐ö%חòŒ}òβÑס$$_2
  1217. caps_exit:
  1218.         pop    es
  1219.         pop    si
  1220.         pop    di
  1221.         pop    ax
  1222.         ret
  1223. capsword    endp
  1224.  
  1225. ;-----------------------------------------------------------------------------
  1226. ; REDIRECT CLOSE post process redirection commands
  1227. ; Entry:  DI - Pointer to end of COM file data.
  1228. ; Exit:   CF - Set if error.
  1229. ;      Batch file line updated to remove any redirection symbols
  1230. ;-----------------------------------------------------------------------------
  1231. redirect_close    proc    near
  1232.         assume    cs:code,ds:code
  1233.         cmp    redirect_in,0        ;See if redirecton active
  1234.         je    redirclose_1
  1235.         mov    redirect_in,0
  1236.         mov    bx,offset redirci_next    ;Append close redirect file
  1237.         call    include_code        ;  routine to code.
  1238.         xor    cx,cx
  1239.         call    inline_code
  1240. redirclose_1:
  1241.         cmp    redirect_out,0        ;See if redirecton active
  1242.         je    redirclose_2
  1243.         mov    redirect_out,0
  1244.         mov    bx,offset redirco_next    ;Append close redirect file
  1245.         call    include_code        ;  routine to code.
  1246.         xor    cx,cx
  1247.         call    inline_code
  1248. redirclose_2:
  1249.         cmp    pipein_flag,0        ;See if in pipe curr active
  1250.         je     redirclose_3
  1251.         mov    dx,pipein_file        ;Get offset of input pipe file
  1252.         mov    cx,1            ;Indicate parameter type
  1253.         mov    bx,offset redirdel_next    ;Delete the piping file
  1254.         call    include_code
  1255.         call    inline_code        
  1256.         mov    pipein_flag,0        ;Clear flag
  1257. redirclose_3:
  1258.         cmp    pipeout_flag,0        ;See if out pipe curr active
  1259.         je     redirclose_exit
  1260.         mov    dx,pipeout_file        ;Get offset of input pipe file
  1261.         xor    bx,bx            ;Add output redirection code
  1262.         xor    ax,ax            ;  to file.
  1263.         call    redirect_openi
  1264.         mov    pipein_flag,1        ;Set pipe input flag
  1265.         mov    pipeout_flag,0        ;Clear pipe output flag
  1266.         mov    pipein_file,dx        ;Copy pointer to filename
  1267. redirclose_exit:
  1268.         ret
  1269. redirect_close    endp
  1270.  
  1271. ;-----------------------------------------------------------------------------
  1272. ; REDIRECT CHECK process redirection commands
  1273. ; Entry:  SI - Pointer to current BAT file line
  1274. ;      DI - Pointer to end of COM file data.
  1275. ; Exit:   CF - Set if error.
  1276. ;      Batch file line updated to remove any redirection symbols
  1277. ;-----------------------------------------------------------------------------
  1278. redirect_check    proc    near
  1279.         assume    cs:code,ds:code
  1280.         push    si
  1281.         call    redirect_close
  1282.         mov    quote_flag,0
  1283. redirect_1:
  1284.         mov    bp,si            ;Save current position
  1285.         lodsb
  1286.         cmp    al,'"'                  ;See if quote
  1287.         jne    redirect_2
  1288.         not    quote_flag
  1289. redirect_2:
  1290.         cmp    quote_flag,0        ;Ignore characters in quotes
  1291.         jne    redirect_1
  1292. ;
  1293. ; Check for piping
  1294. ;
  1295.         cmp    al,'|'                  ;Check for piping symbol
  1296.         jne    redirect_5 
  1297.         mov    byte ptr [si-1],13    ;Replace | with CR
  1298.  
  1299.         mov    bx,offset pipe1_file    ;Get offset of pipe file to
  1300.         cmp    pipe_toggle,0        ;  use.  Alternate files so
  1301.         jne    redirect_3         ;  that input and output files
  1302.         mov    bx,offset pipe2_file    ;  don't get mixed up.
  1303. redirect_3:
  1304.         not    pipe_toggle
  1305.         xor    dx,dx            ;If file not already used, 
  1306.         or     dx,[bx]            ;  load the filename into 
  1307.         jne    redirect_4         ;  the COM data buffer.
  1308.         mov    dx,di
  1309.         sub    dx,databuff_start    ;Compute offset of filename
  1310.         mov    [bx],dx            ;Save pointer to filename
  1311.         lea    si,[bx+2]        ;Get address of filename
  1312.         mov    ah,1    
  1313.         call    copy_string        ;Copy name to COM data buffer
  1314.         xor    al,al            ;Terminate filename with zero
  1315.         stosb
  1316. redirect_4:
  1317.         mov    pipeout_file,dx
  1318.         mov    pipeout_flag,1
  1319.         xor    bx,bx            ;Add output redirection code
  1320.         xor    ax,ax            ;  to file.
  1321.         call    redirect_openo
  1322.         jmp    short redirect_exit    ;Terminate line scan.
  1323. ;
  1324. ; Check for output redirection
  1325. ;
  1326. redirect_5:
  1327.         cmp    al,'>'                  ;Check for redirect out
  1328.         jne    redirect_7
  1329.         xor    bx,bx
  1330.         cmp    byte ptr [si],'>'       ;Check for append redirect
  1331.         jne    redirect_6
  1332.         lodsb                ;Remove 2nd >
  1333.         inc    bx
  1334. redirect_6:
  1335.         push    bx            ;Save append flag
  1336.         xor    bl,bl
  1337.         call    scan4char        ;Get filename
  1338.         mov    dx,di
  1339.         mov    ah,1            ;Copy only one word
  1340.         call    copy_string
  1341.         xor    al,al            ;Terminate name with zero
  1342.         stosb
  1343.         sub    dx,databuff_start    ;Compute offset of filename
  1344.         pop    ax
  1345.         call    redirect_openo
  1346.         call    erase_redirect        ;Erase redirect from line.
  1347.         jmp    short redirect_1
  1348. redirect_7:
  1349.         cmp    al,'<'                  ;Check for redirect in
  1350.         jne    redirect_10
  1351.         xor    bl,bl
  1352.         call    scan4char        ;Get filename
  1353.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ODE - Appends the routine to the append list if necessary and
  1354. ;         returns the offset of the routine in the compiled program.
  1355. ; Entry:  BX - Pointer to header of canned routine to append.
  1356. ; Exit:   AX - Offset of canned routine in COM file.
  1357. ;-----------------------------------------------------------------------------
  1358. include_code    proc    near
  1359.         assume    ds:code,es:nothing
  1360.         push    cx
  1361.         push    dx
  1362.         mov    ax,[bx-4]        ;Get COM file offset
  1363.         or    ax,ax            ;If zero, routine has not
  1364.         jne    include_exit        ;  been appended.
  1365.         mov    cx,bx            ;Save pointer to new routine
  1366. ;
  1367. ;Address the prevous 'last' routine header.  Update that header, then use
  1368. ;information in that header to compute the offset of the new routine.
  1369. ;
  1370.         xchg    bx,last_routine
  1371.         mov    [bx],cx         ;Add code to chain.
  1372.         mov    ax,[bx-2]        ;Compute offset of new routine
  1373.         add    ax,[bx-4]        ;  by adding the offset of the
  1374.         sub    ax,[bx+2]        ;  prevous routine to its size.
  1375.         mov    bx,cx
  1376.  
  1377.         mov    cx,[bx+2]        ;Get number of called routines.
  1378.         add    ax,cx
  1379.         mov    [bx-4],ax        ;Set offset of code.
  1380.         jcxz    include_exit
  1381.         shr    cx,1            ;If this routine needs other
  1382.         add    bx,4            ;  routines, include them in
  1383.         push    ax            ;  the COM file.
  1384. include_1:
  1385.         push    cx
  1386.         push    bx
  1387.         mov    bx,[bx]
  1388.         call    include_code
  1389.         pop    bx
  1390.         mov    [bx],ax
  1391.         add    bx,2
  1392.         pop    cx
  1393.         loop    include_1
  1394.         pop    ax
  1395. include_exit:
  1396.         pop    dx
  1397.         pop    cx
  1398.         ret
  1399. include_code    endp
  1400. ;-----------------------------------------------------------------------------
  1401. ; PRINTMSG prints the message pointed to by DX to the screen.
  1402. ; Entry:  DX - pointer to ASCII message terminated by $
  1403. ;-----------------------------------------------------------------------------
  1404. printmsg    proc    near
  1405.         assume    ds:nothing,es:nothing
  1406.         push    ds
  1407.         push    cs
  1408.         pop    ds
  1409.         assume    ds:code
  1410.         mov    ah,9            ;Print message
  1411.         int    21h
  1412.         pop    ds
  1413.         ret
  1414. printmsg    endp
  1415.  
  1416. ;-----------------------------------------------------------------------------
  1417. ; PRINTMSGCR calls PRINTMSG, then appends a carriage return to the message.
  1418. ; Entry:  DX - pointer to ASCII message terminated by $
  1419. ;-----------------------------------------------------------------------------
  1420. printmsgcr    proc    near
  1421.         assume    ds:nothing,es:nothing
  1422.         push    dx
  1423.         call    printmsg
  1424.         mov    dx,offset endmsg
  1425.         call    printmsg
  1426.         pop    dx
  1427.         ret
  1428. printmsgcr    endp
  1429.  
  1430. ;-----------------------------------------------------------------------------
  1431. ; HEX2ASC converts a binary number to ASCII and prints it to the screen.
  1432. ; Entry:  AX - binary number
  1433. ;-----------------------------------------------------------------------------
  1434. hex2asc     proc near
  1435.         assume    ds:nothing,es:nothing
  1436.         push    bx
  1437.         mov    cx,5            ;Allow max of five digits
  1438. hex_loop1:
  1439.         xor    dx,dx            ;Clear high word
  1440.         mov    bx,10            ;Load number base
  1441.         div    bx            ;Divide by base (10)
  1442.         add    dl,30h            ;Convert to ascii
  1443.         push    dx            ;Save digit on stack
  1444.         loop    hex_loop1
  1445.         mov    cx,5            ;Allow max of five digits
  1446.         mov    bl,"0"                  ;Set leading zero indicator
  1447. hex_loop2:
  1448.         pop    dx            ;Get digit off stack
  1449.         or    bl,dl            ;Don't print leading zeros.
  1450.         cmp    bl,"0"                  ;The first non zero will
  1451.         je    hex_1            ?  change bl to non.ê⇦Ç@≡p≥r≥⇨IJג≥rr@⑨É⇦Oî⇨Ä⇦Ä ⇧ê⇦נÇ⇧çÇ⇧≡p≥r⇩ü≥Dה⇨≡pâê⇨ÇF@≡p≥r⇧Ç◆≥⇨ê⇨Ç⇧Ç◆ג≡pâê⇨Ç✓⇨é⇧ij≡p≥r◆Ç◆≥ â≡p≥r⇦ê⇧≡pâê⇨גÄ⇦ O≥✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ppijOæÉ⑨£ß⇧ÿÆ①ÿOüÇ    äOüâêOéçÇ⇧נ£ß⇧נêé⇧ê@≡pijOÿüäé@ננÖä@ä②OijOçÇ⇩üê⇦נüÇOüâêOÇÄ✓OÇ✓נüâêOêé⇧êOüÇOÇ◆ê≡pijOÿ⇨é⇧ijננננננ£⑧נijOî⇧ê⇦נé✓נä ✓⇦⇦✓Ç⇧≡pijppijOנä◆çÇ⇦üנêÇ⇦נ£ß⇧נêé⇧ê⇦OüÄ⇦ê✓⇦נüâÄנה@נÉOé⇦OÇÇ⇧נî⇦äêüüéOé◆üé✓üê    ij≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@se_3
  1452.         mov    dx,pipein_file        ;Get offset of input pipe file
  1453.         mov    cx,1            ;Indicate parameter type
  1454.         mov    bx,offset redirdel_next    ;Delete the piping file
  1455.         call    include_code
  1456.         call    inline_code        
  1457.         mov    pipein_flag,0        ;Clear flag
  1458. redirclose_3:
  1459.         cmp    pipeout_flag,0        ;See if out pipe curr active
  1460.         je     redirclose_exit
  1461.         mov    dx,pipeout_file        ;Get offset of input pipe file
  1462.         xor    bx,bx            ;Add output redirection code
  1463.         xor    ax,ax            ;  to file.
  1464.         call    redirect_openi
  1465.         mov    pipein_flag,1        ;Set pipe input flag
  1466.         mov    pipeout_flag,0        ;Clear pipe output flag
  1467.         mov    pipein_file,dx        ;Copy pointer to filename
  1468. redirclose_exit:
  1469.         ret
  1470. redirect_close    endp
  1471.  
  1472. ;-----------------------------------------------------------------------------
  1473. ; REDIRECT CHECK process redirection commands
  1474. ; Entry:  SI - Pointer to current BAT file line
  1475. ;      DI - Pointer to end of COM file data.
  1476. ; Exit:   CF - Set if error.
  1477. ;      Batch file line updated to remove any redirection symbols
  1478. ;-----------------------------------------------------------------------------
  1479. redirect_check    proc    near
  1480.         assume    cs:code,ds:code
  1481.         push    si
  1482.         call    redirect_close
  1483.         mov    quote_flag,0
  1484. redirect_1:
  1485.         mov    bp,si            ;Save current position
  1486.         lodsb
  1487.         cmp    al,'"'                  ;See if quote
  1488.         jne    redirect_2
  1489.         not    quote_flag
  1490. redirect_2:
  1491.         cmp    quote_flag,0        ;Ignore characters in quotes
  1492.         jne    redirect_1
  1493. ;
  1494. ; Check for piping
  1495. ;
  1496.         cmp    al,'|'                  ;Check for piping symbol
  1497.         jne    redirect_5 
  1498.         mov    byte ptr [si-1],13    ;Replace | with CR
  1499.  
  1500.         mov    bx,offset pipe1_file    ;Get offset of pipe file to
  1501.         cmp    pipe_toggle,0        ;  use.  Alternate files so
  1502.         jne    redirect_3         ;  that input and output files
  1503.         mov    bx,offset pipe2_file    ;  don't get mixed up.
  1504. redirect_3:
  1505.         not    pipe_toggle
  1506.         xor    dx,dx            ;If file not already used, 
  1507.         or     dx,[bx]            ;  load the filename into 
  1508.         jne    redirect_4         ;  the COM data buffer.
  1509.         mov    dx,di
  1510.         sub    dx,databuff_start    ;Compute offset of filename
  1511.         mov    [bx],dx            ;Save pointer to filename
  1512.         lea    si,[bx+2]        ;Get address of filename
  1513.         mov    ah,1    
  1514.         call    copy_string        ;Copy name to COM data buffer
  1515.         xor    al,al            ;Terminate filename with zero
  1516.         stosb
  1517. redirect_4:
  1518.         mov    pipeout_file,dx
  1519.         mov    pipeout_flag,1
  1520.         xor    bx,bx            ;Add output redirection code
  1521.         xor    ax,ax            ;  to file.
  1522.         call    redirect_openo
  1523.         jmp    short redirect_exit    ;Terminate line scan.
  1524. ;
  1525. ; Check for output redirection
  1526. ;
  1527. redirect_5:
  1528.         cmp    al,'>'                  ;Check for redirect out
  1529.         jne    redirect_7
  1530.         xor    bx,bx
  1531.         cmp    byte ptr [si],'>'       ;Check for append redirect
  1532.         jne    redirect_6
  1533.         lodsb                ;Remove 2nd >
  1534.         inc    bx
  1535. redirect_6:
  1536.         push    bx            ;Save append flag
  1537.         xor    bl,bl
  1538.         call    scan4char        ;Get filename
  1539.         mov    dx,di
  1540.         mov    ah,1            ;Copy only one word
  1541.         call    copy_string
  1542.         xor    al,al            ;Terminate name with zero
  1543.         stosb
  1544.         sub    dx,databuff_start    ;Compute offset of filename
  1545.         pop    ax
  1546.         call    redirect_openo
  1547.         call    erase_redirect        ;Erase redirect from line.
  1548.         jmp    short redirect_1
  1549. redirect_7:
  1550.         cmp    al,'<'                  ;Check for redirect in
  1551.         jne    redirect_10
  1552.         xor    bl,bl
  1553.         call    scan4char        ;Get filename
  1554.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@c    near
  1555.         mov    si,[bp+1234h]        ;Load data
  1556. code_movsi_end    =    $
  1557. code_movsi    endp
  1558.  
  1559. code_movsiim    proc    near
  1560.         mov    si,1234h        ;Load immediate data
  1561. code_movsiim_end  =    $
  1562. code_movsiim    endp
  1563.  
  1564. code_leadi    proc    near
  1565.         lea    di,[bp+1234h]        ;Load address of data
  1566. code_leadi_end    =    $
  1567. code_leadi    endp
  1568.  
  1569. code_movdi    proc    near
  1570.         mov    di,[bp+1234h]        ;Load data
  1571. code_movdi_end    =    $
  1572. code_movdi    endp
  1573.  
  1574. code_movdiim    proc    near
  1575.         mov    di,1234h        ;Load immediate data
  1576. code_movdiim_end  =    $
  1577. code_movdiim    endp
  1578.  
  1579. ;----------------------------------------------------------------------------
  1580. ;Predefined data needed for all compiled programs.
  1581. ;----------------------------------------------------------------------------
  1582. data_start    =    $
  1583. code_start    dw    ?            ;Offset of main code routine
  1584. stack_ptr    dw    ?            ;Offset of end of code + stack
  1585. prog_segsize    dw    ?            ;Size of COM prog in paragraphs
  1586. prse_buff_ptr    dw    ?            ;Buffer for parsing strings
  1587. prs2_buff_ptr    dw    ?            ;Buffer for parsing strings
  1588. exec_buff_ptr    dw    ?            ;Buffer for exec function
  1589. for_buff_ptr    dw    ?            ;Buffer for For loop variables
  1590. floop_ptr    dw    ?            ;Pointer to for loop string
  1591. file_handle1    dw    ?            ;Saved handle of std output
  1592. file_handle2    dw    ?            ;Handle of output file
  1593. file_handle3    dw    ?            ;Saved handle of std input
  1594. file_handle4    dw    ?            ;Handle of input file
  1595. label_list_strt dw    ?            ;Offset into data of 1st label.
  1596. master_env    dw    ?            ;Segment of environment blk
  1597. version_num    dw    ?            ;DOS version number
  1598. proc_rc     db    ?            ;Return code of last program.
  1599. shift_cnt    db    ?            ;Count of shift parameter
  1600. data_end    =    $
  1601.  
  1602. ;----------------------------------------------------------------------------
  1603. ;INIT CODE Routine at the start of all compiled programs.
  1604. ;----------------------------------------------------------------------------
  1605. init_code_off    dw    100h            ;Pointer to offset in COM file
  1606. init_code_size    dw    offset init_code_end-offset init_code_start
  1607. init_code_next    dw    0            ;Ptr to next routine to append
  1608. init_code_lnks    dw    0            ;Bytes in the dependancy header ;Number of routines called
  1609. init_code_start =    $
  1610.  
  1611. init_code    proc    near
  1612.         assume    cs:code,ds:code,es:code,ss:code
  1613.         cld
  1614.         mov    bp,ds:[offset data_start_ptr - offset init_code + 100h]
  1615.         mov    bp,[bp]
  1616.         mov    sp,com_stack_ptr    ;Move stack pointer
  1617.         mov    bx,com_prog_size    ;Reduce memory allocation
  1618.         mov    ah,4ah            ;Resize memory block
  1619.         int    21h
  1620.         mov    ax,ds:[2ch]        ;Get program environment seg
  1621.         mov    environment_seg,ax    ;  use unless SET cmd used.
  1622.         mov    bx,code_start_ptr    ;Get starting code offset
  1623.         jmp    bx            ;Jump to start of code.
  1624. data_start_ptr    dw    ?            ;Offset of data area.
  1625. init_code    endp
  1626. init_code_end    =    $
  1627.  
  1628. ;----------------------------------------------------------------------------
  1629. ;END CODE Routine appended at the end of all compiled programs.
  1630. ;----------------------------------------------------------------------------
  1631. end_code_off    dw    0            ;Pointer to offset in COM file
  1632. end_code_size    dw    offset end_code_end-offset end_code_start
  1633. end_code_next    dw    0            ;Ptr to next routine to append
  1634. end_code_lnks    dw    0            ;Bytes in the dependancy header ;Number of routines called
  1635. end_code_start    =    $
  1636.  
  1637. end_code    proc    near
  1638.         assume    cs:code,ds:code
  1639.         mov    ax,4c00h        ;Terminate program
  1640.         int    21h
  1641. end_code    endp
  1642. end_code_end    =    $
  1643.  
  1644. ;----------------------------------------------------------------------------
  1645. ;ECHO MSG CODE Routine used print a string to the standard output device
  1646. ; Entry:  DS:SI - offset of string to print.
  1647. ;----------------------------------------------------------------------------
  1648. echo_msg_off    dw    0            ;Pointer to offset in COM file
  1649. echo_msg_size    dw    offset echo_msg_epëij✓êä✓⇧נê ⇨Ç⇦✓⇦⇧Ä⇦ü≡pê ⇨Ç⇦✓ê⇨ü≥    ÇrG≥rr@◆üäנüÇOÇê⇨üנäÇ⇧éêOüÇOÄ◆çêë≡pê ⇨Ç⇦✓⇧ÇÇ⇦r    ÇrG≥rr@é⇧ê⇦OéנüâêOëê◆êëÄî⇩Oâê    ê⇦נij⓪Ç ê⇦נÇ✓נäÇ⇧éê⇦Oî⇧üê    ≡pê ⇨Ç⇦✓⇦⇧Ä⇦ü≥@rI≡p≡pê ⇨Ç⇦✓     êr◆äÇ rê⇦≡p≥r⇦⇦✓r ⇦@î    êAëä@î    êpp≥r≥    üIJÇ⇦⇩O≥r@⑧✓⇧נî 0¨0õ´2¨╱à⇦äœÃ1䨜åà⇦äè⇦Ø6⑥26╱à⇦äŒ2äØõœ7»À¨ø»ÿåà⇦äÀÆ⇦ãœ⑥⑨⇦ä䥿94Ã:⓪1œ0¨0õ´2¨╱à⇦äœÃ:⇦Ö⑧œ╱à⇦äŒ6Õ⇦¨œ7¨:⓪2õœ7»À¨ø»õÃØ2åà2õœ7»À¨ø»ÿ¥╱à⇦ä¨2´╱à2õœ7»À¨ø»õÃØ2äØÃ28╱à2õœ7»À¨ø»ØÃ2⇦ßäÆ╱à╱àûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû-
  1650. ;ECHO STATUS CODE Routine used to report the status of the echo flag.
  1651. ; Entry:  AL - Echo flag.
  1652. ;----------------------------------------------------------------------------
  1653. echo_stat_ptr    dw    0            ;Pointer to offset in COM file
  1654. echo_stat_size    dw    offset echo_sta|_end-offset echo_stat_start
  1655. echo_stat_next    dw    0            ;Ptr to next routine to append
  1656. echo_stat_lnks    dw    0            ;Bytes in the dependancy header ;Number of routines called
  1657. echo_stat_start =    $
  1658.  
  1659. echo_stat_code    proc    near
  1660.         assume    cs:code,ds:code
  1661.         cal-----------------------
  1662. redirect_check    proc    near
  1663.         assume    cs:code,ds:code
  1664.         push    si
  1665.         call    redirect_close
  1666.         mov    quote_flag,0
  1667. redirect_1:
  1668.         mov    bp,si            ;Save current position
  1669.         lodsb
  1670.         cmp    al,'"'                  ;See if quote
  1671.         jne    redirect_2
  1672.         not    quote_flag
  1673. redirect_2:
  1674.         cmp    quote_flag,0        ;Ignore characters in quotes
  1675.         jne    redirect_1
  1676. ;
  1677. ; Check for piping
  1678. ;
  1679.         cmp    al,'|'                  ;Check for piping symbol
  1680.         jne    redirect_5 
  1681.         mov    byte ptr [si-1],13    ;Replace | with CR
  1682.  
  1683.         mov    bx,offset pipe1_file    ;Get offset of pipe file to
  1684.         cmp    pipe_toggle,0        ;  use.  Alternate files so
  1685.         jne    redirect_3         ;  that input and output files
  1686.         mov    bx,offset pipe2_file    ;  don't get mixed up.
  1687. redirect_3:
  1688.         not    pipe_toggle
  1689.         xor    dx,dx            ;If file not already used, 
  1690.         or     dx,[bx]            ;  load the filename into 
  1691.         jne    redirect_4         ;  the COM data buffer.
  1692.         mov    dx,di
  1693.         sub    dx,databuff_start    ;Compute offset of filename
  1694.         mov    [bx],dx            ;Save pointer to filename
  1695.         lea    si,[bx+2]        ;Get address of filename
  1696.         mov    ah,1    
  1697.         call    copy_string        ;Copy name to COM data buffer
  1698.         xor    al,al            ;Terminate filename with zero
  1699.         stosb
  1700. redirect_4:
  1701.         mov    pipeout_file,dx
  1702.         mov    pipeout_flag,1
  1703.         xor    bx,bx            ;Add output redirection code
  1704.         xor    ax,ax            ;  to file.
  1705.         call    redirect_openo
  1706.         jmp    short redirect_exit    ;Terminate line scan.
  1707. ;
  1708. ; Check for output redirection
  1709. ;
  1710. redirect_5:
  1711.         cmp    al,'>'                  ;Check for redirect out
  1712.         jne    redirect_7
  1713.         xor    bx,bx
  1714.         cmp    byte ptr [si],'>'       ;Check for append redirect
  1715.         jne    redirect_6
  1716.         lodsb                ;Remove 2nd >
  1717.         inc    bx
  1718. redirect_6:
  1719.         push    bx            ;Save append flag
  1720.         xor    bl,bl
  1721.         call    scan4char        ;Get filename
  1722.         mov    dx,di
  1723.         mov    ah,1            ;Copy only one word
  1724.         call    copy_string
  1725.         xor    al,al            ;Terminate name with zero
  1726.         stosb
  1727.         sub    dx,databuff_start    ;Compute offset of filename
  1728.         pop    ax
  1729.         call    redirect_openo
  1730.         call    erase_redirect        ;Erase redirect from line.
  1731.         jmp    short redirect_1
  1732. redirect_7:
  1733.         cmp    al,'<'                  ;Check for redirect in
  1734.         jne    redirect_10
  1735.         xor    bl,bl
  1736.         call    scan4char        ;Get filename
  1737.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ze    dw    offset getmember_end - offset getmember_start
  1738. getmember_next    dw    0            ;Ptr to next routine to append
  1739. getmember_lnks    dw    2            ;Bytes in the dependancy header
  1740. getmember_start =    $
  1741.         dw    offset scan4_next    ;Offset of called routine.
  1742.  
  1743. getmember    proc    near
  1744.         assume    cs:code,ds:code,es:code,ss:code
  1745.         push    bx
  1746.         call    getmember_0
  1747. getmember_0:
  1748.         pop    bx
  1749. getmember_1:
  1750.         xor    dl,dl
  1751.         call    getmember_scan4     ;Find next word
  1752.         jc    getmember_notfound
  1753.         dec    dh            ;Dec parameter count
  1754.         jle    getmember_2
  1755.         inc    dl
  1756.         call    getmember_scan4     ;Find next space
  1757.         jc    getmember_exit
  1758.         jmp    short getmember_1    ;If not done, loop back.
  1759. getmember_2:
  1760.         dec    si            ;Backup to 1st char in word.
  1761.         clc
  1762. getmember_exit:
  1763.         pop    bx
  1764.         ret
  1765. getmember_notfound:
  1766.         stc
  1767.         jmp    short getmember_exit
  1768. getmember    endp
  1769. getmember_end    =    $
  1770.  
  1771. ;-----------------------------------------------------------------------------
  1772. ; PROCSTRING processes a string to convert any environment variables or
  1773. ;         command line variables.
  1774. ; Entry:  DS:SI - ASCIIZ string to process
  1775. ;      ES:DI - pointer to output buffer.
  1776. ; Exit:   DS:SI - pointer to beginning of new ASCIIZ string.
  1777. ;     [SI-1] - Length of new string.
  1778. ;-----------------------------------------------------------------------------
  1779. procstr_cmdl    equ    [bx-8]
  1780. procstr_env    equ    [bx-6]
  1781. procstr_off    dw    0            ;Pointer to offset in COM file
  1782. procstr_size    dw    offset procstr_end - offset procstr_start
  1783. procstr_next    dw    0            ;Ptr to next routine to append
  1784. procstr_lnks    dw    4            ;Bytes in the dependancy header
  1785.  
  1786. procstr_start    =    $
  1787.         dw    offset subparm_next    ;Offset of called routines.
  1788.         dw    offset subenv_next
  1789.  
  1790. procstr_code    proc    near
  1791.         assume    cs:code,ds:code,es:code
  1792.         push    bx
  1793.         call    procstr_0
  1794. procstr_0:
  1795.         pop    bx
  1796.         push    di
  1797.         push    si
  1798.         mov    ah,BUFF_SIZE        ;Set size of buffer
  1799. procstr_1:
  1800.         lodsb                ;Get byte from string
  1801.         or    al,al            ;Check for end of string
  1802.         je    procstr_exit
  1803.         cmp    al,"%"                  ;See if special character
  1804. procstr_jmp:
  1805.         je    procstr_3        ;Yes, process special char.
  1806. procstr_2:
  1807.         stosb                ;Store byte from string
  1808.         dec    ah
  1809.         jne    procstr_1
  1810. procstr_exit:
  1811.         xor    al,al            ;Force zero byte end.
  1812.         stosb
  1813.         pop    si
  1814.         pop    di
  1815.         mov    bl,BUFF_SIZE
  1816.         sub    bl,ah
  1817.         mov    ds:[di-1],bl        ;Store length of string
  1818.         pop    bx
  1819.         ret
  1820. ;
  1821. ;A percent sign has been found indicating a 'soft' parameter.  Three types of
  1822. ;soft parameters are allowed; command line parameter, environment variable,
  1823. ;and for loop parameter.
  1824. ;
  1825. procstr_3:
  1826.         lodsb                ;Get next character
  1827.         dec    cx
  1828.         cmp    al,"%"                  ;If double %, include one
  1829.         je    procstr_2        ;  in string.
  1830.         cmp    al,7fh            ;See if for loop var
  1831.         jne    procstr_32
  1832.         push    si
  1833.         mov    si,forloop_ptr        ;Get ptr to for loop string
  1834. procstr_30:
  1835.         lodsb
  1836.         cmp    al,0            ;If zero, end of string
  1837.         je    procstr_31
  1838.         stosb
  1839.         dec    ah            ;Dec buffer size counter
  1840.         jne    procstr_30        ;If buffer not full, continue
  1841. procstr_31:
  1842.         pop    si            ;Get back source string pointer
  1843.         jmp    short procstr_4
  1844. procstr_32:
  1845.         mov    dh,al            ;Copy and check to see if
  1846.         sub    dh,"0"                  ;  the next char is a number.
  1847.         jb    procstr_5        ;  If so, assume a line
  1848.         cmp    dh,9            ;  parameter.
  1849.         ja    procstr_5
  1850.         call    procstr_cmdl        ;Call cmd line param routine
  1851. procstr_4:
  1852.         or    ah,ah
  1853.         jne    procstr_1
  1854.         jmp    short procstr_exit    ;If at end of string, done
  1855. procstr_5:
  1856.         dec    si            ;Backup to 1st character
  1857.         inc    cx
  1858.         call    procstr_env
  1859.         jmp    short procstr_4
  1860. procstr_code    endp
  1861. procstr_end    =    $
  1862.  
  1863. ;-----------------------------------------------------------------------------
  1864. ; SUBLINEPARAM substitutes a parameter from the command line.
  1865. ; Entry:  ES:DI - pointer to buffer to copy the line parameter
  1866. ;         DH - binary number of the line parameter
  1867. ;         AH - size of buffer
  1868. ; Exit:   ES:DI - pointer to byte after the parameter in the buffer
  1869. ;         CX - remaining length of the buffer
  1870. ;-----------------------------------------------------------------------------
  1871. subparm_getmem    equ    [bx-6]
  1872. subparm_off    dw    0            ;Pointer to offset in COM file
  1873. subparm_size    dw    offset subparm_end - offset subparm_start
  1874. subparm_next    dw    0            ;Ptr to next routine to append
  1875. subparm_lnks    dw    2            ;Bytes in the dependancy header
  1876. subparm_start    =    $
  1877.         dw    offset getmember_next    ;Offset of called routine.
  1878.  
  1879. sublineparam    proc    near
  1880.         assume    cs:code,ds:code,es:code,ss:code
  1881.         push    bx
  1882.         call    sublineparam_1
  1883.         db    "DOS2X",0        ;Dummy %0 parameter for DOS 2x
  1884. sublineparam_1:
  1885.         pop    bx
  1886.         push    cx
  1887.         push    si
  1888.         push    ds
  1889.         mov    si,80h            ;Get ptr to cmd line
  1890.         xor    cx,cx
  1891.         mov    cl,[si]         ;Get number of chars in buffer.
  1892.         inc    si            ;Point to data
  1893.         add    dh,ds:shift_count    ;Add in shift cou~t.
  1894.         or    dh,dh            ;Check coupüנÇ✓נçÄ⇦ÄOüÇOêéëij≡p≥rÇÇ≥⇦ üéê◆Ä⇦ÄFD≡pijppij⑧Ç⇦נçÄ⇦Ä✓⇧ê⇦נוIJנÄ⇧üê◆üנüÇOüÇOéנüâêOêÇנîüÇ OêÇ⇦נüâêP70ÀØÉ7ø⓪:42É897øù╱àåà⇦äÕ:¨œ⇦ã¶⇦ää¥⌐ã†2É1:ø32¨⓪9œ©2É4Ã⓪ ñ╱à⇦äÀÆ⇦ãœ⑥⑨ÿ4⇦ää¥úØ´⓪"'⌐É;2¨9œÃÃ⓪╱à⇦äœÃ:⇦Ö⑧œ⇦ää¥ñø⓪"'⌐É⑨⑦<⑥⓪897ø¨0ÀÉ70Ã2É77´╱à⇦äõÀÕ⇦ãÀ⑥⑨⇦ää¥É⓪4Ã⓪:42É2Ã;⓪9ØøÀØÃ:⑦⓪⓪*¨Øåà⇦äÕ7Õ⇦ã¶╱à⇦äŒ0䨴õ64Ã2Õ0¨0À»ÿÿ⇦ä¥É⓪2:Ã7<É70ÀØÉ4Ã9´2ãØ⑦╱à⇦äÀ2ã䨜û-õ<.ää䥿7œÃ:⓪:7É2:ÀÀ¶É80¨0ÀØ´2¨╱à⇦äŒ6Õ⇦¨Œij⇩@τא╱@IJD⇨ו⇩G"x8B╱@IJD⇨ו⇩G##αx8y9⇨ij⇩⇧∙⇦⇩88y9⇨ij⇩⇧∙⇦IJ88y9y⇦⇩ גא Aכÿם⑦BBNעffset pipe1_file    ;Get offset of pipe file to
  1895.         cmp    pipe_toggle,0        ;  use.  Alternate files so
  1896.         jne    redirect_3         ;  that input and output files
  1897.         mov    bx,offset pipe2_file    ;  don't get mixed up.
  1898. redirect_3:
  1899.         not    pipe_toggle
  1900.         xor    dx,dx            ;If file not already used, 
  1901.         or     dx,[bx]            ;  load the filename into 
  1902.         jne    redirect_4         ;  the COM data buffer.
  1903.         mov    dx,di
  1904.         sub    dx,databuff_start    ;Compute offset of filename
  1905.         mov    [bx],dx            ;Save pointer to filename
  1906.         lea    si,[bx+2]        ;Get address of filename
  1907.         mov    ah,1    
  1908.         call    copy_string        ;Copy name to COM data buffer
  1909.         xor    al,al            ;Terminate filename with zero
  1910.         stosb
  1911. redirect_4:
  1912.         mov    pipeout_file,dx
  1913.         mov    pipeout_flag,1
  1914.         xor    bx,bx            ;Add output redirection code
  1915.         xor    ax,ax            ;  to file.
  1916.         call    redirect_openo
  1917.         jmp    short redirect_exit    ;Terminate line scan.
  1918. ;
  1919. ; Check for output redirection
  1920. ;
  1921. redirect_5:
  1922.         cmp    al,'>'                  ;Check for redirect out
  1923.         jne    redirect_7
  1924.         xor    bx,bx
  1925.         cmp    byte ptr [si],'>'       ;Check for append redirect
  1926.         jne    redirect_6
  1927.         lodsb                ;Remove 2nd >
  1928.         inc    bx
  1929. redirect_6:
  1930.         push    bx            ;Save append flag
  1931.         xor    bl,bl
  1932.         call    scan4char        ;Get filename
  1933.         mov    dx,di
  1934.         mov    ah,1            ;Copy only one word
  1935.         call    copy_string
  1936.         xor    al,al            ;Terminate name with zero
  1937.         stosb
  1938.         sub    dx,databuff_start    ;Compute offset of filename
  1939.         pop    ax
  1940.         call    redirect_openo
  1941.         call    erase_redirect        ;Erase redirect from line.
  1942.         jmp    short redirect_1
  1943. redirect_7:
  1944.         cmp    al,'<'                  ;Check for redirect in
  1945.         jne    redirect_10
  1946.         xor    bl,bl
  1947.         call    scan4char        ;Get filename
  1948.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@n COM file
  1949. searchenv_size    dw    offset searchenv_end - offset searchenv_start
  1950. searchenv_next    dw    0               ;Ptr to next routine to append
  1951. searchenv_lnks    dw    0
  1952. searchenv_start =    $
  1953.  
  1954. search_env    proc near
  1955.         assume    ds:nothing,es:nothing
  1956.         push    bx
  1957.         push    cx
  1958.         push    di
  1959.         push    es
  1960.         mov    es,environment_seg    ;Get seg of environment blk
  1961.         xor    di,di            ;Point ES:DI to environment.
  1962.         mov    bx,si            ;Save pointer to var name
  1963. search_env_1:
  1964.         mov    si,bx            ;Get back ptr to var name.
  1965.         mov    cx,dx            ;Compare env var to var in
  1966.         repe    cmpsb            ;  string.
  1967.         je    search_env_2        ;Variable found, exit loop
  1968.         xor    al,al            ;Find next environment var.
  1969.         mov    cx,-1            ;Scan the entire segment.
  1970.         repne    scasb
  1971.         cmp    byte ptr es:[di],0    ;If double zero, end of env
  1972.         jne    search_env_1        ;  block. else, loop back.
  1973. search_env_not_found:
  1974.         mov    si,di            ;Point SI to end of env data
  1975.         push    es
  1976.         pop    ds
  1977.         stc
  1978.         jmp    short search_env_exit
  1979. search_env_2:
  1980. ;
  1981. ;Environment variable found. Point DS:SI to the string.
  1982. ;
  1983.         mov    si,di
  1984.         push    es            ;DS:SI points to env string
  1985.         pop    ds
  1986. search_env_3:
  1987.         lodsb                ;Move environment pointer past
  1988.         cmp    al,"="                  ;  the equals sign.
  1989.         jne    search_env_3
  1990.         cmp    byte ptr [si],0
  1991.         je    search_env_not_found
  1992. search_env_4:
  1993.         lodsb                ;Move pointer to first
  1994.         or    al,al            ;  non-space character.
  1995.         jb    search_env_5
  1996.         cmp    al," "
  1997.         jb    search_env_4
  1998. search_env_5:
  1999.         dec    si
  2000.         clc
  2001. search_env_exit:
  2002.         pop    es
  2003.         pop    di
  2004.         pop    cx
  2005.         pop    bx
  2006.         ret
  2007. search_env    endp
  2008. searchenv_end    =    $
  2009.  
  2010. ;----------------------------------------------------------------------------
  2011. ;EXTERNAL CMD  Routine used to launch programs from the COM file.
  2012. ; Entry   DS:SI - Pointer to the ASCIIZ program name
  2013. ;      ES:DI - Pointer to the ASCIIZ command line tail
  2014. ;----------------------------------------------------------------------------
  2015. extern_intcmd    equ    [bx-14]
  2016. extern_echomsg    equ    [bx-12]
  2017. extern_parspath equ    [bx-10]
  2018. extern_launch    equ    [bx-8]
  2019. extern_ifexits    equ    [bx-6]
  2020. extern_pathcnt    equ    [bx]
  2021. extern_path_var equ    [bx+1]
  2022. extern_file_ext equ    [bx+6]
  2023. extern_filename equ    [bx+15]
  2024. extern_filetail equ    [bx+17]
  2025. extern_lostmsg    equ    [bx+19]
  2026. extern_cmdparm    equ    [bx+46]
  2027. extern_pathflag    equ    [bx+49]
  2028. external_ptr    dw    0            ;Pointer to offset in COM file
  2029. external_size    dw    offset external_end - offset external_start
  2030. external_next    dw    0            ;Ptr to next routine to append
  2031. external_lnks    dw    10            ;Bytes in the dependancy header ;Number of routines called
  2032. external_start    =    $
  2033.         dw    intcmd_next        ;Call to launch COMMAND.COM
  2034.         dw    echo_msg_next        ;Call to display string
  2035.         dw    parsepath_next        ;Call to get part of path
  2036.         dw    launch_next        ;Call execute file
  2037.         dw    ifexist_next        ;Call to find file
  2038.  
  2039. external_code    proc    near
  2040.         assume    cs:code,ds:code
  2041.         push    bx
  2042.         call    external_0
  2043.         db    0            ;Cnt to track path search.
  2044.         db    "PATH="
  2045.         db    "COMEXEBAT"
  2046.         dw    0            ;Pointer to filename
  2047.         dw    0            ;Pointer to command line tail
  2048.         db    "Bad command or file name",13,10,0
  2049.         db    "/C "
  2050.         db    0            ;Flag for path search
  2051. external_0:
  2052.         pop    bx            ;Get pointer to local vars.
  2053.         mov    extern_filename,si    ;Save ptr to file name
  2054.         mov    extern_filetail,di    ;Save ptr to command line tail
  2055.         mov    dx,exec_buff         ;Get pointer to free buffer.
  2056.         add    dx,4            ;Make room for /C if needed.
  2057.         mov    byte ptr extern_pathflag,0
  2058.         mov    byte ptr extern_pathcnt,0
  2059. ;Parse path to generate filename.
  2060. external_1:
  2061.         mov    di,dx            ;Get ptr to start of buffer
  2062.         xor    cx,cx            ;Check to see if we need to
  2063.         or    cl,extern_pathcnt    ;  check the directorys in
  2064.         jne    external_19        ;  the path.
  2065. ;The first time through, parse the name without using the path.
  2066.         push    dx
  2067.         push    si
  2068.         xor    dx,dx            ;Assume default drive
  2069.         cmp    byte ptr [si+1],':'    ;See if drive specified    
  2070.         jne    external_11
  2071.         mov    dl,[si]
  2072.         and    dl,0dfh            ;Set to upper case
  2073.         sub    dl,'@'            ;Convert ASCII to number
  2074.         movsw                ;Copy drive letter
  2075.         add    word ptr extern_filename,2  ;Don't use drive in path
  2076. external_11:
  2077.         cmp    byte ptr [si],'\'    ;See if starting at root.
  2078.         je    external_110
  2079.         mov    al,'\'            ;Start at root dir
  2080.         stosb
  2081.         push    si
  2082.         mov    si,di            ;Get pointer to buffer.
  2083.         mov    ah,47h            ;Get current directory
  2084.         int    21h
  2085.         pop    si
  2086.         xor    al,al
  2087.         mov    cx,64
  2088.         repne    scasb            ;Find end of directory string
  2089.         dec    di
  2090.         cmp    byte ptr [di-1],'\'    ;Unless at root dir, add
  2091.         je     external_110
  2092.         mov    al,'\'
  2093.         stosb
  2094. external_110:
  2095.         xor    ax,ax
  2096. external_12:
  2097.         lodsb                ;Get a byte
  2098.         cmp    ax,2e2eh        ;See if we need to back up
  2099.         jne    external_13        ;  one directory.
  2100.         std
  2101.         mov    al,'\'            ;Scan backwards to erase    
  2102.         mov    cx,18            ;  last directory.
  2103.         repne    scasb
  2104.         repne    scasb
  2105.         cld
  2106.         inc    di
  2107.         jmp    short external_12
  2108. external_13:
  2109.         stosb    
  2110.         mov    ah,al            ;Copy last character.
  2111.         cmp    al,'\'            ;See if name specifies a path
  2112.         jne    external_14
  2113.         inc    byte ptr extern_pathflag
  2114. external_14:
  2115.         cmp    al,0
  2116.         jne    external_12
  2117. external_15:
  2118.         dec    di            ;Since DOS does not let the
  2119.         mov    dx,di            ;  user specify the file ext.
  2120.         std                ;  scan back to make sure one
  2121.         mov    cx,5            ;  is not attached.
  2122.         mov    al,'.'
  2123.         repne   scasb    
  2124.         cld
  2125.         jne    external_16
  2126.         inc    di
  2127.         mov    dx,di
  2128. external_16:
  2129.         mov    di,dx
  2130.         pop    si
  2131.         pop    dx
  2132.         jmp    short external_4
  2133. ;Parse the path string to search remaining directorys.
  2134. external_19:
  2135.         cmp    byte ptr extern_pathflag,0  ;If a complete path was
  2136.         jne    external_badcmd            ;  specified, don't search
  2137.         mov    si,extern_filename        ;  the path.
  2138.         call    extern_parspath
  2139.         jnc    external_2        ;If we have checked all
  2140. external_badcmd:
  2141.         lea    si,extern_lostmsg    ;  directories in the path,
  2142.         call    extern_echomsg        ;  display file not found msg.
  2143.         jmp    short external_exit
  2144.  
  2145. ;Append filename to the end of the path.
  2146. external_2:
  2147.         mov    cx,73            ;Max length of filename
  2148. external_3:
  2149.         lodsb
  2150.         cmp    al,' '                  ;See if end of word
  2151.         jbe    external_4
  2152.         cmp    al,'.'                  ;See if end of filename
  2153.         je    external_4
  2154.         stosb
  2155.         loop    external_3
  2156. external_4:
  2157.         mov    al,'.'                  ;Append '.' to filename
  2158.         stosb
  2159.         lea    si,extern_file_ext    ;Get pointer to extensions
  2160.         mov    cx,3            ;3 extension types COM EXE BAT
  2161. external_5:
  2162.         movsw                ;Append extension to filename
  2163.         movsb
  2164.         xor    al,aq≥rr@⇧ê⇦Ç⇩Ä⇧êOÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r◆Ç⇦⇨≥    â≡p≥r◆Ç⇦⇨≥⇦⇩pp≥r◆Ç⇦⇨≥ ⇨≡p≥r≥⇦⇩Aëâ≥rr@⑧✓⇧נçüäנüÇOä⇧Ä⇦üנÇ✓נÇÄ✓pp≥r ⇧ü≥✓⇨üê⇦ÇÇ⇩✓ê⇨é⇧ärr@⇦✓⇦î⇨נêÇ⇦נêé⇧êpp≥r◆Ç◆≥ ⇨≡p≥r◆Ç◆≥⇦⇩pp≥r◆Ç◆≥    â≡p≥rÇîr✓⇨üê⇦ÇÄ⇧Ç@≡p≥r⇦ ≥    éAIJ≥rr@Ä ◆נüÇOêé⇧êOê⇨üêä⇩≡p≥r⇧Ç◆≥✓⇨üê⇦ÇÄ⇧Ç@pp≥r⇩îr é⇧êOçüäנê⇨üê⇦ÇÇ◆Ä⇧âîüנij①ÇOéנüâêOÇê⇨üנçÄ⇧âנä⇧ä≡p≥rÇ◆≥✓⇨üê⇦ÇÄ⇧ÇFppê⇨üê⇦ÇÄ⇧Ç@ij≡p≥r ◆≥ ⇨IJהrrr@⇦✓✓P4ägמOτג⇧ijגB⇧x8y9@D9⇦⇧ijג⇩@Gij!°8y9ג◆9⇩⇧ ג⇧ijג⇩@@╱⇦בו⇩@9  ⇦τבij⇧@ג⇩gijij'α88y9⇩╱y⇦IJαΓ88y9y⇦IJ גIJ∙99  ⇦τבijאgijij'אאAD'ה@⇦DD⇩x8y9B9999     xor    bl,bl
  2165.         call    scan4char        ;Get filename
  2166.         mp≥    âIJëépp≥r≥⇨IJהrrr@◆éOÇüéOÇêOÇ⇦ë≡p≥r ⇧ü≥ ◆é⇦⇧äéêpp≥r⇨Ç⇦≥⇧IJÄ⇧≥rr@⇧ê⇦Ç⇩Ä⇧êOÇÄ✓OÇ⇩⇧âנÇê⇦Çpp≥r⇦⇧Ç⇦ ≡p≥r⇦ ≥    âIJëÄ⇧Ä Ç✓êÇ⇦⇧Ä⇦ü≥@◆Ç⇧êOÇ✓êä✓⇧נÇ✓נêé⇧ê✓Ä✓pp≥r ⇧ü≥⇦ê    é⇦ê ⇧Ç◆êépp≥r ⇧ü≥✓⇦Ä⇦✓⇦ê    é⇦ê ⇧≥r@⑧⇦Ä⇦✓Oäê    é⇦ê ⇧נêäÇOæéê@≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧ÇFGij≡p≥r ◆≥⇧IJהDpp≥rêr⇦ê    é⇦ê ⇧Ç✓⇨é⇧≡p≥rÇ◆≥⇦ê    é⇦ê ⇧ÇFppäê    é⇦ê ⇧Ç✓⇨é⇧ij≡p≥r ⇧îpp≥r◆Ç◆≥⇦⇩pp≥r⇦ê⇧≡päê    é⇦ê ⇧Ç ⇨ê r✓ëç≡p≡pij@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@to next routine to append
  2167. parsepath_lnks    dw    2
  2168. parsepath_start =    $
  2169.         dw    offset searchenv_next     ;Call to search env block
  2170.  
  2171. parsepath    proc    near
  2172.         assume    cs:code,ds:code,es:code,ss:code
  2173.         push    bx
  2174.         call    parsepath_1
  2175.         db    "PATH"
  2176. parsepath_1:
  2177.         pop    bx        
  2178.         push    dx
  2179.         push    si
  2180.         push    ds
  2181.         mov    dx,4            ;Length of PATH string
  2182.         mov    si,bx            ;Point SI to PATH string
  2183.         call    getcom_srchenv        ;PATH var ptr return in DS:SI
  2184. parsepath_2:
  2185.         dec    cx            ;Dec path segment count
  2186.         jcxz    parsepath_4
  2187. parsepath_3:
  2188.         lodsb                ;Get character
  2189.         or    al,al            ;See if end of path string
  2190.         je    parsepath_notfound
  2191.         cmp    al,';'                  ;See if end of path segment
  2192.         jne    parsepath_3
  2193.         jmp    short parsepath_2
  2194. parsepath_4:
  2195.         lodsb
  2196.         cmp    al,';'                  ;See if end of path segment
  2197.         je    parsepath_5
  2198.         or    al,al            ;See if end of path
  2199.         je    parsepath_5
  2200.         stosb
  2201.         jmp    short parsepath_4
  2202. parsepath_5:
  2203.         push    cs
  2204.         pop    ds
  2205.         cmp    byte ptr es:[di-1],'\'  ;Append \ if necessary.
  2206.         je    parsepath_6
  2207.         mov    al,'\'
  2208.         stosb
  2209. parsepath_6:
  2210.         clc
  2211. parsepath_exit:
  2212.         pop    ds
  2213.         pop    si
  2214.         pop    dx
  2215.         pop    bx
  2216.         ret
  2217. parsepath_notfound:
  2218.         stc
  2219.         jmp    short parsepath_exit
  2220. parsepath    endp
  2221. parsepath_end      =      $
  2222.  
  2223. ;-----------------------------------------------------------------------------
  2224. ; INTCMD  Launches the shell ,usually COMMAND.COM, to run an internal command.
  2225. ; Entry   DS:SI - pointer to the ASCIIZ internal command to run.
  2226. ;-----------------------------------------------------------------------------
  2227. intcmd_launch    equ    [bx-8]
  2228. intcmd_getcom    equ    [bx-6]
  2229. intcmd_off    dw     0            ;Pointer to offset in COM file
  2230. intcmd_size    dw     offset intcmd_end - offset intcmd_start
  2231. intcmd_next    dw     0            ;Ptr to next routine to append
  2232. intcmd_lnks    dw     4
  2233. intcmd_start    =      $
  2234.         dw     offset launch_next    ;Call to load and run program.
  2235.         dw     offset getcom_next    ;Call to find shell name.
  2236.  
  2237. intcommand    proc    near
  2238.         assume    cs:code,ds:code,es:code,ss:code
  2239.         push    bx
  2240.         call    intcmd_1
  2241. intcmd_1:
  2242.         pop    bx            ;Get pointer to sub calls.
  2243.         mov    di,si            ;Copy ptr to command
  2244.         dec    di            ;Back up to cmd line size.
  2245.         mov    al,process_rc        ;Get and save return code
  2246.         push    ds
  2247.         push    ax
  2248.         call    intcmd_getcom        ;Get comspec string.
  2249.         call    cs:intcmd_launch    ;Run program.
  2250.         pop    ax
  2251.         pop    ds
  2252.         mov    process_rc,al        ;Restore return code    
  2253.         pop    bx
  2254.         ret
  2255. intcommand    endp
  2256. intcmd_end    =    $
  2257.  
  2258. ;-----------------------------------------------------------------------------
  2259. ; GETCOMSPEC  Gets the name of the shell program running
  2260. ; Exit:   DS:SI - pointer to the ASCIIZ name of the shell porgram.
  2261. ;-----------------------------------------------------------------------------
  2262. getcom_srchenv    equ    [bx-6]
  2263. getcom_off    dw    0             ;Pointer to offset in COM file
  2264. getcom_size    dw    offset getcom_end - offset getcom_start
  2265. getcom_next    dw    0             ;Ptr to next routine to append
  2266. getcom_lnks    dw    2
  2267. getcom_start    =    $
  2268.         dw    offset searchenv_next     ;Call to search environment blk
  2269.  
  2270. getcomspec    proc    near
  2271.         assume    cs:code,ds:code,es:code,ss:code
  2272.         push    bx
  2273.         call    getcom_1
  2274. getcom_str    db    "COMSPEC"
  2275. getcom_1:
  2276.         pop    bx
  2277.         mov    dx,offset getcom_1 - offset getcom_str
  2278.         mov    si,bx
  2279.         call    getcom_srchenv        ;Get pointer to comspec string
  2280.         pop    bx
  2281.         ret
  2282. getcomspec    endp
  2283. getcom_end    =    $
  2284.  
  2285. ;----------------------------------------------------------------------------
  2286. ;LAUNCH PROG  Routine used to load and run programs.
  2287. ; Entry   DS:SI - pointer to the program name to run.
  2288. ;      ES:DI - pointer to the command line tail.
  2289. ; Exit      return code variable set.
  2290. ;----------------------------------------------------------------------------
  2291. launch_fcb1    equ    [bx]
  2292. launch_fcb2    equ    [bx+16]
  2293. launch_ptr    dw    0            ;Pointer to offset in COM file
  2294. launch_size    dw    offset launch_end - offset launch_start
  2295. launch_next    dw    0            ;Ptr to next routine to append
  2296. launch_lnks    dw    0            ;Bytes in the dependancy header ;Number of routines called
  2297. launch_start    =    $
  2298.  
  2299. launch_code    proc    near
  2300.         assume    cs:code,ss:code
  2301.         push    bx
  2302.         call    launch_1        ;Push IP on stack
  2303.         db    0            ;Dummy FCB for program
  2304.         db    "DUMMY   FCB"
  2305.         db    0,0,0,0
  2306.         db    0            ;Dummy FCB for program
  2307.         db    "DUMMY   FCB"
  2308.         db    0,0,0,0
  2309. launch_1:
  2310.         pop    bx            ;Get pointer to local vars.
  2311.  
  2312.         push    ds
  2313.         push    es            ;Save stack ptr since it is not
  2314.         mov    com_stack_ptr,sp    ;  saved under DOS 2.x.
  2315. ;Parse first two parameters into FCBs.
  2316.         push    di            ;Save ptr to tail
  2317.         push    si            ;Save ptr to name
  2318.         mov    si,di            ;Copy ptr to cmd line
  2319.         inc    si            ;Skip size byte
  2320.         lea    di,launch_fcb1
  2321.         mov    ax,2903h        ;Parse FCB
  2322.         int    21h
  2323.         lea    di,launch_fcb2
  2324.         mov    ax,2903h
  2325.         int    21h
  2326.         pop    si
  2327.         pop    di
  2328.  
  2329.         push    cs            ;Create Parameter block on
  2330.         lea    dx,launch_fcb2        ;  the stack. Start with 2nd
  2331.         push    dx            ;  FCB.
  2332.         push    cs
  2333.         lea    dx,launch_fcb1
  2334.         push    dx
  2335.         push    cs            ;Push ptr to command line tail.
  2336.         push    di
  2337.         mov    ax,cs:[environment_seg]    ;Use env block set by prog.
  2338.         push    ax
  2339.         mov    bx,sp            ;Copy pointer to parameter blk
  2340.  
  2341.         mov    ax,4b00h        ;DOS EXEC program.
  2342.         mov    dx,si            ;Get pointer to filename
  2343.         int    21h
  2344.         mov    bp,offset data_start_ptr - offset init_code + 100h
  2345.         mov    bp,cs:[bp]
  2346.         mov    bx,cs            ;Reload BP to access local data
  2347.         cli
  2348.         mov    ss,bx            ;Restore stack
  2349.         mov    sp,com_stack_ptr
  2350.         sti
  2351.         cld                ;Restore default direction
  2352.         pop    es
  2353.         pop    ds
  2354. ;Get return code
  2355.         mov    ah,4dh            ;Get return code
  2356.         int    21h
  2357.         mov    process_rc,al        ;Save
  2358.         pop    bx
  2359.         ret
  2360. launch_code    endp
  2361. launch_end    =       $
  2362.  
  2363. ;----------------------------------------------------------------------------
  2364. ;GOTO  Routine to jump to a label pointed to by a cmd line parameter or
  2365. ;      environment variable.
  2366. ; Entry   DS:SI - pointer to label to find.
  2367. ;            DI - Wait flag/ptr. If <> 0, put goto address at pointer.
  2368. ; Exit      This routine does not return unless the label is not found.
  2369. ;----------------------------------------------------------------------------
  2370. goto_echomsg    equ    [bx-7]
  2371. goto_lblsrch    equ    [bx-5]
  2372. goto_ptr    dw    0            ;Pointer to offset in COM file
  2373. goto_size    dw    offset goto_end - offset goto_start
  2374. goto_next    dw    0            ;Ptr to next routine to append
  2375. goto_lnks    dw    4            ;Bytes in the dependancy header ;Number of routines called
  2376. goto_start    =    $
  2377.         dw    echo_msg_next        ;Used to print error msg
  2378.         dw    lblsrch_next        ;Used to find label
  2379.  
  2380. goto_code    proc    near
  2381.         assume    cs:code,ds:code
  2382.         call    goto_1
  2383.         db    8 dup (" ")
  2384.         db    " Label not found",13,10,0
  2385. goto_1:
  2386.         pop    bx
  2387.         push    di            ;Save wait flag/pointer
  2388.         mov    di,bx            ;Load label into error msg
  2389.         xor    dx,dx            ;Get size of label as it is
  2390.         mov    cx,8            ;  copied into error msg.
  2391. goto_2:
  2392.         lodsb
  2393.         cmp    al," "
  2394.         jbe    goto_4
  2395.         cmp    al,'a'
  2396.         jb    goto_3
  2397.         and    al,0dfh         ;Capitalize label
  2398.         cmp    al,'Z'
  2399.         ja    goto_4
  2400. goto_3:
  2401.         stosb
  2402.         inc    dx
  2403.         loop    goto_2
  2404. gotpÜαx8y9y╱⇧αגIJ∙99  ⇦τא⇧D'ij⇦gijו╱D°8y9y⇩⇧ הA∙99  ⇦τבij⇧@ג⇩gijij'ijו╱D°8y9y⇦IJ הו╱Dij⇩ו⇩@∙  ⇦τבijאgijij'או⇩@τij⇦gijו╱DτijIJ⇩°8y9◆⇦ג∙⇦IJ הC∙99 ⇦גτij⇦DB⇦τij⇦gגוו88y9⇨ij⇩⇧∙╱A∙99 ⇩◆D'בijאgijij'ij⇩⇦88y9╱◆ij∙⇦ijה@א⇩F⇧∙9 ◆ijτא⇦◆⇩F⇧τא@IJD88y9⇨ij⇨∙⇦IJ∙99 ⇩D⇩ij⇩D'בijאgijij'ij⇦⇩⇩◆⇦⇦88y9⇨ij⇨∙⇩⇧999 ⇩D⇩ij⇩D'ij◆⇧τג@ו⇦ ⇨ij⇧@ג⇩x8y9F9⇦ij 999  gא⇦ατijו╱Dτij@τג@Dαx8y9y◆⇧αij╱Aα"@99  ⇦τגג⇩IJGIJgבijאx8y9⇩y⇩⇧ א⇧999 ⇩⇦⇦'IJ⇦gגגו⇧'ג@ו⇦'ααgπ°8y9D9⇦ij π999 eader ;Number of routines called
  2405. gotodly_start    =    $
  2406.  
  2407. gotodly_code    proc    near
  2408.         assume    cs:code,ds:code
  2409.         xor    ax,ax            ;Get pointer, test if zero.
  2410.         or    ax,[si]            ;If zero, return.  If not
  2411.         je    gotodly_exit        ;  push the new destination
  2412.         pop    bx            ;  on the stack and return.
  2413.         push    ax
  2414. gotodly_exit:
  2415.         ret
  2416. gotodly_code    endp
  2417. gotodly_end     =         $
  2418.  
  2419. ;----------------------------------------------------------------------------
  2420. ;LABEL SEARCH Routine to search list of labels to determine goto destination.
  2421. ; Entry   ES:DI - pointer to the first entry in the list. (Assume ES = DS)
  2422. ;      DS:SI - pointer to label to find.
  2423. ;         CX - Length of label
  2424. ; Exit         BX - pointer to matching list entry, or last entry if not found.
  2425. ;         CF - Set if label not found.
  2426. ;----------------------------------------------------------------------------
  2427. lblsrch_ptr    dw    0            ;Pointer to offset in COM file
  2428. lblsrch_size    dw    offset lblsrch_end - offset lblsrch_start
  2429. lblsrch_next    dw    0            ;Ptr to next routine to append
  2430. lblsrch_lnks    dw    0            ;Bytes in the dependancy header ;Number of routines called
  2431. lblsrch_start    =    $
  2432.  
  2433. lblsrch_code    proc    near
  2434.         assume    cs:code,ds:code
  2435.         push    si
  2436.         mov    dx,si            ;Save ptr to label
  2437.         mov    ax,cx            ;Save label length
  2438.         mov    bx,di            ;Get ptr to list
  2439. lblsrch_1:
  2440.         mov    di,bx
  2441.         add    di,4            ;Move to label string
  2442.         mov    si,dx            ;Get ptr to new label
  2443.         mov    cx,ax            ;Get length of label
  2444.         cmp    [di],cl         ;Compare lengths of the labels
  2445.         jne    lblsrch_2
  2446.         inc    di            ;Skip past length byte
  2447.         repe    cmpsb            ;Compare labels.
  2448.         je    lblsrch_4
  2449. lblsrch_2:
  2450.         cmp    word ptr [bx],-1    ;See if at end of list
  2451.         je    lblsrch_3
  2452.         add    bx,[bx]         ;Point to next label
  2453.         jmp    short lblsrch_1
  2454. lblsrch_3:
  2455.         stc                ;No label found.
  2456.         jmp    short lblsrch_exit
  2457. lblsrch_4:
  2458.         clc                ;Label found
  2459. lblsrch_exit:
  2460.         pop    si
  2461.         ret
  2462. lblsrch_code    endp
  2463. lblsrch_end    =    $
  2464.  
  2465. ;-----------------------------------------------------------------------------
  2466. ; IFEQUAL  Compares two strings.
  2467. ; Entry:  DS:SI - Pointer to first ASCIIZ String
  2468. ;      ES:DI - Pointer to second ASCIIZ String
  2469. ;         CX - Length of strings.
  2470. ; Exit:      CF - Clear if equal
  2471. ;-----------------------------------------------------------------------------
  2472. ifequal_off    dw     0            ;Pointer to offset in COM file
  2473. ifequal_size    dw     offset ifequal_end - offset ifequal_start
  2474. ifequal_next    dw     0            ;Ptr to next routine to append
  2475. ifequal_lnks    dw     0
  2476. ifequal_start    =      $
  2477.  
  2478. ifequal     proc    near
  2479.         assume    cs:code,ds:code,es:code,ss:code
  2480.         xor    cx,cx
  2481.         mov    cl,[si-1]        ;Get size of string
  2482.         cmp    cl,[di-1]        ;Compare sizes of strings
  2483.         jne    ifequal_notequal
  2484.         rep    cmpsb            ;Compare strings
  2485.         jne    ifequal_notequal
  2486.         clc
  2487.         ret
  2488. ifequal_notequal:
  2489.         stc
  2490.         ret
  2491. ifequal     endp
  2492. ifequal_end    =    $
  2493.  
  2494. ;-----------------------------------------------------------------------------
  2495. ; IFEXIST  Determines if a file exists.
  2496. ; Entry:  DS:SI - Pointer to ASCIIZ filename.
  2497. ;         DI - Pointer to buffer for disk transfer area.
  2498. ; Exit:      CF - Clear if file exists
  2499. ;         DI - IF file exists, points to filename.
  2500. ;-----------------------------------------------------------------------------
  2501. ifexist_off    dw     0            ;Pointer to offset in COM file
  2502. ifexist_size    dw     offset ifexist_end - offset ifexist_start
  2503. ifexist_next    dw     0            ;Ptr to next routine to append
  2504. ifexist_lnks    dw     0
  2505. ifexist_start    =      $
  2506.  
  2507. ifexist     proc    near
  2508.         assume    cs:code,ds:code,es:code,ss:code
  2509.         mov    dx,di
  2510.         mov    ah,1ah            ;Set DTA
  2511.         int    21h
  2512.  
  2513.         mov    dx,si            ;Copy pointer to filename
  2514.         xor    cx,cx            ;Normal attributes
  2515.         mov    ah,4eh            ;DOS Find First
  2516.         int    21h
  2517.         jc    ifexist_exit
  2518.         add    di,1eh            ;Point DI to filename in DTA
  2519.         clc
  2520. ifexist_exit:
  2521.         ret
  2522. ifexist     endp
  2523. ifexist_end    =    $
  2524.  
  2525. ;-----------------------------------------------------------------------------
  2526. ; IFERRLEV  Compares the value passed with the return code of the last
  2527. ;        program executed.
  2528. ; Entry:     SI - Pointer to ASCIIZ Error level.
  2529. ; Exit:      CF - Clear if process error level above or equal to SI
  2530. ;-----------------------------------------------------------------------------
  2531. iferrlev_off    dw     0            ;Pointer to offset in COM file
  2532. iferrlev_size    dw     offset iferrlev_end - offset iferrlev_start
  2533. iferrlev_next    dw     0            ;Ptr to next routine to append
  2534. iferrlev_lnks    dw     0
  2535. iferrlev_start    =      $
  2536.  
  2537. iferrlev    proc    near
  2538.         assume    cs:code,ds:code,es:code,ss:code
  2539.         xor    ax,ax            ;Convert ASCIIZ number into
  2540.         mov    bx,ax            ;  decimal
  2541. iferrlev_1:
  2542.         mov    bl,[si]         ;Convert error level number
  2543.         sub    bl,'0'                  ;  from ASCII to decimal.
  2544.         jb    iferrlev_2
  2545.         cmp    bl,9
  2546.         ja    iferrlev_2
  2547.         mov    dx,10
  2548.         mul    dx
  2549.         jc    iferrlev_2
  2550.         add    ax,bx            ;Add in digit
  2551.         inc    si
  2552.         jmp    short iferrlev_1
  2553. iferrlev_2:
  2554.         cmp    process_rc,al        ;Compare to last program
  2555.         ret
  2556. iferrlev    endp
  2557. iferrlev_end    =    $
  2558.  
  2559. ;-----------------------------------------------------------------------------
  2560. ; FORLOOP  Processes commands in a FOR loop.
  2561. ; Entry:     SI - Pointer to ASCIIZ set of parameters.
  2562. ;         DI - Pointer loop structure in data area
  2563. ;          LoopCnt    db     0    Member of the set to use
  2564. ;          FirstFlag    db     0    Indicates Find first/next
  2565. ; Exit:      CF - Set if FOR loop complete.
  2566. ;-----------------------------------------------------------------------------
  2567. forloop_getmem    equ    [bx-6]
  2568. forloop_savchr    equ    [bx]
  2569. forloop_eptr    equ    [bx+1]
  2570. forloop_dta       equ    [bx+3]
  2571. forloop_off    dw    0            ;Pointer to offset in COM file
  2572. forloop_size    dw    offset forloop_end - offset forloop_start
  2573. forloop_next    dw    0            ;Ptr to next routine to append
  2574. forloop_lnks    dw    2
  2575. forloop_start    =    $
  2576.         dw    getmember_next
  2577.  
  2578. forloop     proc    near
  2579.         assume    cs:code,ds:code,es:code,ss:code
  2580.         push    bx
  2581.         call    forloop_0
  2582.         db    0            ;Saved termaination character
  2583.         dw    0            ;Ptr to term character address
  2584.         db    43 dup (0)        ;Used for DTA
  2585. forloop_0:
  2586.         pop    bx
  2587.         push    si
  2588.         mov    si,forloop_eptr
  2589.         or    si,si
  2590.         je    forloop_01
  2591.         mov    al,forloop_savchr
  2592.         mov    byte ptr [si-1],al     ;Remove zero terminator
  2593. forloop_01:
  2594.         pop    si
  2595. ;
  2596. ;Set DTA. If 2nd time or later time looping on a member, use find next to
  2597. ;determine the string for this time through the loop.
  2598. ;
  2599.         lea    dx,forloop_dta        
  2600.         mov    ah,1ah            ;Set DTA
  2601.         int    21h
  2602.  
  2603.         cmp    byte ptr [di+1],0    ;See if first time for member
  2604.         je    forloop_1
  2605.         mov    ah,4fh            ;Find next file
  2606.         int    21h
  2607.         jc    forloop_1        ;Not found, go to next member
  2608.         lea    dx,[bx+21h]        ;Point to filename in DTA
  2609.         jmp    short forloop_notdone    ;Execute loop body
  2610. ;
  2611. ;First time with this member of the set, if wildcards are in the member,
  2612. ;use DOS find first to get the loop string.
  2613. ;
  2614. forloop_1:
  2615.         mov    byte ptr [di+1],0    ;Clear first/next flag
  2616.         inc    byte ptr [di]        ;Look at next member of the set
  2617.         mov    dh,[di]         ;Get loop count
  2618.         call    forloop_getmem        ;Get member of set.  If no
  2619.         jc    forloop_done        ;  more members, loop done.
  2620.         mov    dx,si            ;Save pointer to member
  2621.         xor    ah,ah            ;Clear wildcard flag
  2622. forloop_2:
  2623.         lodsb                ;Scan set member to check for
  2624.         cmp    al,' '                  ;  any wildcard chars.
  2625.         jbe    forloop_4
  2626.         cmp    al,'?'
  2627.         jne    forloop_3
  2628.         inc    ah            ;Set wildcard found flag
  2629. forloop_3:
  2630.         cmp    al,'*'
  2631.         jne    forloop_2
  2632.         inc    ah            ;Set wildcard found flag
  2633.         jmp    short forloop_2
  2634. forloop_4:
  2635.         xor    al,al
  2636.         xchg    byte ptr [si-1],al    ;Set zero terminator.
  2637.         mov    forloop_savchr,al    ;Save char over written
  2638.         or    ah,ah            ;If no wildcards, execute
  2639.         je    forloop_notdone     ;Execute loop body
  2640.         mov    byte ptr [di+1],1    ;Set first/next flag
  2641.         xor    cx,cx            ;Normal attributes
  2642.         mov    ah,4eh            ;DOS find first
  2643.         int    21h
  2644.         jc    forloop_1        ;If not found, get next member
  2645.         lea    dx,[bx+1eh]        ;Set ptr to filename in DTA
  2646. forloop_notdone:
  2647.         mov    forloop_ptr,dx        ;Set loop data ptr
  2648.         mov    forloop_eptr,si
  2649.         clc
  2650. forloop_exit:
  2651.         pop    bx
  2652.         ret
  2653. forloop_done:
  2654.         mov    word ptr [di],0     ;Clear loop variables
  2655.         mov    word ptr forloop_eptr,0
  2656.         stc
  2657.         jmp    short forloop_exit
  2658. forloop     endp
  2659. forloop_end    =    $
  2660.  
  2661. ;-----------------------------------------------------------------------------
  2662. ; FINDENV  Finds the master environment block.
  2663. ; Exit:    Variable Environment_seg set with segment of master environment.
  2664. ;-----------------------------------------------------------------------------
  2665. findenv_dosver    equ    [bx+7]
  2666. findenv_cmdname equ    [bx]
  2667. findenv_off    dw    0             ;Pointer to offset in COM file
  2668. findenv_size    dw    offset findenv_end - offset findenv_start
  2669. findenv_next    dw    0             ;Ptr to next routine to append
  2670. fipëèÃ;/À75¨äØ;äÿ╱à34Ã22Ã;/¨´0¨:⇦ßäÆ╱à╱à34Ã22Ã;⓪⇦Õ97õäÃ2ã¨╱à⇦ä㨨´ÀØäõ¨¥1ÃØ2û29¥1Õ⇦ג ג⇩ F⇦ג א⇩ F⇦ג88y9⇨ij⇩⇧∙╱A°8y9╱◆ij∙⇦A◆Ö⑨[¥ùכ⇨BâBéBY⑧éHÉצצSPSæ✓âBéBYאL⇨BÖÜ[Ö⑨[¥ùכâBéB\ץ⇩Xß⇨BéB\\ם⇩Y\בBâBéB[[§éX^♪⑨מûכÿם⑦BBNעך]✓⑨⑨Yÿ][✓⑨[¥âBéBXף\⇩Y[¥Ü\¢ף¢Y[¥⑦ץךYי⑧^⇩Nסם⑨XםזזךYHəYê⑧[ÖXYCBéBZ¢ÖBYÜ[Ö⑨[¥ùם¢tion.
  2671. ; Entry   ES:DI - pointer to the first entry in the list. (Assume ES = DS)
  2672. ;      DS:SI - pointer to label to find.
  2673. ;         CX - Length of label
  2674. ; Exit         BX - pointer to matching list entry, or last entry if not found.
  2675. ;         CF - Set if label not found.
  2676. ;----------------------------------------------------------------------------
  2677. lblsrch_ptr    dw    0            ;Pointer to offset in COM file
  2678. lblsrch_size    dw    offset lblsrch_end - offset lblsrch_start
  2679. lblsrch_next    dw    0            ;Ptr to next routine to append
  2680. lblsrch_lnks    dw    0            ;Bytes in the dependancy header ;Number of routines called
  2681. lblsrch_start    =    $
  2682.  
  2683. lblsrch_code    proc    near
  2684.         assume    cs:code,ds:code
  2685.         push    si
  2686.         mov    dx,si            ;Save ptr to label
  2687.         mov    ax,cx            ;Save label length
  2688.         mov    bx,di            ;Get ptr to list
  2689. lblsrch_1:
  2690.         mov    di,bx
  2691.         add    di,4            ;Move to label string
  2692.         mov    si,dx            ;Get ptr to new label
  2693.         mov    cx,ax            ;Get length of label
  2694.         cmp    [di],cl         ;Compare lengths of the labels
  2695.         jne    lblsrch_2
  2696.         inc    di            ;Skip past length byte
  2697.         repe    cmpsb            ;Compare labels.
  2698.         je    lblsrch_4
  2699. lblsrch_2:
  2700.         cmp    word ptr [bx],-1    ;See if at end of list
  2701.         je    lblsrch_3
  2702.         add    bx,[bx]         ;Point to next label
  2703.         jmp    short lblsrch_1
  2704. lblsrch_3:
  2705.         stc                ;No label found.
  2706.         jmp    short lblsrch_exit
  2707. lblsrch_4:
  2708.         clc                ;Label found
  2709. lblsrch_exit:
  2710.         pop    si
  2711.         ret
  2712. lblsrch_code    endp
  2713. lblsrch_end    =    $
  2714.  
  2715. ;-----------------------------------------------------------------------------
  2716. ; IFEQUAL  Compares two strings.
  2717. ; Entry:  DS:SI - Pointer to first ASCIIZ String
  2718. ;      ES:DI - Pointer to second ASCIIZ String
  2719. ;         CX - Length of strings.
  2720. ; Exit:      CF - Clear if equal
  2721. ;-----------------------------------------------------------------------------
  2722. ifequal_off    dw     0            ;Pointer to offset in COM file
  2723. ifequal_size    dw     offset ifequal_end - offset ifequal_start
  2724. ifequal_next    dw     0            ;Ptr to next routine to append
  2725. ifequal_lnks    dw     0
  2726. ifequal_start    =      $
  2727.  
  2728. ifequal     proc    near
  2729.         assume    cs:code,ds:code,es:code,ss:code
  2730.         xor    cx,cx
  2731.         mov    cl,[si-1]        ;Get size of string
  2732.         cmp    cl,[di-1]        ;Compare sizes of strings
  2733.         jne    ifequal_notequal
  2734.         rep    cmpsb            ;Compare strings
  2735.         jne    ifequal_notequal
  2736.         clc
  2737.         ret
  2738. ifequal_notequal:
  2739.         stc
  2740.         ret
  2741. ifequal     endp
  2742. ifequal_end    =    $
  2743.  
  2744. ;-----------------------------------------------------------------------------
  2745. ; IFEXIST  Determines if a file exists.
  2746. ; Entry:  DS:SI - Pointer to ASCIIZ filename.
  2747. ;         DI - Pointer to buffer for disk transfer area.
  2748. ; Exit:      CF - Clear if file exists
  2749. ;         DI - IF file exists, points to filename.
  2750. ;-----------------------------------------------------------------------------
  2751. ifexist_off    dw     0            ;Pointer to offset in COM file
  2752. ifexist_size    dw     offset ifexist_end - offset ifexist_start
  2753. ifexist_next    dw     0            ;Ptr to next routine to append
  2754. ifexist_lnks    dw     0
  2755. ifexist_start    =      $
  2756.  
  2757. ifexist     proc    near
  2758.         assume    cs:code,ds:code,es:code,ss:code
  2759.         mov    dx,di
  2760.         mov    ah,1ah            ;Set DTA
  2761.         int    21h
  2762.  
  2763.         mov    dx,si            ;Copy pointer to filename
  2764.         xor    cx,cx            ;Normal attributes
  2765.         mov    ah,4eh            ;DOS Find First
  2766.         int    21h
  2767.         jc    ifexist_exit
  2768.         add    di,1eh            ;Point DI to filename in DTA
  2769.         clc
  2770. ifexist_exit:
  2771.         ret
  2772. ifexist     endp
  2773. ifexist_end    =    $
  2774.  
  2775. ;-----------------------------------------------------------------------------
  2776. ; IFERRLEV  Compares the value passed with the return code of the last
  2777. ;        program executed.
  2778. ; Entry:     SI - Pointer to ASCIIZ Error level.
  2779. ; Exit:      CF - Clear if process error level above or equal to SI
  2780. ;-----------------------------------------------------------------------------
  2781. iferrlev_off    dw     0            ;Pointer to offset in COM file
  2782. iferrlev_size    dw     offset iferrlev_end - offset iferrlev_start
  2783. iferrlev_next    dw     0            ;Ptr to next routine to append
  2784. iferrlev_lnks    dw     0
  2785. iferrlev_start    =      $
  2786.  
  2787. iferrlev    proc    near
  2788.         assume    cs:code,ds:code,es:code,ss:code
  2789.         xor    ax,ax            ;Convert ASCIIZ number into
  2790.         mov    bx,ax            ;  decimal
  2791. iferrlev_1:
  2792.         mov    bl,[si]         ;Convert error level number
  2793.         sub    bl,'0'                  ;  from ASCII to decimal.
  2794.         jb    iferrlev_2
  2795.         cmp    bl,9
  2796.         ja    iferrlev_2
  2797.         mov    dx,10
  2798.         mul    dx
  2799.         jc    iferrlev_2
  2800.         add    ax,bx            ;Add in digit
  2801.         inc    si
  2802.         jmp    short iferrlev_1
  2803. iferrlev_2:
  2804.         cmp    process_rc,al        ;Compare to last program
  2805.         ret
  2806. iferrlev    endp
  2807. iferrlev_end    =    $
  2808.  
  2809. ;-----------------------------------------------------------------------------
  2810. ; FORLOOP  Processes commands in a FOR loop.
  2811. ; Entry:     SI - Pointer to ASCIIZ set of parameters.
  2812. ;         DI - Pointer loop structure in data area
  2813. ;          LoopCnt    db     0    Member of the set to use
  2814. ;          FirstFlag    db     0    Indicates Find first/next
  2815. ; Exit:      CF - Set if FOR loop complete.
  2816. ;-----------------------------------------------------------------------------
  2817. forloop_getmem    equ    [bx-6]
  2818. forloop_savchr    equ    [bx]
  2819. forloop_eptr    equ    [bx+1]
  2820. forloop_dta       equ    [bx+3]
  2821. forloop_off    dw    0            ;Pointer to offset in COM file
  2822. forloop_size    dw    offset forloop_end - offset forloop_start
  2823. forloop_next    dw    0            ;Ptr to next routine to append
  2824. forloop_lnks    dw    2
  2825. forloop_start    =    $
  2826.         dw    getmember_next
  2827.  
  2828. forloop     proc    near
  2829.         assume    cs:code,ds:code,es:code,ss:code
  2830.         push    bx
  2831.         call    forloop_0
  2832.         db    0            ;Saved termaination character
  2833.         dw    0            ;Ptr to term character address
  2834.         db    43 dup (0)        ;Used for DTA
  2835. forloop_0:
  2836.         pop    bx
  2837.         push    si
  2838.         mov    si,forloop_eptr
  2839.         or    si,si
  2840.         je    forloop_01
  2841.         mov    al,forloop_savchr
  2842.         mov    byte ptr [si-1],al     ;Remove zero terminator
  2843. forloop_01:
  2844.         pop    si
  2845. ;
  2846. ;Set DTA. If 2nd time or later time looping on a member, use find next to
  2847. ;determine the string for this time through the loop.
  2848. ;
  2849.         lea    dx,forloop_dta        
  2850.         mov    ah,1ah            ;Set DTA
  2851.         int    21h
  2852.  
  2853.         cmp    byte ptr [di+1],0    ;See if first time for member
  2854.         je    forloop_1
  2855.         mov    ah,4fh            ;Find next file
  2856.         int    21h
  2857.         jc    forloop_1        ;Not found, go to next member
  2858.         lea    dx,[bx+21h]        ;Point to filename in DTA
  2859.         jmp    short forloop_notdone    ;Execute loop body
  2860. ;
  2861. ;First time with this member of the set, if wildcards are in the member,
  2862. ;use DOS find first to get the loop string.
  2863. ;
  2864. forloop_1:
  2865.         mov    byte ptr [di+1],0    ;Clear first/next flag
  2866.         inc    byte ptr [di]        ;Look at next member of the set
  2867.         mov    dh,[di]         ;Get loop count
  2868.         call    forloop_getmem        ;Get member of set.  If no
  2869.         jc    forloop_done        ;  more members, loop done.
  2870.         mov    dx,si            ;Save pointer to member
  2871.         xor    ah,ah            ;Clear wildcard flag
  2872. forloop_2:
  2873.         lodsb                ;Scan set member to check for
  2874.         cmp    al,' '                  ;  any wildcard chars.
  2875.         jbe    forloop_4
  2876.         cmp    al,'?'
  2877.         jne    forloop_3
  2878.         inc    ah            ;Set wildcard found flag
  2879. forloop_3:
  2880.         cmp    al,'*'
  2881.         jne    forloop_2
  2882.         inc    ah            ;Set wildcard found flag
  2883.         jmp    short forloop_2
  2884. forloop_4:
  2885.         xor    al,al
  2886.         xchg    byte ptr [si-1],al    ;Set zero terminator.
  2887.         mov    forloop_savchr,al    ;Save char over written
  2888.         or    ah,ah            ;If no wildcards, execute
  2889.         je    forloop_notdone     ;Execute loop body
  2890.         mov    byte ptr [di+1],1    ;Set first/next flag
  2891.         xor    cx,cx            ;Normal attributes
  2892.         mov    ah,4eh            ;DOS find first
  2893.         int    21h
  2894.         jc    forloop_1        ;If not found, get next member
  2895.         lea    dx,[bx+1eh]        ;Set ptr to filename in DTA
  2896. forloop_notdone:
  2897.         mov    forloop_ptr,dx        ;Set loop data ptr
  2898.         mov    forloop_eptr,si
  2899.         clc
  2900. forloop_exit:
  2901.         pop    bx
  2902.         ret
  2903. forloop_done:
  2904.         mov    word ptr [di],0     ;Clear loop variables
  2905.         mov    word ptr forloop_eptr,0
  2906.         stc
  2907.         jmp    short forloop_exit
  2908. forloop     endp
  2909. forloop_end    =    $
  2910.  
  2911. ;-----------------------------------------------------------------------------
  2912. ; FINDENV  Finds the master environment block.
  2913. ; Exit:    Variable Environment_seg set with segment of master environment.
  2914. ;-----------------------------------------------------------------------------
  2915. f