     1                                  ;*********************************************************************
     2                                  ;*   MLPASS1A.ASM                                                    *
     3                                  ;*                                                                   *
     4                                  ;*   By:            Michael Devore                                   *
     5                                  ;*   Date:          05/10/93                                         *
     6                                  ;*   Model:         Small                                            *
     7                                  ;*   Version:       2.7                                              *
     8                                  ;*   Assembler:     MASM 5.0                                         *
     9                                  ;*   Environment:   MS-DOS 2.x+                                      *
    10                                  ;*                                                                   *
    11                                  ;*   linker pass 1 routines part A                                   *
    12                                  ;*                                                                   *
    13                                  ;*********************************************************************
    14                                  
    15                                  ;TITLE   WARPLINK mlpass1a
    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  pass1_obj_proc,get_pubdecl_entry,add_pubdef_name
    38                                  PUBLIC  make_pubdecl_blk
    39                                  PUBLIC	proc_cextdef
    40                                  
    41                                  ; variables
    42                                  PUBLIC  parse_complete,name_field
    43                                  ;*** PUBLIC	local_comm_count
    44                                  PUBLIC  segment_rec_index,group_rec_index,frame_number
    45                                  PUBLIC  com_val1,com_val2,libobj_flag,first_pdnameblk_ptr
    46                                  PUBLIC	def_lib_flag,mod_ovl_count,ovl_entry_id
    47                                  PUBLIC	known_clipper,maybe_clipper,symbol_overflow
    48                                  PUBLIC	clipper_segdef_ptr,clipper_symseg_ptr,clipper_segindex
    49                                  PUBLIC	first_clipmod_ptr,current_clipmod_ptr
    50                                  PUBLIC	unique_symbol_count,prev_symbol_count,module_symbol_count
    51                                  PUBLIC	is_summer87,is_clipper5
    52                                  PUBLIC	is_local,is_cextdef
    53                                  PUBLIC	ignore_fixupp_flag
    54                                  
    55                                  ;*****************************
    56                                  ;* Data begins               *
    57                                  ;*****************************
    58                                  
    59                                  .DATA
    60                                  
    61                                  ;*****************************
    62                                  ;* External declarations     *
    63                                  ;*****************************
    64                                  
    65                                  ; variables
    66                                  EXTRN   filename:BYTE
    67                                  EXTRN   in_overlay:BYTE,ovlpub_array_seg:WORD
    68                                  EXTRN   curseg_nearovlpub_count:WORD,curseg_farovlpub_count:WORD
    69                                  EXTRN	writing_qlk_flag:BYTE
    70                                  EXTRN	must_parse_flag:BYTE,clip_fix_compress:BYTE
    71                                  EXTRN   mod_alloc_base:WORD
    72                                  
    73                                  ; initialized local variables
    74                                  
    75                                  ; byte values
    76                                  EVEN                        ; maximize speed on 8086 and better
    77 00000000 00                      def_lib_flag    DB  0       ; nonzero if default library from COMENT record
    78 00000001 00                      maybe_clipper	DB	0		; nonzero if module may be Clipper compiled
    79 00000002 00                      known_clipper	DB	0		; nonzero if current module is known Clipper module
    80 00000003 00                      is_clipper5		DB	0		; nonzero if any known Clipper 5.x program
    81 00000004 00                      is_summer87		DB	0		; nonzero if any known Clipper S'87 program
    82 00000005 00                      symbol_overflow	DB	0		; nonzero if symbol table compaction overflow
    83                                  
    84                                  ; word values
    85                                  EVEN
    86 00000006 0000                    first_pdnameblk_ptr DW  0   ; segment of last allocated pubdef names block
    87 00000008 0000                    clipper_segdef_ptr	DW	0	; current module clipper SYMBOLS segdef pointer
    88 0000000A 0000                    clipper_symseg_ptr	DW	0	; first module SYMBOLS segdef pointer
    89 0000000C 0000                    clipper_segindex	DW	0	; current module SYMBOLS segment index, relative 0
    90 0000000E 0000                    first_clipmod_ptr	DW	0	; pointer to first clipper module entry
    91 00000010 0000                    current_clipmod_ptr	DW	0	; pointer to current clipper module entry
    92 00000012 0000                    module_symbol_count	DW	0	; clipper module current symbol count (from SYMBOLS)
    93 00000014 0000                    unique_symbol_count	DW	0	; total count of unique SYMBOLS symbols up to overflow
    94 00000016 0000                    prev_symbol_count	DW	0	; previous to current module total count of unique SYMBOLS symbols
    95                                  
    96                                  EVEN
    97                                  data_counter:
    98                                  data_wllist_header:
    99                                  .:
   100                                  	istruc TEMPWLLIST
   101 00000018 00<rep Ah>              	iend
   102                                  .size equ $ - .
   103                                  
   104                                  
   105                                  .DATA?
   106                                  
   107                                  ; uninitialized local variables
   108                                  
   109                                  ; byte values
   110                                  EVEN                        ; maximize speed on 8086 and better
   111 00000000 ??                      parse_complete  DB  ?       ; nonzero if record parsing is complete for object module
   112 00000001 ??                      EVEN
   113                                  ;***theadr_count    DB  ?       ; count of THEADR records in object module
   114                                  EVEN
   115 00000002 ??                      which_def       DB  ?       ; 1 if current record is pubdef record, 2 if comdef, 0 otherwise
   116 00000003 ??                      EVEN
   117 00000004 <res 100h>              name_field      DB  256 DUP (?) ; ASCIIZ temporary storage of public, external, etc. name from record
   118                                  EVEN
   119 00000104 ??                      segment_rec_index   DB  ?   ; segment record index in pubdef record
   120 00000105 ??                      EVEN
   121 00000106 ??                      group_rec_index DB  ?       ; group record index in pubdef record
   122 00000107 ??                      EVEN
   123 00000108 ??                      near_communal   DB  ?       ; near communal flag
   124 00000109 ??                      EVEN
   125 0000010A ??                      libobj_flag     DB  ?       ; nonzero if lib being linked as obj
   126 0000010B ??                      EVEN
   127 0000010C ??                      is_local    DB  ?           ; nonzero if local EXTDEF
   128 0000010D ??                      is_cextdef	DB	?			; nonzero if COMDAT EXTDEF
   129 0000010E ??                      ignore_fixupp_flag	DB	?	; nonzero if should ignore following fixupp (LEDATA32)
   130                                  
   131                                  ; word values
   132                                  
   133 0000010F ??                      EVEN
   134 00000110 ????                    frame_number    DW  ?       ; pubdef record frame_number
   135                                  ;***local_comm_count    DW  ?   ; count of true local communal variables for module
   136                                  %IFNDEF JUNIOR
   137 00000112 ????                    mod_ovl_count   DW  ?       ; count of overlaid segments in module
   138 00000114 ????                    ovl_entry_id    DW  ?       ; value of ovl_code_id upon module entry
   139                                  %ENDIF
   140                                  
   141                                  ; doubleword values
   142 00000116 ????????                com_val1    DD  ?           ; communal field value holder
   143 0000011A ????????                com_val2    DD  ?           ; communal field value holder
   144                                  
   145                                  ;*****************************
   146                                  ;* Constant data             *
   147                                  ;*****************************
   148                                  
   149                                  .CONST
   150                                  
   151                                   global string_wllist
   152 00000000 574C4C49535400          string_wllist:	asciz "WLLIST"
   153 00000007 53554D4D4552383700      summer87text	DB	'SUMMER87',0	; EXTDEF name if Clipper S'87 module
   154                                  ;clipper5text	DB	'CLIPPER501',0	; EXTDEF name if Clipper 5.01 module
   155 00000010 434C495050455235        clipper5text	DB	'CLIPPER5'		; EXTDEF name if Clipper 5.01 module
   156 00000018 4335305231303000        clipper5text2	DB	'C50R100',0		; EXTDEF name if Clipper 5.0 module
   157                                  
   158                                  ;*****************************
   159                                  ;* Code begins               *
   160                                  ;*****************************
   161                                  
   162                                  .CODE
   163                                  
   164                                  ;*****************************
   165                                  ;* External declarations     *
   166                                  ;*****************************
   167                                  
   168                                  EXTRN   link_error:NEAR,dos_error:NEAR,get_name:NEAR,load_file:NEAR
   169                                  EXTRN   get_hash:NEAR,alloc_memory:NEAR,link_warning:NEAR
   170                                  EXTRN   proc1_lnames:NEAR,proc1_segdef:NEAR,proc1_grpdef:NEAR
   171                                  EXTRN   make_symbols:NEAR,check_extension:NEAR,save_lib_name:NEAR
   172                                  EXTRN   error_bx_pos:NEAR,error_read_buff_pos:NEAR
   173                                  EXTRN   scan_comfield:NEAR,compute_comm_len:NEAR
   174                                  ;*** EXTRN   proc_locals:NEAR,zero_local_blocks:NEAR,save_local_comm:NEAR
   175                                  EXTRN   chk_pub_in_ovl:NEAR
   176                                  EXTRN   proc1_datarec:NEAR,proc1_fixupp:NEAR
   177                                  EXTRN   flush_publics:NEAR
   178                                  ;*** EXTRN	proc2_lextdef:NEAR
   179                                  EXTRN   update_incinfo:NEAR,check_cliplib:NEAR
   180                                  EXTRN	create_clipmod_entry:NEAR,clip_final_compress:NEAR
   181                                  EXTRN	write_qlk_modsize:NEAR
   182                                  
   183                                  %IFNDEF DEMO
   184                                  EXTRN   save_module_type:NEAR
   185                                  EXTRN	write_ddl_module:NEAR
   186                                  %ENDIF
   187                                  
   188                                  ;*****************************
   189                                  ;* PASS1_OBJ_PROC            *
   190                                  ;*****************************
   191                                  
   192                                  ; parse and process records in object modules
   193                                  ; all registers used or destroyed
   194                                  
   195                                  pass1_obj_proc  PROC
   196 00000000 31F6                        xor si,si               ; si points into buffer for parsed chars
   197 00000002 89F0                        mov ax,si
   198 00000004 A2[0A01]                    mov [libobj_flag],al
   199 00000007 A1[0000]                    mov ax,[buffer_tail]      ; get buffer_tail variable in register for quick compares
   200 0000000A 89C5                        mov bp,ax               ; bp holds variable value
   201                                  
   202                                  ; entry point to process next module if more than one in specified OBJ
   203                                  p1_proc_next:
   204 0000000C FF06[0000]                  inc word [module_count]        ; bump count of total modules (for DDL use)
   205                                  
   206                                  %IFNDEF DEMO
   207 00000010 803E[0000]00                cmp byte [any_ddl],0           ; see if creating or using DDL
   208 00000015 7403                        je  pop_init            ; no
   209 00000017 E8(0000)                    call    save_module_type    ; save the type of module (required/elective, root/overlaid)
   210                                  %ENDIF
   211                                  
   212                                  pop_init:
   213 0000001A 31C0                        xor ax,ax
   214 0000001C A2[0000]                    mov [parse_complete],al   ; init flag indicating record parsing is complete for object module
   215 0000001F A2[0100]                	mov	[maybe_clipper],al	; init flag for Clipper symbol table compression
   216                                  ;***    mov local_comm_count,ax ; init count of local communal variables
   217 00000022 A3[0000]                    mov [current_lnames],ax   ; init count of current record types
   218 00000025 A3[0000]                    mov [current_extdef],ax
   219 00000028 A3[0000]                    mov [current_segdef],ax
   220 0000002B A3[0000]                    mov [current_grpdef],ax
   221 0000002E A2[0000]                    mov [seg_ovlclass],al     ; init overlay class segment in module flag
   222 00000031 A2[0200]                	mov	[known_clipper],al
   223 00000034 A2[0000]                	mov	[must_parse_flag],al	; init symbol compression flags
   224 00000037 A2[0000]                	mov	[clip_fix_compress],al
   225 0000003A A2[0E01]                	mov	[ignore_fixupp_flag],al
   226 0000003D A3[0000]                    mov [_dt_seg_size],ax     ; init clarion data segments
   227 00000040 A3[0000]                    mov [_dat_seg_size],ax
   228 00000043 A3[1201]                    mov [mod_ovl_count],ax    ; init count of overlaid segments in module
   229 00000046 A3[0000]                    mov [curseg_nearovlpub_count],ax  ; init overlay variables
   230 00000049 A3[0000]                    mov [curseg_farovlpub_count],ax
   231 0000004C A3[1200]                	mov	[module_symbol_count],ax	; init current module clipper symbol count
   232 0000004F 48                          dec ax			; = -1
   233 00000050 A3[0000]                    mov [ovlpub_array_seg],ax
   234 00000053 A1[1400]                	mov	ax,[unique_symbol_count]	; save previously unique symbol count in case of restore on overflow
   235 00000056 A3[1600]                	mov	[prev_symbol_count],ax
   236 00000059 A1[0000]                    mov ax,[ovl_code_id]
   237 0000005C A3[1401]                    mov [ovl_entry_id],ax     ; save ovl_code_id entry value
   238                                  ;***    call    zero_local_blocks   ; zero any pre-existing local blocks (don't carry locals to next module)
   239                                  
   240 0000005F 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if udl processing pass
   241 00000064 7406                        je  p1_proc_loop        ; yes, no base reset
   242                                  
   243 00000066 A1[0000]                    mov ax,[allocation_base]
   244 00000069 A3[0000]                    mov [mod_alloc_base],ax   ; save base of allocations for this module
   245                                  
   246                                  p1_proc_loop:
   247 0000006C 8936[0000]                  mov [read_buff_ptr],si    ; keep beginning of object record
   248 00000070 A1[0000]                    mov ax,[buffer_base]      ; get i/o buffer segment
   249 00000073 8EC0                        mov es,ax               ; es -> i/o buffer
   250 00000075 268A04                      mov al,[es:si]          ; get record type
   251                                  
   252                                  pop_2:
   253 00000078 46                          inc si                  ; bump si past record type
   254 00000079 39EE                        cmp si,bp               ; check boundary conditions
   255 0000007B 7203                        jb  pop_2a              ; okay
   256 0000007D E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   257                                  pop_2a:
   258 00000080 268A0C                      mov cl,[es:si]          ; get record length low byte
   259 00000083 46                          inc si
   260 00000084 39EE                        cmp si,bp               ; check boundary conditions
   261 00000086 7203                        jb  pop_2c              ; okay
   262 00000088 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   263                                  
   264                                  pop_2c:
   265 0000008B 268A2C                      mov ch,[es:si]          ; get record length high byte
   266 0000008E 46                          inc si                  ; bump si past length word
   267 0000008F 39EE                        cmp si,bp               ; check boundary conditions
   268 00000091 7203                        jb  pop_2e              ; okay
   269 00000093 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   270                                  
   271                                  ; check that record doesn't exceed file length
   272                                  pop_2e:
   273 00000096 803E[0000]00                cmp byte [eof_flag],0          ; see if end of file encountered
   274 0000009B 7406                        je  len_chk             ; nope
   275 0000009D 89CA                        mov dx,cx               ; get record length
   276 0000009F 01F2                        add dx,si               ; add in current position
   277 000000A1 720F                        jc  unexpected_eof      ; overflow, record file length exceeded
   278                                  
   279                                  len_chk:
   280 000000A3 83F901                      cmp cx,1                ; see if null record
   281 000000A6 7650                        jbe to_update_pos       ; yes, ignore it
   282                                  
   283                                  pop_pubdef:
   284 000000A8 3C90                        cmp al,PUBDEF           ; is it a PUBDEF record
   285 000000AA 750F                        jne pop_extdef
   286                                  
   287                                  pop_pubproc:
   288 000000AC E86701                      call    proc1_pubdef    ; process the record
   289 000000AF E90201                      jmp NEAR PTR parse_chk
   290                                  
   291                                  unexpected_eof:
   292 000000B2 BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   293 000000B5 B80A00                      mov ax,UNEXPECT_EOF_ERR ; unexpected end of file
   294 000000B8 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   295                                  
   296                                  pop_extdef:
   297 000000BB 3C8C                        cmp al,EXTDEF           ; is it an EXTDEF record
   298 000000BD 7506                        jne pop_cextdef
   299                                  
   300                                  pop_extproc:
   301 000000BF E8B203                      call    proc1_extdef    ; process the record
   302 000000C2 E9D600                      jmp NEAR PTR update_pos
   303                                  
   304                                  pop_cextdef:
   305 000000C5 3CBC                    	cmp	al,CEXTDEF			; see if COMDAT EXTDEF record
   306 000000C7 74F6                    	je	pop_extproc			; yes
   307                                  
   308 000000C9 3CB0                        cmp al,COMDEF           ; is it a COMDEF record
   309 000000CB 7506                        jne pop_lnames
   310                                  pop_comproc:
   311 000000CD E89E04                      call    proc1_comdef    ; process the record
   312 000000D0 E9E100                      jmp NEAR PTR parse_chk
   313                                  
   314                                  pop_lnames:
   315 000000D3 3C96                        cmp al,LNAMES           ; is it a LNAMES record
   316 000000D5 7506                        jne pop_segdef
   317 000000D7 E8(0000)                    call    proc1_lnames    ; process the record
   318 000000DA E9D700                      jmp NEAR PTR parse_chk
   319                                  
   320                                  pop_segdef:
   321 000000DD 3C98                        cmp al,SEGDEF           ; is it a SEGDEF record
   322 000000DF 7506                        jne pop_grpdef
   323 000000E1 E8(0000)                    call    proc1_segdef    ; process the record
   324 000000E4 E9CD00                      jmp NEAR PTR parse_chk
   325                                  
   326                                  pop_grpdef:
   327 000000E7 3C9A                        cmp al,GRPDEF           ; is it a GRPDEF record
   328 000000E9 7506                        jne pop_coment
   329 000000EB E8(0000)                    call    proc1_grpdef    ; process the record
   330 000000EE E9C300                      jmp NEAR PTR parse_chk
   331                                  
   332                                  pop_coment:
   333 000000F1 3C88                        cmp al,COMENT           ; is it a COMENT record
   334 000000F3 7506                        jne pop_theadr
   335 000000F5 E8B405                      call    proc1_coment    ; process the record
   336                                  
   337                                  to_update_pos:
   338 000000F8 E9A000                      jmp NEAR PTR update_pos
   339                                  
   340                                  pop_theadr:
   341 000000FB 3C80                        cmp al,THEADR           ; is record a THEADR record
   342 000000FD 7506                        jne pop_lheadr
   343                                  pop_headr:
   344 000000FF E80801                      call    proc1_theadr    ; process the record
   345 00000102 E99600                      jmp NEAR PTR update_pos
   346                                  pop_lheadr:
   347 00000105 3C82                        cmp al,LHEADR           ; is record a LHEADR record
   348 00000107 74F6                        je  pop_headr           ; process the record (LHEADR processes same as THEADR)
   349                                  
   350                                  pop_modend:
   351 00000109 3C8A                        cmp al,MODEND           ; is it a MODEND record
   352 0000010B 7523                        jne pop_mslhed
   353 0000010D A2[0000]                    mov [parse_complete],al   ; al is known nonzero value, put it in parse_complete flag
   354                                  
   355                                  ; check if need to compress out clipper symbols
   356 00000110 803E[0000]00            	cmp	byte [must_parse_flag],0
   357 00000115 7403                    	je	pop_nocomp
   358 00000117 E8(0000)                	call	clip_final_compress	; do clipper symbol compression code
   359                                  
   360                                  pop_nocomp:
   361 0000011A 803E[0000]00                cmp byte [is_clpinc],0         ; see if clipper incremental link in force
   362 0000011F 7403                        je  pop_chkddl          ; no
   363 00000121 E8(0000)                    call    update_incinfo  ; update the incremental link info
   364                                  
   365                                  pop_chkddl:
   366                                  %IFNDEF DEMO
   367 00000124 803E[0000]00                cmp byte [any_ddl],0           ; see if DDL's used
   368 00000129 74CD                        je  to_update_pos       ; no
   369 0000012B E8(0000)                    call    write_ddl_module    ; write DDL module info
   370                                  %ENDIF
   371 0000012E EB6B                        jmp NEAR PTR update_pos
   372                                  
   373                                  pop_mslhed:
   374 00000130 3CF0                        cmp al,MSLHED           ; make library header records valid
   375 00000132 7505                        jne pop_11
   376 00000134 A2[0A01]                    mov [libobj_flag],al      ; set library as object flag
   377 00000137 EB62                        jmp NEAR PTR update_pos
   378                                  
   379                                  pop_11:
   380 00000139 3CB8                        cmp al,LCOMDEF          ; check if local COMDEF
   381 0000013B 7505                        jne pop_11a             ; no
   382 0000013D EB8E                    	jmp	SHORT pop_comproc
   383                                  
   384                                  to_pop_pubproc:
   385 0000013F E96AFF                      jmp NEAR PTR pop_pubproc
   386                                  
   387                                  pop_11a:
   388 00000142 3CB6                        cmp al,LPUBDEF1         ; check if local PUBDEF records
   389 00000144 74F9                    	je	to_pop_pubproc
   390 00000146 3CB7                        cmp al,LPUBDEF2
   391 00000148 74F5                    	je	to_pop_pubproc
   392                                  
   393                                  pop_ledata:
   394 0000014A 3CA0                        cmp al,LEDATA           ; check if a LEDATA record
   395 0000014C 7505                        jne pop_lidata          ; no
   396                                  pop_datarec:
   397 0000014E E8(0000)                    call    proc1_datarec   ; process the data record
   398 00000151 EB48                        jmp SHORT update_pos
   399                                  
   400                                  pop_lidata:
   401 00000153 3CA2                        cmp al,LIDATA           ; check if a LIDATA record
   402 00000155 74F7                        je  pop_datarec         ; yes, process as LEDATA record
   403                                  
   404 00000157 3CB4                        cmp al,LEXTDEF          ; check if a local EXTDEF record
   405 00000159 7503                        jne pop_fixupp          ; no
   406 0000015B E961FF                  	jmp	NEAR PTR pop_extproc
   407                                  
   408                                  pop_fixupp:
   409 0000015E 3C9C                        cmp al,FIXUPP           ; check if a FIXUPP record
   410 00000160 7505                        jne pop_ledata32		; no
   411 00000162 E8(0000)                    call    proc1_fixupp    ; process the fixup
   412 00000165 EB34                        jmp SHORT update_pos
   413                                  
   414                                  pop_ledata32:
   415 00000167 3CA1                        cmp al,LEDATA32			; check if a LEDATA32 record
   416 00000169 7507                        jne pop_valid			; no
   417 0000016B C606[0E01]01            	mov	byte [ignore_fixupp_flag],1	; flag ignore following fixupp
   418 00000170 EB29                        jmp SHORT update_pos
   419                                  
   420                                  pop_valid:
   421 00000172 3C94                        cmp al,LINNUM
   422 00000174 7425                        je  update_pos
   423 00000176 3C92                        cmp al,LOCSYM
   424 00000178 7421                        je  update_pos
   425 0000017A 3C7A                        cmp al,BLKDEF
   426 0000017C 741D                        je  update_pos
   427 0000017E 3C7C                        cmp al,BLKEND
   428 00000180 7419                        je  update_pos
   429 00000182 3C7E                        cmp al,DEBSYM
   430 00000184 7415                        je  update_pos
   431 00000186 3C99                        cmp al,SEGDEF32
   432 00000188 7411                        je  update_pos
   433                                  
   434 0000018A 3C8E                        cmp al,TYPDEF
   435 0000018C 740D                        je  update_pos
   436                                  
   437                                  bad_rectype:
   438 0000018E BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   439 00000191 88C1                        mov cl,al               ; value in cx
   440 00000193 30ED                        xor ch,ch               ; zap high byte
   441 00000195 B80600                      mov ax,BAD_RECTYPE_ERR  ; bad record type
   442 00000198 E9(0000)                    jmp NEAR PTR error_read_buff_pos    ; transfer control to error handler
   443                                  
   444                                  update_pos:                 ; update si to point past record
   445 0000019B 89F2                        mov dx,si               ; save current position prior to update
   446 0000019D 01CE                        add si,cx               ; scan past checksum
   447 0000019F 730F                        jnc pop_12              ; no overflow
   448                                  
   449                                  pop_13:
   450 000001A1 89D6                        mov si,dx               ; restore si to current position
   451 000001A3 89E8                        mov ax,bp               ; get overflow point
   452 000001A5 29F0                        sub ax,si               ; get difference from current position to overflow
   453 000001A7 89EE                        mov si,bp               ; put si at overflow point
   454 000001A9 29C1                        sub cx,ax               ; update cx to account for changed si position
   455 000001AB E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   456 000001AE EBEB                        jmp SHORT update_pos    ; loop back for next attempt
   457                                  
   458                                  pop_12:
   459 000001B0 39EE                        cmp si,bp               ; check boundary conditions
   460 000001B2 73ED                        jae pop_13              ; out of bounds
   461                                  
   462                                  parse_chk:
   463 000001B4 A0[0000]                    mov al,[parse_complete]
   464 000001B7 08C0                        or  al,al               ; see if parsing should continue
   465 000001B9 7503                        jne pop_done            ; parsing complete, return
   466 000001BB E9AEFE                      jmp NEAR PTR p1_proc_loop   ; loop for next record
   467                                  
   468                                  pop_done:
   469 000001BE 31C0                        xor ax,ax
   470                                  
   471                                  %IFNDEF DEMO
   472 000001C0 3806[0000]                  cmp [any_ddl],al          ; see if creating/using DDL's
   473 000001C4 7407                        je  pop_chklocal        ; no
   474 000001C6 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
   475 000001CB 751F                        jne pop_chkmod          ; no, bypass local processing for DDLs
   476                                  %ENDIF
   477                                  
   478                                  pop_chklocal:
   479                                  
   480                                  %if 0 ;COMMENT # **********
   481                                      cmp [local_comm_count],ax ; see if any local communal variables
   482                                      je  pop_done2           ; no
   483                                      call    save_local_comm ; save local communals in comdef declarations for memory allocation
   484                                  ********** END COMMENT #
   485                                  %endif
   486                                  
   487                                  pop_done2:
   488 000001CD A1[0000]                    mov ax,[curseg_nearovlpub_count]
   489 000001D0 0B06[0000]                  or  ax,[curseg_farovlpub_count]   ; see if any overlaid publics not flushed to table
   490 000001D4 7403                        je  pop_done3           ; no
   491 000001D6 E8(0000)                    call    flush_publics
   492                                  
   493                                  pop_done3:
   494 000001D9 31C0                        xor ax,ax
   495 000001DB 3806[0000]                  cmp [is_inlib],al         ; see if processing library
   496 000001DF 740B                    	je	pop_chkmod			; no
   497                                  
   498 000001E1 803E[0000]00            	cmp	byte [writing_qlk_flag],0	; see if writing to QLK file
   499 000001E6 741E                    	je	pop_ret				; no
   500 000001E8 E8(0000)                	call	write_qlk_modsize	; write size of library module to QLK file
   501 000001EB C3                      	ret
   502                                  
   503                                  pop_chkmod:
   504 000001EC 3806[0A01]                  cmp [libobj_flag],al      ; see if library treated as object module
   505 000001F0 7414                        je  pop_ret             ; no
   506                                  
   507 000001F2 268A04                      mov al,[es:si]          ; get next record type
   508 000001F5 3C80                        cmp al,THEADR           ; see if start of new object module
   509 000001F7 740E                        je  pop_more            ; yes
   510 000001F9 3C82                        cmp al,LHEADR           ; see if start of new object module
   511 000001FB 740A                        je  pop_more            ; yes
   512                                  
   513 000001FD 08C0                        or  al,al               ; see if zero (padding)
   514 000001FF 7505                        jne pop_ret             ; no
   515 00000201 B90100                      mov cx,1                ; setup to eat one byte
   516 00000204 EB95                        jmp SHORT update_pos    ; loop back
   517                                  
   518                                  pop_ret:
   519 00000206 C3                          ret
   520                                  
   521                                  pop_more:
   522 00000207 E902FE                      jmp NEAR PTR p1_proc_next   ; get next module in file
   523                                  
   524                                  pass1_obj_proc  ENDP
   525                                  
   526                                  ;*****************************
   527                                  ;* PROC1_THEADR              *
   528                                  ;*****************************
   529                                  
   530                                  ; process THEADR record
   531                                  ; upon entry cx=record length,bp=buffer_end,al=record type
   532                                  ; si -> first byte of record past record length
   533                                  ; destroys ax
   534                                  ; updates si
   535                                  
   536                                  proc1_theadr    PROC
   537 0000020A C606[0C01]00            	mov	byte [is_local],0			; reset local flag for get_name procedure
   538                                  
   539 0000020F BF[0000]                    mov di,OFFSET tmod_name wrt DGROUP  ; di -> field to place name
   540 00000212 E8(0000)                    call    get_name        ; get and save T-module name
   541                                  
   542                                  ; kill check for multiple THEADRs, MSC 6.0 can generate them
   543                                  
   544                                  pt_ret:
   545 00000215 C3                          ret                     ; all done
   546                                  proc1_theadr    ENDP
   547                                  
   548                                  ;*****************************
   549                                  ;* PROC1_PUBDEF              *
   550                                  ;*****************************
   551                                  
   552                                  ; process PUBDEF record
   553                                  ; upon entry cx=record length,bp=buffer_end,al=record type
   554                                  ; si -> first byte of record past record length
   555                                  ; destroys ax,bx,dx,di,es
   556                                  ; updates si
   557                                  
   558                                  proc1_pubdef    PROC
   559 00000216 30E4                        xor ah,ah
   560 00000218 8826[0C01]                  mov [is_local],ah         ; init local flag
   561 0000021C 3CB6                        cmp al,LPUBDEF1         ; see if local
   562 0000021E 7404                        je  pp_local            ; yes
   563 00000220 3CB7                        cmp al,LPUBDEF2         ; check if other local type
   564 00000222 7505                        jne pp_1                ; no
   565                                  
   566                                  pp_local:
   567 00000224 C606[0C01]04                mov byte [is_local],4          ; set local flag
   568                                  
   569                                  pp_1:
   570 00000229 268A14                      mov dl,[es:si]          ; get low byte of group_index
   571 0000022C 80FA15                      cmp dl,GRPDEF_MAX       ; exceeded maximum
   572 0000022F 760B                        jbe pp_2                ; no
   573                                  
   574                                  ; group index too large error
   575                                  pp_bad_grpind:
   576 00000231 88D1                        mov cl,dl               ; get value in cl
   577 00000233 BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   578 00000236 B80800                      mov ax,GRPDEF_VAL_ERR   ; group index value too high
   579 00000239 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   580                                  
   581                                  pp_2:
   582 0000023C 46                          inc si
   583 0000023D 49                          dec cx                  ; decrement record length to parse
   584 0000023E 39EE                        cmp si,bp               ; check boundary conditions
   585 00000240 7203                        jb  pp_3                ; okay
   586 00000242 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   587                                  pp_3:
   588 00000245 A1[0000]                    mov ax,[current_grpdef]   ; get count of current grpdef records in object module
   589 00000248 38C2                        cmp dl,al               ; compare to given group index value
   590 0000024A 77E5                        ja  pp_bad_grpind       ; out of bounds
   591                                  
   592                                  pp_4:
   593 0000024C 268A34                      mov dh,[es:si]          ; get first byte of segment index
   594 0000024F 89F3                        mov bx,si               ; keep offset pointer to index in case of error
   595 00000251 46                          inc si
   596 00000252 49                          dec cx                  ; decrement record length to parse
   597 00000253 39EE                        cmp si,bp               ; check boundary conditions
   598 00000255 7203                        jb  pp_5                ; okay
   599 00000257 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   600                                  
   601                                  pp_5:
   602 0000025A 80FE80                      cmp dh,80h              ; check if high bit set
   603 0000025D 7219                        jb  pp_7                ; no, only 1 byte index
   604                                  
   605                                  ; two byte index, dh contains high-order byte with high bit set
   606 0000025F 740B                        je  pp_6a               ; if greater than 0x80 then segment index > 255, out of bounds
   607                                  
   608                                  pp_bad_segind:
   609 00000261 88F1                        mov cl,dh               ; get value in cl
   610 00000263 BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   611 00000266 B80900                      mov ax,SEGDEF_VAL_ERR   ; segment index greater than 255 maximum, or higher than count of segdef records
   612 00000269 E9(0000)                    jmp NEAR PTR error_bx_pos   ; transfer control to error handler
   613                                  
   614                                  pp_6a:
   615 0000026C 268A34                      mov dh,[es:si]          ; get second byte of segment index
   616 0000026F 46                          inc si
   617 00000270 49                          dec cx                  ; decrement record length to parse
   618 00000271 39EE                        cmp si,bp               ; check boundary conditions
   619 00000273 7203                        jb  pp_7                ; okay
   620 00000275 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   621                                  
   622                                  ; dh contains segment index value, dl contains group index value
   623                                  pp_7:
   624 00000278 A1[0000]                    mov ax,[current_segdef]   ; get count of current segdef records in object module
   625 0000027B 38C6                        cmp dh,al               ; compare to given segment index value
   626 0000027D 77E2                        ja  pp_bad_segind       ; out of bounds
   627                                  
   628 0000027F 08F6                        or  dh,dh               ; see if nonzero segment index
   629 00000281 750D                        jne pp_8                ; yes
   630 00000283 08D2                        or  dl,dl               ; zero segment index, see if zero group index
   631 00000285 7409                        je  pp_8                ; yes
   632                                  
   633                                  ; group and segment index values conflict (segment index zero, group index nonzero)
   634 00000287 BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   635 0000028A B82300                      mov ax,SEG_GRP_CONF_ERR ; PUBDEF group and segment index values conflict
   636 0000028D E9(0000)                    jmp NEAR PTR error_bx_pos   ; transfer control to error handler
   637                                  
   638                                  pp_8:
   639 00000290 31DB                        xor bx,bx               ; zero bx, will contain frame number, if any
   640 00000292 88D0                        mov al,dl
   641 00000294 08F0                        or  al,dh               ; check if both segment and group index value are zero
   642 00000296 7518                        jne pp_12               ; nope
   643                                  
   644                                  ; record contains a frame number
   645 00000298 268A1C                      mov bl,[es:si]          ; get low byte of frame number
   646 0000029B 46                          inc si
   647 0000029C 49                          dec cx                  ; decrement record length to parse
   648 0000029D 39EE                        cmp si,bp               ; check boundary conditions
   649 0000029F 7203                        jb  pp_11               ; okay
   650 000002A1 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   651                                  
   652                                  pp_11:
   653 000002A4 268A3C                      mov bh,[es:si]          ; get high byte of frame number
   654 000002A7 46                          inc si
   655 000002A8 49                          dec cx                  ; decrement record length to parse
   656 000002A9 39EE                        cmp si,bp               ; check boundary conditions
   657 000002AB 7203                        jb  pp_12               ; okay
   658 000002AD E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   659                                  
   660                                  ; bx contains frame number, zero if none
   661                                  ; dh holds segment index value, dl holds group index value
   662                                  pp_12:
   663 000002B0 8836[0401]                  mov [segment_rec_index],dh    ; save values to memory variables
   664 000002B4 8816[0601]                  mov [group_rec_index],dl
   665 000002B8 891E[1001]                  mov [frame_number],bx
   666 000002BC 83F901                      cmp cx,1                ; see if empty PUBDEF
   667 000002BF 7703                        ja  pp_loop             ; no
   668 000002C1 E9A701                      jmp NEAR PTR pp_out     ; yes
   669                                  
   670                                  pp_loop:
   671 000002C4 BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at field to place name
   672 000002C7 E8(0000)                    call    get_name        ; get public name from record
   673                                  
   674                                  do_wllist_save_pubdef:
   675 000002CA D006[0000]              	rol byte [is_wllist_enabled], 1
   676 000002CE 7203E9A100              	jnc .skip
   677 000002D3 06                      	push es
   678 000002D4 56                      	push si
   679 000002D5 51                      	push cx
   680 000002D6 1E                      	 push ds
   681 000002D7 07                      	 pop es			; => DGROUP
   682 000002D8 BE[0400]                	mov si, name_field	; -> name stored, ASCIZ
   683 000002DB 813C2E2E                	cmp word [si], ".."
   684 000002DF 7509                    	jne @F
   685 000002E1 807C0240                	cmp byte [si + 2], '@'
   686 000002E5 7503                    	jne @F
   687 000002E7 83C603                  	add si, 3
   688                                  @@:
   689 000002EA BF[0000]                	mov di, string_wllist
   690                                  @@:
   691 000002ED A6                      	cmpsb
   692 000002EE 7508                    	jne .check
   693 000002F0 807CFF00                	cmp byte [si - 1], 0
   694 000002F4 75F7                    	jne @B
   695 000002F6 EB79                    	jmp .mismatch_pop
   696                                  .check:
   697 000002F8 26807DFF00              	cmp byte [es:di - 1], 0
   698 000002FD 7572                    	jne .mismatch_pop
   699                                  .match:
   700 000002FF 4E                      	dec si
   701                                  @@:
   702 00000300 AC                      	lodsb
   703 00000301 3C5F                    	cmp al, '_'
   704 00000303 74FB                    	je @B
   705                                  
   706 00000305 B9FFFF                  	mov cx, -1
   707 00000308 31C0                    	xor ax, ax
   708 0000030A BF[0400]                	mov di, name_field
   709 0000030D 57                      	push di
   710 0000030E F2AE                    	repne scasb
   711 00000310 F7D1                    	not cx			; = length including 0
   712 00000312 268805                  	mov byte [es:di], al
   713                                  
   714 00000315 8B1E[0000]              	mov bx, [_wllist_temp_handle]
   715 00000319 F6C101                  	test cl, 1
   716 0000031C 7401                    	jz @F
   717 0000031E 41                      	inc cx			; write the second NUL too (alignment)
   718                                  @@:
   719 0000031F 51                      	push cx
   720 00000320 880E[1800]              	mov byte [data_counter], cl
   721 00000324 BA[1800]                	mov dx, data_wllist_header
   722 00000327 B90A00                  	mov cx, data_wllist_header.size
   723 0000032A A1[0000]                	mov ax, word [current_obj]
   724 0000032D A3[2000]                	mov word [data_wllist_header + twlObjIndex], ax
   725 00000330 B440                    	mov ah, 40h
   726 00000332 CD21                    	int 21h
   727                                   extern restore_ems_map
   728 00000334 E8(0000)                    call    restore_ems_map
   729 00000337 7216                    	jc .doserror
   730 00000339 39C8                    	cmp ax, cx
   731 0000033B 750F                    	jne .shortwrite
   732 0000033D 59                      	pop cx
   733 0000033E 5A                      	pop dx
   734 0000033F B440                    	mov ah, 40h
   735 00000341 CD21                    	int 21h
   736 00000343 E8(0000)                    call    restore_ems_map
   737 00000346 7207                    	jc .doserror
   738 00000348 39C8                    	cmp ax, cx
   739 0000034A 7409                    	je @F
   740                                  .shortwrite:
   741 0000034C B82700                  	mov ax, 27h
   742                                  .doserror:
   743 0000034F BA[0000]                    mov dx,OFFSET _wllist_temp_file_name wrt DGROUP
   744 00000352 E9(0000)                    jmp dos_error		; error writing to file
   745                                  
   746                                  @@:
   747                                  %if 01
   748 00000355 803E[0000]02            	cmp byte [_wllist_debug_flag], 2
   749 0000035A 7215                    	jb @F
   750 0000035C 52                      	push dx
   751 0000035D B402                    	mov ah, 02h
   752 0000035F B20D                    	mov dl, 13
   753 00000361 CD21                    	int 21h
   754 00000363 B402                    	mov ah, 02h
   755 00000365 B20A                    	mov dl, 10
   756 00000367 CD21                    	int 21h
   757 00000369 5A                      	pop dx
   758 0000036A B440                    	mov ah, 40h
   759 0000036C BB0100                  	mov bx, 1
   760 0000036F CD21                    	int 21h
   761                                  @@:
   762                                  %endif
   763                                  
   764                                  .mismatch_pop:
   765 00000371 59                      	pop cx
   766 00000372 5E                      	pop si
   767 00000373 07                      	pop es
   768                                  
   769                                  .skip:
   770 00000374 268A1C                      mov bl,[es:si]          ; get low byte of public offset
   771 00000377 46                          inc si
   772 00000378 49                          dec cx                  ; decrement record length to parse
   773 00000379 39EE                        cmp si,bp               ; check boundary conditions
   774 0000037B 7203                        jb  pp_14               ; okay
   775 0000037D E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   776                                  
   777                                  pp_14:
   778 00000380 268A3C                      mov bh,[es:si]          ; get high byte of public offset
   779 00000383 46                          inc si
   780 00000384 49                          dec cx                  ; decrement record length to parse
   781 00000385 39EE                        cmp si,bp               ; check boundary conditions
   782 00000387 7203                        jb  pp_15               ; okay
   783 00000389 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   784                                  
   785                                  ; gobble the type index value
   786                                  pp_15:
   787 0000038C 268A04                      mov al,[es:si]          ; get low byte of type index
   788 0000038F 46                          inc si
   789 00000390 49                          dec cx                  ; decrement record length to parse
   790 00000391 39EE                        cmp si,bp               ; check boundary conditions
   791 00000393 7203                        jb  ps_15a              ; okay
   792 00000395 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   793                                  ps_15a:
   794 00000398 3C80                        cmp al,80h              ; check if more than one byte index value
   795 0000039A 7209                        jb  pp_16               ; no, continue
   796 0000039C 46                          inc si                  ; scan past second byte
   797 0000039D 49                          dec cx                  ; decrement record length to parse
   798 0000039E 39EE                        cmp si,bp               ; check boundary conditions
   799 000003A0 7203                        jb  pp_16               ; okay
   800 000003A2 E8(0000)                    call    load_file
   801                                  
   802                                  pp_16:
   803 000003A5 BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at name field for get_pubdecl_entry procedure
   804 000003A8 B001                        mov al,1                ; flag to get_pubdecl_entry procedure that current record is a pubdef record
   805 000003AA E82C04                      call    get_pubdecl_entry   ; find or create public declaration entry segment
   806 000003AD 09C0                        or  ax,ax               ; check if it was a duplicate definition (ax==0)
   807 000003AF 7503                        jne pp_17               ; nope
   808 000003B1 E9AF00                      jmp NEAR PTR pp_checksum    ; check for end of record, loop for another
   809                                  
   810                                  pp_17:
   811 000003B4 50                          push    ax              ; save public declaration entry segment
   812                                  
   813 000003B5 BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at name field for add_pubdef_name procedure
   814 000003B8 E81307                      call    add_pubdef_name ; add name to pubdef names block
   815                                  
   816 000003BB 8CC7                        mov di,es               ; save es
   817 000003BD 07                          pop es                  ; es -> public declaration entry
   818 000003BE 2680260F009F                and BYTE PTR [es:15],09fh   ; reset communal bit flags
   819 000003C4 26A30400                    mov [es:4],ax           ; save offset pointer to name in pubdef names block
   820 000003C8 A0[0C01]                    mov al,[is_local]
   821 000003CB 2608060F00                  or  BYTE PTR [es:15],al ; set local flags (if DDL)
   822 000003D0 2689160600                  mov [es:6],dx           ; save segment pointer to name in pubdef names block
   823 000003D5 26891E0800                  mov [es:8],bx           ; save public offset
   824                                  
   825 000003DA A0[0601]                    mov al,[group_rec_index]
   826 000003DD 08C0                        or  al,al               ; see if group index for this pubdef
   827 000003DF 741C                        je  pp_17a              ; no
   828                                  
   829 000003E1 26800E0F0080                or  BYTE PTR [es:15],80h    ; flag that group is associated with public declaration
   830                                  
   831                                  ;get pointer to group entry in ax
   832 000003E7 30E4                        xor ah,ah               ; zap high byte
   833                                  
   834                                  %IFNDEF DEMO
   835 000003E9 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDL's
   836 000003EE 7510                        jne pp_17b              ; yes, use group index value
   837                                  %ENDIF
   838                                  
   839 000003F0 BB[0000]                    mov bx,offset grp_ent_indptr wrt DGROUP ; bx -> base of group index pointer array
   840 000003F3 FEC8                        dec al                  ; make segment index value relative zero
   841 000003F5 D1E0                        shl ax,1                ; make group index value a word offset into index pointer array
   842 000003F7 01C3                        add bx,ax               ; bx -> proper group index array element
   843 000003F9 8B07                        mov ax,[bx]             ; get segment pointer to group entry
   844 000003FB EB03                        jmp SHORT pp_17b        ; save pointer to group entry
   845                                  
   846                                  pp_17a:
   847 000003FD A1[1001]                    mov ax,[frame_number]     ; get frame number
   848                                  
   849                                  pp_17b:
   850 00000400 26A30200                    mov [es:2],ax           ; save frame number/pointer to group entry
   851                                  
   852                                  pp_nofrptr:
   853 00000404 A0[0401]                    mov al,[segment_rec_index]
   854 00000407 0A06[0601]                  or  al,[group_rec_index]  ; al is zero only if frame number (absolute public)
   855 0000040B 7508                        jne pp_not_abs
   856                                  
   857                                  ; absolute public declaration
   858 0000040D 26C6060E0003                mov BYTE PTR [es:14],3  ; flag that it was an absolute public entry
   859 00000413 EB0C                        jmp SHORT pp_17c
   860                                  
   861                                  pp_not_abs:
   862 00000415 26A00400                	mov	al,[es:4]
   863 00000419 2420                    	and	al,20h				; save clipper symbol bit
   864 0000041B 0402                    	add	al,2				; flag as pubdef entry
   865 0000041D 26A20E00                    mov BYTE PTR [es:14],al	; flag that it was a pubdef entry
   866                                  
   867                                  pp_17c:
   868 00000421 8A16[0401]                  mov dl,[segment_rec_index]
   869 00000425 08D2                        or  dl,dl               ; was there a segment index
   870 00000427 742E                        je  pp_18               ; no, bypass segment partition entry code
   871                                  
   872 00000429 30F6                        xor dh,dh               ; zap high byte
   873 0000042B BB[0000]                    mov bx,offset seg_defent_indptr wrt DGROUP  ; set bx to base of segment index pointer array
   874 0000042E FECA                        dec dl                  ; make segment index value relative zero
   875 00000430 D1E2                        shl dx,1                ; make segment index value a word offset into index pointer array
   876 00000432 01D3                        add bx,dx               ; bx -> proper segment index array element
   877 00000434 8B07                        mov ax,[bx]             ; get segment pointer to segdef entry
   878 00000436 8CC3                        mov bx,es               ; save es -> pubdef entry
   879 00000438 8EC0                        mov es,ax               ; es -> segdef entry
   880 0000043A 26A11800                    mov ax,[es:24]          ; get pointer to last segment partition entry
   881 0000043E 8EC3                        mov es,bx               ; restore es -> pubdef entry
   882 00000440 26A30000                    mov [es:0],ax           ; save segment partition entry pointer
   883                                  
   884                                  ; see if public is in an overlay, zero group entry pointer if necessary
   885 00000444 E8(0000)                    call    chk_pub_in_ovl  ; set overlay flag if in overlay
   886                                  
   887                                  %IFNDEF DEMO
   888 00000447 803E[0000]00                cmp byte [any_ddl],0           ; see if creating/using DDL
   889 0000044C 7409                        je  pp_18               ; no
   890 0000044E A0[0401]                    mov al,[segment_rec_index]
   891 00000451 30E4                        xor ah,ah
   892 00000453 26A30000                    mov [es:0],ax           ; using DDL's, save segment index instead of pointer
   893                                  %ENDIF
   894                                  
   895                                  pp_18:
   896 00000457 8EC7                        mov es,di               ; restore es
   897 00000459 8306[0000]01                add WORD [pub_sym_count],1    ; update low word count
   898 0000045E 8316[0200]00                adc WORD [pub_sym_count+2],0  ; add in carry from low word, if any
   899                                  
   900                                  pp_checksum:
   901 00000463 83F901                      cmp cx,1                ; check if at checksum byte
   902 00000466 7603                        jbe pp_out              ; yes, gobble it and return
   903 00000468 E959FE                      jmp NEAR PTR pp_loop    ; loop back for next definition
   904                                  
   905                                  pp_out:
   906 0000046B 46                          inc si                  ; bump past checksum byte
   907 0000046C 39EE                        cmp si,bp               ; check boundary conditions
   908 0000046E 7203                        jb  pp_ret              ; okay
   909 00000470 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   910                                  
   911                                  pp_ret:
   912 00000473 C3                          ret
   913                                  proc1_pubdef    ENDP
   914                                  
   915                                  ;*****************************
   916                                  ;* PROC1_EXTDEF              *
   917                                  ;*****************************
   918                                  
   919                                  ; process EXTDEF record
   920                                  ; upon entry cx=record length,bp=buffer_end,al=record type
   921                                  ; si -> first byte of record past record length
   922                                  ; updates si
   923                                  ; destroys ax,bx,dx,di
   924                                  
   925                                  proc1_extdef    PROC
   926 00000474 30E4                        xor ah,ah
   927 00000476 8826[0C01]                  mov [is_local],ah         ; init local flag
   928 0000047A 8826[0D01]              	mov	[is_cextdef],ah		; init comdat extdef flag
   929 0000047E 3CB4                        cmp al,LEXTDEF          ; see if local
   930 00000480 7505                        jne pe_1				; no
   931 00000482 C606[0C01]04                mov byte [is_local],4          ; set local flag
   932                                  
   933                                  pe_1:
   934 00000487 3CBC                        cmp al,CEXTDEF          ; see if COMDAT extdef
   935 00000489 7503                        jne pe_loop				; no
   936 0000048B A2[0D01]                	mov	[is_cextdef],al		; yes, flag it
   937                                  
   938                                  pe_loop:
   939 0000048E 803E[0D01]00            	cmp	byte [is_cextdef],0		; see if COMDAT extdef
   940 00000493 7405                    	je	pe_notcext			; no
   941 00000495 E8DB06                  	call	proc_cextdef	; parse COMDAT extdef entry
   942 00000498 EB72                    	jmp	SHORT pe_2a			; process regular extdef parsing
   943                                  
   944                                  pe_notcext:
   945 0000049A BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at field to place name
   946 0000049D E8(0000)                    call    get_name        ; get public name from record
   947                                  
   948                                  ; see if maybe_clipper set and !known_clipper and !overflowed symbol table,
   949                                  ; if so, check if name is SUMMER87 or CLIPPER5, 
   950                                  ; if so set known_clipper and is_summer87 or
   951                                  ; is_clipper5 variables appropriately
   952 000004A0 30C0                    		xor	al,al
   953 000004A2 3806[0100]              	cmp	[maybe_clipper],al	; check if symbol table compression on and possible clipper module
   954 000004A6 744B                    	je	pe_gettype			; no
   955 000004A8 3806[0200]              	cmp	[known_clipper],al	; see if module already known clipper
   956 000004AC 7545                    	jne	pe_gettype			; yes
   957 000004AE 3806[0500]              	cmp	[symbol_overflow],al	; see if overflowed symbol table
   958 000004B2 753F                    	jne	pe_gettype			; yes
   959                                  
   960 000004B4 06                      	push	es				; save critical registers
   961 000004B5 56                      	push	si
   962 000004B6 51                      	push	cx
   963                                  
   964 000004B7 1E                      	push	ds
   965 000004B8 07                      	pop	es
   966 000004B9 B001                    	mov	al,1
   967 000004BB BF[0700]                	mov	di,OFFSET summer87text wrt DGROUP
   968 000004BE BE[0400]                	mov	si,OFFSET name_field wrt DGROUP
   969 000004C1 B90900                  	mov	cx,9				; nine chars in name, including null terminator
   970 000004C4 F3A6                    	repe	cmpsb			; compare extdef name to summer87
   971 000004C6 7505                    	jne	pe_chk5				; didn't match
   972                                  
   973                                  ; clipper summer87 module
   974 000004C8 A2[0400]                	mov	[is_summer87],al		; flag as such
   975 000004CB EB1D                    	jmp	SHORT pe_clipmod
   976                                  
   977                                  pe_chk5:
   978 000004CD BF[1000]                	mov	di,OFFSET clipper5text wrt DGROUP
   979 000004D0 BE[0400]                	mov	si,OFFSET name_field wrt DGROUP
   980                                  ;	mov	cx,11				; eleven chars in name
   981 000004D3 B90800                  	mov	cx,8				; eight chars in name
   982 000004D6 F3A6                    	repe	cmpsb			; compare extdef name to clipper5
   983 000004D8 740D                    	je	pe_isclip5			; is clipper5
   984                                  
   985 000004DA BF[1800]                	mov	di,OFFSET clipper5text2 wrt DGROUP
   986 000004DD BE[0400]                	mov	si,OFFSET name_field wrt DGROUP
   987 000004E0 B90800                  	mov	cx,8				; eight chars in name
   988 000004E3 F3A6                    	repe	cmpsb			; compare extdef name to c50r100
   989 000004E5 7509                    	jne	pe_vardone			; didn't match
   990                                  
   991                                  ; clipper 5 module
   992                                  pe_isclip5:
   993 000004E7 A2[0300]                	mov	[is_clipper5],al		; flag as such
   994                                  
   995                                  pe_clipmod:
   996 000004EA A2[0200]                	mov	[known_clipper],al	; flag known clipper module
   997 000004ED E8(0000)                	call	create_clipmod_entry	; create clipper module entry
   998                                  
   999                                  pe_vardone:
  1000 000004F0 59                      	pop	cx					; restore critical registers
  1001 000004F1 5E                      	pop	si
  1002 000004F2 07                      	pop	es
  1003                                  
  1004                                  pe_gettype:
  1005 000004F3 268A04                      mov al,[es:si]          ; get type index byte
  1006 000004F6 46                          inc si                  ; scan past first type index byte
  1007 000004F7 49                          dec cx                  ; decrement record length to parse
  1008 000004F8 39EE                        cmp si,bp               ; check boundary conditions
  1009 000004FA 7203                        jb  pe_2                ; okay
  1010 000004FC E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1011                                  
  1012                                  pe_2:
  1013 000004FF 2480                        and al,80h              ; see if two-byte type index 
  1014 00000501 7409                        je  pe_2a               ; no
  1015 00000503 46                          inc si                  ; scan past second type index byte
  1016 00000504 49                          dec cx                  ; decrement record length to parse
  1017 00000505 39EE                        cmp si,bp               ; check boundary conditions
  1018 00000507 7203                        jb  pe_2a               ; okay
  1019 00000509 E8(0000)                    call    load_file
  1020                                  
  1021                                  pe_2a:
  1022 0000050C BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at name field for get_pubdecl_entry procedure
  1023 0000050F 30C0                        xor al,al               ; flag to get_pubdecl_entry procedure that current record is an extdef record
  1024 00000511 E8C502                      call    get_pubdecl_entry   ; find or create public declaration entry segment
  1025                                  
  1026                                  ; keep public declaration segment in ext_defint_indptr array if overlays
  1027 00000514 09C0                        or  ax,ax               ; see if returned ax was null
  1028 00000516 7402                        je  pe_2b               ; yes, use returned value in dx
  1029 00000518 89C2                        mov dx,ax               ; no, set dx to ax return value
  1030                                  pe_2b:
  1031 0000051A BB[0000]                    mov bx,OFFSET ext_defent_indptr wrt DGROUP    ; bx -> base of array pointers to extdef'ed public entries
  1032 0000051D 8B3E[0000]                  mov di,[current_extdef]   ; get array element (current extdef number)
  1033 00000521 D1E7                        shl di,1                ; make di a word offset
  1034 00000523 01FB                        add bx,di               ; bx -> proper array element
  1035 00000525 8917                        mov [bx],dx             ; save pointer to public declaration entry
  1036                                  
  1037                                  %IFNDEF DEMO
  1038 00000527 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDL's
  1039 0000052C 740C                        je  pe_noddl            ; no
  1040                                  
  1041                                  ; using DDLs, set bit 1 (2) in general flag in case external was
  1042                                  ; later declared in PUBDEF
  1043 0000052E 8CC7                        mov di,es
  1044 00000530 8EC2                        mov es,dx               ; es -> public entry
  1045 00000532 26800E0F0002                or  BYTE PTR [es:15],2h ; set external flag
  1046 00000538 8EC7                        mov es,di
  1047                                  %ENDIF
  1048                                  
  1049                                  pe_noddl:
  1050 0000053A 09C0                        or  ax,ax               ; check if it was a duplicate declaration (ax==0)
  1051 0000053C 7423                        je  pe_checksum         ; yes, already declared
  1052                                  
  1053                                  pe_3:
  1054 0000053E 50                          push    ax              ; save public declaration entry segment
  1055 0000053F BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at name field for add_pubdef_name procedure
  1056 00000542 E88905                      call    add_pubdef_name ; add name to pubdef names block
  1057                                  
  1058 00000545 8CC7                        mov di,es               ; save es
  1059 00000547 07                          pop es                  ; es -> public declaration entry
  1060 00000548 26A30400                    mov [es:4],ax           ; save offset pointer to name in pubdef names block
  1061 0000054C 2689160600                  mov [es:6],dx           ; save segment pointer to name in pubdef names block
  1062 00000551 26C6060E0081                mov BYTE PTR [es:14],81h    ; flag as extdef entry, unknown strong or weak
  1063 00000557 A0[0C01]                    mov al,[is_local]
  1064 0000055A 2608060F00                  or  BYTE PTR [es:15],al ; set local flag (if using DDLs)
  1065 0000055F 8EC7                        mov es,di               ; restore es
  1066                                  
  1067                                  pe_checksum:
  1068 00000561 FF06[0000]                  inc word [current_extdef]      ; update global memory variable
  1069 00000565 83F901                      cmp cx,1                ; check if at checksum byte
  1070 00000568 7603                        jbe pe_ret              ; yes, return
  1071 0000056A E921FF                      jmp NEAR PTR pe_loop    ; loop back for next definition
  1072                                  
  1073                                  pe_ret:
  1074 0000056D C3                          ret
  1075                                  proc1_extdef    ENDP
  1076                                  
  1077                                  %IFNDEF JUNIOR
  1078                                  
  1079                                  ;*****************************
  1080                                  ;* PROC1_COMDEF              *
  1081                                  ;*****************************
  1082                                  
  1083                                  ; process COMDEF record
  1084                                  ; upon entry cx=record length,bp=buffer_end,al=record type
  1085                                  ; si -> first byte of record past record length
  1086                                  ; updates si
  1087                                  ; destroys ax,bx,dx,di
  1088                                  
  1089                                  proc1_comdef    PROC
  1090 0000056E 30E4                        xor ah,ah
  1091 00000570 8826[0C01]                  mov [is_local],ah         ; init local flag
  1092 00000574 3CB8                        cmp al,LCOMDEF          ; see if local
  1093 00000576 7505                        jne pcf_loop            ; no
  1094 00000578 C606[0C01]20                mov byte [is_local],20h        ; set local flag
  1095                                  
  1096                                  pcf_loop:
  1097 0000057D 31C0                        xor ax,ax
  1098 0000057F A3[1601]                    mov WORD PTR [com_val1],ax    ; init communal value variables
  1099 00000582 A3[1801]                    mov WORD PTR [com_val1+2],ax
  1100 00000585 A3[1A01]                    mov WORD PTR [com_val2],ax
  1101 00000588 A3[1C01]                    mov WORD PTR [com_val2+2],ax
  1102 0000058B BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at field to place name
  1103 0000058E E8(0000)                    call    get_name        ; get public name from record
  1104                                  
  1105 00000591 268A04                      mov al,[es:si]          ; get type index byte
  1106 00000594 46                          inc si                  ; scan past first type index byte
  1107 00000595 49                          dec cx                  ; decrement record length to parse
  1108 00000596 39EE                        cmp si,bp               ; check boundary conditions
  1109 00000598 7203                        jb  pcf_2               ; okay
  1110 0000059A E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1111                                  
  1112                                  pcf_2:
  1113 0000059D 2480                        and al,80h              ; see if two-byte type index 
  1114 0000059F 7409                        je  pcf_2a              ; no
  1115 000005A1 46                          inc si                  ; scan past second type index byte
  1116 000005A2 49                          dec cx                  ; decrement record length to parse
  1117 000005A3 39EE                        cmp si,bp               ; check boundary conditions
  1118 000005A5 7203                        jb  pcf_2a              ; okay
  1119 000005A7 E8(0000)                    call    load_file
  1120                                  
  1121                                  pcf_2a:
  1122 000005AA 268A14                      mov dl,[es:si]          ; get data segment type
  1123 000005AD 89F3                        mov bx,si               ; save offset in case of error
  1124 000005AF 46                          inc si
  1125 000005B0 49                          dec cx                  ; decrement record length to parse
  1126 000005B1 39EE                        cmp si,bp               ; check boundary conditions
  1127 000005B3 7203                        jb  pcf_2b              ; okay
  1128 000005B5 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1129                                  
  1130                                  pcf_2b:
  1131 000005B8 268A34                      mov dh,[es:si]          ; get low byte of variable size (NEAR)/number of elements (FAR)
  1132 000005BB 80FA61                      cmp dl,61h              ; check if FAR variable
  1133 000005BE 7528                        jne pcf_3
  1134 000005C0 89F3                        mov bx,si               ; save offset in case of error
  1135 000005C2 BF[1601]                    mov di,OFFSET com_val1 wrt DGROUP   ; di -> first communal value field
  1136 000005C5 E8(0000)                    call    scan_comfield   ; scan past communal length field number of elements
  1137 000005C8 268A34                      mov dh,[es:si]          ; get low byte of element size
  1138 000005CB 89F3                        mov bx,si               ; save offset in case of error
  1139 000005CD BF[1A01]                    mov di,OFFSET com_val2 wrt DGROUP   ; di -> second communal value field
  1140 000005D0 E8(0000)                    call    scan_comfield   ; scan past communal length field element size
  1141 000005D3 E8(0000)                    call    compute_comm_len    ; compute communal length, return in com_val1
  1142 000005D6 C606[0801]00                mov byte [near_communal],0h    ; reset near communal flag bit
  1143 000005DB EB1D                        jmp SHORT pcf_5         ; bypass NEAR variable code
  1144                                  
  1145                                  ; invalid data segment type, neither 61h or 62h
  1146                                  pcf_invalid:
  1147 000005DD 88D1                        mov cl,dl               ; get value in cl
  1148 000005DF BA[0000]                    mov dx,OFFSET filename wrt DGROUP
  1149 000005E2 B80B00                      mov ax,INV_DSTYPE_ERR   ; invalid data segment type value
  1150 000005E5 E9(0000)                    jmp NEAR PTR error_bx_pos   ; transfer control to error handler
  1151                                  
  1152                                  pcf_3:
  1153 000005E8 80FA62                      cmp dl,62h              ; check if NEAR variable
  1154 000005EB 75F0                        jne pcf_invalid         ; no, invalid communal variable type
  1155                                  
  1156                                  pcf_4:
  1157 000005ED 89F3                        mov bx,si               ; save offset in case of error
  1158 000005EF BF[1601]                    mov di,OFFSET com_val1 wrt DGROUP   ; di -> first communal value field
  1159 000005F2 E8(0000)                    call    scan_comfield   ; scan past communal length field variable size
  1160 000005F5 C606[0801]10                mov byte [near_communal],10h   ; set near communal flag bit
  1161                                  
  1162                                  pcf_5:
  1163 000005FA BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at name field for get_pubdecl_entry procedure
  1164 000005FD B002                        mov al,2                ; flag to get_pubdecl_entry procedure that current record is an comdef record
  1165 000005FF E8D701                      call    get_pubdecl_entry   ; find or create public declaration entry segment
  1166                                  
  1167 00000602 09C0                        or  ax,ax               ; see if returned ax was null
  1168 00000604 7402                        je  pcf_dup             ; yes, use returned value in dx
  1169 00000606 89C2                        mov dx,ax               ; no, set dx to ax return value
  1170                                  pcf_dup:
  1171 00000608 BB[0000]                    mov bx,OFFSET ext_defent_indptr wrt DGROUP    ; bx -> base of array pointers to extdef'ed public entries
  1172 0000060B 8B3E[0000]                  mov di,[current_extdef]   ; get array element (current extdef number)
  1173 0000060F D1E7                        shl di,1                ; make di a word offset
  1174 00000611 01FB                        add bx,di               ; bx -> proper array element
  1175 00000613 8917                        mov [bx],dx             ; save pointer to public declaration entry
  1176                                  
  1177                                  %IFNDEF DEMO
  1178 00000615 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDL's
  1179 0000061A 740C                        je  pcf_noddl           ; no
  1180                                  
  1181                                  ; using DDLs, set bit 1 (2) in general flag in case comdef was
  1182                                  ; later declared in PUBDEF
  1183 0000061C 8CC7                        mov di,es
  1184 0000061E 8EC2                        mov es,dx               ; es -> public entry
  1185 00000620 26800E0F0002                or  BYTE PTR [es:15],2h ; set external flag
  1186 00000626 8EC7                        mov es,di
  1187                                  %ENDIF
  1188                                  
  1189                                  pcf_noddl:
  1190 00000628 09C0                        or  ax,ax               ; check if it was a duplicate declaration (ax==0)
  1191 0000062A 746B                        je  pcf_checksum        ; yes, already declared
  1192                                  
  1193 0000062C FF06[0000]                  inc word [communal_count]      ; bump count of communal variables
  1194 00000630 8306[0000]01                add WORD [pub_sym_count],1    ; update low word count
  1195 00000635 8316[0200]00                adc WORD [pub_sym_count+2],0  ; add in carry from low word, if any
  1196                                  
  1197 0000063A 50                          push    ax              ; save public declaration entry segment
  1198                                  
  1199 0000063B 803E[0200]03                cmp byte [which_def],3         ; see if extdef changed to comdef
  1200 00000640 7406                        je  pcf_5a              ; yes, bypass name addition
  1201                                  
  1202 00000642 BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point di at name field for add_pubdef_name procedure
  1203 00000645 E88604                      call    add_pubdef_name ; add name to pubdef names block
  1204                                  
  1205                                  pcf_5a:
  1206 00000648 8CC7                        mov di,es               ; save es
  1207 0000064A 07                          pop es                  ; es -> public declaration entry
  1208                                  
  1209 0000064B 803E[0200]03                cmp byte [which_def],3         ; see if extdef changed to comdef
  1210 00000650 7409                        je  pcf_5b              ; yes, bypass name update
  1211                                  
  1212 00000652 2689160600                  mov [es:6],dx           ; save segment pointer to name in pubdef names block
  1213 00000657 26A30400                    mov [es:4],ax           ; save offset pointer to name in pubdef names block
  1214                                  
  1215                                  pcf_5b:
  1216 0000065B 26800E0F0040                or  BYTE PTR [es:15],40h    ; flag as communal without public declaration
  1217 00000661 A0[0C01]                    mov al,[is_local]
  1218 00000664 2608060F00                  or  BYTE PTR [es:15],al ; set local flag (if using DDLs)
  1219 00000669 A0[0801]                    mov al,[near_communal]
  1220 0000066C 2608060F00                  or  BYTE PTR [es:15],al ; set or reset near communal bit as appropriate
  1221 00000671 26C6060E0001                mov BYTE PTR [es:14],1  ; flag that it was an extdef/comdef entry
  1222                                  
  1223 00000677 A1[1801]                    mov ax,WORD PTR [com_val1+2]  ; get communal length high word
  1224 0000067A 263B060200                  cmp ax,[es:2]           ; make sure that it is greater or equal to pre-existing value
  1225 0000067F 7214                        jb  pcf_7               ; less than, skip update
  1226 00000681 26A30200                    mov [es:2],ax           ; save in entry
  1227 00000685 A1[1601]                    mov ax,WORD PTR [com_val1]    ; get communal length low word
  1228 00000688 7707                        ja  pcf_6               ; high word is greater, always update low word
  1229 0000068A 263B060800                  cmp ax,[es:8]           ; see if low word is greater than or equal to pre-existing value
  1230 0000068F 7604                        jbe pcf_7               ; no, don't update low word
  1231                                  
  1232                                  pcf_6:
  1233 00000691 26A30800                    mov [es:8],ax           ; save in entry
  1234                                  
  1235                                  pcf_7:
  1236 00000695 8EC7                        mov es,di               ; restore es
  1237                                  
  1238                                  pcf_checksum:
  1239 00000697 FF06[0000]                  inc word [current_extdef]      ; update global memory variable
  1240 0000069B 83F901                      cmp cx,1                ; check if at checksum byte
  1241 0000069E 7603                        jbe pcf_out             ; yes, gobble it and return
  1242 000006A0 E9DAFE                      jmp NEAR PTR pcf_loop   ; loop back for next definition
  1243                                  
  1244                                  pcf_out:
  1245 000006A3 46                          inc si                  ; bump past checksum byte
  1246 000006A4 39EE                        cmp si,bp               ; check boundary conditions
  1247 000006A6 7203                        jb  pcf_ret             ; okay
  1248 000006A8 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1249                                  
  1250                                  pcf_ret:
  1251 000006AB C3                          ret
  1252                                  proc1_comdef    ENDP
  1253                                  
  1254                                  %ENDIF
  1255                                  
  1256                                  ;*****************************
  1257                                  ;* PROC1_COMENT              *
  1258                                  ;*****************************
  1259                                  
  1260                                  ; process COMENT record
  1261                                  ; upon entry cx=record length,bp=buffer_end,al=record type
  1262                                  ; si -> first byte of record past record length word
  1263                                  ; destroys ax,bx,dx,di
  1264                                  ; updates si,cx
  1265                                  
  1266                                  proc1_coment    PROC
  1267 000006AC 46                          inc si                  ; bump si past attrib byte to comment class
  1268 000006AD 49                          dec cx                  ; adjust record length to account for scan past attrib byte
  1269 000006AE 39EE                        cmp si,bp               ; check boundary conditions
  1270 000006B0 7203                        jb  pct_2               ; okay
  1271 000006B2 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1272                                  
  1273                                  pct_2:
  1274 000006B5 268A04                      mov al,[es:si]          ; get comment class
  1275                                  
  1276                                  pct_3:
  1277                                  %IFNDEF JUNIOR
  1278 000006B8 3C9E                        cmp al,DOSSEG_MARK      ; see if DOSSEG ordering flagged
  1279 000006BA 7510                        jne pct_4               ; no
  1280 000006BC 803E[0000]00                cmp byte [is_dosseg],0         ; see if DOSSEG ordering previously flagged
  1281 000006C1 7509                        jne pct_4               ; yes
  1282 000006C3 C606[0000]01                mov byte [is_dosseg],1         ; set DOSSEG segment ordering flag
  1283 000006C8 E8(0000)                    call    make_symbols    ; generate _edata and _end symbol declarations
  1284 000006CB C3                          ret
  1285                                  
  1286                                  pct_4:
  1287 000006CC 3C81                        cmp al,LIB_SEARCH_1     ; see if default library search type 1
  1288 000006CE 7404                        je  pct_lib             ; yes
  1289 000006D0 3C9F                        cmp al,LIB_SEARCH_2     ; see if default library search type 2
  1290 000006D2 7552                        jne pct_chkweak         ; no
  1291                                  
  1292                                  ; default library name in comment field
  1293                                  pct_lib:
  1294 000006D4 BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point to place to put library name
  1295                                  
  1296                                  pct_loop:
  1297 000006D7 46                          inc si
  1298 000006D8 49                          dec cx                  ; decrement record length to parse
  1299 000006D9 39EE                        cmp si,bp               ; check boundary conditions
  1300 000006DB 7203                        jb  pct_l2              ; okay
  1301 000006DD E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1302                                  pct_l2:
  1303 000006E0 268A04                      mov al,[es:si]          ; get file name char
  1304 000006E3 08C0                        or  al,al               ; check if zero
  1305 000006E5 740A                        je  pct_l3              ; yes, transfer complete
  1306 000006E7 83F901                      cmp cx,1                ; check if last char
  1307 000006EA 7605                        jbe pct_l3              ; yes, transfer complete
  1308 000006EC 8805                        mov [di],al             ; transfer char
  1309 000006EE 47                          inc di                  ; point to next char to transfer
  1310 000006EF EBE6                        jmp SHORT pct_loop      ; loop back for it
  1311                                  
  1312                                  pct_l3:
  1313 000006F1 C60500                      mov BYTE PTR [di],0     ; zero terminate filename, di -> zero terminator for check_extension
  1314 000006F4 E8(0000)                    call    check_cliplib
  1315                                  
  1316                                  ; check for default libraries allowed AFTER saving the name in case of
  1317                                  ; incremental link where still need to set status of CLIPPER default lib
  1318                                  ; encountered to flag Clipper module
  1319                                  pct_5:
  1320 000006F7 803E[0000]00                cmp byte [is_nodeflib],0       ; see if default libraries allowed
  1321 000006FC 752F                        jne pct_ret             ; no
  1322                                  
  1323 000006FE 06                          push    es              ; save critical register
  1324 000006FF 51                          push    cx
  1325 00000700 BA[0400]                    mov dx,OFFSET name_field wrt DGROUP ; dx -> library name for check_extension
  1326 00000703 E8(0000)                    call    check_extension ; set no_extension flag status for save_lib_name call
  1327 00000706 BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; di -> library name for save_lib_name
  1328 00000709 C606[0000]00                mov byte [in_overlay],0        ; default libraries are never in overlays
  1329 0000070E C606[0000]01                mov byte [def_lib_flag],1      ; set default library flag
  1330 00000713 FF36[0000]                  push    word [current_lib]     ; save current library number so library module code doesn't screw up
  1331 00000717 E8(0000)                    call    save_lib_name   ; save the library name
  1332 0000071A 8F06[0000]                  pop word [current_lib]         ; restore current library number
  1333 0000071E C606[0000]00                mov byte [def_lib_flag],0      ; reset default library flag
  1334 00000723 59                          pop cx                  ; restore critical register
  1335 00000724 07                          pop es
  1336 00000725 C3                          ret
  1337                                  
  1338                                  pct_chkweak:
  1339 00000726 3CA8                        cmp al,WKEXT            ; see if weak extern type
  1340 00000728 7503                        jne pct_ret             ; no
  1341 0000072A E80100                      call    get_weak_extern ; yes, get the weak extern type
  1342                                  %ENDIF
  1343                                  
  1344                                  pct_ret:
  1345 0000072D C3                          ret
  1346                                  proc1_coment    ENDP
  1347                                  
  1348                                  ;*****************************
  1349                                  ;* GET_WEAK_EXTERN           *
  1350                                  ;*****************************
  1351                                  
  1352                                  ; get weak extern and the default resolution declaration
  1353                                  ; upon entry si-> COMENT class a8h
  1354                                  ; destroys ax,bx,dx,di
  1355                                  ; updates cx,si
  1356                                  
  1357                                  get_weak_extern PROC
  1358 0000072E 46                          inc si                  ; bump si to weak extdef index
  1359 0000072F 49                          dec cx                  ; decrement record length to parse
  1360 00000730 39EE                        cmp si,bp               ; check boundary conditions
  1361 00000732 7203                        jb  gwe_loop            ; okay
  1362 00000734 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1363                                  
  1364                                  gwe_loop:
  1365 00000737 83F901                      cmp cx,1                ; see if at checksum
  1366 0000073A 7701                        ja  gwe_1               ; no
  1367 0000073C C3                          ret                     ; yes, return
  1368                                  
  1369                                  gwe_1:
  1370 0000073D 30E4                        xor ah,ah               ; zero high byte of index
  1371 0000073F 268A04                      mov al,[es:si]          ; get low byte of weak extdef index
  1372 00000742 46                          inc si
  1373 00000743 49                          dec cx                  ; decrement record length to parse
  1374 00000744 39EE                        cmp si,bp               ; check boundary conditions
  1375 00000746 7203                        jb  gwe_2               ; okay
  1376 00000748 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1377                                  gwe_2:
  1378 0000074B 3C80                        cmp al,80h              ; check if two byte index value
  1379 0000074D 7210                        jb  gwe_3               ; no, continue
  1380 0000074F 247F                        and al,7fh              ; mask off high bit
  1381 00000751 88C4                        mov ah,al               ; move value to high byte
  1382                                  
  1383 00000753 268A04                      mov al,[es:si]          ; get second byte of index
  1384 00000756 46                          inc si
  1385 00000757 49                          dec cx                  ; decrement record length to parse
  1386 00000758 39EE                        cmp si,bp               ; check boundary conditions
  1387 0000075A 7203                        jb  gwe_3               ; okay
  1388 0000075C E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1389                                  
  1390                                  ; ax holds weak extdef
  1391                                  gwe_3:
  1392 0000075F 30FF                        xor bh,bh               ; zero high byte of index
  1393 00000761 268A1C                      mov bl,[es:si]          ; get low byte of weak extdef index
  1394 00000764 46                          inc si
  1395 00000765 49                          dec cx                  ; decrement record length to parse
  1396 00000766 39EE                        cmp si,bp               ; check boundary conditions
  1397 00000768 7203                        jb  gwe_4               ; okay
  1398 0000076A E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1399                                  gwe_4:
  1400 0000076D 80FB80                      cmp bl,80h              ; check if two byte index value
  1401 00000770 7211                        jb  gwe_5               ; no, continue
  1402 00000772 80E37F                      and bl,7fh              ; mask off high bit
  1403 00000775 88DF                        mov bh,bl               ; move value to high byte
  1404                                  
  1405 00000777 268A1C                      mov bl,[es:si]          ; get second byte of index
  1406 0000077A 46                          inc si
  1407 0000077B 49                          dec cx                  ; decrement record length to parse
  1408 0000077C 39EE                        cmp si,bp               ; check boundary conditions
  1409 0000077E 7203                        jb  gwe_5               ; okay
  1410 00000780 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1411                                  
  1412                                  ; ax holds weak extdef
  1413                                  ; bx holds default extdef
  1414                                  gwe_5:
  1415 00000783 48                          dec ax                  ; make indices relative zero
  1416 00000784 4B                          dec bx
  1417 00000785 BF[0000]                    mov di,OFFSET ext_defent_indptr wrt DGROUP  ; di -> base of array pointers to extdef'ed public entries
  1418 00000788 D1E0                        shl ax,1                ; make index a word offset
  1419 0000078A 01C7                        add di,ax               ; di -> proper array element
  1420 0000078C 8B05                        mov ax,[di]             ; get -> weak extdef
  1421 0000078E 8CC2                        mov dx,es               ; save -> i/o buffer
  1422 00000790 8EC0                        mov es,ax
  1423 00000792 26A10E00                    mov ax,[es:14]          ; get declaration flag in al, general flags in ah
  1424                                  
  1425 00000796 2403                        and al,3
  1426 00000798 3C01                        cmp al,1                ; see if extdef or comdef
  1427 0000079A 7737                        ja  gwe_nextent         ; no, already resolved
  1428                                  
  1429 0000079C 80E440                      and ah,40h              ; see if comdef
  1430 0000079F 7532                        jne gwe_nextent         ; yes
  1431                                  
  1432 000007A1 26A00E00                    mov al,[es:14]          ; get declaration flag
  1433                                  
  1434                                  ; two possibilities
  1435                                  ; al==81h if this extdef can be made weak
  1436                                  ; al==1 if this extdef CANNOT be made weak because it was either declared as a
  1437                                  ; comdef or previously extdef without WKEXT mechanism in module or previously
  1438                                  ; weak and mismatch of default resolution extdefs occurred
  1439                                  
  1440 000007A5 2480                        and al,80h              ; see if can be made weak
  1441 000007A7 742A                        je  gwe_nextent         ; no
  1442                                  
  1443 000007A9 89D8                        mov ax,bx               ; ax holds index of default extdef
  1444 000007AB BB[0000]                    mov bx,OFFSET ext_defent_indptr wrt DGROUP  ; bx -> base of array pointers to extdef'ed public entries
  1445 000007AE D1E0                        shl ax,1                ; make index a word offset
  1446 000007B0 01C3                        add bx,ax               ; bx -> proper array element
  1447 000007B2 8B07                        mov ax,[bx]             ; get -> default extdef
  1448                                  
  1449 000007B4 268B1E0000                  mov bx,[es:0]           ; get previous default resolution extdef
  1450 000007B9 09DB                        or  bx,bx               ; see if existed
  1451 000007BB 740C                        je  gwe_6               ; no
  1452 000007BD 39D8                        cmp ax,bx               ; see if previous default resolution matches current
  1453 000007BF 7408                        je  gwe_6               ; yes
  1454                                  
  1455                                  ; previous default resolution does not match current resolution
  1456                                  ; make this a strong extdef and ignore mismatched weaks
  1457 000007C1 26C6060E0001                mov BYTE PTR [es:14],1  ; strong extdef
  1458 000007C7 EB0A                        jmp SHORT gwe_nextent   ; bypass weak extdef code
  1459                                  
  1460                                  gwe_6:
  1461 000007C9 26C6060E0080                mov BYTE PTR [es:14],80h    ; indicate weak extdef
  1462 000007CF 26A30000                    mov [es:0],ax           ; save -> default resolution extdef entry
  1463                                  
  1464                                  gwe_nextent:
  1465 000007D3 8EC2                        mov es,dx               ; es -> i/o buffer
  1466 000007D5 E95FFF                      jmp NEAR PTR gwe_loop   ; loop for next entry
  1467                                  
  1468                                  gwe_ret:
  1469 000007D8 C3                          ret
  1470                                  get_weak_extern ENDP
  1471                                  
  1472                                  ;*****************************
  1473                                  ;* GET_PUBDECL_ENTRY         *
  1474                                  ;*****************************
  1475                                  
  1476                                  ; find or make public declaration entry for pubdef/extdef/comdef name
  1477                                  ; upon entry ds:di -> warplink data location holding public name,
  1478                                  ; al is 1 if current record is a pubdef record, 2 if comdef, 0 otherwise
  1479                                  ; returns segment pointer to entry in ax, 0 if none or duplicate extdef/comdef
  1480                                  ; return segment pointer to entry in dx if duplicate extdef/comdef
  1481                                  ; destroys ax,dx,di
  1482                                  
  1483                                  get_pubdecl_entry   PROC
  1484 000007D9 53                          push    bx              ; save critical registers
  1485 000007DA 51                          push    cx
  1486 000007DB 56                          push    si
  1487 000007DC 06                          push    es
  1488 000007DD A2[0200]                    mov [which_def],al        ; save current record type
  1489 000007E0 89FE                        mov si,di               ; si -> name to get hash code of
  1490 000007E2 E8(0000)                    call    get_hash        ; get hash code of name in ax
  1491                                  
  1492 000007E5 BE[0000]                    mov si,OFFSET pubdecl_hash wrt DGROUP   ; si -> base of hash pointers to public declaration entries
  1493 000007E8 D1E0                        shl ax,1                ; convert ax to word offset
  1494 000007EA 01C6                        add si,ax               ; si points to proper name hash code entry
  1495 000007EC 833C00                      cmp WORD PTR [si],0     ; is hash code used (nonzero value)
  1496 000007EF 7403                        je  gp_new_hash         ; no
  1497 000007F1 E9A900                      jmp NEAR PTR gp_2       ; yes
  1498                                  
  1499                                  ; hash code not used, new name
  1500                                  gp_new_hash:
  1501 000007F4 803E[0200]02                cmp byte [which_def],2         ; see if comdef (promoted or first)
  1502 000007F9 7213                        jb  gp_1                ; no
  1503                                  
  1504                                  %IFNDEF DEMO
  1505 000007FB 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDLs (save COMDEFs with PUBDEFs)
  1506 00000800 7407                        je  gp_usecdec          ; no
  1507 00000802 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
  1508 00000807 7505                        jne gp_1                ; no, using DDLs
  1509                                  %ENDIF
  1510                                  
  1511                                  gp_usecdec:
  1512 00000809 A1[0000]                    mov ax,[alloc_cdeclblk_ptr]   ; not using DDLs or 1st udl pass
  1513 0000080C EB03                        jmp SHORT gp_1a
  1514                                  
  1515                                  gp_1:
  1516 0000080E A1[0000]                    mov ax,[alloc_pdeclblk_ptr]
  1517                                  
  1518                                  gp_1a:
  1519 00000811 09C0                        or  ax,ax               ; check if any pubdef declarations blocks were previously allocated
  1520 00000813 7537                        jne gp_3                ; yes
  1521                                  
  1522                                  ; make initial pubdef declarations block allocation
  1523                                  gp_init_blk:
  1524 00000815 BB8100                      mov bx,PUB_DECLBLK_SIZE ; number of paragraphs to allocate
  1525 00000818 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1526                                  
  1527 0000081B 803E[0200]02                cmp byte [which_def],2         ; see if comdef (2, or 3 if promoted from extdef)
  1528 00000820 7216                        jb  gp_1b               ; no
  1529                                  
  1530                                  %IFNDEF DEMO
  1531 00000822 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDLs (save COMDEFs with PUBDEFs)
  1532 00000827 7407                        je  gp_usec2            ; no
  1533 00000829 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
  1534 0000082E 7508                        jne gp_1b               ; no, using DDLs
  1535                                  %ENDIF
  1536                                  
  1537                                  gp_usec2:
  1538 00000830 A3[0000]                    mov [alloc_cdeclblk_ptr],ax   ; update last allocated block pointer
  1539 00000833 A3[0000]                    mov [first_cdeclblk_ptr],ax   ; update first allocated block pointer
  1540 00000836 EB06                        jmp SHORT gp_1c
  1541                                  
  1542                                  gp_1b:
  1543 00000838 A3[0000]                    mov [alloc_pdeclblk_ptr],ax   ; update last allocated block pointer
  1544 0000083B A3[0000]                    mov [first_pdeclblk_ptr],ax   ; update first allocated block pointer
  1545                                  
  1546                                  gp_1c:
  1547 0000083E 8EC0                        mov es,ax               ; es == current (new) block segment
  1548 00000840 31C0                        xor ax,ax
  1549 00000842 26A30000                    mov WORD PTR [es:0],ax  ; zero count of entries in block
  1550 00000846 26A30200                    mov WORD PTR [es:2],ax  ; zero pointer to next block
  1551 0000084A EB0E                        jmp SHORT gp_4          ; bypass block full check code
  1552                                  
  1553                                  ; at least one prior pubdef declaration made, check if block is full
  1554                                  gp_3:
  1555 0000084C 8EC0                        mov es,ax               ; es -> current block
  1556 0000084E 26813E00008000              cmp WORD PTR [es:0],PUB_DECLENT_COUNT  ; see if any free entries in block
  1557 00000855 7203                        jb  gp_4                ; yes
  1558 00000857 E81B02                      call    make_pubdecl_blk    ; no free entries in block, make a new block
  1559                                  
  1560                                  gp_4:
  1561 0000085A 268B1E0000                  mov bx,[es:0]           ; get entry count
  1562 0000085F 8CC0                        mov ax,es               ; get block segment address in ax
  1563 00000861 01C3                        add bx,ax               ; get first free entry segment value
  1564 00000863 43                          inc bx                  ; adjust for block system info size of 1 paragraph
  1565 00000864 891C                        mov [si],bx             ; update hash code segment pointer
  1566 00000866 89D8                        mov ax,bx               ; get public declaration entry address in ax for return
  1567                                  
  1568 00000868 8CC2                        mov dx,es               ; save extra segment
  1569 0000086A 8EC3                        mov es,bx               ; es -> public declaration entry
  1570 0000086C 31DB                        xor bx,bx
  1571 0000086E 26891E0000                  mov [es:0],bx           ; zero init values in pubdef declaration entry
  1572 00000873 26891E0200                  mov [es:2],bx
  1573 00000878 26891E0800                  mov [es:8],bx
  1574 0000087D 26891E0E00                  mov [es:14],bx
  1575 00000882 803E[0200]03                cmp byte [which_def],3         ; see if comdef promotion
  1576 00000887 7505                        jne gp_4a               ; no
  1577                                  
  1578                                  ; comdef promotion from extdef declaration entry, cx -> declaration entry
  1579                                  ; update hi/low pointers and name pointers from cx -> to es ->
  1580 00000889 E8C101                      call    promote_comdef
  1581 0000088C EB0A                        jmp SHORT gp_4b         ; bypass low/high pointer zero'ing code
  1582                                  
  1583                                  gp_4a:
  1584 0000088E 26891E0A00                  mov [es:10],bx
  1585 00000893 26891E0C00                  mov [es:12],bx
  1586                                  
  1587                                  gp_4b:
  1588 00000898 8EC2                        mov es,dx               ; restore extra segment
  1589                                  
  1590 0000089A E95F01                      jmp NEAR PTR gp_update  ; bypass dup/collision code
  1591                                  
  1592                                  ; hash code used, check whether duplicate name or hash collision
  1593                                  gp_2:
  1594 0000089D 57                          push    di              ; save di pointing to name
  1595 0000089E 8B04                        mov ax,[si]             ; get segment pointer to pubdef declaration entry
  1596                                  
  1597                                  gp_testloop:
  1598 000008A0 5E                          pop si                  ; si -> name
  1599 000008A1 56                          push    si              ; put it back on stack
  1600 000008A2 8EC0                        mov es,ax               ; es -> segment of pubdef declaration entry testing name against
  1601 000008A4 89C3                        mov bx,ax               ; save entry segment in bx
  1602 000008A6 26C43E0400                  les di,[es:4]           ; -> pubdef name in pubdef names block
  1603                                  
  1604                                  ; ds:si -> name, es:di -> name to test against
  1605                                  gp_byteloop:
  1606 000008AB 8A04                        mov al,[si]
  1607 000008AD 260A05                      or  al,[es:di]          ; see if both values are zero (matched to null terminator)
  1608 000008B0 740F                        je  to_gp_match         ; strings matched
  1609 000008B2 A6                          cmpsb                   ; compare a nonzero byte in the two names
  1610 000008B3 74F6                        je  gp_byteloop         ; bytes match, loop for next byte test
  1611 000008B5 8EC3                        mov es,bx               ; get pubdef declaration entry segment value
  1612 000008B7 720B                        jc  gp_7                ; old name greater than new name
  1613                                  
  1614                                  ; new name greater than old name
  1615 000008B9 26A10C00                    mov ax,[es:12]          ; get entry having a greater name
  1616 000008BD 30D2                        xor dl,dl               ; flag new > old, update high pointer
  1617 000008BF EB09                        jmp SHORT gp_8          ; check for null pointer
  1618                                  
  1619                                  ; stepping stone to matched code
  1620                                  to_gp_match:
  1621 000008C1 E9C500                      jmp NEAR PTR gp_match
  1622                                  
  1623                                  ; old name greater than new name
  1624                                  gp_7:
  1625 000008C4 26A10A00                    mov ax,[es:10]          ; get entry having a lesser name
  1626 000008C8 B201                        mov dl,1                ; flag old > new update low pointer
  1627                                  
  1628                                  gp_8:
  1629 000008CA 8CC1                        mov cx,es               ; save -> parent entry in cx
  1630 000008CC 09C0                        or  ax,ax               ; check if a null pointer (ax=0)
  1631 000008CE 75D0                        jne gp_testloop         ; no, keep checking entries
  1632                                  
  1633                                  ; new name, no matches for any pubdef declaration entry
  1634                                  gp_newname:
  1635 000008D0 803E[0200]02                cmp byte [which_def],2         ; see if comdef (promoted or first)
  1636 000008D5 7213                        jb  gp_8a               ; no
  1637                                  
  1638                                  %IFNDEF DEMO
  1639 000008D7 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDLs (save COMDEFs with PUBDEFs)
  1640 000008DC 7407                        je  gp_usec3            ; no
  1641 000008DE 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
  1642 000008E3 7505                        jne gp_8a               ; no, using DDLs
  1643                                  %ENDIF
  1644                                  
  1645                                  gp_usec3:
  1646 000008E5 A1[0000]                    mov ax,[alloc_cdeclblk_ptr]   ; get last allocated block
  1647 000008E8 EB03                        jmp SHORT gp_8b
  1648                                  
  1649                                  gp_8a:
  1650 000008EA A1[0000]                    mov ax,[alloc_pdeclblk_ptr]   ; get last allocated block
  1651                                  
  1652                                  gp_8b:
  1653 000008ED 09C0                        or  ax,ax               ; see if block previously existed
  1654 000008EF 753B                        jne gp_8d               ; yes
  1655 000008F1 89DF                        mov di,bx               ; save bx
  1656 000008F3 BB8100                      mov bx,PUB_DECLBLK_SIZE ; number of paragraphs to allocate
  1657 000008F6 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1658 000008F9 89FB                        mov bx,di               ; restore bx
  1659                                  
  1660 000008FB 803E[0200]02                cmp byte [which_def],2         ; see if comdef
  1661 00000900 7216                        jb  gp_pub_alloc        ; no
  1662                                  
  1663                                  %IFNDEF DEMO
  1664 00000902 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDLs (save COMDEFs with PUBDEFs)
  1665 00000907 7407                        je  gp_usec4            ; no
  1666 00000909 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
  1667 0000090E 7508                        jne gp_pub_alloc        ; no, using DDLs
  1668                                  %ENDIF
  1669                                  
  1670                                  gp_usec4:
  1671 00000910 A3[0000]                    mov [alloc_cdeclblk_ptr],ax   ; update last allocated block pointer
  1672 00000913 A3[0000]                    mov [first_cdeclblk_ptr],ax   ; update first allocated block pointer
  1673 00000916 EB06                        jmp SHORT gp_8c
  1674                                  
  1675                                  gp_pub_alloc:
  1676 00000918 A3[0000]                    mov [alloc_pdeclblk_ptr],ax   ; update last allocated block pointer
  1677 0000091B A3[0000]                    mov [first_pdeclblk_ptr],ax   ; update first allocated block pointer
  1678                                  
  1679                                  gp_8c:
  1680 0000091E 8EC0                        mov es,ax               ; es -> block
  1681 00000920 31C0                        xor ax,ax
  1682 00000922 26A30000                    mov WORD PTR [es:0],ax  ; zero count of entries in block
  1683 00000926 26A30200                    mov WORD PTR [es:2],ax  ; zero pointer to next block
  1684 0000092A EB0E                        jmp SHORT gp_9          ; bypass check for block full (new block)
  1685                                  
  1686                                  gp_8d:
  1687 0000092C 8EC0                        mov es,ax               ; es -> block
  1688 0000092E 26813E00008000              cmp WORD PTR [es:0],PUB_DECLENT_COUNT   ; see if any free entries in block
  1689 00000935 7203                        jb  gp_9                ; yes
  1690 00000937 E83B01                      call    make_pubdecl_blk    ; no free entries in block, make a new block
  1691                                  
  1692                                  gp_9:
  1693 0000093A 268B3E0000                  mov di,[es:0]           ; get entry count
  1694 0000093F 06                          push    es              ; save segdef block address
  1695 00000940 8CC0                        mov ax,es               ; get block segment address
  1696 00000942 01C7                        add di,ax               ; get first free entry segment value
  1697 00000944 47                          inc di                  ; adjust for block system info size of 1 paragraph
  1698                                  
  1699 00000945 8CC6                        mov si,es               ; save extra segment
  1700 00000947 8EC7                        mov es,di               ; es -> new public declaration entry
  1701 00000949 31C0                        xor ax,ax
  1702 0000094B 26A30000                    mov [es:0],ax           ; zero init values in pubdef declaration entry
  1703 0000094F 26A30200                    mov [es:2],ax
  1704 00000953 26A30800                    mov [es:8],ax
  1705 00000957 26A30E00                    mov [es:14],ax
  1706 0000095B 803E[0200]03                cmp byte [which_def],3         ; see if comdef promotion
  1707 00000960 7505                        jne gp_9a               ; no
  1708                                  
  1709                                  ; comdef promotion from extdef declaration entry, cx -> declaration entry
  1710                                  ; bx -> parent entry to declaration entry
  1711                                  ; update hi/low pointers and name pointers from cx -> to es ->
  1712 00000962 E8E800                      call    promote_comdef
  1713 00000965 EB08                        jmp SHORT gp_9b         ; bypass low/high pointer zero'ing code
  1714                                  
  1715                                  gp_9a:
  1716 00000967 26A30A00                    mov [es:10],ax
  1717 0000096B 26A30C00                    mov [es:12],ax
  1718                                  
  1719                                  gp_9b:
  1720 0000096F 8EC6                        mov es,si               ; restore extra segment
  1721 00000971 89F8                        mov ax,di               ; ax -> new public declaration entry for return
  1722                                  
  1723 00000973 8EC3                        mov es,bx               ; get entry that pointed to this new entry (parent entry)
  1724 00000975 08D2                        or  dl,dl               ; zero if high pointer update, nonzero if low pointer update
  1725 00000977 7508                        jne gp_10               ; low pointer update
  1726 00000979 26893E0C00                  mov [es:12],di          ; update high name pointer
  1727 0000097E 07                          pop es                  ; restore es -> segdef block
  1728 0000097F EB7A                        jmp SHORT gp_11         ; perform new entry code
  1729                                  
  1730                                  gp_10:
  1731 00000981 26893E0A00                  mov [es:10],di          ; update low name pointer
  1732 00000986 07                          pop es                  ; restore es -> segdef block
  1733 00000987 EB72                        jmp SHORT gp_11         ; perform new entry code
  1734                                  
  1735                                  ; names match
  1736                                  gp_match:
  1737 00000989 803E[0200]01                cmp byte [which_def],1         ; check if a pubdef record
  1738 0000098E 7444                        je  gp_12               ; yes it is
  1739                                  
  1740                                  ; duplicate extdef or comdef declaration, ignore without warning
  1741                                  ; HOWEVER, first check if a comdef declaration that was first extdef
  1742                                  ; declared.  If so, make a comdef entry and redirect the pointers to it.
  1743                                  gp_null:
  1744 00000990 89D6                        mov si,dx               ; save flag value of dl in si
  1745 00000992 89DA                        mov dx,bx               ; return pubdef declaration entry value in dx, if needed
  1746 00000994 5F                          pop di                  ; restore di pointing to name
  1747                                  
  1748 00000995 8EC3                        mov es,bx               ; es -> pubdef declaration entry
  1749 00000997 26A00E00                    mov al,[es:14]
  1750 0000099B 2483                    	and	al,83h				; mask off nonrelevant bits
  1751 0000099D A802                        test    al,2            ; see if previously declared public
  1752 0000099F 752F                        jne null_ret            ; yes, ignore
  1753                                  
  1754 000009A1 803E[0200]02                cmp byte [which_def],2         ; see if current declaration is comdef
  1755 000009A6 7418                        je  gp_iscomdef         ; yes
  1756                                  
  1757                                  ; extdef has three possible values at this point
  1758                                  ; 1 == strong extdef, not weak through WKEXT mechanism at least once, keep it strong
  1759                                  ; 81 == unknown extdef in previous use, not modified by WKEXT mechanism, make strong
  1760                                  ; 80 == known weak extdef, change to unknown status
  1761                                  
  1762 000009A8 3C01                        cmp al,1                ; see if extdef (not weak)
  1763 000009AA 7424                        je  null_ret            ; yes
  1764 000009AC 3C81                        cmp al,81h              ; see if previously unknown extdef never 'weak'ened
  1765 000009AE 7508                        jne gp_weakext          ; no
  1766 000009B0 2401                        and al,1                ; yes, set as known strong extdef
  1767 000009B2 26A20E00                    mov BYTE PTR [es:14],al ; save new value
  1768 000009B6 EB18                        jmp SHORT null_ret
  1769                                  
  1770                                  ; assume al value is 80h (previously weakened extdef)
  1771                                  gp_weakext:
  1772 000009B8 B081                        mov al,81h              ; set as unknown extdef in previous use
  1773 000009BA 26A20E00                    mov BYTE PTR [es:14],al ; save new value
  1774 000009BE EB10                        jmp SHORT null_ret
  1775                                  
  1776                                  gp_iscomdef:
  1777 000009C0 B001                        mov al,1
  1778 000009C2 26A20E00                    mov BYTE PTR [es:14],al ; force any weak extdefs to be ignored for comdef
  1779 000009C6 26A00F00                    mov al,[es:15]
  1780 000009CA 2440                        and al,40h              ; see if previous declaration was comdef
  1781 000009CC 7502                        jne null_ret            ; yes
  1782 000009CE EB51                        jmp NEAR PTR ext_to_com ; no
  1783                                  
  1784                                  null_ret:
  1785 000009D0 31C0                        xor ax,ax
  1786 000009D2 EB37                        jmp SHORT gp_ret
  1787                                  
  1788                                  ; current record is a pubdef record
  1789                                  gp_12:
  1790 000009D4 8EC3                        mov es,bx               ; get pubdef declaration entry segment value
  1791 000009D6 26A00E00                    mov al,[es:14]          ; get previous entry definition flag
  1792 000009DA 2403                        and al,3                ; get pubdef/extdef/comdef field
  1793 000009DC 3C02                        cmp al,2                ; check if previous entry was a pubdef/absolute
  1794 000009DE 7330                        jae gp_mult_warn        ; yes, symbol defined more than once
  1795                                  
  1796 000009E0 26F6060F0040                test BYTE PTR [es:15],40h   ; check if previous definition was a communal
  1797 000009E6 740E                        je  gp_14               ; no
  1798 000009E8 FF0E[0000]                  dec word [communal_count]      ; decrement count of communals, public declaration supersedes communal
  1799 000009EC 832E[0000]01                sub WORD [pub_sym_count],1    ; update low word count
  1800 000009F1 831E[0200]00                sbb WORD [pub_sym_count+2],0  ; borrow from low word, if any
  1801                                  
  1802                                  ; previous entry was comdef or extdef, return valid pointer value
  1803                                  gp_14:
  1804 000009F6 89D8                        mov ax,bx               ; get segment value in ax
  1805 000009F8 5F                          pop di                  ; restore di pointing to name
  1806 000009F9 EB10                        jmp SHORT gp_ret        ; all done, exit
  1807                                  
  1808                                  gp_11:
  1809 000009FB 5F                          pop di                  ; restore di pointing to name
  1810                                  
  1811                                  gp_update:
  1812 000009FC 26FF060000                  inc WORD PTR [es:0]     ; bump count of entries
  1813 00000A01 8306[0000]01                add WORD [tot_sym_count],1    ; update low word count of total symbols
  1814 00000A06 8316[0200]00                adc WORD [tot_sym_count+2],0  ; update high word count with low word carry
  1815                                  
  1816                                  gp_ret:
  1817 00000A0B 07                          pop es                  ; restore critical register
  1818 00000A0C 5E                          pop si
  1819 00000A0D 59                          pop cx
  1820 00000A0E 5B                          pop bx
  1821 00000A0F C3                          ret
  1822                                  
  1823                                  ; warning, symbol defined more than once
  1824                                  gp_mult_warn:
  1825 00000A10 26C43E0400                  les di,[es:4]           ; -> name
  1826 00000A15 BA[0000]                    mov dx,OFFSET filename wrt DGROUP
  1827 00000A18 B82E00                      mov ax,MULT_DEF_SYM_WARN    ; flag symbol defined multiple times
  1828 00000A1B E8(0000)                    call    link_warning    ; give warning feedback
  1829 00000A1E E96FFF                      jmp NEAR PTR gp_null    ; ignore public definition
  1830                                  
  1831                                  ; comdef and previous declaration was extdef, redirect pointers and
  1832                                  ; create as a new name
  1833                                  ext_to_com:
  1834 00000A21 89F2                        mov dx,si               ; get dl flag value back from si
  1835 00000A23 C606[0200]03                mov byte [which_def],3         ; flag extdef to comdef promotion
  1836 00000A28 832E[0000]01                sub WORD [tot_sym_count],1    ; back off total symbols by one (new entry will re-increment)
  1837 00000A2D 831E[0200]00                sbb WORD [tot_sym_count+2],0
  1838 00000A32 89FE                        mov si,di               ; si -> name to get hash code of
  1839 00000A34 E8(0000)                    call    get_hash        ; get hash code of name in ax
  1840 00000A37 BE[0000]                    mov si,OFFSET pubdecl_hash wrt DGROUP   ; si -> base of hash pointers to public declaration entries
  1841 00000A3A D1E0                        shl ax,1                ; convert ax to word offset
  1842 00000A3C 01C6                        add si,ax               ; si points to proper name hash code entry
  1843 00000A3E 391C                        cmp WORD PTR [si],bx    ; is hash code -> this entry
  1844 00000A40 7505                        jne etc_2               ; no
  1845 00000A42 89D9                        mov cx,bx               ; cx -> extdef declaration entry
  1846 00000A44 E9ADFD                      jmp NEAR PTR gp_new_hash    ; transfer to new hash code entry code
  1847                                  
  1848                                  ; not the first entry -> hash code, cx -> parent of extdef declaration entry
  1849                                  etc_2:
  1850 00000A47 57                          push    di              ; save di -> name on stack
  1851 00000A48 87D9                        xchg  bx,cx             ; bx -> parent of extdef declaration entry.
  1852                                                              ; cx -> extdef declaration entry
  1853 00000A4A E983FE                      jmp NEAR PTR gp_newname ; transfer to new name code
  1854                                  
  1855                                  get_pubdecl_entry   ENDP
  1856                                  
  1857                                  ;*****************************
  1858                                  ;* PROMOTE_COMDEF            *
  1859                                  ;*****************************
  1860                                  
  1861                                  ; code to promote extdef entry to comdef
  1862                                  ; no registers destroyed
  1863                                  
  1864                                  promote_comdef  PROC
  1865 00000A4D 1E                          push    ds
  1866 00000A4E 50                          push    ax
  1867 00000A4F 8ED9                        mov ds,cx               ; ds -> extdef declaration entry
  1868 00000A51 800E0F0020                  or  BYTE PTR [15],20h    ; set local communal bit in abandoned extdef entry so map won't pick it up
  1869 00000A56 A10400                      mov ax,[4]
  1870 00000A59 26A30400                    mov [es:4],ax           ; transfer name pointer offset
  1871 00000A5D A10600                      mov ax,[6]
  1872 00000A60 26A30600                    mov [es:6],ax           ; transfer name pointer segment
  1873 00000A64 A10A00                      mov ax,[10]
  1874 00000A67 26A30A00                    mov [es:10],ax          ; transfer entry low pointer
  1875 00000A6B A10C00                      mov ax,[12]
  1876 00000A6E 26A30C00                    mov [es:12],ax          ; transfer entry high pointer
  1877 00000A72 58                          pop ax
  1878 00000A73 1F                          pop ds
  1879 00000A74 C3                          ret
  1880                                  promote_comdef  ENDP
  1881                                  
  1882                                  ;*****************************
  1883                                  ;* MAKE_PUBDECL_BLK          *
  1884                                  ;*****************************
  1885                                  
  1886                                  ; make a new pubdef declarations block
  1887                                  ; return segment of new block in es
  1888                                  ; destroys ax,es
  1889                                  
  1890                                  make_pubdecl_blk    PROC
  1891 00000A75 53                          push    bx              ; save critical registers
  1892 00000A76 52                          push    dx
  1893                                  
  1894 00000A77 803E[0200]02                cmp byte [which_def],2         ; see if comdef (promoted ==3 or first ==2)
  1895 00000A7C 7214                        jb  mpb_1               ; no
  1896                                  
  1897                                  %IFNDEF DEMO
  1898 00000A7E 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDLs (save COMDEFs with PUBDEFs)
  1899 00000A83 7407                        je  mpb_usec            ; no
  1900 00000A85 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
  1901 00000A8A 7506                        jne mpb_1               ; no, using DDLs
  1902                                  %ENDIF
  1903                                  
  1904                                  mpb_usec:
  1905 00000A8C 8B16[0000]                  mov dx,[alloc_cdeclblk_ptr]   ; use comdef declaration block
  1906 00000A90 EB04                        jmp SHORT mpb_2
  1907                                  
  1908                                  mpb_1:
  1909 00000A92 8B16[0000]                  mov dx,[alloc_pdeclblk_ptr]   ; keep previously last allocated block segment
  1910                                  
  1911                                  mpb_2:
  1912 00000A96 BB8100                      mov bx,PUB_DECLBLK_SIZE ; number of paragraphs to allocate
  1913 00000A99 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1914                                  
  1915 00000A9C 803E[0200]02                cmp byte [which_def],2         ; see if comdef
  1916 00000AA1 7213                        jb  mpb_3               ; no
  1917                                  
  1918                                  %IFNDEF DEMO
  1919 00000AA3 803E[0000]00                cmp byte [any_ddl],0           ; see if using DDLs (save COMDEFs with PUBDEFs)
  1920 00000AA8 7407                        je  mpb_usec2           ; no
  1921 00000AAA 803E[0000]01                cmp byte [udl_proc_pass],1     ; see if pass 1 udl processing
  1922 00000AAF 7505                        jne mpb_3               ; no, using DDLs
  1923                                  %ENDIF
  1924                                  
  1925                                  mpb_usec2:
  1926 00000AB1 A3[0000]                    mov [alloc_cdeclblk_ptr],ax   ; update last allocated comdef block pointer
  1927 00000AB4 EB03                        jmp SHORT mpb_4
  1928                                  
  1929                                  mpb_3:
  1930 00000AB6 A3[0000]                    mov [alloc_pdeclblk_ptr],ax   ; update last allocated block pointer
  1931                                  
  1932                                  mpb_4:
  1933 00000AB9 8EC2                        mov es,dx               ; es -> old block
  1934 00000ABB 26A30200                    mov [es:2],ax           ; update old block to point to new block
  1935                                  
  1936 00000ABF 8EC0                        mov es,ax               ; es -> new block
  1937 00000AC1 31C0                        xor ax,ax
  1938 00000AC3 26A30000                    mov [es:0],ax           ; zero count of entries in block
  1939 00000AC7 26A30200                    mov [es:2],ax           ; zero pointer to next block
  1940 00000ACB 5A                          pop dx                  ; restore critical registers
  1941 00000ACC 5B                          pop bx
  1942 00000ACD C3                          ret
  1943                                  make_pubdecl_blk    ENDP
  1944                                  
  1945                                  ;*****************************
  1946                                  ;* ADD_PUBDEF_NAME           *
  1947                                  ;*****************************
  1948                                  
  1949                                  ; add name to pubdef names block
  1950                                  ; upon entry ds:di -> warplink data location holding public name
  1951                                  ; returns segment:offset pointer to entry in dx:ax
  1952                                  ; destroys ax,dx,di
  1953                                  
  1954                                  add_pubdef_name PROC
  1955 00000ACE 53                          push    bx              ; save critical registers
  1956 00000ACF 51                          push    cx
  1957 00000AD0 56                          push    si
  1958 00000AD1 06                          push    es
  1959 00000AD2 A1[0000]                    mov ax,[alloc_pdnameblk_ptr]
  1960 00000AD5 09C0                        or  ax,ax               ; check if any pubdef name blocks were previously allocated
  1961 00000AD7 751A                        jne apn_2               ; yes
  1962                                  
  1963                                  ; make initial pubdef names block allocation
  1964 00000AD9 BBA100                      mov bx,PUB_NAMBLK_SIZE  ; number of paragraphs to allocate
  1965 00000ADC E8(0000)                    call    alloc_memory    ; get memory for block allocation
  1966 00000ADF A3[0600]                    mov [first_pdnameblk_ptr],ax  ; save first allocated block pointer
  1967 00000AE2 A3[0000]                    mov [alloc_pdnameblk_ptr],ax  ; update last allocated block pointer
  1968 00000AE5 8EC0                        mov es,ax               ; es == current (new) block segment
  1969 00000AE7 31DB                        xor bx,bx
  1970 00000AE9 26C7070C0A                  mov word [es:bx],PUB_NAMELIST_SIZE   ; all name list space is free
  1971 00000AEE 26891E0200                  mov WORD PTR [es:2],bx  ; zero pointer to next block
  1972                                  
  1973                                  apn_2:
  1974 00000AF3 8EC0                        mov es,ax               ; es -> current block
  1975 00000AF5 26A10000                    mov ax,[es:0]           ; get free space in block
  1976                                  
  1977                                  ; get length of name in dx INCLUDING zero terminator
  1978 00000AF9 BA0100                      mov dx,1                ; init length of name
  1979 00000AFC 803E[0000]00            	cmp	byte [any_ddl],0			; see if using DDL's
  1980 00000B01 7401                    	je	apn_2a				; no
  1981 00000B03 42                      	inc	dx					; adjust for prepended length byte
  1982                                  
  1983                                  apn_2a:
  1984 00000B04 89FB                        mov bx,di               ; save start of name in bx
  1985                                  apn_lenloop:
  1986 00000B06 803D00                      cmp BYTE PTR [di],0     ; check if at end of name
  1987 00000B09 7404                        je  apn_3               ; yes, at end
  1988 00000B0B 42                          inc dx                  ; bump count of chars in string
  1989 00000B0C 47                          inc di                  ; point to next char
  1990 00000B0D EBF7                        jmp SHORT apn_lenloop   ; check next char
  1991                                  
  1992                                  apn_3:
  1993 00000B0F 89DF                        mov di,bx               ; restore start of name in di
  1994 00000B11 52                          push    dx              ; save length of name string on stack
  1995 00000B12 39D0                        cmp ax,dx               ; see if name will fit in block
  1996 00000B14 7207                        jb  apn_4               ; no, it won't
  1997                                  
  1998                                  ; name will fit into current pubdef names block
  1999 00000B16 BA0C0A                      mov dx,PUB_NAMELIST_SIZE
  2000 00000B19 29C2                        sub dx,ax               ; get beginning slot for name
  2001 00000B1B EB05                        jmp SHORT apn_5         ; bypass block allocation code
  2002                                  
  2003                                  ; not enough room for name in this block, allocate another pubdef names block
  2004                                  apn_4:
  2005 00000B1D E82F00                      call    make_pubdef_name_blk
  2006 00000B20 31D2                        xor dx,dx               ; name begins at offset zero of namelist
  2007                                  
  2008                                  apn_5:
  2009 00000B22 89FE                        mov si,di               ; si -> public name
  2010 00000B24 89D7                        mov di,dx               ; di -> space in pubdef names block where name goes
  2011 00000B26 83C704                      add di,4                ; adjust for 2 words system info before namelist
  2012                                  
  2013 00000B29 59                          pop cx                  ; get length of name string including zero terminator
  2014 00000B2A 26290E0000                  sub [es:0],cx           ; update space free in block, subtracting off name length
  2015 00000B2F 8CC2                        mov dx,es               ; dx:ax == segment:offset of pubdef name
  2016 00000B31 89F8                        mov ax,di
  2017                                  
  2018 00000B33 803E[0000]00            	cmp	byte [any_ddl],0			; see if using DDL's
  2019 00000B38 7408                    	je	apn_6				; no
  2020 00000B3A 89C3                    	mov	bx,ax				; save ax critical register value
  2021 00000B3C 89C8                    	mov	ax,cx				; total length in ax (al)
  2022 00000B3E AA                      	stosb					; store length byte as prepended to actual name
  2023 00000B3F 49                      	dec	cx					; drop count of bytes to transfer
  2024 00000B40 89D8                    	mov	ax,bx				; restore ax critical register value
  2025                                  
  2026                                  apn_6:
  2027 00000B42 D1E9                        shr cx,1                ; convert to words
  2028 00000B44 F3A5                        rep movsw               ; move the string
  2029 00000B46 D1D1                        rcl cx,1                ; pick up carry
  2030 00000B48 F3A4                        rep movsb               ; transfer leftover byte, if any
  2031                                  
  2032 00000B4A 07                          pop es                  ; restore critical registers
  2033 00000B4B 5E                          pop si
  2034 00000B4C 59                          pop cx
  2035 00000B4D 5B                          pop bx
  2036 00000B4E C3                          ret
  2037                                  add_pubdef_name ENDP
  2038                                  
  2039                                  ;*****************************
  2040                                  ;* MAKE_PUBDEF_NAME_BLK      *
  2041                                  ;*****************************
  2042                                  
  2043                                  ; make a new pubdef name block
  2044                                  ; return segment of new block in es
  2045                                  ; destroys ax,bx,es
  2046                                  
  2047                                  make_pubdef_name_blk    PROC
  2048 00000B4F 52                          push    dx              ; save critical register
  2049 00000B50 8B16[0000]                  mov dx,[alloc_pdnameblk_ptr]  ; keep previously last allocated block segment
  2050 00000B54 BBA100                      mov bx,PUB_NAMBLK_SIZE  ; number of paragraphs to allocate
  2051 00000B57 E8(0000)                    call    alloc_memory    ; get memory for block allocation
  2052 00000B5A A3[0000]                    mov [alloc_pdnameblk_ptr],ax  ; update last allocated block pointer
  2053                                  
  2054 00000B5D 8EC2                        mov es,dx               ; es -> old block
  2055 00000B5F 26A30200                    mov [es:2],ax           ; update old block to point to new block
  2056                                  
  2057 00000B63 8EC0                        mov es,ax               ; es -> new block
  2058 00000B65 31DB                        xor bx,bx
  2059 00000B67 26C7070C0A                  mov word [es:bx],PUB_NAMELIST_SIZE   ; all name list space is free
  2060 00000B6C 26891E0200                  mov WORD PTR [es:2],bx  ; zero pointer to next block
  2061 00000B71 5A                          pop dx                  ; restore critical registers
  2062 00000B72 C3                          ret
  2063                                  make_pubdef_name_blk    ENDP
  2064                                  
  2065                                  ;*****************************
  2066                                  ;* PROC_CEXTDEF              *
  2067                                  ;*****************************
  2068                                  
  2069                                  ; parse CEXTDEF record, put name in name_field
  2070                                  ; upon entry cx=record length,bp=buffer_end,al=record type
  2071                                  ; si -> first byte of record past record length
  2072                                  ; updates si
  2073                                  ; destroys ax,bx,dx,di
  2074                                  
  2075                                  proc_cextdef	PROC
  2076 00000B73 06                      	push	es				; save critical register
  2077                                  
  2078 00000B74 30E4                        xor ah,ah               ; zero high byte
  2079 00000B76 26AC                    	es lodsb	; get low byte of comdat external index
  2080 00000B78 49                          dec cx                  ; decrement record length to parse
  2081 00000B79 39EE                        cmp si,bp               ; check boundary conditions
  2082 00000B7B 7203                        jb  ce_2                ; okay
  2083 00000B7D E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  2084                                  
  2085                                  ce_2:
  2086 00000B80 3C80                        cmp al,80h              ; check if more than one byte index value
  2087 00000B82 720E                        jb  ce_3				; no, continue
  2088 00000B84 247F                        and al,7fh              ; mask off high bit
  2089 00000B86 88C4                        mov ah,al               ; transfer to high word
  2090 00000B88 26AC                    	es lodsb	; get second byte, actual value
  2091 00000B8A 49                          dec cx                  ; decrement record length to parse
  2092 00000B8B 39EE                        cmp si,bp               ; check boundary conditions
  2093 00000B8D 7203                        jb  ce_3				; okay
  2094 00000B8F E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  2095                                  
  2096                                  ; ax holds index value
  2097                                  ce_3:
  2098 00000B92 48                          dec ax                  ; make count relative zero
  2099 00000B93 D1E0                        shl ax,1                ; convert to word index
  2100 00000B95 D1E0                        shl ax,1                ; convert to doubleword index
  2101 00000B97 56                      	push	si				; save critical register
  2102 00000B98 BE[0000]                    mov si,OFFSET lnames_ent_indptr wrt DGROUP  ; si -> base of lnames array
  2103 00000B9B 01C6                        add si,ax               ; si -> array element with segment:offset of name in lnames block
  2104                                  
  2105 00000B9D 1E                      	push	ds		; save warplink's data segment
  2106 00000B9E 07                      	pop	es		; es -> warplink's data
  2107 00000B9F C534                        lds si,[si]             ; -> name in lnames block
  2108 00000BA1 BF[0400]                    mov di,OFFSET name_field wrt DGROUP ; point to slot to place name
  2109 00000BA4 83C608                      add si,8                ; bump si past hi/low segment:offset pointers in lnames entry
  2110                                  
  2111                                  ; ds:si -> lnames name, es:di -> warplink data name field
  2112                                  ce_get_name:
  2113 00000BA7 A4                          movsb                   ; transfer a char
  2114 00000BA8 807CFF00                    cmp BYTE PTR [si-1],0   ; zero char flags end of transfer
  2115 00000BAC 75F9                        jne ce_get_name			; not zero, keep transferring
  2116                                  
  2117 00000BAE 06                      	push	es
  2118 00000BAF 1F                      	pop	ds					; restore ds -> warplink data
  2119 00000BB0 5E                      	pop	si					; restore critical registers
  2120 00000BB1 07                      	pop	es
  2121 00000BB2 C3                      	ret
  2122                                  proc_cextdef	ENDP
  2123                                  
  2124                                  END
