     1                                  ;*********************************************************************
     2                                  ;*   MLPARSE.ASM                                                     *
     3                                  ;*                                                                   *
     4                                  ;*   By:            Michael Devore                                   *
     5                                  ;*   Date:          04/17/93                                         *
     6                                  ;*   Model:         Small                                            *
     7                                  ;*   Version:       2.5                                              *
     8                                  ;*   Assembler:     MASM 5.0                                         *
     9                                  ;*   Environment:   MS-DOS 2.x+                                      *
    10                                  ;*                                                                   *
    11                                  ;*   Parse linker command line or response file, nonoverlay options  *
    12                                  ;*                                                                   *
    13                                  ;*********************************************************************
    14                                  
    15                                  ;TITLE   WARPLINK mlparse
    16                                  ;PAGE    50,80
    17                                  
    18                                  ;.MODEL  SMALL
    19                                  
    20                                  ;*****************************
    21                                  ;* Include files             *
    22                                  ;*****************************
    23                                  
    24                                  [list -]
    14                              <1> [list -]
    26                                  [list -]
    31                                       
    32                                  ;*****************************
    33                                  ;* Public declarations       *
    34                                  ;*****************************
    35                                  
    36                                  ; procedures
    37                                  PUBLIC  parse,check_extension,save_lib_name,in_overlay
    38                                  PUBLIC	file_not_found,is_terminator,set_exe_name
    39                                  
    40                                  ; variables
    41                                  PUBLIC  exe_pathspec,libtext,objtext,module_flag
    42                                  PUBLIC  clip_libnum,clp5_lib,first_udlent_ptr
    43                                  PUBLIC	rsp_line,parfilename,exe_ext_ptr
    44                                  PUBLIC	ddl_depend_count
    45                                  
    46                                  ;*****************************
    47                                  ;* Data begins               *
    48                                  ;*****************************
    49                                       
    50                                  .DATA
    51                                  
    52                                  ;*****************************
    53                                  ;* External declarations     *
    54                                  ;*****************************
    55                                  
    56                                  ; variables
    57                                  EXTRN   def_lib_flag:BYTE,temp_file_name:BYTE
    58                                  EXTRN   dir_pages:WORD,lib_pages_count:WORD,lib_handle:WORD
    59                                  EXTRN   lib_page_num:WORD,lib_page_size:WORD,dir_offset:DWORD
    60                                  EXTRN	reading_qlk_flag:BYTE
    61                                  
    62 00000000 00                      parse_pass	DB	0			; parsing pass, redone on incremental linking
    63 00000001 00                      ddl_depend_count	DB	0	; count of dependent DDL's
    64                                  
    65                                  ; uninitialized local variables
    66                                  .DATA?
    67                                  
    68                                  ; previously initialized variables
    69                                  ; byte values
    70 00000000 ??                      in_overlay  DB  ?           ; 80h if parsed files are in any overlay,
    71                                                              ; 40h set if nonvectored root call overlay, 0 otherwise
    72 00000001 ??                      arg_type    DB  ?           ; command argument type, 0==.obj,1==.exe,2==.map,3==.lib
    73                                   global no_extension
    74 00000002 ??                      no_extension    DB  ?       ; nonzero if file name parse has no extension
    75 00000003 ??                      lib_nonmod_flag DB  ?       ; nonzero if library specified that is not a module (used for /udl)
    76                                  
    77                                  ; word values
    78 00000004 ????                    exe_ext_ptr DW  ?           ; pointer to executable file's extension in exe_name, zero if none
    79 00000006 ????                    first_udlent_ptr    DW  ?   ; pointer to first allocated use ddl entry
    80 00000008 ????                    alloc_udlent_ptr    DW  ?   ; pointer to last allocated use ddl entrym
    81                                  
    82 0000000A ????                    clip_libnum DW  ?			; library number of CLIPPER.LIB, if exists
    83                                  
    84                                  .DATA
    85                                  ; byte character strings
    86 00000002 434C49505045522E4C-     clp5_lib    DB  'CLIPPER.LIB',0,0
    86 0000000B 49420000           
    87                                  
    88                                  .DATA?
    89                                  ; previously uninitialized variables
    90                                  ; byte values
    91 0000000C ??                      plus_flag   DB  ?           ; nonzero if plus sign was parsed in response file
    92 0000000D ??                      comma_flag  DB  ?           ; nonzero if commas was parsed in response file
    93 0000000E ??                      comment_flag    DB  ?       ; nonzero if comment line in response file
    94 0000000F ??                      module_flag DB  ?           ; nonzero if library specified was specific module
    95                                  
    96                                  ; word values
    97 00000010 ????                    rsp_handle  DW  ?           ; response file handle
    98 00000012 ????                    libname_ptr DW  ?           ; pointer to current library name, including path and drivespec if necessar
    99                                  
   100                                  ; byte character strings
   101                                   global parfilename
   102 00000014 <res 80h>               parfilename	DB	128 DUP (?)	; file name being parsed from command line
   103 00000094 <res 80h>               rsp_line    DB  128 DUP (?) ; line read from response file
   104 00000114 <res 7Eh>               modname     DB  126 DUP (?) ; name of library module specified in command line
   105 00000192 <res 7Fh>               exe_pathspec    DB  127 DUP (?) ; path and drive spec of EXE file, if any
   106 00000211 ??????????              tbuff   DB  5 DUP (?)       ; temporary buffer
   107                                  
   108                                  ;*****************************
   109                                  ;* Constant data             *
   110                                  ;*****************************
   111                                  
   112                                  .CONST
   113                                  
   114 00000000 574152504C494E4B3D      linktext	DB	LINKERCAPS,'='
   115 00000009 4C49423D                libtext		DB  'LIB='		; environment string to check for library file path
   116 0000000D 4F424A3D                objtext		DB  'OBJ='		; e-var to check for object module path
   117 00000011 0D0A2A2A2A204C6F63-     parsetext	DB	CR,LF,'*** Locating library module: ',0
   117 0000001A 6174696E67206C6962-
   117 00000023 72617279206D6F6475-
   117 0000002C 6C653A2000         
   118                                  
   119                                  ;*****************************
   120                                  ;* Code begins               *
   121                                  ;*****************************
   122                                       
   123                                  .CODE
   124                                  
   125                                  ;*****************************
   126                                  ;* External declarations     *
   127                                  ;*****************************
   128                                  
   129                                  ; procedures
   130                                  EXTRN   link_error:NEAR,dos_error:NEAR,alloc_memory:NEAR
   131                                  EXTRN   check_libobj_path:NEAR,get_lib_sys_info:NEAR,remove_dup_pages:NEAR
   132                                  EXTRN   make_libmod_entry:NEAR
   133                                  
   134                                  EXTRN   parse_ovl_option:NEAR,save_ovl_name:NEAR,parse_clp_option:NEAR
   135                                  EXTRN   read_to_ems:NEAR
   136                                  EXTRN	is_qlk_file:NEAR
   137                                  
   138                                  %IFNDEF DEMO
   139                                  EXTRN	parse_ddl_option:NEAR
   140                                  %ENDIF
   141                                  
   142                                  ;*****************************
   143                                  ;* PARSE                     *
   144                                  ;*****************************
   145                                  
   146                                  ; main parsing loop
   147                                  ; destroys ax,bx,cx,dx,si,di,es
   148                                  
   149                                  parse       PROC
   150 00000000 FE06[0000]              	inc	byte [parse_pass]			; bump parsing pass count
   151 00000004 E8A90D                      call    get_env_options ; get any options specified by environment
   152 00000007 31C0                        xor ax,ax
   153 00000009 A3[0000]                    mov [current_lib],ax      ; init current library module number for module specification
   154 0000000C A2[0000]                    mov [prev_libname],al     ; zero out previous name of library for module specification
   155 0000000F A2[0000]                	mov	[in_overlay],al
   156 00000012 A2[0100]                	mov	[arg_type],al
   157 00000015 A2[0200]                	mov	[no_extension],al
   158 00000018 A2[0300]                	mov	[lib_nonmod_flag],al
   159 0000001B A3[0400]                	mov	[exe_ext_ptr],ax
   160 0000001E A3[0600]                	mov	[first_udlent_ptr],ax
   161 00000021 A3[0800]                	mov	[alloc_udlent_ptr],ax
   162 00000024 A3[0000]                	mov	[obj_count],ax
   163 00000027 A3[0000]                	mov	[lib_count],ax
   164 0000002A A3[0000]                	mov	[first_libblk_ptr],ax
   165 0000002D A3[0000]                	mov	[last_libblk_ptr],ax
   166 00000030 A3[0000]                	mov	[last_objblk_ptr],ax
   167 00000033 C706[0A00]FFFF          	mov	word [clip_libnum],-1
   168                                  
   169 00000039 BE[0100]                    mov si,OFFSET cmd_line+1 wrt DGROUP ; point to command line, past char count
   170 0000003C E8AB05                      call    deplus          ; change plus signs to spaces
   171 0000003F BE[0100]                    mov si,OFFSET cmd_line+1 wrt DGROUP ; point to modified command line, past char count
   172                                  ploop1:
   173 00000042 89F7                        mov di,si               ; save first char of parse string
   174 00000044 AC                          lodsb                   ; get char from command line string
   175 00000045 08C0                        or  al,al               ; if zero then end of command line string
   176 00000047 7503                        jne parse_char          ; not at end
   177 00000049 E99500                      jmp NEAR PTR endparse   ; at end
   178                                  
   179                                  parse_char:
   180 0000004C 3C20                        cmp al,' '              ; ignore white space chars
   181 0000004E 76F2                        jbe ploop1              ; loop for next char
   182 00000050 3C2F                        cmp al,'/'              ; linker option
   183 00000052 747D                        je  parse_option
   184 00000054 3C40                        cmp al,'@'              ; response file
   185 00000056 747F                        je  parse_response
   186 00000058 3C28                        cmp al,'('              ; begin overlay
   187 0000005A 7419                        je  parse_beginovl
   188 0000005C 3C5B                        cmp al,'['              ; begin nonvectored root call overlay
   189 0000005E 7415                        je  parse_beginovl
   190 00000060 3C29                        cmp al,')'              ; end overlay
   191 00000062 743C                        je  parse_endovl
   192 00000064 3C5D                        cmp al,']'              ; end overlay
   193 00000066 7438                        je  parse_endovl
   194 00000068 3C2C                        cmp al,','              ; next command line argument type
   195 0000006A 7456                        je  next_argtype
   196 0000006C 3C3B                        cmp al,';'              ; end of command line argument
   197 0000006E 7471                        je  endparse            ; all done parsing, ignore anything after semi-colon
   198                                  
   199                                  parse_name:                 ; file name with or without path
   200 00000070 E81207                      call    parse_file_type
   201 00000073 EBCD                        jmp SHORT ploop1        ; parse next char
   202                                  
   203                                  parse_beginovl:             ; begin overlay
   204 00000075 803E[0100]00                cmp byte [arg_type],0          ; only allow overlays for object modules and libraries
   205 0000007A 7407                        je  pb_2                ; okay, object module
   206 0000007C 803E[0100]03                cmp byte [arg_type],3          ; check if library
   207 00000081 75ED                        jne parse_name          ; no, assume file name
   208                                  
   209                                  pb_2:
   210 00000083 803E[0000]00                cmp byte [in_overlay],0        ; check flag to make sure not already in an overlay
   211 00000088 7510                        jne bad_left_paren      ; already in an overlay
   212 0000008A C606[0000]80                mov byte [in_overlay],80h      ; set flag
   213 0000008F 3C28                        cmp al,'('              ; see if nonvectored root call overlay
   214 00000091 75AF                        jne ploop1              ; no, parse next char
   215 00000093 800E[0000]40                or  byte [in_overlay],40h      ; set nonvectored root call overlay
   216 00000098 EBA8                        jmp SHORT ploop1        ; parse next char
   217                                  
   218                                  bad_left_paren:             ; nested parenthesis, fatal error
   219 0000009A B80300                      mov ax,NEST_PAREN_ERR   ; put warplink error code in ax
   220 0000009D E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   221                                  
   222                                  parse_endovl:               ; end overlay
   223 000000A0 803E[0100]00                cmp byte [arg_type],0          ; only allow overlays for object modules and libraries
   224 000000A5 7407                        je  pe_2                ; okay, object module
   225 000000A7 803E[0100]03                cmp byte [arg_type],3          ; check if library
   226 000000AC 75C2                        jne parse_name          ; no, assume file name
   227                                  
   228                                  pe_2:
   229 000000AE 803E[0000]00                cmp byte [in_overlay],0        ; check flag to make sure in overlay
   230 000000B3 7407                        je  bad_right_paren     ; not in an overlay
   231 000000B5 C606[0000]00                mov byte [in_overlay],0        ; reset flag
   232 000000BA EB86                        jmp SHORT ploop1
   233                                  
   234                                  bad_right_paren:            ; improperly matched parenthesis, fatal error
   235 000000BC B80200                      mov ax,UNM_RIGHT_PAREN_ERR  ; put warplink error code in ax
   236 000000BF E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   237                                  
   238                                  next_argtype:               ; next command line argument type
   239 000000C2 A0[0100]                    mov al,[arg_type]         ; get previous arg_type value
   240 000000C5 FEC0                        inc al                  ; bump it up one
   241 000000C7 A2[0100]                    mov [arg_type],al         ; save back to memory variable
   242 000000CA 3C05                        cmp al,5                ; check bounds
   243 000000CC 7313                        jae endparse            ; ignore input after .lib name
   244 000000CE E971FF                      jmp NEAR PTR ploop1
   245                                  
   246                                  parse_option:               ; linker option
   247 000000D1 E8A701                      call    set_option
   248 000000D4 E96BFF                      jmp NEAR PTR ploop1
   249                                  
   250                                  parse_response:             ; response file
   251 000000D7 E82A05                      call    use_rsp
   252 000000DA 08C9                        or  cl,cl               ; see if parsing termination occurred in response file
   253 000000DC 7503                        jne endparse            ; yes
   254 000000DE E961FF                      jmp NEAR PTR ploop1     ; no
   255                                  
   256                                  endparse:
   257 000000E1 803E[0000]00                cmp byte [in_overlay],0        ; check flag to make sure not still in an overlay
   258 000000E6 7406                        je  ep_chk_obj          ; not in an overlay, no overlay error
   259 000000E8 B80100                      mov ax,UNM_LEFT_PAREN_ERR   ; put warplink error code in ax
   260 000000EB E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   261                                  
   262                                  ; check that at least one object module was given in command line
   263                                  ep_chk_obj:
   264 000000EE 31C0                        xor ax,ax
   265 000000F0 3906[0000]                  cmp [obj_count],ax        ; is count of object modules nonzero
   266 000000F4 7518                        jne ep_2                ; yes
   267 000000F6 3806[0000]                  cmp [is_ddl],al           ; see if creating DDL
   268 000000FA 7506                        jne ep_noobj_ok         ; yes
   269 000000FC 3806[0000]                  cmp [use_ddl],al          ; see if using DDL's
   270 00000100 7406                        je  ep_noobj            ; no, must specify object module name
   271                                  
   272                                  ; using or creating DDL
   273                                  ep_noobj_ok:
   274 00000102 3906[0000]                  cmp [lib_count],ax        ; see if count of libraries is zero
   275 00000106 7506                        jne ep_2                ; no, okay if no object modules
   276                                  
   277                                  ; no object modules specified, or DDL and no object or library modules
   278                                  ep_noobj:
   279 00000108 B81300                      mov ax,NO_OBJMOD_ERR
   280 0000010B E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   281                                  
   282                                  ep_2:
   283 0000010E 1E                          push    ds
   284 0000010F 07                          pop es                  ; es -> warplink data
   285 00000110 BE[0000]                    mov si,OFFSET exe_name wrt DGROUP   ; point to executable name
   286 00000113 3804                        cmp [si],al             ; check if name exists, nonzero first filename char
   287 00000115 7509                        jne ep_3                ; yes
   288                                  
   289                                  ; no EXE name given, use first object module name
   290 00000117 3906[0000]                  cmp [obj_count],ax        ; see if any object modules (can only be zero if DDL's)
   291 0000011B 74EB                        je  ep_noobj            ; no object module, no EXE (DDL) name, give error
   292 0000011D E81401                  	call	set_exe_name
   293                                  
   294                                  ep_3:
   295 00000120 A0[0000]                    mov al,[is_ddl]
   296 00000123 0A06[0000]                  or  al,[use_ddl]          ; see if DDLs used
   297 00000127 7432                        je  ep_notddl           ; no
   298                                  
   299                                  ; DDL's are used, force DDL extension
   300 00000129 8B36[0400]                  mov si,[exe_ext_ptr]      ; see if need to add an extension to executable file name
   301 0000012D 09F6                        or  si,si
   302 0000012F 7413                        je  ep_changext         ; no, must change pre-existing extension
   303 00000131 C6042E                      mov BYTE PTR [si],'.'   ; both extensions have period in name
   304                                  
   305                                  ep_makeddl:
   306 00000134 C6440144                    mov BYTE PTR [si+1],'D' ; add DDL extension
   307 00000138 C6440244                    mov BYTE PTR [si+2],'D'
   308 0000013C C644034C                    mov BYTE PTR [si+3],'L'
   309 00000140 31C0                        xor ax,ax
   310 00000142 EB44                        jmp SHORT ep_nullterm
   311                                  
   312                                  ; extension exists, but it's not DDL
   313                                  ep_changext:
   314 00000144 BF[0000]                    mov di,OFFSET exe_name wrt DGROUP   ; si -> start of executable name
   315 00000147 B501                        mov ch,1                ; name known shorter than 256 bytes
   316 00000149 30C0                        xor al,al
   317 0000014B F2AE                        repne   scasb           ; find end of name
   318 0000014D 83EF02                      sub di,2                ; di -> last char in name
   319 00000150 FD                          std                     ; string ops auto decrement
   320 00000151 B02E                        mov al,'.'              ; look backwards for period, cx known to be >128 bytes max name length
   321 00000153 F2AE                        repne   scasb
   322 00000155 FC                          cld                     ; string ops auto increment as normal
   323 00000156 89FE                        mov si,di               ; si -> char before '.'
   324 00000158 46                          inc si                  ; si -> '.'
   325 00000159 EBD9                        jmp SHORT ep_makeddl    ; add DDL extension
   326                                  
   327                                  ep_notddl:
   328 0000015B 31C0                        xor ax,ax
   329 0000015D 8B36[0400]                  mov si,[exe_ext_ptr]      ; see if need to add an extension to executable file name
   330 00000161 09F6                        or  si,si               ; if zero, then no extension will be added
   331 00000163 7426                        je  ep_4                ; don't add default extension
   332 00000165 C6042E                      mov BYTE PTR [si],'.'   ; both extensions have period in name
   333                                  
   334                                  ;***IFNDEF DEMO
   335 00000168 3806[0000]                  cmp [is_comfile],al       ; if .com file add .com extension
   336 0000016C 740E                        je  add_exe             ; .exe file
   337 0000016E C6440143                    mov BYTE PTR [si+1],'C' ; add COM extension
   338 00000172 C644024F                    mov BYTE PTR [si+2],'O'
   339 00000176 C644034D                    mov BYTE PTR [si+3],'M'
   340 0000017A EB0C                        jmp SHORT ep_nullterm   ; bypass EXE extension code
   341                                  ;***ENDIF
   342                                  
   343                                  add_exe:
   344 0000017C C6440145                    mov BYTE PTR [si+1],'E' ; add EXE extension
   345 00000180 C6440258                    mov BYTE PTR [si+2],'X'
   346 00000184 C6440345                    mov BYTE PTR [si+3],'E'
   347                                  
   348                                  ep_nullterm:
   349 00000188 884404                      mov BYTE PTR [si+4],al  ; null terminate filename string with extension
   350                                  
   351                                  ep_4:
   352 0000018B 3806[0000]                  cmp [is_mapfile],al       ; see if map file indicated
   353 0000018F 7442                        je  par_ovl             ; no
   354 00000191 BF[0000]                    mov di,OFFSET map_name wrt DGROUP   ; point to map name
   355 00000194 3805                        cmp BYTE PTR [di],al    ; check if name exists, nonzero first filename char
   356 00000196 753B                        jne par_ovl             ; yes
   357                                  
   358                                  ; use executable file name, without extension, as map file name
   359 00000198 BF[1400]                    mov di,OFFSET parfilename wrt DGROUP	; di -> filename string
   360 0000019B BE[0000]                    mov si,OFFSET exe_name wrt DGROUP
   361                                  
   362                                  ; ds:si -> name of first object module, es:di -> filename slot
   363 0000019E 31DB                        xor bx,bx               ; bx will index into strings
   364 000001A0 89DA                        mov dx,bx               ; dx will hold position of last found period
   365                                  
   366                                  ; find end of string, not counting extension
   367                                  mp_2loop:
   368 000001A2 8A00                        mov al,BYTE PTR [bx+si] ; get char from string
   369 000001A4 08C0                        or  al,al               ; check if char in string is null terminator
   370 000001A6 7411                        je  mp_2a               ; zero char, end of string found
   371 000001A8 3C5C                        cmp al,'\'              ; backslash char resets last found period position
   372 000001AA 7504                        jne mp_2loopa           ; bypass backslash code
   373 000001AC 31D2                        xor dx,dx               ; reset last char position
   374 000001AE EB06                        jmp SHORT mp_2loopb     ; bypass period check code
   375                                  mp_2loopa:
   376 000001B0 3C2E                        cmp al,'.'              ; is char a period
   377 000001B2 7502                        jne mp_2loopb           ; no
   378 000001B4 89DA                        mov dx,bx               ; track last found period
   379                                  mp_2loopb:
   380 000001B6 43                          inc bx                  ; bump char count
   381 000001B7 EBE9                        jmp SHORT mp_2loop      ; loop back for next char
   382                                  
   383                                  mp_2a:
   384 000001B9 09D2                        or  dx,dx               ; was a period found not in a path (extension marker)
   385 000001BB 7402                        je  mp_2b               ; no
   386 000001BD 89D3                        mov bx,dx               ; set termination position at period
   387                                  
   388                                  mp_2b:    
   389 000001BF C60100                      mov BYTE PTR [bx+di],0  ; put null terminator in filename string
   390                                  mp_2c:
   391 000001C2 4B                          dec bx                  ; back up one char
   392 000001C3 8A00                        mov al,[bx+si]          ; get object module name char
   393 000001C5 8801                        mov [bx+di],al          ; transfer it
   394 000001C7 09DB                        or  bx,bx               ; if bx is zero then transfer is done
   395 000001C9 75F7                        jne mp_2c               ; not done, transfer next char
   396                                  
   397 000001CB C606[0200]01                mov byte [no_extension],1      ; flag that file name does not have an extension (add .MAP extension)
   398 000001D0 E84F06                      call    save_map_name   ; filename contains first object module name as map file
   399                                  
   400                                  ; check if overlay file needed, executable name still in filename variable
   401                                  par_ovl:
   402 000001D3 31C0                        xor ax,ax
   403 000001D5 3806[0000]                  cmp [is_comfile],al       ; see if COM file
   404 000001D9 740C                        je  par_saveovl         ; no
   405 000001DB 3806[0000]                  cmp [is_anyovls],al       ; see if any overlays specified
   406 000001DF 7412                        je  par_chkconf         ; no, check com file/dynamic libraries conflict
   407                                  
   408                                  ; COM file specified with overlays
   409 000001E1 B83F00                      mov ax,OVLCOM_CLASH_ERR
   410                                  par_to_err:
   411 000001E4 E9(0000)                    jmp NEAR PTR link_error
   412                                  
   413                                  par_saveovl:
   414 000001E7 A0[0000]                    mov al,[is_ddl]
   415 000001EA 0A06[0000]                  or  al,[use_ddl]          ; see if creating/using DDL's
   416 000001EE 7503                        jne par_chkconf         ; yes, don't save overlay file name
   417 000001F0 E8(0000)                    call    save_ovl_name   ; yes, save overlay file name
   418                                  
   419                                  par_chkconf:
   420 000001F3 31C0                        xor ax,ax
   421 000001F5 3806[0000]                  cmp [is_ddl],al           ; see if create dynamic library option
   422 000001F9 740B                        je  chk_use             ; no 
   423 000001FB A2[0000]                    mov [use_ddl],al          ; shut off use dynamic library option
   424 000001FE A2[0000]                    mov [is_dosseg],al        ; shut off explicit DOSSEG
   425 00000201 A2[0000]                    mov [is_smartmem],al      ; shut off smartmem use
   426 00000204 EB12                        jmp SHORT chk_com
   427                                  
   428                                  chk_use:
   429 00000206 3806[0000]                  cmp [use_ddl],al          ; see if use dynamic library option
   430 0000020A 7427                        je  par_ret             ; no
   431 0000020C 803E[0300]00                cmp byte [lib_nonmod_flag],0   ; see if any libraries specified with /udl
   432 00000211 7405                        je  chk_com             ; no
   433 00000213 C606[0000]01                mov byte [udl_proc_pass],1     ; flag udl processing, pass 1
   434                                  
   435                                  chk_com:
   436 00000218 C606[0000]01                mov byte [is_no_ems],1         ; shut off use of EMS when using DDLs
   437 0000021D C606[0000]01                mov byte [is_nodeflib],1       ; shut off default libraries, too
   438 00000222 A2[0000]                    mov [is_clpinc],al        ; force clipper incremental linking shut off
   439 00000225 A2[0000]                    mov [is_xms],al           ; shut of extended memory use
   440 00000228 3806[0000]                  cmp [is_comfile],al       ; see if COM file
   441 0000022C 7405                        je  par_ret             ; no
   442                                  
   443                                  ; conflict with /c and dynamic libraries
   444                                  par_conflict:
   445 0000022E B84800                      mov ax,COMCONFLICT_ERR
   446 00000231 EBB1                        jmp SHORT par_to_err
   447                                  
   448                                  par_ret:
   449 00000233 C3                          ret
   450                                  parse       ENDP
   451                                  
   452                                  ;*****************************
   453                                  ;* SET_EXE_NAME              *
   454                                  ;*****************************
   455                                  
   456                                  ; set the exe_name variable if not set
   457                                  ; destroys ax,bx,dx,di,si,es
   458                                  
   459                                  set_exe_name	PROC
   460 00000234 1E                      	push	ds
   461 00000235 07                      	pop	es					; es -> warplink data
   462 00000236 8E1E[0000]                  mov ds,[first_objblk_ptr] ; ds -> block containing name of first object module
   463 0000023A BE0400                      mov si,4                ; si -> first name in block
   464 0000023D 46                          inc si                  ; adjust past prepended flag byte
   465 0000023E BF[1400]                    mov di,OFFSET parfilename wrt DGROUP	; di -> filename string
   466                                  
   467                                  ; ds:si -> name of first object module, es:di -> filename slot
   468 00000241 31DB                        xor bx,bx               ; bx will index into strings
   469 00000243 89DA                        mov dx,bx               ; dx will hold position of last found period
   470                                  
   471                                  ; find end of string, not counting extension
   472                                  ep_2loop:
   473 00000245 8A00                        mov al,BYTE PTR [bx+si] ; get char from string
   474 00000247 08C0                        or  al,al               ; check if char in string is null terminator
   475 00000249 7411                        je  ep_2a               ; zero char, end of string found
   476 0000024B 3C5C                        cmp al,'\'              ; backslash char resets last found period position
   477 0000024D 7504                        jne ep_2loopa           ; bypass backslash code
   478 0000024F 31D2                        xor dx,dx               ; reset last char position
   479 00000251 EB06                        jmp SHORT ep_2loopb     ; bypass period check code
   480                                  ep_2loopa:
   481 00000253 3C2E                        cmp al,'.'              ; is char a period
   482 00000255 7502                        jne ep_2loopb           ; no
   483 00000257 89DA                        mov dx,bx               ; track last found period
   484                                  ep_2loopb:
   485 00000259 43                          inc bx                  ; bump char count
   486 0000025A EBE9                        jmp SHORT ep_2loop      ; loop back for next char
   487                                  
   488                                  ep_2a:
   489 0000025C 09D2                        or  dx,dx               ; was a period found not in a path (extension marker)
   490 0000025E 7402                        je  ep_2b               ; no
   491 00000260 89D3                        mov bx,dx               ; set termination position at period
   492                                  
   493                                  ep_2b:    
   494 00000262 26C60100                    mov BYTE PTR [es:bx+di],0   ; put null terminator in filename string
   495                                  ep_2c:
   496 00000266 4B                          dec bx                  ; back up one char
   497 00000267 8A00                        mov al,[bx+si]          ; get object module name char
   498 00000269 268801                      mov [es:bx+di],al       ; transfer it
   499 0000026C 09DB                        or  bx,bx               ; if bx is zero then transfer is done
   500 0000026E 75F6                        jne ep_2c               ; not done, transfer next char
   501                                  
   502 00000270 06                          push    es
   503 00000271 1F                          pop ds                  ; ds -> warplink data
   504 00000272 C606[0200]01                mov byte [no_extension],1      ; flag that file name does not have an extension (set up for .COM or .EXE addition)
   505 00000277 E85605                      call    save_exe_name   ; filename contains first object module name as executable file
   506 0000027A C3                      	ret
   507                                  set_exe_name	ENDP
   508                                  
   509                                  ;*****************************
   510                                  ;* SET_OPTION                *
   511                                  ;*****************************
   512                                  
   513                                  ; set linker option
   514                                  ; ds:si points to option char upon entry
   515                                  ; destroys ax,bx,dx,di,es
   516                                  ; updates si
   517                                  
   518                                  set_option  PROC
   519 0000027B 51                          push    cx              ; save critical register
   520 0000027C 89F1                        mov cx,si               ; cx -> start of option
   521 0000027E AC                          lodsb                   ; get option char from command line string
   522 0000027F 3C41                        cmp al,'A'              ; check for out of bounds char value, too low
   523 00000281 7303E9CE00                  jb  so_bad              ; out of bounds
   524 00000286 3C7A                        cmp al,'z'              ; check for out of bounds char value, too high
   525 00000288 7603E9C700                  ja  so_bad              ; out of bounds
   526 0000028D 24DF                        and al,0dfh             ; force char to be uppercase for following compares
   527                                  
   528                                  ; determine the linker option.
   529                                  ; set the option with a nonzero value, for best efficiency use AL as the
   530                                  ; value for Boolean flags since all allowed options are nonzero chars.
   531                                  
   532 0000028F 3C41                        cmp al,'A'              ; maximum Allocated Space option
   533 00000291 7516                        jne so_cla
   534 00000293 8A04                        mov al,[si]             ; peek ahead at next char
   535 00000295 3C73                        cmp al,'s'              ; see if allocated space option
   536 00000297 7407                        je  so_as               ; yes
   537 00000299 3C53                        cmp al,'S'              ; check for uppercase option
   538 0000029B 7403E9B400                  jne so_bad              ; no
   539                                  so_as:
   540 000002A0 A2[0000]                    mov [is_maxparval],al     ; set maximum allocation space flag
   541 000002A3 E8EC02                      call    get_maxpar_size ; get size of allocated space
   542 000002A6 E99E00                      jmp to_cont_opt_chk   ; continue checking options
   543                                  
   544                                  so_cla:
   545 000002A9 3C43                        cmp al,'C'              ; create com file option
   546 000002AB 7403E99A00                  jne so_2
   547                                  
   548 000002B0 8A04                        mov al,[si]             ; peek ahead at next char
   549 000002B2 3C7A                    	cmp al, 'z'
   550 000002B4 7447                    	je so_comzero
   551 000002B6 3C5A                    	cmp al, 'Z'
   552 000002B8 7443                    	je so_comzero
   553 000002BA 3C62                    	cmp al, 'b'
   554 000002BC 744C                    	je so_combig
   555 000002BE 3C42                    	cmp al, 'B'
   556 000002C0 7448                    	je so_combig
   557 000002C2 3C6C                    	cmp al, 'l'
   558 000002C4 7454                    	je so_comseg
   559 000002C6 3C4C                    	cmp al, 'L'
   560 000002C8 7450                    	je so_comseg
   561 000002CA 3C73                    	cmp al, 's'
   562 000002CC 7444                    	je so_comstack
   563 000002CE 3C53                    	cmp al, 'S'
   564 000002D0 7440                    	je so_comstack
   565 000002D2 3C6C                        cmp al,'l'              ; see if clarion or clipper option
   566 000002D4 7406                        je  so_1a               ; possibly
   567 000002D6 3C4C                        cmp al,'L'              ; check uppercase clarion or clipper option
   568                                  ;***IFNDEF DEMO
   569 000002D8 756A                        jne so_com              ; no
   570                                  ;***ELSE
   571 000002DA 7578                        jne so_bad              ; no
   572                                  ;***ENDIF
   573                                  
   574                                  so_1a:
   575 000002DC AC                          lodsb                   ; gobble 2nd char of clarion option
   576 000002DD 8A04                        mov al,[si]             ; peek ahead at next char
   577                                  %IFNDEF DEMO
   578 000002DF 3C61                        cmp al,'a'              ; see if clarion option
   579 000002E1 740E                        je  so_1b               ; yes
   580 000002E3 3C41                        cmp al,'A'              ; check uppercase clarion option
   581 000002E5 740A                        je  so_1b               ; yes
   582                                  %ENDIF
   583 000002E7 3C70                        cmp al,'p'              ; see if clipper option
   584 000002E9 740C                        je  so_clp              ; yes
   585 000002EB 3C50                        cmp al,'P'              ; check uppercase clipper option
   586 000002ED 7565                        jne so_bad              ; no, bad option
   587 000002EF EB06                        jmp SHORT so_clp
   588                                  
   589                                  %IFNDEF DEMO
   590                                  so_1b:
   591 000002F1 AC                          lodsb                   ; gobble 3rd char of clarion option
   592 000002F2 A2[0000]                    mov [is_clarion],al       ; set clarion flag
   593 000002F5 EB50                        jmp SHORT to_cont_opt_chk   ; continue checking options
   594                                  %ENDIF
   595                                  
   596                                  so_clp:
   597 000002F7 E8(0000)                    call    parse_clp_option    ; parse the clipper options
   598 000002FA E96502                      jmp NEAR PTR cont_opt_chk
   599                                  
   600                                  so_comzero:
   601 000002FD 46                      	inc si
   602 000002FE C606[0000]FF            	mov byte [is_comzero_set], -1
   603 00000303 8326[0000]00            	and word [comfile_cut_length], 0
   604 00000308 EB3D                    	jmp to_cont_opt_chk
   605                                  
   606                                  so_combig:
   607 0000030A 46                      	inc si
   608 0000030B C606[0000]FF            	mov byte [is_combig_set], -1
   609 00000310 EB35                    	jmp to_cont_opt_chk
   610                                  
   611                                  so_comstack:
   612 00000312 46                      	inc si
   613 00000313 C606[0000]FF            	mov byte [is_comstack_set], -1
   614 00000318 EB2D                    	jmp to_cont_opt_chk
   615                                  
   616                                  so_comseg:
   617                                   extern _wlcalc_parse_number
   618 0000031A C606[0000]FF            	mov byte [is_comseg_set], -1
   619 0000031F 53                          push    bx              ; save critical register
   620 00000320 52                          push    dx
   621 00000321 51                          push    cx
   622 00000322 46                          inc si                  ; point si past 'L'
   623 00000323 AC                          lodsb                   ; get next char
   624 00000324 3C3D                    	cmp al, '='
   625 00000326 7404                    	je @F
   626 00000328 3C3A                        cmp al,':'
   627 0000032A 7511                        jne .bad_option		; error, not a colon nor equals sign -->
   628                                  @@:
   629                                  
   630 0000032C E8(0000)                    call _wlcalc_parse_number	; get location value
   631 0000032F 720C                        jc .bad_option		; carry flag set, bad value -->
   632                                  
   633 00000331 85D2                    	test dx, dx		; >= 64 Ki ?
   634 00000333 7508                    	jnz .bad_option		; invalid -->
   635 00000335 A3[0000]                	mov word [comseg_relocation_factor], ax
   636                                  				; store it for later use (mlimage1.nas)
   637 00000338 59                          pop cx                  ; restore critical register
   638 00000339 5A                          pop dx
   639 0000033A 5B                          pop bx
   640 0000033B EB0A                    	jmp to_cont_opt_chk
   641                                  
   642                                  .bad_option:
   643 0000033D 59                          pop cx                  ; restore cx -> start of option
   644 0000033E B80500                      mov ax,BAD_OPTION_ERR   ; error value
   645 00000341 E9(0000)                    jmp link_error		; transfer control to error handler
   646                                  
   647                                  so_com:
   648 00000344 A2[0000]                    mov [is_comfile],al       ; set com file flag, AL is known nonzero value
   649                                  to_cont_opt_chk:
   650 00000347 E91802                      jmp NEAR PTR cont_opt_chk
   651                                  
   652                                  so_2:
   653 0000034A 3C44                        cmp al,'D'              ; specify DOSSEG segment ordering/DDL option
   654 0000034C 7509                        jne so_3
   655                                  %IFNDEF DEMO
   656 0000034E E8(0000)                    call    parse_ddl_option    ; either DDL option or DOSSEG option
   657 00000351 E90E02                      jmp NEAR PTR cont_opt_chk
   658                                  %ENDIF
   659                                  
   660                                  ; intermediate jump to bad_option code
   661                                  so_bad:
   662 00000354 E90502                      jmp NEAR PTR bad_option
   663                                  
   664                                  so_3:
   665                                  %IFNDEF DEMO
   666 00000357 3C42                        cmp al,'B'              ; see if beep on exit
   667 00000359 7506                        jne so_4                ; no
   668 0000035B A2[0000]                    mov [is_beep],al          ; set beep flag
   669 0000035E E90102                      jmp NEAR PTR cont_opt_chk
   670                                  %ENDIF
   671                                  
   672                                  so_4:
   673 00000361 3C4D                        cmp al,'M'              ; create map file option
   674 00000363 7514                        jne so_5
   675 00000365 A2[0000]                    mov [is_mapfile],al       ; set map file flag
   676                                  
   677 00000368 8A04                        mov al,[si]             ; peek ahead at next char
   678 0000036A 3C78                        cmp al,'x'              ; see if expanded map file option
   679 0000036C 7404                        je  so_4a               ; yes
   680 0000036E 3C58                        cmp al,'X'              ; check uppercase expanded map file option
   681 00000370 7504                        jne to_cont_opt         ; no
   682                                  
   683                                  so_4a:
   684 00000372 AC                          lodsb                   ; gobble expanded map option char
   685 00000373 A2[0000]                    mov [is_mapexpand],al     ; set expanded map file flag
   686                                  
   687                                  to_cont_opt:
   688 00000376 E9E901                      jmp NEAR PTR cont_opt_chk
   689                                  
   690                                  so_5:
   691 00000379 3C54                        cmp al,'T'              ; see if possible temporary file option
   692 0000037B 7556                        jne so_6                ; no
   693 0000037D 8A04                        mov al,[si]             ; peek ahead at next char
   694 0000037F 3C6C                    	cmp al, 'l'
   695 00000381 7440                    	je so_list_file
   696 00000383 3C4C                    	cmp al, 'L'
   697 00000385 743C                    	je so_list_file
   698 00000387 3C6F                    	cmp al, 'o'
   699 00000389 7428                    	je so_obj_file
   700 0000038B 3C4F                    	cmp al, 'O'
   701 0000038D 7424                    	je so_obj_file
   702 0000038F 3C7A                    	cmp al, 'z'		; Zwang
   703 00000391 7418                    	je so_temp_forced
   704 00000393 3C5A                    	cmp al, 'Z'
   705 00000395 7414                    	je so_temp_forced
   706 00000397 3C66                        cmp al,'f'              ; see if temporary file name option
   707 00000399 7404                        je  so_tfile            ; yes
   708 0000039B 3C46                        cmp al,'F'              ; check for uppercase option
   709 0000039D 75B5                        jne so_bad              ; no
   710                                  
   711                                  so_tfile:
   712 0000039F AC                          lodsb                   ; gobble second char
   713 000003A0 AC                          lodsb                   ; get colon
   714 000003A1 3C3A                        cmp al,':'              ; must be colon
   715 000003A3 75AF                        jne so_bad              ; not a colon
   716 000003A5 E8EE09                      call    get_tempfile_name   ; get the temporary file name
   717 000003A8 E9B701                      jmp NEAR PTR cont_opt_chk
   718                                  
   719                                  so_temp_forced:
   720 000003AB 46                      	inc si
   721 000003AC C606[0000]FF            	mov byte [is_temp_forced], -1
   722 000003B1 EB94                    	jmp to_cont_opt_chk
   723                                  
   724                                  so_obj_file:
   725 000003B3 AC                      	lodsb
   726 000003B4 AC                      	lodsb
   727 000003B5 3C3D                    	cmp al, '='
   728 000003B7 7404                    	je @F
   729 000003B9 3C3A                    	cmp al, ':'
   730 000003BB 7597                    	jne so_bad
   731                                  @@:
   732 000003BD E8C609                  	call get_wllist_obj_file_name
   733 000003C0 E99F01                  	jmp cont_opt_chk
   734                                  
   735                                  so_list_file:
   736 000003C3 AC                      	lodsb
   737 000003C4 AC                      	lodsb
   738 000003C5 3C3D                    	cmp al, '='
   739 000003C7 7404                    	je @F
   740 000003C9 3C3A                    	cmp al, ':'
   741 000003CB 7587                    	jne so_bad
   742                                  @@:
   743 000003CD E8BB09                  	call get_wllist_temp_file_name
   744 000003D0 E98F01                  	jmp cont_opt_chk
   745                                  
   746                                  so_6:
   747 000003D3 3C53                        cmp al,'S'              ; make symbols case sensitive, set stack, or sympac option
   748 000003D5 7532                        jne so_info
   749 000003D7 8A24                        mov ah,[si]             ; peek ahead at next char
   750 000003D9 80FC54                      cmp ah,'T'              ; see if set stack option
   751 000003DC 7405                        je  so_stack
   752 000003DE 80FC74                      cmp ah,'t'              ; check if lowercase set stack option
   753 000003E1 750A                        jne so_checksp          ; no
   754                                  
   755                                  so_stack:
   756 000003E3 8826[0000]                  mov [is_stackval],ah      ; set stack value set flag
   757 000003E7 E88401                      call    get_stack_size  ; get size of stack
   758 000003EA E97501                      jmp NEAR PTR cont_opt_chk
   759                                  
   760                                  so_checksp:
   761 000003ED 80FC50                      cmp ah,'P'              ; see if symbol table compaction option
   762 000003F0 7405                        je  so_sympac
   763 000003F2 80FC70                      cmp ah,'p'              ; check if lowercase
   764 000003F5 750C                        jne so_case             ; no, case sensitive flag
   765                                  
   766                                  so_sympac:
   767 000003F7 A2[0000]                    mov [is_sympac],al		; set symbol pack flag
   768 000003FA C606[0000]00            	mov	byte [is_clpinc],0			; kill incremental linking
   769 000003FF 46                          inc si                  ; point si past 'P'
   770 00000400 E95F01                      jmp NEAR PTR cont_opt_chk
   771                                  
   772                                  so_case:
   773                                  %IFNDEF DEMO
   774 00000403 A2[0000]                    mov [is_casesense],al     ; set case sensitive flag
   775 00000406 E95901                      jmp NEAR PTR cont_opt_chk
   776                                  %ENDIF
   777                                  
   778                                  so_info:
   779 00000409 3C49                        cmp al,'I'              ; see if print linker info
   780 0000040B 7506                        jne so_7                ; no
   781 0000040D A2[0000]                    mov [is_linkinfo],al      ; set info flag
   782 00000410 E94F01                      jmp NEAR PTR cont_opt_chk
   783                                  
   784                                  so_7:
   785 00000413 3C4F                        cmp al,'O'              ; Overlay option
   786 00000415 7506                        jne so_udl
   787 00000417 E8(0000)                    call    parse_ovl_option
   788 0000041A E94501                      jmp NEAR PTR cont_opt_chk
   789                                  
   790                                  so_udl:
   791                                  %IFNDEF DEMO
   792 0000041D 3C55                        cmp al,'U'              ; possible Use Dynamic Libraries option
   793 0000041F 7506                        jne so_8
   794 00000421 E8000A                      call    parse_udl_option
   795 00000424 E93B01                      jmp NEAR PTR cont_opt_chk
   796                                  %ENDIF
   797                                  
   798                                  so_8:
   799 00000427 3C4E                        cmp al,'N'              ; No default libraries option
   800 00000429 7514                        jne so_9
   801 0000042B 8A04                        mov al,[si]             ; peek ahead at next char
   802 0000042D 3C64                        cmp al,'d'              ; see if no default libraries option
   803 0000042F 7407                        je  so_nodef            ; yes
   804 00000431 3C44                        cmp al,'D'              ; check for uppercase option
   805 00000433 7403E92401                  jne bad_option          ; no
   806                                  
   807                                  so_nodef:
   808 00000438 AC                          lodsb                   ; gobble second char
   809 00000439 A2[0000]                    mov [is_nodeflib],al      ; set no default libraries flag
   810 0000043C E92301                      jmp cont_opt_chk
   811                                  
   812                                  so_9:
   813                                  %IFNDEF DEMO
   814 0000043F 3C45                        cmp al,'E'              ; extended libraries option, maybe, needs second char
   815 00000441 7514                        jne so_chkquick
   816 00000443 8A04                        mov al,[si]             ; peek ahead at next char
   817 00000445 3C6D                        cmp al,'m'              ; see if Microsoft extended library option
   818 00000447 7407                        je  so_9a               ; yes
   819 00000449 3C4D                        cmp al,'M'              ; check for uppercase option
   820 0000044B 7403E90C01                  jne bad_option          ; no
   821                                  so_9a:
   822 00000450 AC                          lodsb                   ; gobble second char
   823 00000451 A2[0000]                    mov [is_msextlib],al      ; set Microsoft extended library flag
   824 00000454 E90B01                      jmp cont_opt_chk
   825                                  %ENDIF
   826                                  
   827                                  so_chkquick:
   828 00000457 3C51                        cmp al,'Q'				; maybe quick linker option
   829 00000459 7516                        jne so_10
   830 0000045B 8A04                        mov al,[si]				; peek ahead at next char
   831 0000045D 3C6C                        cmp al,'l'
   832 0000045F 7407                        je  so_quicka			; yes
   833 00000461 3C4C                        cmp al,'L'				; check for uppercase option
   834 00000463 7403E9F400                  jne bad_option			; no
   835                                  so_quicka:
   836 00000468 AC                          lodsb
   837 00000469 C606[0000]58                mov byte [is_quick],'X'		; set quick linker flag, unknown reading or writing
   838 0000046E E9F100                      jmp cont_opt_chk
   839                                  
   840                                  so_10:
   841 00000471 3C52                        cmp al,'R'              ; reload active swapped out overlays option
   842 00000473 7506                        jne so_expand
   843 00000475 A2[0000]                    mov [is_reload],al        ; set reload overlays flag
   844 00000478 E9E700                      jmp cont_opt_chk
   845                                  
   846                                  so_expand:
   847 0000047B 3C58                        cmp al,'X'              ; expanded/extended memory use, maybe
   848 0000047D 7403E9A000                  jne so_warn
   849 00000482 AC                          lodsb                   ; get next char
   850 00000483 3C70                        cmp al,'p'              ; see if expanded memory use
   851 00000485 7404                        je  so_ems              ; yes
   852 00000487 3C50                        cmp al,'P'              ; check for uppercase option
   853 00000489 7508                        jne so_chkxms           ; no
   854                                  so_ems:
   855 0000048B C606[0000]00                mov byte [is_no_ems],0         ; reset no use of EMS flag
   856 00000490 E9CF00                      jmp cont_opt_chk
   857                                  
   858                                  so_chkxms:
   859 00000493 3C74                        cmp al,'t'              ; see if extended memory use
   860 00000495 7404                        je  so_xms              ; yes
   861 00000497 3C54                        cmp al,'T'              ; check for uppercase option
   862 00000499 7506                        jne so_check_xc         ; no
   863                                  so_xms:
   864 0000049B A2[0000]                    mov [is_xms],al           ; set XMS flag
   865 0000049E E9C100                      jmp cont_opt_chk
   866                                  
   867                                  so_check_xc:
   868 000004A1 3C63                        cmp al,'c'
   869 000004A3 7404                        je  so_xc
   870 000004A5 3C43                        cmp al,'C'
   871 000004A7 751B                        jne so_check_xe
   872                                  so_xc:
   873 000004A9 8A04                    	mov al, [si]
   874 000004AB 3C77                    	cmp al, 'w'
   875 000004AD 740C                    	je .warn
   876 000004AF 3C57                    	cmp al, 'W'
   877 000004B1 7408                    	je .warn
   878 000004B3 C606[0000]FF                mov byte [is_wlcalc_enabled], -1
   879 000004B8 E9A700                      jmp cont_opt_chk
   880                                  
   881                                  .warn:
   882 000004BB 46                      	inc si
   883 000004BC C606[0000]FF            	mov byte [is_wlcalc_error_as_warning], -1
   884 000004C1 E99E00                  	jmp cont_opt_chk
   885                                  
   886                                  so_check_xe:
   887 000004C4 3C65                        cmp al,'e'
   888 000004C6 7404                        je  so_xe
   889 000004C8 3C45                        cmp al,'E'
   890 000004CA 7508                        jne so_check_xa
   891                                  so_xe:
   892 000004CC C606[0000]FF                mov byte [is_wlemitalign_enabled], -1
   893 000004D1 E98E00                      jmp cont_opt_chk
   894                                  
   895                                  so_check_xa:
   896 000004D4 3C61                        cmp al,'a'
   897 000004D6 7404                        je  so_xa
   898 000004D8 3C41                        cmp al,'A'
   899 000004DA 7507                        jne so_check_xs
   900                                  so_xa:
   901 000004DC C606[0000]FF                mov byte [is_wlemitalign_enabled], -1
   902 000004E1 EBC6                        jmp so_xc
   903                                  
   904                                  so_check_xs:
   905 000004E3 3C73                        cmp al,'s'
   906 000004E5 7404                        je  so_xs
   907 000004E7 3C53                        cmp al,'S'
   908 000004E9 7507                        jne so_check_xl
   909                                  so_xs:
   910 000004EB C606[0000]FF                mov byte [is_wllist_preserve_enabled], -1
   911 000004F0 EB70                        jmp cont_opt_chk
   912                                  
   913                                  so_check_xl:
   914 000004F2 3C6C                        cmp al,'l'
   915 000004F4 7404                        je  so_xl
   916 000004F6 3C4C                        cmp al,'L'
   917 000004F8 7562                        jne bad_option
   918                                  so_xl:
   919 000004FA 8A04                    	mov al, [si]
   920 000004FC 3C64                    	cmp al, 'd'
   921 000004FE 741B                    	je so_xd
   922 00000500 3C44                    	cmp al, 'D'
   923 00000502 7417                    	je so_xd
   924 00000504 3C77                    	cmp al, 'w'
   925 00000506 740B                    	je .warn
   926 00000508 3C57                    	cmp al, 'W'
   927 0000050A 7407                    	je .warn
   928 0000050C C606[0000]FF                mov byte [is_wllist_enabled], -1
   929 00000511 EB4F                        jmp cont_opt_chk
   930                                  
   931                                  .warn:
   932 00000513 46                      	inc si
   933 00000514 C606[0000]FF            	mov byte [is_wllist_error_as_warning], -1
   934 00000519 EB47                    	jmp cont_opt_chk
   935                                  
   936                                  so_xd:
   937 0000051B 46                      	inc si
   938 0000051C FE06[0000]                  inc byte [_wllist_debug_flag]
   939 00000520 EB40                        jmp cont_opt_chk
   940                                  
   941                                  so_warn:
   942 00000522 3C57                        cmp al,'W'              ; disable warnings or generate 0 exit code for warnings
   943 00000524 7536                        jne bad_option
   944 00000526 AC                          lodsb                   ; get second char
   945 00000527 3C53                    	cmp al, 'S'
   946 00000529 741A                    	je so_stack_warning
   947 0000052B 3C73                    	cmp al, 's'
   948 0000052D 7416                    	je so_stack_warning
   949                                  
   950                                  %IFNDEF DEMO
   951 0000052F 3C4E                        cmp al,'N'              ; see if disable warnings option
   952 00000531 740D                        je  so_diswarn          ; yes
   953 00000533 3C6E                        cmp al,'n'              ; check if lowercase disable warnings option
   954 00000535 7409                        je  so_diswarn          ; yes
   955                                  %ENDIF
   956 00000537 3C30                        cmp al,'0'              ; see if warnings exit code of 0 option
   957 00000539 7521                        jne bad_option          ; no, bad option
   958                                  
   959                                  ; set warnings generate exit code of 0 option
   960                                  so_warnzero:
   961 0000053B A2[0000]                    mov [is_exit0],al
   962 0000053E EB22                        jmp cont_opt_chk
   963                                  
   964                                  ; set disable warnings flag
   965                                  so_diswarn:
   966 00000540 A2[0000]                    mov [is_nowarn],al
   967 00000543 EB1D                        jmp cont_opt_chk
   968                                  
   969                                  so_stack_warning:
   970 00000545 AC                      	lodsb
   971 00000546 3C4E                        cmp al,'N'              ; see if disable warnings option
   972 00000548 740D                        je  so_stack_diswarn          ; yes
   973 0000054A 3C6E                        cmp al,'n'              ; check if lowercase disable warnings option
   974 0000054C 7409                        je  so_stack_diswarn          ; yes
   975 0000054E 3C30                        cmp al,'0'              ; see if warnings exit code of 0 option
   976 00000550 750A                        jne bad_option          ; no, bad option
   977                                  
   978                                  so_stack_warnzero:
   979 00000552 A2[0000]                    mov [is_stack_exit0],al
   980 00000555 EB0B                        jmp cont_opt_chk
   981                                  
   982                                  so_stack_diswarn:
   983 00000557 A2[0000]                    mov [is_stack_nowarn],al
   984 0000055A EB06                        jmp cont_opt_chk
   985                                  
   986                                  ; no valid options left
   987                                  bad_option:                 ; bad option specified
   988 0000055C B80500                      mov ax,BAD_OPTION_ERR   ; error value
   989 0000055F E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   990                                  
   991                                  cont_opt_chk:               ; check for non-whitespace chars after option
   992 00000562 8A04                        mov al,[si]             ; peek ahead at following char
   993 00000564 3C2F                        cmp al,'/'              ; if another option then okay
   994 00000566 7404                        je  so_ret
   995 00000568 3C20                        cmp al,' '              ; if zero or whitespace then okay
   996 0000056A 77F0                        ja  bad_option          ; non-whitespace, non-option char follows, bad option
   997                                  
   998                                  so_ret:
   999 0000056C 59                          pop cx                  ; restore critical register
  1000 0000056D C3                          ret
  1001                                  set_option  ENDP
  1002                                  
  1003                                  ;*****************************
  1004                                  ;* GET_STACK_SIZE            *
  1005                                  ;*****************************
  1006                                  
  1007                                  ; get size of stack specified on command line
  1008                                  ; ds:si -> 'T' ('t') upon entry, cx -> start of option
  1009                                  ; destroys ax
  1010                                  ; updates si
  1011                                  
  1012                                  get_stack_size  PROC
  1013 0000056E 53                          push    bx              ; save critical register
  1014 0000056F 52                          push    dx
  1015 00000570 51                          push    cx
  1016 00000571 46                          inc si                  ; point si past 'T'
  1017 00000572 AC                          lodsb                   ; get next char
  1018 00000573 3C3A                        cmp al,':'              ; should always be a colon
  1019 00000575 7514                        jne gss_bad_option      ; error, not a colon
  1020                                  
  1021 00000577 E83400                      call    get_int_value   ; get value of stack size
  1022 0000057A 720F                        jc  gss_bad_option      ; carry flag set, bad value
  1023                                  
  1024 0000057C 83C001                      add ax,1
  1025 0000057F 83E0FE                      and ax,0fffeh           ; make value even, round up
  1026 00000582 7407                        je  gss_bad_option      ; value was either 0 or 65535, bad value
  1027 00000584 A3[0000]                    mov [stack_value],ax      ; save value
  1028                                  
  1029                                  gss_ret:
  1030 00000587 59                          pop cx                  ; restore critical register
  1031 00000588 5A                          pop dx
  1032 00000589 5B                          pop bx
  1033 0000058A C3                          ret
  1034                                  
  1035                                  gss_bad_option:
  1036 0000058B 59                          pop cx                  ; restore cx -> start of option
  1037 0000058C B80500                      mov ax,BAD_OPTION_ERR   ; error value
  1038 0000058F E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1039                                  
  1040                                  get_stack_size  ENDP
  1041                                  
  1042                                  ;*****************************
  1043                                  ;* GET_MAXPAR_SIZE           *
  1044                                  ;*****************************
  1045                                  
  1046                                  ; get size of maximum paragraph allocation specified on command line
  1047                                  ; ds:si -> 'S' ('s') upon entry, cx -> start of option
  1048                                  ; destroys ax
  1049                                  ; updates si
  1050                                  
  1051                                  get_maxpar_size  PROC
  1052 00000592 53                          push    bx              ; save critical register
  1053 00000593 52                          push    dx
  1054 00000594 51                          push    cx
  1055 00000595 46                          inc si                  ; point si past 'S'
  1056 00000596 AC                          lodsb                   ; get next char
  1057 00000597 3C3A                        cmp al,':'              ; should always be a colon
  1058 00000599 750C                        jne gms_bad_option      ; error, not a colon
  1059                                  
  1060 0000059B E81000                      call    get_int_value   ; get value of stack size
  1061 0000059E 7207                        jc  gms_bad_option      ; carry flag set, bad value
  1062                                  
  1063 000005A0 A3[0000]                    mov [maxpar_value],ax     ; save value
  1064                                  
  1065 000005A3 59                          pop cx                  ; restore critical register
  1066 000005A4 5A                          pop dx
  1067 000005A5 5B                          pop bx
  1068 000005A6 C3                          ret
  1069                                  
  1070                                  gms_bad_option:
  1071 000005A7 59                          pop cx                  ; restore cx -> start of option
  1072 000005A8 B80500                      mov ax,BAD_OPTION_ERR   ; error value
  1073 000005AB E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1074                                  
  1075                                  get_maxpar_size  ENDP
  1076                                  
  1077                                  ;*****************************
  1078                                  ;* GET_INT_VALUE             *
  1079                                  ;*****************************
  1080                                  
  1081                                  ; get int (0-65535) value from command line, return in ax
  1082                                  ; return carry flag set if invalid value, reset if valid
  1083                                  ; upon entry ds:si-> first digit
  1084                                  ; destroys ax,bx,cx,dx
  1085                                  ; updates si
  1086                                  
  1087                                   global get_int_value
  1088                                  get_int_value   PROC
  1089 000005AE 31C9                        xor cx,cx               ; cx will hold count of digits
  1090 000005B0 BB[1102]                    mov bx,OFFSET tbuff wrt DGROUP  ; bx -> buffer to hold digits
  1091                                  
  1092                                  giv_scanloop:
  1093 000005B3 AC                          lodsb                   ; get number
  1094 000005B4 3C30                        cmp al,'0'              ; see if nondigit
  1095 000005B6 7211                        jb  giv_done            ; yes, done
  1096 000005B8 3C39                        cmp al,'9'              ; see if nondigit
  1097 000005BA 770D                        ja  giv_done            ; yes
  1098 000005BC 41                          inc cx                  ; bump count of digits
  1099 000005BD 83F905                      cmp cx,5                ; check bounds
  1100 000005C0 7726                        ja  giv_badval          ; more than five digits, bad value
  1101 000005C2 240F                        and al,0fh              ; strip ASCII value
  1102 000005C4 8807                        mov [bx],al             ; save digit
  1103 000005C6 43                          inc bx                  ; bump to next save char slot
  1104 000005C7 EBEA                        jmp SHORT giv_scanloop  ; loop for next
  1105                                  
  1106                                  giv_done:
  1107 000005C9 4E                          dec si                  ; drop si back to -> nondigit char
  1108 000005CA BB[1102]                    mov bx,OFFSET tbuff wrt DGROUP  ; bx -> buffer holding digits
  1109 000005CD 31C0                        xor ax,ax               ; ax holds value
  1110                                  
  1111                                  giv_mulloop:
  1112 000005CF 8A17                        mov dl,[bx]             ; get char value
  1113 000005D1 30F6                        xor dh,dh               ; zero high byte
  1114 000005D3 01D0                        add ax,dx               ; add to previous stack value
  1115 000005D5 7211                        jc  giv_badval          ; overflow, value too large
  1116 000005D7 49                          dec cx                  ; drop count of digits
  1117 000005D8 E30C                        jcxz    giv_goodval     ; all done
  1118 000005DA BA0A00                      mov dx,10
  1119 000005DD F7E2                        mul dx                  ; shift value by 1 digit (*10)
  1120 000005DF 09D2                        or  dx,dx               ; check if overflow
  1121 000005E1 7505                        jne giv_badval          ; overflow occurred
  1122 000005E3 43                          inc bx                  ; move to next digit
  1123 000005E4 EBE9                        jmp SHORT giv_mulloop   ; add in value of next digit
  1124                                  
  1125                                  giv_goodval:
  1126 000005E6 F8                          clc                     ; clear carry flag to indicate good number
  1127 000005E7 C3                          ret
  1128                                  
  1129                                  giv_badval:
  1130 000005E8 F9                          stc                     ; set carry flag ot indicate bad number
  1131 000005E9 C3                          ret
  1132                                  get_int_value   ENDP
  1133                                  
  1134                                  ;*****************************
  1135                                  ;* DEPLUS                    *
  1136                                  ;*****************************
  1137                                  
  1138                                  ; remove plus signs from passed command line string
  1139                                  ; ds:si point to string upon entry
  1140                                  ; destroys ax,si
  1141                                  
  1142                                  deplus      PROC
  1143                                  dp2:
  1144 000005EA AC                          lodsb                   ; get char from command line string
  1145 000005EB 08C0                        or  al,al               ; if zero then end of command line string
  1146 000005ED 7414                        je  dp4
  1147 000005EF 3C0D                        cmp al,CR               ; if carriage return then end of command line string
  1148 000005F1 7506                        jne dp3                 ; not a carriage return
  1149 000005F3 C644FF00                    mov BYTE PTR [si-1],0   ; replace carriage return with null terminator
  1150 000005F7 EB0A                        jmp SHORT dp4           ; flag from CR compare, end of command line string
  1151                                  dp3:
  1152 000005F9 3C2B                        cmp al,'+'              ; replace plus signs with spaces
  1153 000005FB 75ED                        jne dp2
  1154 000005FD C644FF20                    mov BYTE PTR [si-1],' ' ; replace with space
  1155 00000601 EBE7                        jmp SHORT dp2
  1156                                  dp4:
  1157 00000603 C3                          ret
  1158                                  deplus      ENDP
  1159                                  
  1160                                  ;*****************************
  1161                                  ;* USE_RSP                   *
  1162                                  ;*****************************
  1163                                  
  1164                                  ; use response file
  1165                                  ; ds:si points to first filename char upon entry
  1166                                  ; destroys ax,bx,cx,dx,di,es
  1167                                  ; return cl == nonzero if parsing termination occurred (';' or
  1168                                  ;   all phases encountered), cl ==0 if not
  1169                                  ; updates si past file name
  1170                                  
  1171                                  use_rsp     PROC
  1172 00000604 AC                          lodsb                   ; point at first char of file name
  1173 00000605 E85F01                      call    get_file_name   ; setup filename string
  1174 00000608 56                          push    si              ; save si -> first char after file name
  1175 00000609 BA[1400]                    mov dx,OFFSET parfilename wrt DGROUP	; ds:dx -> ASCIIZ file specification
  1176 0000060C B8003D                      mov ax,3d00h            ; open file for read access
  1177 0000060F CD21                        int 21h
  1178 00000611 7303                        jnc ur_1                ; no error opening file
  1179 00000613 E9(0000)                    jmp NEAR PTR dos_error  ; error opening file
  1180                                  
  1181                                  ur_1:
  1182 00000616 A3[1000]                    mov [rsp_handle],ax       ; save response file handle
  1183                                  
  1184                                  ur_readloop:
  1185 00000619 30C0                        xor al,al
  1186 0000061B A2[0C00]                    mov [plus_flag],al        ; reset plus flag
  1187 0000061E A2[0D00]                    mov [comma_flag],al       ; reset comma flag
  1188 00000621 A2[0E00]                    mov [comment_flag],al     ; reset comment flag
  1189 00000624 8B1E[1000]                  mov bx,[rsp_handle]
  1190 00000628 B98000                      mov cx,128              ; number of bytes to read
  1191 0000062B BA[9400]                    mov dx,OFFSET rsp_line wrt DGROUP   ; buffer to dump bytes read from response file
  1192 0000062E B43F                        mov ah,3fh              ; read file (no short read error)
  1193 00000630 CD21                        int 21h
  1194 00000632 7306                        jnc ur_2                ; no error reading file
  1195 00000634 BA[1400]                    mov dx,OFFSET parfilename wrt DGROUP
  1196 00000637 E9(0000)                    jmp NEAR PTR dos_error  ; error reading file
  1197                                  
  1198                                  ur_2:
  1199 0000063A 09C0                        or  ax,ax               ; check if at end of file
  1200 0000063C 7503                        jne ur_2a               ; no
  1201                                  to_ur_no_term:
  1202 0000063E E91A01                      jmp NEAR PTR ur_no_term ; yes
  1203                                  
  1204                                  ur_2a:
  1205 00000641 89C1                        mov cx,ax               ; keep count of read chars
  1206 00000643 BE[9400]                    mov si,OFFSET rsp_line wrt DGROUP   ; point to base of response file line
  1207                                  
  1208 00000646 803C23                      cmp BYTE PTR [si],'#'   ; see if comment line
  1209 00000649 7505                        jne ur_notcomment       ; no
  1210 0000064B C606[0E00]01                mov byte [comment_flag],1      ; flag comment line
  1211                                  
  1212                                  ur_notcomment:
  1213 00000650 3D8000                      cmp ax,128              ; see if all chars were read in line
  1214 00000653 740C                        je  ur_eol_chk          ; yes, bypass next char slot code
  1215 00000655 89F2                        mov dx,si               ; save -> base of response file line
  1216 00000657 01C6                        add si,ax               ; si -> first char slot past last read-in char
  1217 00000659 C60400                      mov BYTE PTR [si],0     ; zero terminate response file line
  1218 0000065C 89D6                        mov si,dx               ; restore si -> base of response file line
  1219 0000065E EB01                        jmp SHORT ur_eol_chk    ; bypass next char slot code
  1220                                  
  1221                                  ur_next_char:
  1222 00000660 46                          inc si                  ; point to next char
  1223                                  
  1224                                  ur_eol_chk:
  1225 00000661 81FE[1301]                  cmp si,OFFSET rsp_line+127 wrt DGROUP
  1226 00000665 7206                        jb  ur_3                ; no
  1227                                  
  1228                                  ; response line longer than 127 characters (not counting CR/LF)
  1229 00000667 B82100                      mov ax,RSP_LINE_ERR     ; response line too long
  1230 0000066A E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1231                                  
  1232                                  ur_3:
  1233 0000066D 8A04                        mov al,[si]
  1234 0000066F 08C0                        or  al,al               ; zero char means end of file reached
  1235 00000671 74CB                        je  to_ur_no_term       ; route to end of parse routine jump
  1236                                  
  1237 00000673 3C0D                        cmp al,CR               ; check for carriage return, end of line
  1238 00000675 7545                        jne ur_4
  1239                                  
  1240 00000677 46                          inc si                  ; bump to account for line feed char
  1241 00000678 30C0                        xor al,al
  1242 0000067A 3806[0E00]                  cmp [comment_flag],al     ; see if comment line
  1243 0000067E 751B                        jne ur_rewind_chk       ; yes, don't modify argument type
  1244 00000680 3806[0C00]                  cmp [plus_flag],al        ; see if line ended with '+' continuation char
  1245 00000684 7515                        jne ur_rewind_chk       ; yes, argument type remains the same
  1246 00000686 3806[0D00]                  cmp [comma_flag],al       ; see if line ended with comma (next argument type already set)
  1247 0000068A 750F                        jne ur_rewind_chk       ; yes, argument type already updated
  1248                                  
  1249                                  ; no line continuation character or previous comma update, move to next argument type
  1250 0000068C A0[0100]                    mov al,[arg_type]         ; get previous arg_type value
  1251 0000068F FEC0                        inc al                  ; bump it up one
  1252 00000691 A2[0100]                    mov [arg_type],al         ; save back to memory variable
  1253 00000694 3C05                        cmp al,5                ; check bounds
  1254 00000696 7203                        jb  ur_rewind_chk       ; within bounds, continue parsing
  1255 00000698 E9AB00                      jmp NEAR PTR ur_terminate   ; out of bounds (beyond .lib), flag termination of parsing
  1256                                  
  1257                                  ur_rewind_chk:
  1258 0000069B B8[9300]                    mov ax,OFFSET rsp_line-1 wrt DGROUP ; get base of buffer less 1
  1259 0000069E 01C8                        add ax,cx               ; compute end of last read
  1260 000006A0 39F0                        cmp ax,si               ; see if CR/LF was at end of last read
  1261 000006A2 7703                        ja  ur_endlogic         ; no, rewind file
  1262 000006A4 E972FF                      jmp NEAR PTR ur_readloop    ; yes, get next line, if any
  1263                                  
  1264                                  ; end of logical line reached before end of physical line, rewind file to end of logical line
  1265                                  ur_endlogic:
  1266 000006A7 29F0                        sub ax,si               ; see how many bytes to rewind file
  1267 000006A9 89C2                        mov dx,ax               ; dx holds file offset low word
  1268 000006AB F7DA                        neg dx                  ; make it a negative number
  1269 000006AD B9FFFF                      mov cx,0ffffh           ; sign extend thru cx
  1270 000006B0 8B1E[1000]                  mov bx,[rsp_handle]       ; get response file handle
  1271 000006B4 B80142                      mov ax,4201h            ; move file pointer from current location
  1272 000006B7 CD21                        int 21h                 ; rewind file
  1273 000006B9 E95DFF                      jmp NEAR PTR ur_readloop
  1274                                  
  1275                                  ur_4:
  1276 000006BC 803E[0E00]00                cmp byte [comment_flag],0      ; see if comment line
  1277 000006C1 759D                        jne ur_next_char        ; yes, don't parse line, just gobble chars
  1278 000006C3 3C2B                        cmp al,'+'              ; see if plus sign concatenator
  1279 000006C5 7507                        jne ur_5                ; no
  1280 000006C7 C606[0C00]01                mov byte [plus_flag],1         ; flag a plus sign in case of line continuation
  1281 000006CC EB92                        jmp SHORT ur_next_char  ; get next char in response line
  1282                                  
  1283                                  ur_5:
  1284 000006CE 3C20                        cmp al,' '              ; see if whitespace char
  1285 000006D0 768E                        jbe ur_next_char        ; yes
  1286                                  
  1287 000006D2 3C2C                        cmp al,','              ; see if comma, next argument type indicator
  1288 000006D4 7514                        jne ur_6                ; no
  1289                                  
  1290 000006D6 C606[0D00]01                mov byte [comma_flag],1        ; flag a comma in case of no further arguments on line
  1291 000006DB A0[0100]                    mov al,[arg_type]         ; get previous arg_type value
  1292 000006DE FEC0                        inc al                  ; bump it up one
  1293 000006E0 A2[0100]                    mov [arg_type],al         ; save back to memory variable
  1294 000006E3 3C05                        cmp al,5                ; check bounds
  1295 000006E5 735F                        jae ur_terminate        ; out of bounds (beyond .lib), flag termination of parsing
  1296 000006E7 E976FF                      jmp NEAR PTR ur_next_char   ; within bounds, continue parsing
  1297                                  
  1298                                  ur_6:
  1299 000006EA 3C2F                        cmp al,'/'              ; see if option char
  1300 000006EC 7507                        jne ur_7                ; no
  1301 000006EE 46                          inc si                  ; set si up for set_option procedure
  1302 000006EF E889FB                      call    set_option      ; set the option
  1303 000006F2 E96CFF                      jmp NEAR PTR ur_eol_chk
  1304                                  
  1305                                  ur_7:
  1306 000006F5 3C28                        cmp al,'('              ; see if left paren, begin nonvectored root call overlay
  1307 000006F7 7404                        je  ur_ovlchk           ; yes
  1308 000006F9 3C5B                        cmp al,'['              ; see if left bracket, begin overlay
  1309 000006FB 751E                        jne ur_8                ; no
  1310                                  
  1311                                  ur_ovlchk:
  1312 000006FD 803E[0000]00                cmp byte [in_overlay],0        ; check flag to make sure not already in an overlay
  1313 00000702 7406                        je  ur_7a               ; no
  1314                                  
  1315                                  ; nested parens
  1316 00000704 B80300                      mov ax,NEST_PAREN_ERR
  1317 00000707 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1318                                  
  1319                                  ur_7a:
  1320 0000070A C606[0000]80                mov byte [in_overlay],80h      ; set flag
  1321 0000070F 3C28                        cmp al,'('              ; see if nonvectored root call overlay
  1322 00000711 7505                        jne ur_7b               ; no
  1323 00000713 800E[0000]40                or  byte [in_overlay],40h      ; set nonvectored root call flag
  1324                                  
  1325                                  ur_7b:
  1326 00000718 E945FF                      jmp NEAR PTR ur_next_char
  1327                                  
  1328                                  ur_8:
  1329 0000071B 3C5D                        cmp al,']'              ; see if right bracket, end overlay
  1330 0000071D 7404                        je  ur_endchk           ; yes
  1331 0000071F 3C29                        cmp al,')'              ; see if right paren, end overlay
  1332 00000721 7515                        jne ur_at_chk           ; no
  1333                                  
  1334                                  ur_endchk:
  1335 00000723 803E[0000]00                cmp byte [in_overlay],0        ; check flag to make sure in overlay
  1336 00000728 7506                        jne ur_8a               ; yes
  1337                                  
  1338                                  ; improperly matched parenthesis, fatal error
  1339 0000072A B80200                      mov ax,UNM_RIGHT_PAREN_ERR
  1340 0000072D E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1341                                  
  1342                                  ur_8a:
  1343 00000730 C606[0000]00                mov byte [in_overlay],0        ; reset flag
  1344 00000735 E928FF                      jmp NEAR PTR ur_next_char
  1345                                  
  1346                                  ur_at_chk:
  1347 00000738 3C40                        cmp al,'@'              ; see if @ (nested response file)
  1348 0000073A 7506                        jne ur_semi_chk         ; no
  1349                                  
  1350                                  ; attempt to nest response files
  1351 0000073C B82200                      mov ax,RSP_NEST_ERR     ; cannot nest response files, fatal error
  1352 0000073F E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  1353                                  
  1354                                  ur_semi_chk:
  1355 00000742 3C3B                        cmp al,';'              ; see if semicolon terminator
  1356 00000744 7504                        jne ur_file_chk         ; no
  1357                                  
  1358                                  ur_terminate:
  1359 00000746 B101                        mov cl,1                ; flag that parsing termination occurred
  1360 00000748 EB13                        jmp SHORT ur_out        ; and exit
  1361                                  
  1362                                  ; check if valid file name
  1363                                  ur_file_chk:
  1364 0000074A 46                          inc si                  ; set si up for parse_file_type procedure
  1365 0000074B E83700                      call    parse_file_type
  1366 0000074E C606[0C00]00                mov byte [plus_flag],0         ; reset plus flag
  1367 00000753 C606[0D00]00                mov byte [comma_flag],0        ; reset comma flag
  1368 00000758 E906FF                      jmp NEAR PTR ur_eol_chk
  1369                                  
  1370                                  ur_no_term:
  1371 0000075B 30C9                        xor cl,cl               ; flag that termination of parsing did not occur
  1372                                  
  1373                                  ur_out:
  1374 0000075D 8B1E[1000]                  mov bx,[rsp_handle]       ; get response file handle
  1375 00000761 B43E                        mov ah,3eh              ; close file
  1376 00000763 CD21                        int 21h
  1377 00000765 5E                          pop si                  ; restore si -> first char after file name
  1378 00000766 C3                          ret
  1379                                  use_rsp     ENDP
  1380                                  
  1381                                  ;*****************************
  1382                                  ;* GET_FILE_NAME             *
  1383                                  ;*****************************
  1384                                  
  1385                                  ; get file name in filename string, force to all caps
  1386                                  ; ds:si points to second char of file name upon entry, al holds first char
  1387                                  ; destroys ax,di
  1388                                  ; updates si
  1389                                  ; returns di -> filename zero terminator,
  1390                                  ; si -> char following last filename char
  1391                                  
  1392                                  get_file_name   PROC
  1393 00000767 BF[1400]                    mov di,OFFSET parfilename wrt DGROUP	; point to buffer for file name
  1394                                  
  1395                                  ; alternate entry point allows nonroutine-set name buffer
  1396                                  getfile_alt_entry:
  1397                                  
  1398                                  ; force file name to all caps
  1399                                  gfn_loop:
  1400 0000076A 3C61                        cmp al,'a'              ; check lower bounds
  1401 0000076C 7206                        jb  gfn_2               ; not a lowercase letter
  1402 0000076E 3C7A                        cmp al,'z'              ; check upper bounds
  1403 00000770 7702                        ja  gfn_2               ; not a lowercase letter
  1404 00000772 2C20                        sub al,32               ; force lowercase to uppercase
  1405                                  
  1406                                  gfn_2:
  1407 00000774 8805                        mov [di],al             ; put file name char in buffer
  1408 00000776 47                          inc di                  ; bump to next file name buffer slot
  1409 00000777 8A04                        mov al,[si]             ; peek ahead at following char
  1410 00000779 E83A07                  	call	is_terminator	; see if file name parse terminator
  1411 0000077C 7403                        je  end_filename_string
  1412                                  
  1413 0000077E AC                          lodsb                   ; get char from command line string
  1414 0000077F EBE9                        jmp SHORT gfn_loop      ; loop back to process
  1415                                  
  1416                                  end_filename_string:
  1417 00000781 C60500                      mov BYTE PTR [di],0     ; zero terminate file name buffer
  1418 00000784 C3                          ret
  1419                                  get_file_name   ENDP
  1420                                  
  1421                                  ;*****************************
  1422                                  ;* PARSE_FILE_TYPE           *
  1423                                  ;*****************************
  1424                                  
  1425                                  ; parse file name, save as appropriate type (.obj, .exe, .com, .map, .lib)
  1426                                  ; ds:si points to second char of file name upon entry
  1427                                  ; destroys ax,dx,di
  1428                                  ; updates si
  1429                                  
  1430                                  parse_file_type   PROC
  1431 00000785 51                          push    cx              ; save critical register
  1432 00000786 E8DEFF                      call    get_file_name   ; setup filename string
  1433 00000789 BA[1400]                    mov dx,OFFSET parfilename wrt DGROUP	; point to first char of filename
  1434 0000078C E82600                      call    check_extension ; set no_extension flag status
  1435                                  
  1436                                  save_name:
  1437 0000078F A0[0100]                    mov al,[arg_type]         ; save filename as .obj, .exe, .map, or .lib
  1438 00000792 08C0                        or  al,al               ; check for .obj type, type 0
  1439 00000794 7505                        jne sn_2
  1440 00000796 E8C100                      call    save_obj_name   ; save the object module name
  1441 00000799 59                          pop cx                  ; restore critical register
  1442 0000079A C3                          ret
  1443                                  sn_2:
  1444 0000079B 3C01                        cmp al,1                ; check for .exe (.com) type
  1445 0000079D 7505                        jne sn_3
  1446 0000079F E82E00                      call    save_exe_name   ; save the executable name
  1447 000007A2 59                          pop cx                  ; restore critical register
  1448 000007A3 C3                          ret
  1449                                  sn_3:
  1450 000007A4 3C02                        cmp al,2                ; check for .map type
  1451 000007A6 7505                        jne libtype
  1452 000007A8 E87700                      call    save_map_name   ; save the map name
  1453 000007AB 59                          pop cx                  ; restore critical register
  1454 000007AC C3                          ret
  1455                                  
  1456                                  libtype:                    ; assume module is library if arg_type matches nothin else
  1457 000007AD BF[1400]                    mov di,OFFSET parfilename wrt DGROUP
  1458 000007B0 E88A01                      call    save_lib_name   ; save the library name
  1459 000007B3 59                          pop cx                  ; restore critical register
  1460 000007B4 C3                          ret
  1461                                  parse_file_type ENDP
  1462                                  
  1463                                  ;*****************************
  1464                                  ;* CHECK_EXTENSION           *
  1465                                  ;*****************************
  1466                                  
  1467                                  ; get the file's extension, if none set no_extension flag
  1468                                  ; upon entry di -> zero terminator of filename
  1469                                  ; dx -> filename
  1470                                  ; destroys dx,di
  1471                                  
  1472                                  check_extension PROC
  1473                                  ce_loop:
  1474 000007B5 4F                          dec di                  ; back up to previous char
  1475 000007B6 39FA                        cmp dx,di               ; are we at the first char of filename
  1476 000007B8 7310                        jae set_ext_off         ; yes, this file has no extension
  1477 000007BA 803D5C                      cmp BYTE PTR [di],'\'   ; backslash indicates end of filename (start of path)
  1478 000007BD 740B                        je  set_ext_off         ; no extension in filename before path was indicated
  1479 000007BF 803D2E                      cmp BYTE PTR [di],'.'   ; period indicates file extension exists
  1480 000007C2 75F1                        jne ce_loop             ; not a period, keep looking
  1481 000007C4 C606[0200]00                mov byte [no_extension],0      ; flag that file name does have an extension
  1482 000007C9 C3                          ret
  1483                                  
  1484                                  set_ext_off:
  1485 000007CA C606[0200]01                mov byte [no_extension],1      ; flag that file name has no extension
  1486                                  
  1487                                  ce_ret:
  1488 000007CF C3                          ret
  1489                                  check_extension ENDP
  1490                                  
  1491                                  ;*****************************
  1492                                  ;* SAVE_EXE_NAME             *
  1493                                  ;*****************************
  1494                                  
  1495                                  ; upon entry, filename buffer contains name of executable file
  1496                                  ; destroys ax,di,es (to ds, if changed)
  1497                                  
  1498                                  save_exe_name   PROC
  1499 000007D0 56                          push    si              ; save critical register
  1500 000007D1 BF[0000]                    mov di,OFFSET exe_name wrt DGROUP   ; point to exe_name global string
  1501 000007D4 803D00                      cmp BYTE PTR [di],0     ; check if not zero (previously set)
  1502 000007D7 7546                        jne sen_exit           ; previous executable name specified, ignore this one
  1503                                  
  1504                                  sen_2:
  1505 000007D9 BE[1400]                    mov si,OFFSET parfilename wrt DGROUP	; point to filename to transfer to global string
  1506 000007DC 8CD8                        mov ax,ds
  1507 000007DE 8EC0                        mov es,ax               ; es -> WarpLink data
  1508                                  sen_3:
  1509 000007E0 A4                          movsb                   ; transfer a char
  1510 000007E1 807CFF00                    cmp BYTE PTR [si-1],0   ; zero byte signals end of transfer
  1511 000007E5 75F9                        jne sen_3               ; not zero, keep tranferring
  1512                                  
  1513 000007E7 803E[0200]00                cmp byte [no_extension],0      ; check to see if default extension should be added
  1514 000007EC 7405                        je  sen_savepath        ; nope, extension exists
  1515                                  
  1516                                  ; since the default extension of .com or .exe is indeterminate,
  1517                                  ; save a pointer to where it goes and add it in at end of parse
  1518 000007EE 4F                          dec di                  ; back up one char slot
  1519 000007EF 893E[0400]                  mov [exe_ext_ptr],di      ; save pointer to where extension goes
  1520                                  
  1521                                  ; save the path and drive spec of the EXE file, if any
  1522                                  sen_savepath:
  1523 000007F3 C606[9201]00                mov BYTE [exe_pathspec],0 ; init path specification
  1524 000007F8 83EE02                      sub si,2                ; si -> last char of name
  1525 000007FB FD                          std                     ; auto-decrement string moves
  1526                                  
  1527                                  pathloop:
  1528 000007FC AC                          lodsb                   ; get name char
  1529 000007FD 3C5C                        cmp al,'\'              ; see if directory indicator
  1530 000007FF 740C                        je  sen_pathspec        ; yes
  1531 00000801 3C3A                        cmp al,':'              ; see if drive specifier
  1532 00000803 7408                        je  sen_pathspec        ; yes
  1533 00000805 81FE[1400]                  cmp si,OFFSET parfilename wrt DGROUP	; see if at beginning or before
  1534 00000809 7614                        jbe sen_exit            ; yes, no pathspec
  1535 0000080B EBEF                        jmp SHORT pathloop      ; not at end, keep checking
  1536                                  
  1537                                  sen_pathspec:
  1538 0000080D FC                          cld                     ; auto-increment string moves
  1539 0000080E 46                          inc si                  ; si -> directory/drive indicator
  1540 0000080F 89F0                        mov ax,si
  1541 00000811 BE[1400]                    mov si,OFFSET parfilename wrt DGROUP	; si-> start of pathspec
  1542 00000814 BF[9201]                    mov di,OFFSET exe_pathspec wrt DGROUP   ; di-> destination
  1543                                  
  1544                                  sen_transloop:
  1545 00000817 A4                          movsb                   ; transfer pathspec char
  1546 00000818 39C6                        cmp si,ax               ; see if at end
  1547 0000081A 76FB                        jbe sen_transloop       ; no
  1548 0000081C C60500                      mov BYTE PTR [di],0     ; null terminate pathspec
  1549                                  
  1550                                  sen_exit:
  1551 0000081F FC                          cld
  1552 00000820 5E                          pop si                  ; restore critical register
  1553 00000821 C3                          ret
  1554                                  save_exe_name   ENDP
  1555                                  
  1556                                  ;*****************************
  1557                                  ;* SAVE_MAP_NAME             *
  1558                                  ;*****************************
  1559                                  
  1560                                  ; upon entry, filename buffer contains name of map file
  1561                                  ; destroys ax,di,es
  1562                                  
  1563                                  save_map_name   PROC
  1564 00000822 56                          push    si              ; save critical register
  1565 00000823 BF[0000]                    mov di,OFFSET map_name wrt DGROUP   ; point to map_name global string
  1566 00000826 803D00                      cmp BYTE PTR [di],0     ; check if not zero (previously set)
  1567 00000829 752D                        jne smn_exit            ; previous map name specified, ignore this one
  1568                                  
  1569                                  smn_2:
  1570 0000082B C606[0000]01                mov byte [is_mapfile],1        ; flag that map file exists
  1571 00000830 BE[1400]                    mov si,OFFSET parfilename wrt DGROUP	; point to filename to transfer to global string
  1572 00000833 8CD8                        mov ax,ds
  1573 00000835 8EC0                        mov es,ax               ; ES -> DGROUP data
  1574                                  smn_3:
  1575 00000837 A4                          movsb                   ; transfer a char
  1576 00000838 807CFF00                    cmp BYTE PTR [si-1],0   ; zero byte signals end of transfer
  1577 0000083C 75F9                        jne smn_3               ; not zero, keep tranferring
  1578                                  
  1579 0000083E 803E[0200]00                cmp byte [no_extension],0      ; check to see if default extension should be added
  1580 00000843 7413                        je  smn_exit            ; nope, extension exists
  1581 00000845 C645FF2E                    mov BYTE PTR [di-1],'.' ; add period
  1582 00000849 C6054D                      mov BYTE PTR [di],'M'   ; add MAP extension
  1583 0000084C C6450141                    mov BYTE PTR [di+1],'A'
  1584 00000850 C6450250                    mov BYTE PTR [di+2],'P'
  1585 00000854 C6450300                    mov BYTE PTR [di+3],0   ; null terminate string
  1586                                  
  1587                                  smn_exit:
  1588 00000858 5E                          pop si                  ; restore critical register
  1589 00000859 C3                          ret
  1590                                  save_map_name   ENDP
  1591                                  
  1592                                  ;*****************************
  1593                                  ;* SAVE_OBJ_NAME             *
  1594                                  ;*****************************
  1595                                  
  1596                                  ; upon entry, filename string buffer contains name of object module
  1597                                  ; destroys ax,bx,cx,dx,di,es
  1598                                  
  1599                                   global save_obj_name
  1600                                  save_obj_name   PROC
  1601 0000085A 56                          push    si              ; save critical register
  1602 0000085B BF[1400]                    mov di,OFFSET parfilename wrt DGROUP
  1603                                  
  1604                                  son_getlen:
  1605 0000085E 57                          push    di              ; save di -> file name
  1606 0000085F 1E                          push    ds              ; save critical segment register
  1607 00000860 31C9                        xor cx,cx               ; cx will hold length of filename string, including zero terminator
  1608 00000862 89FB                        mov bx,di               ; bx -> file name
  1609                                  
  1610                                  son_loop:
  1611 00000864 41                          inc cx                  ; bump string char count
  1612 00000865 803D00                      cmp BYTE PTR [di],0     ; check for string terminator
  1613 00000868 7417                        je  son_ext             ; all chars in string counted
  1614 0000086A 803D3A                      cmp BYTE PTR [di],':'   ; check if colon
  1615 0000086D 7403                        je  son_colon           ; yes
  1616                                  
  1617                                  son_nextchar:
  1618 0000086F 47                          inc di                  ; bump offset in string
  1619 00000870 EBF2                        jmp SHORT son_loop      ; loop back for more
  1620                                  
  1621                                  ; check if colon at nondrive+ position, if so, then this is a library module,
  1622                                  son_colon:
  1623 00000872 89F8                        mov ax,di
  1624 00000874 29D8                        sub ax,bx               ; get position of colon in file name
  1625 00000876 83F802                      cmp ax,2                ; see if library module name
  1626 00000879 72F4                        jb  son_nextchar        ; no, colon at first or second position
  1627                                  
  1628                                  ; library module, restore stack and transfer control to save_lib_name
  1629 0000087B 58                          pop ax                  ; trash
  1630 0000087C 5F                          pop di                  ; restore di -> file name
  1631 0000087D 58                          pop ax                  ; trash
  1632 0000087E E9BC00                      jmp NEAR PTR save_lib_name  ; save_lib_name will save library module appropriately
  1633                                  
  1634                                  son_ext:
  1635 00000881 803E[0200]00                cmp byte [no_extension],0      ; check to see if default extension should be added
  1636 00000886 7416                        je  son_2               ; nope, extension exists
  1637 00000888 83C104                      add cx,4                ; add four chars to string
  1638 0000088B C6052E                      mov BYTE PTR [di],'.'   ; add period
  1639 0000088E C645014F                    mov BYTE PTR [di+1],'O' ; add OBJ extension
  1640 00000892 C6450242                    mov BYTE PTR [di+2],'B'
  1641 00000896 C645034A                    mov BYTE PTR [di+3],'J'
  1642 0000089A C6450400                    mov BYTE PTR [di+4],0   ; null terminate string
  1643                                  
  1644                                  son_2:
  1645 0000089E 89DF                        mov di,bx               ; restore di -> filename
  1646 000008A0 41                          inc cx                  ; adjust for leading flag byte
  1647                                  
  1648 000008A1 A1[0000]                    mov ax,[last_objblk_ptr]  ; get segment of last object module name block allocation
  1649 000008A4 09C0                        or  ax,ax               ; zero if none made yet
  1650 000008A6 751B                        jne son_3               ; at least one name block allocation made
  1651 000008A8 BB2100                      mov bx,OBJ_NAMBLK_SIZE  ; number of paragraphs to allocate
  1652 000008AB E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1653 000008AE A3[0000]                    mov [first_objblk_ptr],ax ; set first object module name block pointer
  1654 000008B1 A3[0000]                    mov [last_objblk_ptr],ax  ; set last pointer to only block
  1655 000008B4 8ED8                        mov ds,ax               ; point data segment at block
  1656 000008B6 31C0                        xor ax,ax
  1657 000008B8 A30200                      mov WORD PTR [2],ax  ; set next block pointer to null value
  1658 000008BB B80C02                      mov ax,OBJ_NAMELIST_SIZE    ; free namelist space in block, all free
  1659 000008BE A30000                      mov WORD PTR [0],ax  ; save to block
  1660 000008C1 8CD8                        mov ax,ds
  1661                                  
  1662                                  son_3:
  1663 000008C3 50                          push    ax              ; save -> object module block
  1664 000008C4 51                          push    cx              ; save object module name char count
  1665                                  
  1666                                  ; check if object module exists, if not check OBJ e-var directories for it
  1667                                  ; and set di appropriately
  1668 000008C5 B8[ssss]                    mov ax,DGROUP
  1669 000008C8 8ED8                        mov ds,ax
  1670 000008CA 89FA                        mov dx,di               ; ds:dx -> .OBJ file spec
  1671 000008CC B80043                      mov ax,4300h            ; get file attributes (check for file existence)
  1672 000008CF CD21                        int 21h
  1673 000008D1 7314                        jnc son_obj_found       ; file found okay
  1674 000008D3 E83B05                  	call	file_not_found	; see if file not found error
  1675                                  
  1676                                  ; .OBJ file not found in current directory, search OBJ environment string
  1677                                  son_find_obj:
  1678 000008D6 BB[0D00]                    mov bx,OFFSET objtext wrt DGROUP    ; bx holds target string address for compares
  1679 000008D9 E8(0000)                    call    check_libobj_path   ; check e-var, error if not found, return di-> path+name
  1680 000008DC C606[0200]00                mov byte [no_extension],0      ; turn off default extension flag, already added if needed
  1681 000008E1 83C408                      add sp,8                ; gobble values on stack
  1682 000008E4 E977FF                      jmp NEAR PTR son_getlen ; get length of new name
  1683                                  
  1684                                  son_obj_found:
  1685 000008E7 59                          pop cx                  ; restore library name char count
  1686 000008E8 1F                          pop ds                  ; ds -> library block
  1687                                  
  1688 000008E9 A10000                      mov ax,[0]           ; get free space in block
  1689 000008EC 39C8                        cmp ax,cx               ; check free space against object module name length
  1690 000008EE 7207                        jb  son_6               ; not enough room, allocate another block
  1691 000008F0 BF0C02                      mov di,OBJ_NAMELIST_SIZE
  1692 000008F3 29C7                        sub di,ax               ; di contains offset to free space in block's name list
  1693 000008F5 EB1F                        jmp SHORT son_7         ; bypass allocation code
  1694                                  
  1695                                  son_6:
  1696 000008F7 8CD8                        mov ax,ds
  1697 000008F9 8EC0                        mov es,ax               ; keep es pointing at old block when new is allocated
  1698 000008FB BB2100                      mov bx,OBJ_NAMBLK_SIZE  ; number of paragraphs to allocate
  1699 000008FE 1F                          pop ds                  ; restore data segment -> WarpLink data prior to memory allocation routine
  1700 000008FF 1E                          push    ds              ; save data segment again, will be destroyed
  1701 00000900 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1702 00000903 A3[0000]                    mov [last_objblk_ptr],ax  ; set last pointer to new block
  1703 00000906 8ED8                        mov ds,ax               ; point data segment at new block
  1704 00000908 31FF                        xor di,di               ; di is offset to free space in block, init to zero
  1705 0000090A C7050C02                    mov WORD PTR [di],OBJ_NAMELIST_SIZE  ;save free namelist space to block, all free
  1706 0000090E 893E0200                    mov [2],di           ; zero pointer to next block
  1707 00000912 26A30200                    mov [es:2],ax           ; save pointer in old block to new block
  1708                                  
  1709                                  son_7:
  1710 00000916 290E0000                    sub [0],cx           ; reduce space free in block the length of object module name
  1711                                  
  1712                                  ; transfer filename string into object module name block
  1713 0000091A 83C704                      add di,4                ; adjust free space offset past the two leading words in block
  1714 0000091D 8CD8                        mov ax,ds
  1715 0000091F 8EC0                        mov es,ax               ; es:di -> destination (offset in block)
  1716 00000921 1F                          pop ds                  ; restore data segment pointing to WarpLink's data
  1717 00000922 5E                          pop si                  ; ds:si -> source string
  1718                                  
  1719                                  ; place flag byte in front of name, 80h overlaid, 40h overlaid nonvectored root call
  1720 00000923 A0[0000]                    mov al,[in_overlay]
  1721 00000926 08C0                        or  al,al               ; see in in overlay
  1722 00000928 7403                        je  son_8               ; no, use zero value for flag byte
  1723 0000092A A2[0000]                    mov [is_anyovls],al       ; set any module overlay flag
  1724                                  
  1725                                  son_8:
  1726 0000092D AA                          stosb                   ; store flag value, di -> destination for string
  1727 0000092E 49                          dec cx                  ; adjust char count for flag byte
  1728                                  
  1729 0000092F D1E9                        shr cx,1                ; convert to words
  1730 00000931 F3A5                        rep movsw               ; move the string
  1731 00000933 D1D1                        rcl cx,1                ; pick up carry
  1732 00000935 F3A4                        rep movsb               ; transfer leftover byte, if any
  1733                                  
  1734 00000937 5E                          pop si                  ; restore critical register
  1735 00000938 FF06[0000]                  inc word [obj_count]           ; bump count of object modules
  1736 0000093C C3                          ret
  1737                                  save_obj_name   ENDP
  1738                                  
  1739                                  ;*****************************
  1740                                  ;* SAVE_LIB_NAME             *
  1741                                  ;*****************************
  1742                                  
  1743                                  ; upon entry, di -> file name
  1744                                  ; destroys ax,bx,cx,dx,di,es
  1745                                  
  1746                                  save_lib_name   PROC
  1747 0000093D 56                          push    si              ; save critical register
  1748 0000093E C606[0F00]00                mov byte [module_flag],0       ; init library module flag
  1749                                  
  1750                                  sln_getlen:
  1751 00000943 57                          push    di              ; save di -> file name
  1752 00000944 1E                          push    ds              ; save critical segment register
  1753 00000945 31C9                        xor cx,cx               ; cx will hold length of filename string, including zero terminator
  1754 00000947 89CE                        mov si,cx               ; si will offset into library name block
  1755 00000949 89FB                        mov bx,di               ; bx -> file name
  1756                                  
  1757                                  sln_loop:
  1758 0000094B 41                          inc cx                  ; bump string char count
  1759 0000094C 803D00                      cmp BYTE PTR [di],0     ; check for string terminator
  1760 0000094F 7417                        je  sln_ext             ; all chars in string counted
  1761 00000951 803D3A                      cmp BYTE PTR [di],':'   ; check if colon
  1762 00000954 7403                        je  sln_colon           ; yes
  1763                                  
  1764                                  sln_nextchar:
  1765 00000956 47                          inc di                  ; bump offset in string
  1766 00000957 EBF2                        jmp SHORT sln_loop      ; loop back for more
  1767                                  
  1768                                  ; check if colon at nondrive+ position, if so, then this is a library module,
  1769                                  sln_colon:
  1770 00000959 89F8                        mov ax,di
  1771 0000095B 29D8                        sub ax,bx               ; get position of colon in file name
  1772 0000095D 83F802                      cmp ax,2                ; see if library module name
  1773 00000960 72F4                        jb  sln_nextchar        ; no, colon at first or second position
  1774 00000962 C60500                      mov BYTE PTR [di],0     ; zero terminate the library name
  1775                                  
  1776                                  ; keep the module name and set no_extension flag appropriately
  1777 00000965 E80101                      call    save_module_name
  1778                                  
  1779                                  sln_ext:
  1780 00000968 803E[0200]00                cmp byte [no_extension],0      ; check to see if default extension should be added
  1781 0000096D 7416                        je  sln_2               ; nope, extension exists
  1782 0000096F 83C104                      add cx,4                ; add four chars to string
  1783 00000972 C6052E                      mov BYTE PTR [di],'.'   ; add period
  1784 00000975 C645014C                    mov BYTE PTR [di+1],'L' ; add LIB extension
  1785 00000979 C6450249                    mov BYTE PTR [di+2],'I'
  1786 0000097D C6450342                    mov BYTE PTR [di+3],'B'
  1787 00000981 C6450400                    mov BYTE PTR [di+4],0   ; null terminate string
  1788                                  
  1789                                  sln_2:
  1790 00000985 89DF                        mov di,bx               ; restore di -> filename
  1791 00000987 893E[1200]                  mov [libname_ptr],di		; save -> filename
  1792 0000098B 41                          inc cx                  ; adjust for leading flag byte
  1793                                  
  1794 0000098C 803E[0F00]00                cmp byte [module_flag],0       ; see if library module
  1795 00000991 750F                        jne sln_3               ; yes, bypass check for library module
  1796                                  
  1797 00000993 C606[0300]01                mov byte [lib_nonmod_flag],1   ; flag at least one library not specified as module
  1798 00000998 E87503                      call    check_lib_dupe  ; check for duplicate library name
  1799 0000099B 7305                    	jnc	sln_3				; no duplicate found
  1800                                  
  1801                                  ; duplicate library name, don't save it, ax -> name entry
  1802 0000099D 83C404                      add sp,4                ; gobble pushed ds,di (ds unchanged, di doesn't matter)
  1803 000009A0 5E                          pop si                  ; restore si
  1804 000009A1 C3                          ret                     ; and return without saving name
  1805                                  
  1806                                  sln_3:
  1807 000009A2 A1[0000]                    mov ax,[last_libblk_ptr]  ; get segment of last library name block allocation
  1808 000009A5 09C0                        or  ax,ax               ; zero if none made yet
  1809 000009A7 751A                        jne sln_4               ; at least one name block allocation made
  1810 000009A9 BB1100                      mov bx,LIB_NAMBLK_SIZE  ; number of paragraphs to allocate
  1811 000009AC E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1812 000009AF A3[0000]                    mov [first_libblk_ptr],ax ; set first library name block pointer
  1813 000009B2 A3[0000]                    mov [last_libblk_ptr],ax  ; set last pointer to only block
  1814 000009B5 8ED8                        mov ds,ax               ; point data segment at block
  1815 000009B7 31C0                        xor ax,ax
  1816 000009B9 A30200                      mov WORD PTR [2],ax  ; set next block pointer to null value, si preset to 0
  1817 000009BC B80C01                      mov ax,LIB_NAMELIST_SIZE    ; free namelist space in block, all free
  1818 000009BF 8904                        mov WORD PTR [si],ax    ; save to block, si preset to zero
  1819 000009C1 8CD8                        mov ax,ds
  1820                                  
  1821                                  sln_4:
  1822 000009C3 50                          push    ax              ; save -> library block
  1823 000009C4 51                          push    cx              ; save library name char count
  1824                                  
  1825                                  ; check if library file exists, if not check LIB e-var directories for it
  1826                                  ; and set di appropriately
  1827 000009C5 B8[ssss]                    mov ax,DGROUP
  1828 000009C8 8ED8                        mov ds,ax
  1829 000009CA 89FA                        mov dx,di               ; ds:dx -> .LIB file spec
  1830 000009CC B80043                      mov ax,4300h            ; get file attributes (check for file existence)
  1831 000009CF CD21                        int 21h
  1832 000009D1 7314                        jnc sln_lib_found       ; file found okay
  1833 000009D3 E83B04                  	call	file_not_found	; check for file not found
  1834                                  
  1835                                  ; .LIB file not found in current directory, search LIB environment string
  1836                                  sln_find_lib:
  1837 000009D6 BB[0900]                    mov bx,OFFSET libtext wrt DGROUP ; bx holds target string address for compares
  1838 000009D9 E8(0000)                    call    check_libobj_path   ; check for libraries, error if not found, return di-> path+name
  1839 000009DC C606[0200]00                mov byte [no_extension],0      ; turn off default extension flag, already added if needed
  1840 000009E1 83C408                      add sp,8                ; gobble values on stack
  1841 000009E4 E95CFF                      jmp NEAR PTR sln_getlen ; get length of new name
  1842                                  
  1843                                  sln_lib_found:
  1844 000009E7 893E[1200]                  mov [libname_ptr],di		; save -> filename
  1845 000009EB 59                          pop cx                  ; restore library name char count
  1846 000009EC 1F                          pop ds                  ; ds -> library block
  1847                                  
  1848 000009ED 8B04                        mov ax,[si]             ; get free space in block
  1849 000009EF 39C8                        cmp ax,cx               ; check free space against library name length
  1850 000009F1 7207                        jb  sln_6               ; not enough room, allocate another block
  1851 000009F3 BF0C01                      mov di,LIB_NAMELIST_SIZE
  1852 000009F6 29C7                        sub di,ax               ; di contains offset to free space in block's name list
  1853 000009F8 EB1F                        jmp SHORT sln_7         ; bypass allocation code
  1854                                  
  1855                                  sln_6:
  1856 000009FA 8CD8                        mov ax,ds
  1857 000009FC 8EC0                        mov es,ax               ; keep es pointing at old block when new is allocated
  1858 000009FE BB1100                      mov bx,LIB_NAMBLK_SIZE  ; number of paragraphs to allocate
  1859 00000A01 1F                          pop ds                  ; restore data segment -> WarpLink data prior to memory allocation routine
  1860 00000A02 1E                          push    ds              ; save data segment again, will be destroyed
  1861 00000A03 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1862 00000A06 A3[0000]                    mov [last_libblk_ptr],ax  ; set last pointer to new block
  1863 00000A09 8ED8                        mov ds,ax               ; point data segment at new block
  1864 00000A0B C7040C01                    mov WORD PTR [si],LIB_NAMELIST_SIZE ;save free namelist space to block, all free
  1865 00000A0F 31FF                        xor di,di               ; di is offset to free space in block, init to zero
  1866 00000A11 893E0200                    mov [2],di           ; zero pointer to next block
  1867 00000A15 26A30200                    mov [es:2],ax           ; save pointer in old block to new block
  1868                                  
  1869                                  sln_7:
  1870 00000A19 290C                        sub [si],cx             ; reduce space free in block the length of library name
  1871                                  
  1872                                  ; transfer filename string into library name block
  1873 00000A1B 83C704                      add di,4                ; adjust free space offset past the two leading words in block
  1874 00000A1E 8CD8                        mov ax,ds
  1875 00000A20 8EC0                        mov es,ax               ; es:di -> destination (offset in block)
  1876 00000A22 1F                          pop ds                  ; restore data segment pointing to WarpLink's data
  1877 00000A23 5E                          pop si                  ; ds:si -> source string
  1878                                  
  1879 00000A24 803E[0F00]00                cmp byte [module_flag],0       ; see if library module
  1880 00000A29 7405                        je  sln_clp5            ; no
  1881                                  
  1882 00000A2B E85A00                      call    proc_lib_module ; process library module
  1883 00000A2E EB0E                        jmp SHORT sln_7a        ; bypass /clp5 code
  1884                                  
  1885                                  ; check if /clp5 flag set, if so, check if CLIPPER.LIB, if so, place in overlay
  1886                                  ; and keep library number
  1887                                  sln_clp5:
  1888 00000A30 803E[0000]00                cmp byte [is_clip5],0          ; see if clipper 5 flag set
  1889 00000A35 7407                        je  sln_7a              ; no
  1890 00000A37 E8A102                      call    set_clipper 
  1891 00000A3A 08C0                        or  al,al               ; see if CLIPPER.LIB
  1892 00000A3C 7507                        jne sln_7b              ; yes
  1893                                  
  1894                                  ; place flag byte in front of name, 80h overlaid, 40h overlaid nonvectored root call
  1895                                  sln_7a:
  1896 00000A3E A0[0000]                    mov al,[in_overlay]
  1897 00000A41 08C0                        or  al,al               ; see if in overlay
  1898 00000A43 7403                        je  sln_8               ; no
  1899                                  
  1900                                  sln_7b:
  1901 00000A45 A2[0000]                    mov [is_anyovls],al       ; set any module overlay flag
  1902                                  
  1903                                  sln_8:
  1904 00000A48 0A06[0F00]                  or  al,[module_flag]      ; set bit 0 if library module
  1905                                  
  1906                                  ; need to know if library module was specified in object module list (for DDL's)
  1907 00000A4C 803E[0100]00                cmp byte [arg_type],0          ; see if library module was specified in object module list
  1908 00000A51 7502                        jne sln_9               ; no
  1909 00000A53 0C02                        or  al,2                ; yes, set bit 1 of flag byte
  1910                                  
  1911                                  sln_9:
  1912 00000A55 AA                          stosb                   ; store flag value, di -> destination for string
  1913 00000A56 49                          dec cx                  ; adjust char count for flag byte
  1914                                  
  1915 00000A57 D1E9                        shr cx,1                ; convert to words
  1916 00000A59 F3A5                        rep movsw               ; move the string
  1917 00000A5B D1D1                        rcl cx,1                ; pick up carry
  1918 00000A5D F3A4                        rep movsb               ; transfer leftover byte, if any
  1919                                  
  1920 00000A5F 5E                          pop si                  ; restore critical register
  1921 00000A60 FF06[0000]                  inc word [current_lib]         ; bump current library (for module specification)
  1922 00000A64 FF06[0000]                  inc word [lib_count]           ; bump count of libraries
  1923 00000A68 C3                          ret
  1924                                  save_lib_name   ENDP
  1925                                  
  1926                                  ;*****************************
  1927                                  ;* SAVE_MODULE_NAME          *
  1928                                  ;*****************************
  1929                                  
  1930                                  ; keep the module name and set no_extension flag appropriately
  1931                                  ; upon entry di -> lib name null terminator before module name
  1932                                  ; destroys ax,dx
  1933                                  
  1934                                  save_module_name    PROC
  1935 00000A69 C606[0F00]01                mov byte [module_flag],1       ; flag that this is a library module
  1936 00000A6E 56                          push    si              ; save critical register
  1937                                  
  1938 00000A6F 57                          push    di              ; save -> null terminator of library name
  1939 00000A70 47                          inc di                  ; bump past lib null terminator
  1940 00000A71 89FA                        mov dx,di               ; dx -> start of module name
  1941 00000A73 8A05                        mov al,[di]             ; get first char of filename
  1942 00000A75 47                          inc di                  ; di -> second char of filename
  1943                                  
  1944                                  ; transfer module name to storage
  1945 00000A76 89FE                        mov si,di               ; si -> second char of filename, used by get_file_name procedure
  1946 00000A78 BF[1401]                    mov di,OFFSET modname wrt DGROUP    ; point to buffer for file name
  1947 00000A7B E8ECFC                      call    getfile_alt_entry   ; get the module name
  1948 00000A7E 5F                          pop di                  ; di -> library name null terminator
  1949                                  
  1950 00000A7F 89F8                        mov ax,di               ; keep -> null terminator of library name
  1951 00000A81 E831FD                      call    check_extension ; re/set no_extension flag
  1952 00000A84 89C7                        mov di,ax               ; restore di -> library name null terminator
  1953                                  
  1954 00000A86 5E                          pop si                  ; restore critical register
  1955 00000A87 C3                          ret
  1956                                  save_module_name    ENDP
  1957                                  
  1958                                  ;*****************************
  1959                                  ;* PROC_LIB_MODULE           *
  1960                                  ;*****************************
  1961                                  
  1962                                  ; process library module
  1963                                  ; ds:si -> library name upon entry
  1964                                  ; destroys ax,bx,dx
  1965                                  
  1966                                  proc_lib_module PROC
  1967 00000A88 803E[0000]00            	cmp	byte [is_quick],0			; see if qlk specified
  1968 00000A8D 741E                    	je	plm_checkon			; no
  1969 00000A8F 803E[0000]52            	cmp	byte [is_quick],'R'		; see if reading from qlk file (no lookup required)
  1970 00000A94 7425                    	je	plm_ret				; yes
  1971 00000A96 803E[0000]57            	cmp	byte [is_quick],'W'		; see if writing to qlk file
  1972 00000A9B 7410                    	je	plm_checkon			; yes
  1973 00000A9D E8(0000)                	call	is_qlk_file		; unknown, check if will be reading or writing
  1974 00000AA0 7206                    	jc	plm_writeqlk		; writing
  1975 00000AA2 C606[0000]52            	mov	byte [is_quick],'R'		; flag reading
  1976 00000AA7 C3                      	ret
  1977                                  
  1978                                  plm_writeqlk:
  1979 00000AA8 C606[0000]57            	mov	byte [is_quick],'W'		; flag writing
  1980                                  
  1981                                  plm_checkon:
  1982 00000AAD 803E[0000]00            	cmp	byte [is_clpinc],0			; see if incremental linking
  1983 00000AB2 7408                    	je	plm_notinc			; no
  1984 00000AB4 803E[0000]02            	cmp	byte [parse_pass],2		; see if second parse pass
  1985 00000AB9 7401                    	je	plm_notinc			; yes
  1986                                  
  1987                                  plm_ret:
  1988 00000ABB C3                      	ret						; don't process until incremental linking is over
  1989                                  
  1990                                  plm_notinc:
  1991 00000ABC 06                          push    es              ; save critical register
  1992 00000ABD 56                          push    si
  1993 00000ABE 57                          push    di
  1994 00000ABF 51                          push    cx
  1995                                  
  1996 00000AC0 803E[0000]00                cmp byte [is_linkinfo],0       ; see if linker information to be printed
  1997 00000AC5 7421                        je  plm_1               ; no
  1998 00000AC7 BA[1100]                    mov dx,OFFSET parsetext wrt DGROUP  ; print processing library module text
  1999 00000ACA B91F00                      mov cx,31
  2000 00000ACD BB0100                      mov bx,STDOUT
  2001 00000AD0 B440                        mov ah,40h              ; write to device
  2002 00000AD2 CD21                        int 21h
  2003                                  
  2004 00000AD4 BF[1401]                    mov di,OFFSET modname wrt DGROUP    ; point to buffer for module name
  2005                                  plm_nameloop:
  2006 00000AD7 803D00                      cmp BYTE PTR [di],0     ; see if at end of module name
  2007 00000ADA 740C                        je  plm_1               ; yes
  2008 00000ADC B90100                      mov cx,1
  2009 00000ADF 89FA                        mov dx,di
  2010 00000AE1 47                          inc di                  ; bump to next char of module name
  2011 00000AE2 B440                        mov ah,40h              ; write to device
  2012 00000AE4 CD21                        int 21h
  2013 00000AE6 EBEF                        jmp SHORT plm_nameloop
  2014                                  
  2015                                  plm_1:
  2016 00000AE8 8B16[1200]                  mov dx,[libname_ptr]
  2017 00000AEC B8003D                      mov ax,3d00h            ; open file with read access
  2018 00000AEF CD21                        int 21h
  2019 00000AF1 7306                        jnc plm_lib_open        ; no errors
  2020 00000AF3 E9(0000)                    jmp NEAR PTR dos_error  ; error occurred
  2021                                  
  2022                                  to_plm_search:
  2023 00000AF6 E90901                      jmp NEAR PTR plm_search
  2024                                  
  2025                                  plm_lib_open:
  2026 00000AF9 A3[0000]                    mov [lib_handle],ax       ; save library file handle
  2027                                  
  2028 00000AFC BF[0000]                    mov di,OFFSET prev_libname wrt DGROUP
  2029 00000AFF 89F2                        mov dx,si               ; save -> to start of current library name
  2030 00000B01 8CD8                        mov ax,ds
  2031 00000B03 8EC0                        mov es,ax               ; es -> warplink data
  2032                                  
  2033                                  ; See if current library for module matches previous.
  2034                                  plm_libloop:
  2035 00000B05 8A04                        mov al,[si]
  2036 00000B07 260A05                      or  al,[es:di]          ; see if both values are zero (matched to null terminator)
  2037 00000B0A 74EA                        je  to_plm_search       ; strings matched
  2038 00000B0C A6                          cmpsb                   ; compare a nonzero byte in the two names
  2039 00000B0D 74F6                        je  plm_libloop         ; bytes match, check next byte
  2040                                  
  2041                                  ; libraries did not match, transfer new name to previous
  2042 00000B0F 31C0                        xor ax,ax
  2043 00000B11 A3[0000]                    mov [lib_pages_count],ax  ; init count of library pages
  2044 00000B14 BF[0000]                    mov di,OFFSET prev_libname wrt DGROUP
  2045 00000B17 89D6                        mov si,dx
  2046                                  
  2047                                  plm_transloop:
  2048 00000B19 A4                          movsb                   ; update prev_libname variable with current library
  2049 00000B1A 804CFF00                    or  BYTE PTR [si-1],0   ; see if null terminator reached
  2050 00000B1E 75F9                        jne plm_transloop       ; no
  2051                                  
  2052 00000B20 A1[0000]                    mov ax,[buffer_base]      ; get i/o buffer segment
  2053 00000B23 8EC0                        mov es,ax               ; es -> i/o buffer
  2054 00000B25 31F6                        xor si,si               ; si offsets into i/o buffer
  2055                                  
  2056 00000B27 FF36[0000]                  push    WORD [is_no_ems]  ; save current no ems value (byte following doesn't get changed)
  2057 00000B2B C606[0000]01                mov byte [is_no_ems],1         ; flag no EMS usage for library modules
  2058 00000B30 E8(0000)                    call    get_lib_sys_info    ; get library system information
  2059 00000B33 8F06[0000]                  pop WORD [is_no_ems]  ; restore no ems value
  2060                                  
  2061                                  ; position to library directory
  2062 00000B37 8B16[0000]                  mov dx,WORD PTR [dir_offset]  ; dx has LSW of file offset
  2063 00000B3B 8B0E[0200]                  mov cx,WORD PTR [dir_offset+2]    ; cx has MSW of file offset
  2064                                  
  2065                                  p1_dir_loop:
  2066 00000B3F 8B1E[0000]                  mov bx,[lib_handle]       ; get handle of library file in bx
  2067 00000B43 B80042                      mov ax,4200h            ; move file pointer, from beginning of file
  2068 00000B46 CD21                        int 21h
  2069                                  
  2070 00000B48 A1[0000]                    mov ax,[dir_pages]        ; get total number of pages to read
  2071                                  
  2072                                  ; convert 512-byte pages to bytes in dx:ax
  2073 00000B4B 88E2                        mov dl,ah
  2074 00000B4D 88C4                        mov ah,al
  2075 00000B4F 30C0                        xor al,al
  2076 00000B51 88C6                        mov dh,al               ; dx:ax holds pages*256
  2077 00000B53 D1E0                        shl ax,1
  2078 00000B55 D1D2                        rcl dx,1                ; dx:ax holds pages*512
  2079                                  
  2080                                  plm_readloop:
  2081 00000B57 52                          push    dx
  2082 00000B58 50                          push    ax              ; save directory size left to process on stack
  2083 00000B59 8B0E[0000]                  mov cx,[buffer_end]       ; get maximum read amount
  2084 00000B5D 09D2                        or  dx,dx               ; see if more than 64K to read
  2085 00000B5F 7506                        jne plm_readdir         ; yes
  2086 00000B61 39C8                        cmp ax,cx               ; see if amount left to read is >= maximum able to read
  2087 00000B63 7302                        jae plm_readdir         ; yes
  2088 00000B65 89C1                        mov cx,ax               ; only read amount necessary
  2089                                  
  2090                                  ; read library directory, partial or full
  2091                                  plm_readdir:
  2092 00000B67 31D2                        xor dx,dx
  2093 00000B69 8A1E[0000]                  mov bl,[is_no_ems]
  2094 00000B6D 53                          push    bx
  2095 00000B6E C606[0000]01                mov byte [is_no_ems],1         ; force EMS not to be used
  2096 00000B73 8B1E[0000]                  mov bx,[lib_handle]       ; get handle of library file in bx
  2097 00000B77 1E                          push    ds              ; save ds -> warplink data
  2098 00000B78 8E1E[0000]                  mov ds,[buffer_base]      ; DS:DX -> segment:offset of buffer area
  2099 00000B7C E8(0000)                    call    read_to_ems
  2100 00000B7F 1F                          pop ds                  ; restore ds -> warplink data
  2101 00000B80 5B                          pop bx
  2102 00000B81 881E[0000]                  mov [is_no_ems],bl
  2103 00000B85 89CF                        mov di,cx               ; save count of bytes read
  2104 00000B87 31DB                        xor bx,bx               ; es:bx -> buffer
  2105                                  
  2106                                  ; store library pages, eliminating duplicates as necessary
  2107                                  ; if unique pages >1024 then try immediately try search and fail if not found
  2108                                  plm_pageloop:
  2109 00000B89 268A07                      mov al,[es:bx]          ; get public pointer array element value
  2110 00000B8C 08C0                        or  al,al               ; check if nonzero entry
  2111 00000B8E 7516                        jne plm_goodpage        ; nonzero
  2112                                  
  2113                                  plm_next_entry:
  2114 00000B90 43                          inc bx                  ; point to next element of array
  2115 00000B91 80FB25                      cmp bl,37               ; check entry count of page (lower byte of bx never exceeds 37)
  2116 00000B94 72F3                        jb  plm_pageloop        ; not done yet, keep looking at public entries
  2117                                  
  2118 00000B96 81E300FE                    and bx,0fe00h           ; bx -> first entry of next page (zero lower 511 bytes)
  2119 00000B9A 81C30002                    add bx,512              ; move to next directory page
  2120 00000B9E 724C                        jc  plm_pagedone        ; overflowed, no more directory pages in buffer
  2121 00000BA0 39FB                        cmp bx,di               ; see if past end of directory
  2122 00000BA2 72E5                        jb  plm_pageloop        ; no
  2123 00000BA4 EB46                        jmp SHORT plm_pagedone  ; yes, past end
  2124                                  
  2125                                  plm_goodpage:
  2126 00000BA6 30E4                        xor ah,ah               ; zap high byte
  2127 00000BA8 D1E0                        shl ax,1                ; convert to offset into directory page
  2128 00000BAA 89DA                        mov dx,bx
  2129 00000BAC 81E200FE                    and dx,0fe00h           ; get page value of bx
  2130 00000BB0 08F4                        or  ah,dh               ; merge into bx offset value for true offset
  2131 00000BB2 89C6                        mov si,ax               ; ds:si -> public name
  2132                                  
  2133 00000BB4 268A0C                      mov cl,[es:si]          ; get 1-byte length of name
  2134 00000BB7 30ED                        xor ch,ch               ; zap high byte
  2135 00000BB9 E3D5                        jcxz    plm_next_entry  ; zero length name, ignore it
  2136 00000BBB 46                          inc si                  ; point to first char of name
  2137 00000BBC 01CE                        add si,cx               ; si -> page number of public
  2138                                  
  2139 00000BBE 268B04                      mov ax,[es:si]          ; get page number value of public entry
  2140 00000BC1 A3[0000]                    mov [lib_page_num],ax     ; save to memory variable
  2141                                  
  2142                                  ; check if store another library page or process stored pages
  2143 00000BC4 813E[0000]0004              cmp word [lib_pages_count],1024    ; see if storage is full
  2144 00000BCA 720B                        jb  plm_store_page      ; no
  2145                                  
  2146                                  plm_destore:
  2147 00000BCC E8(0000)                    call    remove_dup_pages    ; remove duplicate pages in storage
  2148 00000BCF 813E[0000]0004              cmp word [lib_pages_count],1024    ; see if storage is still full
  2149 00000BD5 7328                        jae plm_pageproc        ; yes, process the pages
  2150                                  
  2151                                  ; store the library page
  2152                                  plm_store_page:
  2153 00000BD7 A1[0000]                    mov ax,[lib_pages_count]
  2154 00000BDA D1E0                        shl ax,1                ; convert to word offset
  2155 00000BDC BE[0000]                    mov si,OFFSET lib_page_storage wrt DGROUP   ; si -> base of stored pages
  2156 00000BDF 01C6                        add si,ax               ; si -> proper array to store library page number
  2157 00000BE1 A1[0000]                    mov ax,[lib_page_num]
  2158 00000BE4 8904                        mov [si],ax             ; store page
  2159 00000BE6 FF06[0000]                  inc word [lib_pages_count]     ; bump count of library pages stored
  2160 00000BEA EBA4                        jmp plm_next_entry ; loop until complete
  2161                                  
  2162                                  plm_pagedone:
  2163 00000BEC E8(0000)                    call    remove_dup_pages    ; remove duplicate pages in storage
  2164 00000BEF 58                          pop ax
  2165 00000BF0 5A                          pop dx                  ; get directory size to read in dx:ax
  2166 00000BF1 29F8                        sub ax,di               ; subtract off bytes processed
  2167 00000BF3 83DA00                      sbb dx,0                ; borrow to high word
  2168 00000BF6 89C3                        mov bx,ax
  2169 00000BF8 09D3                        or  bx,dx               ; see if any bytes left to read
  2170 00000BFA 7406                        je  plm_search          ; no
  2171 00000BFC E958FF                      jmp plm_readloop   ; yes, get them
  2172                                  
  2173                                  plm_pageproc:
  2174 00000BFF 83C404                      add sp,4                ; gobble directory size on stack
  2175                                  
  2176                                  ; search for library module in library, using pages stored in lib_page_storage array
  2177                                  plm_search:
  2178 00000C02 A1[0000]                    mov ax,[buffer_base]      ; get i/o buffer segment
  2179 00000C05 8EC0                        mov es,ax               ; es -> i/o buffer
  2180 00000C07 BE[0000]                    mov si,OFFSET lib_page_storage wrt DGROUP   ; si -> base of stored pages
  2181 00000C0A FF36[0000]                  push    word [lib_pages_count] ; save page count
  2182                                  
  2183                                  plm_searchloop:
  2184 00000C0E AD                          lodsw                   ; get page to process
  2185                                  
  2186                                  ; get file offset of module in file
  2187 00000C0F F726[0000]                  mul word [lib_page_size]       ; dx:ax has file offset of module
  2188 00000C13 89D1                        mov cx,dx               ; cx == MSW of offset
  2189 00000C15 89C2                        mov dx,ax               ; dx == LSW of offset
  2190 00000C17 8B1E[0000]                  mov bx,[lib_handle]       ; get handle of library file in bx
  2191 00000C1B B80042                      mov ax,4200h            ; move file pointer, offset from beginning
  2192 00000C1E CD21                        int 21h
  2193                                  
  2194 00000C20 B90004                      mov cx,1024             ; THEADR and COMENT should not exceed 1K
  2195 00000C23 8A16[0000]                  mov dl,[is_no_ems]
  2196 00000C27 52                          push    dx
  2197 00000C28 C606[0000]01                mov byte [is_no_ems],1         ; force EMS not to be used
  2198 00000C2D 1E                          push    ds              ; save critical register
  2199 00000C2E 31D2                        xor dx,dx
  2200 00000C30 8E1E[0000]                  mov ds,[buffer_base]      ; DS:DX -> segment:offset of buffer area
  2201 00000C34 E8(0000)                    call    read_to_ems     ; read file, transfer to EMS is necessary
  2202 00000C37 1F                          pop ds                  ; restore critical register
  2203 00000C38 59                          pop cx
  2204 00000C39 880E[0000]                  mov [is_no_ems],cl
  2205                                  
  2206                                  ; check THEADR and COMENT class A3h names for match, caseless compare
  2207 00000C3D 56                          push    si              ; save -> page in array (+2)
  2208 00000C3E BF0300                      mov di,3                ; es:di -> length byte of name
  2209 00000C41 268A0D                      mov cl,[es:di]          ; get length byte
  2210 00000C44 47                          inc di                  ; es:di -> name
  2211 00000C45 BE[1401]                    mov si,OFFSET modname wrt DGROUP    ; ds:si -> module name to match
  2212                                  
  2213                                  plm_theadr:
  2214 00000C48 AC                          lodsb
  2215 00000C49 268A25                      mov ah,[es:di]
  2216 00000C4C 47                          inc di
  2217 00000C4D 80FC61                      cmp ah,'a'              ; check lowercase lower boundary
  2218 00000C50 7208                        jb  plm_capped          ; not a lowercase letter
  2219 00000C52 80FC7A                      cmp ah,'z'              ; check lowercase upper boundary
  2220 00000C55 7703                        ja  plm_capped          ; not a lowercase letter
  2221 00000C57 80EC20                      sub ah,20h              ; convert to uppercase
  2222                                  
  2223                                  ; module name and THEADR byte uppercase if alpha
  2224                                  plm_capped:
  2225 00000C5A 38E0                        cmp al,ah
  2226 00000C5C 750A                        jne plm_chkcoment       ; no, check for COMENT field, if any
  2227 00000C5E FEC9                        dec cl                  ; see if at null terminator for both strings
  2228 00000C60 88C8                        mov al,cl
  2229 00000C62 0A04                        or  al,[si]
  2230 00000C64 75E2                        jne plm_theadr          ; no
  2231 00000C66 EB58                        jmp SHORT plm_modfound  ; yes, this is the correct module
  2232                                  
  2233                                  ; THEADR did not match, check for COMENT class A3h
  2234                                  plm_chkcoment:
  2235 00000C68 268B3E0100                  mov di,[es:1]           ; get length of THEADR record
  2236 00000C6D 81FF0002                    cmp di,512              ; can't be more than 512 bytes
  2237 00000C71 773A                        ja  plm_nomatch 
  2238 00000C73 83C703                      add di,3                ; adjust for record type byte and word length
  2239                                  
  2240                                  ; es:di -> next record
  2241 00000C76 26803D88                    cmp BYTE PTR [es:di],COMENT ; see if COMENT record
  2242 00000C7A 7531                        jne plm_nomatch         ; no
  2243 00000C7C 26807D04A3                  cmp BYTE PTR [es:di+4],0a3h ; see if comment class A3h
  2244 00000C81 752A                        jne plm_nomatch         ; no
  2245 00000C83 83C705                      add di,5                ; es:di -> length byte of name
  2246 00000C86 268A0D                      mov cl,[es:di]          ; get length byte
  2247 00000C89 47                          inc di                  ; es:di -> name
  2248 00000C8A BE[1401]                    mov si,OFFSET modname wrt DGROUP    ; ds:si -> module name to match
  2249                                  
  2250                                  plm_coment:
  2251 00000C8D AC                          lodsb
  2252 00000C8E 268A25                      mov ah,[es:di]
  2253 00000C91 47                          inc di
  2254 00000C92 80FC61                      cmp ah,'a'              ; check lowercase lower boundary
  2255 00000C95 7208                        jb  plm_cap2            ; not a lowercase letter
  2256 00000C97 80FC7A                      cmp ah,'z'              ; check lowercase upper boundary
  2257 00000C9A 7703                        ja  plm_cap2            ; not a lowercase letter
  2258 00000C9C 80EC20                      sub ah,20h              ; convert to uppercase
  2259                                  
  2260                                  ; module name and THEADR byte uppercase if alpha
  2261                                  plm_cap2:
  2262 00000C9F 38E0                        cmp al,ah
  2263 00000CA1 750A                        jne plm_nomatch         ; no, no match for this module
  2264 00000CA3 FEC9                        dec cl                  ; see if at null terminator for both strings
  2265 00000CA5 88C8                        mov al,cl
  2266 00000CA7 0A04                        or  al,[si]
  2267 00000CA9 75E2                        jne plm_coment          ; no
  2268 00000CAB EB13                        jmp SHORT plm_modfound  ; yes, this is the correct module
  2269                                  
  2270                                  plm_nomatch:
  2271 00000CAD 5E                          pop si                  ; restore si -> page in array
  2272 00000CAE FF0E[0000]                  dec word [lib_pages_count]     ; drop count of pages to process
  2273 00000CB2 7403                        je  plm_notfound        ; no more pages
  2274 00000CB4 E957FF                      jmp NEAR PTR plm_searchloop ; more pages left
  2275                                  
  2276                                  ; specified library module was not found
  2277                                  plm_notfound:
  2278 00000CB7 B80200                      mov ax,2                ; force file not found error
  2279 00000CBA BA[1401]                    mov dx,OFFSET modname wrt DGROUP    ; use module name
  2280 00000CBD E9(0000)                    jmp NEAR PTR dos_error
  2281                                  
  2282                                  ; found the module in the library, save library module entry
  2283                                  plm_modfound:
  2284 00000CC0 5E                          pop si                  ; si -> page in array (+2)
  2285 00000CC1 8F06[0000]                  pop word [lib_pages_count]     ; restore original count of pages
  2286 00000CC5 8B44FE                      mov ax,[si-2]
  2287 00000CC8 A3[0000]                    mov [lib_page_num],ax     ; save page number
  2288 00000CCB E8(0000)                    call    make_libmod_entry   
  2289                                  
  2290 00000CCE 8B1E[0000]                  mov bx,[lib_handle]       ; get file handle of open library
  2291 00000CD2 B43E                        mov ah,3eh              ; close file
  2292 00000CD4 CD21                        int 21h
  2293 00000CD6 59                          pop cx                  ; restore critical register
  2294 00000CD7 5F                          pop di
  2295 00000CD8 5E                          pop si
  2296 00000CD9 07                          pop es
  2297 00000CDA C3                          ret
  2298                                  proc_lib_module ENDP
  2299                                  
  2300                                  ;*****************************
  2301                                  ;* SET_CLIPPER               *
  2302                                  ;*****************************
  2303                                  
  2304                                  ; upon entry si-> file name including path
  2305                                  ; if /clp5 library, set clip_libnum and flag in overlay, return al == 0c0h
  2306                                  ; otherwise return al==0
  2307                                  ; destroys ax
  2308                                  
  2309                                  set_clipper PROC
  2310 00000CDB 56                          push    si              ; save critical register
  2311 00000CDC 57                          push    di
  2312 00000CDD 06                          push    es
  2313                                  
  2314                                  set_searchloop:
  2315 00000CDE AC                          lodsb                   ; search for null terminator of file name
  2316 00000CDF 08C0                        or  al,al               ; at null terminator?
  2317 00000CE1 75FB                        jne set_searchloop      ; no
  2318                                  
  2319 00000CE3 4E                          dec si                  ; back up to null terminator
  2320 00000CE4 8CD8                        mov ax,ds
  2321 00000CE6 8EC0                        mov es,ax               ; es -> warplink data
  2322 00000CE8 BF[0200]                    mov di,OFFSET clp5_lib wrt DGROUP
  2323                                  
  2324                                  set_search2:
  2325 00000CEB 268A05                      mov al,[es:di]          ; search for null terminator of /clp5 library
  2326 00000CEE 08C0                        or  al,al
  2327 00000CF0 7403                        je  set_2               ; at null terminator
  2328 00000CF2 47                          inc di                  ; bump to next char
  2329 00000CF3 EBF6                        jmp SHORT set_search2
  2330                                  
  2331                                  ; ds:si -> null terminator of source string
  2332                                  ; es:di -> null terminator of match string
  2333                                  set_2:
  2334 00000CF5 FD                          std                     ; decrement string operations
  2335                                  
  2336                                  set_comploop:
  2337 00000CF6 A6                          cmpsb                   ; match string bytes
  2338 00000CF7 7510                        jne set_noclip          ; no match, not the /clp5 library
  2339 00000CF9 81FF[0200]                  cmp di,OFFSET clp5_lib wrt DGROUP   ; see if matched to beginning of string
  2340 00000CFD 73F7                        jae set_comploop        ; not yet
  2341                                  
  2342                                  ; library names matched
  2343 00000CFF A1[0000]                    mov ax,[lib_count]        ; get current library number
  2344 00000D02 A3[0A00]                    mov [clip_libnum],ax      ; save it
  2345 00000D05 B0C0                        mov al,0c0h             ; flag in overlay, nonvectored root call
  2346 00000D07 EB02                        jmp SHORT set_exit
  2347                                  
  2348                                  set_noclip:
  2349 00000D09 30C0                        xor al,al               ; show not CLIPPER.LIB
  2350                                  
  2351                                  set_exit:
  2352 00000D0B FC                          cld                     ; restore to default increment string operations
  2353 00000D0C 07                          pop es                  ; restore critical register
  2354 00000D0D 5F                          pop di
  2355 00000D0E 5E                          pop si
  2356 00000D0F C3                          ret
  2357                                  set_clipper ENDP
  2358                                  
  2359                                  ;*****************************
  2360                                  ;* CHECK_LIB_DUPE            *
  2361                                  ;*****************************
  2362                                  
  2363                                  ; check for duplicate library name
  2364                                  ; di -> new file name upon entry
  2365                                  ; returns carry flag set if duplicate, reset if not duplicate,
  2366                                  ; destroys ax,bx
  2367                                  
  2368                                  check_lib_dupe  PROC
  2369 00000D10 06                          push    es              ; save critical register
  2370 00000D11 56                          push    si
  2371 00000D12 57                          push    di              ; save -> new file name on stack
  2372                                  
  2373 00000D13 A1[0000]                    mov ax,[first_libblk_ptr] ; get first object name block
  2374 00000D16 09C0                        or  ax,ax               ; check if nonull
  2375 00000D18 741F                        je  cld_nodupe          ; null, no previous libraries, no chance of duplicate
  2376 00000D1A BF0400                      mov di,4                ; di -> first name in block
  2377 00000D1D 8EC0                        mov es,ax               ; point extra segment at object name block
  2378                                  
  2379                                  cld_loop:
  2380 00000D1F 47                          inc di                  ; adjust past prepended flag byte
  2381 00000D20 B81001                      mov ax,LIB_NAMBLK_BYSIZE    ; size of block in bytes
  2382 00000D23 262B060000                  sub ax,[es:0]           ; minus free space, ax == end of used namelist
  2383 00000D28 39F8                        cmp ax,di               ; check that position in list is below end
  2384 00000D2A 7710                        ja  cld_2               ; not at end yet, pull name from this block's namelist
  2385                                  
  2386 00000D2C 26A10200                    mov ax,[es:2]           ; get pointer to next block
  2387 00000D30 BF0400                      mov di,4                ; di -> first name in block
  2388 00000D33 8EC0                        mov es,ax               ; point extra segment at object name block
  2389 00000D35 09C0                        or  ax,ax               ; check that is not null
  2390 00000D37 75E6                        jne cld_loop            ; non-null, next block exists, loop and check it
  2391                                  
  2392                                  cld_nodupe:
  2393 00000D39 F8                      	clc						; show no dupe found
  2394 00000D3A EB46                        jmp SHORT cld_ret
  2395                                  
  2396                                  ; es:di -> library name in block, ds:si -> new library name
  2397                                  cld_2:
  2398 00000D3C 803E[0000]00                cmp byte [def_lib_flag],0      ; see if default library flag set
  2399 00000D41 741D                        je  cld_2a              ; no
  2400                                  
  2401                                  ; find zero terminator and then back up until hit beginning or '\' or ':' char
  2402 00000D43 31DB                        xor bx,bx
  2403                                  
  2404                                  cld_endloop:
  2405 00000D45 268A05                      mov al,[es:di]          ; get char
  2406 00000D48 08C0                        or  al,al
  2407 00000D4A 7404                        je  cld_at_end          ; zero, found terminator
  2408 00000D4C 47                          inc di                  ; bump to next char slot
  2409 00000D4D 43                          inc bx                  ; bump count of chars in name
  2410 00000D4E EBF5                        jmp SHORT cld_endloop   ; loop for next char
  2411                                  
  2412                                  cld_at_end:
  2413 00000D50 4F                          dec di                  ; back up one chars in name
  2414 00000D51 4B                          dec bx                  ; drop count of chars in name
  2415 00000D52 740C                        je  cld_2a              ; no more chars in name, at beginning
  2416 00000D54 268A05                      mov al,[es:di]          ; get char in name
  2417 00000D57 3C5C                        cmp al,'\'              ; see if backslash, directory indicator
  2418 00000D59 7404                        je  cld_gopast          ; yes
  2419 00000D5B 3C3A                        cmp al,':'              ; see if colon, drivespec indicator
  2420 00000D5D 75F1                        jne cld_at_end          ; no, keep looking
  2421                                  
  2422                                  cld_gopast:
  2423 00000D5F 47                          inc di                  ; point di past backslash or colon in name
  2424                                  
  2425                                  cld_2a:
  2426 00000D60 5E                          pop si                  ; si -> new library name
  2427 00000D61 56                          push    si              ; restore -> new library name to stack
  2428                                  
  2429                                  ; es:di -> library name in block, ds:si -> new library name
  2430 00000D62 268A45FF                    mov al,[es:di-1]        ; get flag byte preceding name
  2431 00000D66 2401                        and al,1                ; see if library module
  2432 00000D68 750A                        jne cld_gobble          ; yes, don't check as a dupe
  2433                                  
  2434                                  cld_cmploop:
  2435 00000D6A 268A05                      mov al,[es:di]
  2436 00000D6D 0A04                        or  al,[si]             ; see if both at terminating zero char
  2437 00000D6F 7410                        je  cld_dupe            ; yes, both names match
  2438 00000D71 A6                          cmpsb                   ; compare a char
  2439 00000D72 74F6                        je  cld_cmploop         ; char matched
  2440                                  
  2441                                  ; didn't match, gobble remaining bytes in block's library name
  2442                                  cld_gobble:
  2443 00000D74 268A05                      mov al,[es:di]          ; check if at end of library name in block
  2444 00000D77 08C0                        or  al,al
  2445 00000D79 7403                        je  cld_3               ; yes
  2446 00000D7B 47                          inc di                  ; bump to next char
  2447 00000D7C EBF6                        jmp cld_gobble
  2448                                  
  2449                                  cld_3:
  2450 00000D7E 47                          inc di                  ; bump to first char of next name in block
  2451 00000D7F EB9E                        jmp SHORT cld_loop      ; and loop back to try next name
  2452                                  
  2453                                  ; names match, pointer to name entry on stack
  2454                                  cld_dupe:
  2455 00000D81 F9                      	stc						; flag that dupe was found
  2456                                  
  2457                                  cld_ret:
  2458 00000D82 5F                          pop di                  ; restore critical register
  2459 00000D83 5E                          pop si
  2460 00000D84 07                          pop es
  2461 00000D85 C3                          ret
  2462                                  check_lib_dupe  ENDP
  2463                                  
  2464                                  get_wllist_obj_file_name:
  2465 00000D86 BF[0000]                	mov di, _wllist_obj_file_name
  2466 00000D89 EB03                    	jmp @F
  2467                                  
  2468                                  get_wllist_temp_file_name:
  2469 00000D8B BF[0000]                	mov di, _wllist_temp_file_name
  2470                                  @@:
  2471 00000D8E 1E                      	push ds
  2472 00000D8F 07                      	pop es
  2473 00000D90 C645FEFF                	mov byte [di - 2], -1
  2474 00000D94 EB0C                    	jmp @F
  2475                                  
  2476                                  ;*****************************
  2477                                  ;* GET_TEMPFILE_NAME         *
  2478                                  ;*****************************
  2479                                  
  2480                                  ; get specified temporary file name
  2481                                  ; upon entry ds:si -> first char of temporary file
  2482                                  ; destroys ax,dx,es
  2483                                  ; updates si
  2484                                  
  2485                                  get_tempfile_name   PROC
  2486 00000D96 8CD8                        mov ax,ds
  2487 00000D98 8EC0                        mov es,ax               ; es -> warplink data segment
  2488 00000D9A C606[0000]01                mov byte [is_tempfile],1       ; flag that temporary file name specified
  2489 00000D9F BF[0000]                    mov di,OFFSET temp_file_name wrt DGROUP ; es:di -> place for overlay class name
  2490                                  @@:
  2491                                  
  2492                                  gtn_2:
  2493 00000DA2 AC                          lodsb                   ; get name char
  2494 00000DA3 E81001                  	call	is_terminator	; see if file name parse terminator
  2495 00000DA6 7403                        je  gtn_done            ; yes, done
  2496                                  
  2497 00000DA8 AA                          stosb                   ; name char, transfer it
  2498 00000DA9 EBF7                        jmp SHORT gtn_2         ; get next char
  2499                                  
  2500                                  gtn_done:
  2501 00000DAB 4E                          dec si                  ; drop si back to -> terminating char
  2502 00000DAC 30C0                        xor al,al               ; null terminate string
  2503 00000DAE AA                          stosb                   ; transfer it
  2504 00000DAF C3                          ret                     ; done
  2505                                  get_tempfile_name   ENDP
  2506                                  
  2507                                  ;*****************************
  2508                                  ;* GET_ENV_OPTIONS           *
  2509                                  ;*****************************
  2510                                  
  2511                                  ; get any options from the WARPLINK= environment variable
  2512                                  ; destroys ax,bx,cx,dx,di,si,es
  2513                                  
  2514                                  get_env_options PROC
  2515                                  
  2516                                  ; check for WARPLINK= in the environment
  2517 00000DB0 BB[0000]                    mov bx,OFFSET linktext wrt DGROUP   ; bx holds target string address for compares
  2518 00000DB3 A1[0000]                    mov ax,[psp]
  2519 00000DB6 8EC0                        mov es,ax               ; es -> warplink's PSP
  2520 00000DB8 31F6                        xor si,si               ; starting location for target string check
  2521 00000DBA 26A12C00                    mov ax,[es:2ch]         ; get environment segment from offset 2ch in PSP
  2522 00000DBE 85C0                    	test ax, ax		; environment valid ?
  2523 00000DC0 744E                    	jz geo_ret		; no -->
  2524 00000DC2 8EC0                        mov es,ax               ; es -> environment segment
  2525                                  
  2526                                  geo_find_link:
  2527 00000DC4 31FF                        xor di,di               ; offset into target string
  2528                                  
  2529                                  geo_loop:
  2530 00000DC6 268A04                      mov al,[es:si]          ; get byte from environment string
  2531 00000DC9 46                          inc si                  ; point to next char in environment
  2532 00000DCA 3A01                        cmp al,[bx+di]          ; does environment char match WARPLINK string char
  2533 00000DCC 7407                        je  geo_byte_match      ; yes, try next location
  2534 00000DCE 260A04                      or  al,[es:si]          ; two zero values in a row mean the end of the environment
  2535 00000DD1 75F1                        jne geo_find_link       ; not the end of the environment
  2536 00000DD3 EB3B                        jmp SHORT geo_ret       ; at end of environment, no WARPLINK environment char
  2537                                  
  2538                                  ; check that WARPLINK is not part of another environment string
  2539                                  geo_byte_match:
  2540 00000DD5 09FF                        or  di,di               ; di is zero if first char is matched
  2541 00000DD7 750C                        jne geo_2               ; not first char, test already done
  2542 00000DD9 83FE01                      cmp si,1                ; si equals one if WARPLINK is first string in environment block
  2543 00000DDC 7407                        je  geo_2               ; no previous environment string
  2544 00000DDE 26807CFE00                  cmp BYTE PTR [es:si-2],0    ; check if char before WARPLINK was nonzero
  2545 00000DE3 75DF                        jne geo_find_link       ; yes, WARPLINK is a subset of another string, keep looking
  2546                                  
  2547                                  geo_2:
  2548 00000DE5 47                          inc di                  ; a match, move to next byte of target string
  2549 00000DE6 83FF09                      cmp di,9                ; check if all bytes matched
  2550 00000DE9 72DB                        jb  geo_loop            ; not yet, keep comparing
  2551                                  
  2552                                  ; transfer options to env_opt_storage bytes
  2553                                  geo_found:
  2554 00000DEB 06                      	push	es
  2555 00000DEC 1E                      	push	ds
  2556 00000DED 07                      	pop	es
  2557 00000DEE 1F                      	pop	ds					; es -> warplink data, ds -> environment options
  2558 00000DEF BF[0000]                    mov di,OFFSET env_opt_storage wrt DGROUP
  2559                                  
  2560                                  geo_3:
  2561 00000DF2 A4                          movsb                   ; transfer an option char
  2562 00000DF3 803C00                      cmp BYTE PTR [si],0     ; see if terminator zero char transferred
  2563 00000DF6 75FA                        jne geo_3               ; no, keep transferring
  2564                                  
  2565 00000DF8 06                      	push	es
  2566 00000DF9 1F                      	pop	ds					; restore ds -> warplink data
  2567 00000DFA BE[0000]                    mov si,OFFSET env_opt_storage wrt DGROUP    ; ds:si -> options
  2568                                  
  2569                                  geo_4:
  2570 00000DFD AC                          lodsb                   ; get char from command line string
  2571 00000DFE 08C0                        or  al,al               ; if zero then done
  2572 00000E00 740E                        je  geo_ret
  2573 00000E02 3C20                        cmp al,' '              ; see if whitespace char
  2574 00000E04 76F7                        jbe geo_4               ; yes, ignore it
  2575 00000E06 3C2F                        cmp al,'/'              ; see if option indicator
  2576 00000E08 7401                        je  geo_5               ; yes, call set_option routine
  2577                                  
  2578                                  ; assume an option without leading '/', backup si one space
  2579 00000E0A 4E                          dec si
  2580                                  
  2581                                  geo_5:
  2582 00000E0B E86DF4                      call    set_option      ; set the appropriate option
  2583 00000E0E EBED                        jmp SHORT geo_4         ; loop for next option
  2584                                  
  2585                                  geo_ret:
  2586 00000E10 C3                          ret
  2587                                  get_env_options ENDP
  2588                                  
  2589                                  ;*****************************
  2590                                  ;* FILE_NOT_FOUND            *
  2591                                  ;*****************************
  2592                                  
  2593                                  ; upon entry ax holds error code from file open or check for existence
  2594                                  ; if not a file not found variation, abort to dos with error
  2595                                  ; no registers modified
  2596                                  
  2597                                  file_not_found	PROC
  2598 00000E11 83F802                      cmp ax,2                ; check for file not found error
  2599 00000E14 740D                        je  fnf_ok              ; yes
  2600 00000E16 83F803                      cmp ax,3                ; check if path not found or file doesn't exist error
  2601 00000E19 7408                        je  fnf_ok              ; yes
  2602 00000E1B 83F805                      cmp ax,5                ; check for access denied (not in current directory)
  2603 00000E1E 7403                        je  fnf_ok
  2604 00000E20 E9(0000)                    jmp NEAR PTR dos_error  ; no, dos error
  2605                                  
  2606                                  fnf_ok:
  2607 00000E23 C3                      	ret
  2608                                  file_not_found	ENDP
  2609                                  
  2610                                  %IFNDEF DEMO
  2611                                  
  2612                                  ;*****************************
  2613                                  ;* PARSE_UDL_OPTION          *
  2614                                  ;*****************************
  2615                                  
  2616                                  ; parse /udl option, get DDL library name
  2617                                  ; ds:si -> second  char of option (past 'U')
  2618                                  ; cx -> start of option
  2619                                  ; destroys ax,bx,dx,di,es
  2620                                  ; updates si
  2621                                  
  2622                                  parse_udl_option    PROC
  2623 00000E24 8CD8                        mov ax,ds
  2624 00000E26 8EC0                        mov es,ax               ; es -> warplink data
  2625 00000E28 AC                          lodsb                   ; get second option char
  2626 00000E29 24DF                        and al,0dfh             ; force char to uppercase
  2627 00000E2B 3C44                        cmp al,'D'              ; check if correct
  2628 00000E2D 7563                        jne puo_bad             ; no
  2629 00000E2F AC                          lodsb                   ; get third option char
  2630 00000E30 24DF                        and al,0dfh             ; force char to uppercase
  2631 00000E32 3C4C                        cmp al,'L'              ; check if correct
  2632 00000E34 755C                        jne puo_bad             ; no
  2633 00000E36 AC                          lodsb                   ; get colon
  2634 00000E37 3C3A                        cmp al,':'
  2635 00000E39 7557                        jne puo_bad
  2636                                  
  2637 00000E3B A0[0100]                    mov al,[ddl_depend_count]	; bump count of ddl's used
  2638 00000E3E FEC0                        inc al
  2639 00000E40 3C0F                        cmp al,15
  2640 00000E42 774E                        ja  puo_bad             ; too many ddl's specified (15 max)
  2641                                  ;***    je  puo_bad             ; too many ddl's specified (255 max)
  2642 00000E44 A2[0000]                    mov [use_ddl],al
  2643 00000E47 A2[0100]                	mov	[ddl_depend_count],al
  2644                                  
  2645 00000E4A BB0500                      mov bx,5                ; allocate 5 paragraphs to hold ddl name
  2646 00000E4D E8(0000)                    call    alloc_memory    ; get memory for block allocation
  2647 00000E50 8EC0                        mov es,ax               ; es -> ddl name block (1 entry/block)
  2648 00000E52 31C0                        xor ax,ax
  2649 00000E54 89C7                        mov di,ax
  2650 00000E56 AB                          stosw                   ; zero first word pointer of block
  2651                                  
  2652 00000E57 A1[0600]                    mov ax,[first_udlent_ptr] ; get first pointer to ddl name used
  2653 00000E5A 09C0                        or  ax,ax               ; see if exists
  2654 00000E5C 8CC0                        mov ax,es               ; get current pointer before conditional jump
  2655 00000E5E 7505                        jne puo_2               ; first pointer exists
  2656                                  
  2657 00000E60 A3[0600]                    mov [first_udlent_ptr],ax ; save first pointer
  2658 00000E63 EB0C                        jmp SHORT puo_3
  2659                                  
  2660                                  puo_2:
  2661 00000E65 8E1E[0800]                  mov ds,[alloc_udlent_ptr] ; ds -> previously last allocated block
  2662 00000E69 A30000                      mov [0],ax           ; save pointer to next (new) block
  2663 00000E6C BA[ssss]                    mov dx,DGROUP
  2664 00000E6F 8EDA                        mov ds,dx               ; restore ds -> warplink data
  2665                                  
  2666                                  puo_3:
  2667 00000E71 A3[0800]                    mov [alloc_udlent_ptr],ax ; save segment of last allocated block
  2668                                  
  2669                                  ; ds:si -> dynamic library name
  2670 00000E74 31D2                        xor dx,dx               ; dx holds count of chars in name
  2671 00000E76 89D3                        mov bx,dx               ; nonzero bx flags that '.' was encountered
  2672                                  
  2673                                  puo_loop:
  2674 00000E78 AC                          lodsb                   ; get name char
  2675 00000E79 E83A00                  	call	is_terminator	; see if at end of file name parse
  2676 00000E7C 741A                        je 	puo_done            ; yes, at end of name
  2677 00000E7E 3C3A                        cmp al,':'              ; see if colon
  2678 00000E80 7410                        je  puo_bad             ; yes, bad option, no drivespecs allowed
  2679 00000E82 3C5C                        cmp al,'\'              ; see if backslash
  2680 00000E84 740C                        je  puo_bad             ; yes, bad option, no pathspecs allowed
  2681 00000E86 3C2E                        cmp al,'.'              ; see if period encountered
  2682 00000E88 7501                        jne puo_trans           ; no
  2683 00000E8A 43                          inc bx                  ; flag period in name
  2684                                  
  2685                                  puo_trans:
  2686 00000E8B AA                          stosb                   ; transfer name char
  2687 00000E8C 42                          inc dx                  ; bump count of chars in name
  2688 00000E8D 80FA0C                      cmp dl,12               ; make sure no more than 12 chars
  2689 00000E90 76E6                        jbe puo_loop            ; loop back for next char
  2690                                  
  2691                                  puo_bad:                    ; bad option specified
  2692 00000E92 B80500                      mov ax,BAD_OPTION_ERR   ; error value
  2693 00000E95 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
  2694                                  
  2695                                  puo_done:
  2696 00000E98 08D2                        or  dl,dl               ; make sure at least one character
  2697 00000E9A 74F6                        je  puo_bad             ; no, bad option
  2698 00000E9C 4E                          dec si                  ; drop si back to -> terminating char
  2699 00000E9D 09DB                        or  bx,bx               ; see if period was in name
  2700 00000E9F 7511                        jne puo_term            ; yes
  2701                                  
  2702                                  ; add default DDL extension
  2703 00000EA1 80FA08                      cmp dl,8                ; can't have more than 8 chars in main filename
  2704 00000EA4 77EC                        ja  puo_bad             ; too many
  2705 00000EA6 B02E                        mov al,'.'              ; add .DDL extension
  2706 00000EA8 AA                          stosb
  2707 00000EA9 B044                        mov al,'D'
  2708 00000EAB AA                          stosb
  2709 00000EAC B044                        mov al,'D'
  2710 00000EAE AA                          stosb
  2711 00000EAF B04C                        mov al,'L'
  2712 00000EB1 AA                          stosb
  2713                                  
  2714                                  puo_term:
  2715 00000EB2 30C0                        xor al,al               ; null terminate string
  2716 00000EB4 AA                          stosb                   ; transfer it
  2717                                  ;***    mov al,use_ddl
  2718                                  ;***    mov [es:79],al			; put DDL number at end of list
  2719 00000EB5 C3                          ret
  2720                                  
  2721                                  parse_udl_option    ENDP
  2722                                  
  2723                                  %ENDIF
  2724                                  
  2725                                  ;*****************************
  2726                                  ;* IS_TERMINATOR             *
  2727                                  ;*****************************
  2728                                  
  2729                                  ; check if char in al is parsing terminator '+)(][@/,;' or whitespace
  2730                                  ; return zero flag set if terminator found, reset if not
  2731                                  ; destroys no registers
  2732                                  
  2733                                  is_terminator	PROC
  2734 00000EB6 3C20                    	cmp	al,' '				; check if whitespace
  2735 00000EB8 7705                    	ja	it_2				; no
  2736                                  
  2737                                  ; all whitespace matches, set zero flag
  2738 00000EBA 50                      	push	ax				; save al value
  2739 00000EBB 30C0                    	xor	al,al				; set zero flag
  2740 00000EBD 58                      	pop	ax					; restore al value
  2741 00000EBE C3                      	ret
  2742                                  
  2743                                  it_2:
  2744 00000EBF 3C2B                    	cmp	al,'+'
  2745 00000EC1 741E                    	je	it_ret
  2746 00000EC3 3C29                    	cmp	al,')'
  2747 00000EC5 741A                    	je	it_ret
  2748 00000EC7 3C28                    	cmp	al,'('
  2749 00000EC9 7416                    	je	it_ret
  2750 00000ECB 3C5D                    	cmp	al,']'
  2751 00000ECD 7412                    	je	it_ret
  2752 00000ECF 3C5B                    	cmp	al,'['
  2753 00000ED1 740E                    	je	it_ret
  2754 00000ED3 3C40                    	cmp	al,'@'
  2755 00000ED5 740A                    	je	it_ret
  2756 00000ED7 3C2F                    	cmp	al,'/'
  2757 00000ED9 7406                    	je	it_ret
  2758 00000EDB 3C2C                    	cmp	al,','
  2759 00000EDD 7402                    	je	it_ret
  2760                                  
  2761                                  ; fall through to return on final compare
  2762 00000EDF 3C3B                    	cmp	al,';'
  2763                                  	
  2764                                  it_ret:
  2765 00000EE1 C3                      	ret
  2766                                  is_terminator	ENDP
  2767                                  
  2768                                  END
