home *** CD-ROM | disk | FTP | other *** search
- title order - resequence procedure labels
- include asm.inc
-
- public main
-
- ;
- ; Assemble with /ML switch: C>masm order/ml;
- ; C>link order;
- ;
- ; (C) Soft Advances 1991, All Rights Reserved
-
- PROC_LINE_MAX equ 250
- DOUBLE_CASE_BITS equ 2020h
-
-
- .data
- extb ertx_file_too_big
- extw dgroup_segment
-
-
- write_output_flag db 0 ; set this flag if input file changes
-
- proc_text db 'proc'
- endp_text db 'endp'
- bak_text db 'bak'
-
- ertx_endp_missing db 'ENDP missing',0
- ertx_output_file db 'Error creating, writing, or closing output',0
- ertx_rename db 'Rename failed',0
-
- help_text db 'order file.asm',10
- db 'Resequences procedure labels in file.asm. Labels must be',10
- db 'of the form "n$" or "ABCn" (e.g. 1$, 32$, abc1, foo23).',10
- db 'Before updating file.asm, order renames file.asm to file.bak.',10
- db 'Version 1.2 8-21-91 by John Otken',0
-
- no_update_text db 'sequence OK, nothing written',0
- resequenced_text db ' resequenced',0
-
- .data?
- extd argv
- extw argc
-
- label_count dw ? ; number of labels in procedure body
- label_table dw PROC_LINE_MAX dup(?)
-
- output_bucket dd ? ; output buffer pointer
- output_bc dw ?
-
- proc_initials db ?,?,?,? ; first 3 characters of local label
-
- bak_filename db FILENAME_MAX dup(?)
-
-
- .code
- extn isalpha_,isdigit,isalpha,strskp_white,isalnum,startup,open_output_file
- extn strskp_white,strskp_line,ms_dos,read_entire_file
- extn malloc,puts_dgroup,putchar,set_strerror,perror,remove,rename
- extn close_file_cf,write_to_file
-
-
- ;; atoi skip
- ;
- ; entry DS:SI ascii digits
- ; exit AX binary value
- ; SI updated to digit string delimiter
- ; Cf if bad number
- ;
- atoi_update proc
- call strskp_white
- call isdigit
- jne ati4 ; if bad or negative number
-
- ati1: push dx ; process first digit
- sub al,'0'
- cbw
- mov dx,ax
- inc si
-
- ati2: mov al,[si] ; process each digit
- call isdigit
- jne ati3 ; if end of digits
-
- add dx,dx ; multiply by ten
- mov ax,dx
- add dx,dx
- add dx,dx
- add dx,ax
-
- lodsb ; sum new digit
- sub al,'0'
- cbw
- add dx,ax
- jmp ati2
-
- ati3: clc
- mov ax,dx
- pop dx
- ret
-
- ati4: cmp al,'-' ; here for possible negative number
- jne ati5 ; if bad number
-
- inc si ; else probable negative number
- mov al,[si]
- call isdigit
- je ati5 ; if bad number
-
- call ati1 ; parse digits
- neg ax
- clc
- ret
-
- ati5: stc
- ret
- atoi_update endp
-
-
- ;; atoi special
- ;
- ; entry DS:SI ascii digits
- ; exit AX binary value
- ; SI updated to digit string delimiter
- ; Cf if bad number or leading zeros
- ;
- atoi_special proc
- cmp bptr [si],'0' ; check for leading zero in digit
- jne atoi_update ; if no leading zero
-
- mov al,[si+1] ; else leading 0, check for lone 0
- call isdigit
- jne atoi_update ; if lone zero, parse it
- stc
- ret
- atoi_special endp
-
-
- ;; check label sequence
- ;
- ; exit Cf if labels out of sequence
- ; uses AX,BX
- ;
- check_label_sequence proc
- mov ax,0
- lea bx,label_table
-
- cll1: cmp ax,label_count[bp]
- je cll2 ; if all labels OK (Cf=0)
- inc ax
- cmp ax,ss:[bx]
- lea bx,[bx+2]
- je cll1 ; if label correctly sequenced
- stc ; else indicate bad sequencing
- cll2: ret
- check_label_sequence endp
-
-
- ;; convert label index
- ;
- ; entry AX old label index
- ; exit AX new label index
- ; Cf if bad index
- ;
- convert_label_index proc
- pushm cx,di,es
- mov es,dgroup_segment[bp] ; search table for old label index
- lea di,label_table
- mov cx,label_count[bp]
- repne scasw
- stc
- jne cli1 ; if not found, return error
-
- mov ax,di ; else return correct index
- sub ax,offset label_table
- shr ax,1
- clc
- cli1: popm es,di,cx
- ret
- convert_label_index endp
-
-
- ;; count proc lines
- ;
- ; entry DS:SI procedure text
- ; DX end of proc offset
- ; exit CX number of lines
- ; uses AX
- ;
- count_proc_lines proc
- push si
- mov cx,0
-
- cpl1: cmp si,dx
- jae cpl2 ; if end of procedure
- call strskp_line
- inc cx
- jmp cpl1
-
- cpl2: pop si
- ret
- count_proc_lines endp
-
-
- ;; extract label number
- ;
- ; entry DS:SI local label with colon delimiter
- ; exit AX label #
- ; Cf if unsupported or non-local label
- ;
- extract_label_number proc
- push si
- lodsb
- call isdigit
- je eln1 ; if OPTASM local label (1$:)
- cmp al,proc_initials[bp]
- jne eln3 ; if bad label
- lodsb
- cmp al,proc_initials[bp+1]
- jne eln3 ; if bad label
- lodsb
- cmp al,proc_initials[bp+2]
- jne eln3 ; if bad label
-
- call atoi_special
- jc eln3 ; if bad label index
- jmp eln2
-
- eln1: dec si ; here for OPTASM labels (1$:)
- call atoi_special
- jc eln3
-
- cmp bptr [si],'$'
- jne eln3 ; if dollar sign suffix missing
- inc si
-
- eln2: cmp bptr [si],':'
- je eln4 ; if near label colon OK (Cf=0)
- eln3: stc ; else set error flag
-
- eln4: pop si
- ret
- extract_label_number endp
-
-
- ;; find local labels
- ;
- ; entry DS:SI procedure text
- ; CX nonzero line count
- ; exit Cf if unable to process procedure
- ; uses AX,BX
- ;
- find_local_labels proc
- pushm cx,si
- mov label_count[bp],0
- lea bx,label_table[bp]
-
- fll1: mov al,[si] ; process procedure line
- cmp al,SPACE_CHAR
- jbe fll2 ; if no label on this line
- cmp al,';'
- je fll2 ; if comment then not label
-
- call extract_label_number
- jc fll3 ; if unknown label format
-
- mov ss:[bx],ax ; record label index in label_table
- add bx,2
- inc label_count[bp]
-
- fll2: call strskp_line ; advance to next line
- loop fll1
- clc
-
- fll3: popm si,cx
- ret
- find_local_labels endp
-
-
- ;; find proc endp
- ;
- ; entry DS:SI text ptr
- ; SS:BX points to either "proc" or "endp"
- ; exit SI points to line after proc or endp
- ; DX points to start of proc or endp line
- ; Cf if end of file
- ; uses AX
- ;
- find_proc_endp proc
- jmp fpe2
- fpe1: call strskp_line ; advance to next source line
-
- fpe2: mov al,[si] ; check start of line for proc name
- cmp al,NULL_CHAR
- je fpe4 ; if end of file
- call isalpha_
- jne fpe1 ; if not name (must start w/ letter)
-
- mov dx,si ; skip to token following name
- fpe3: lodsb
- call isalpha_
- je fpe3
- dec si
- call strskp_white
-
- mov ax,[si] ; check for PROC or ENDP tokens
- or ax,DOUBLE_CASE_BITS
- cmp ax,ss:[bx]
- jne fpe1 ; if not PROC or ENDP
- mov ax,[si+2]
- or ax,DOUBLE_CASE_BITS
- cmp ax,ss:[bx+2]
- jne fpe1 ; if not PROC or ENDP
- mov al,[si+4]
- call isalpha_
- je fpe1 ; if not PROC or ENDP
- call strskp_line
-
- fpe4: add al,-1 ; (set Cf if AL==0)
- cmc
- ret
- find_proc_endp endp
-
-
- ;; get proc initials
- ;
- ; entry DS:SI procedure body
- ; CX line count
- ; exit Cf if unsupported label syntax
- ; uses AX
- ;
- get_proc_initials proc
- pushm cx,si
- gpi1: mov al,[si] ; search for "3 initial" local label
- call isalpha
- je gpi2 ; if found (maybe)
- call strskp_line
- loop gpi1
- clc ; no 3 initial label found (not error)
- jmp gpi4
-
- gpi2: mov proc_initials[bp],al ; save initials 1, 2, and 3
-
- mov al,[si+1]
- call isalpha
- jne gpi3 ; if non-alpha, is not local label
- mov proc_initials[bp+1],al
-
- mov al,[si+2]
- call isalpha
- jne gpi3 ; if non-alpha, is not local label
- mov proc_initials[bp+2],al
-
- mov al,[si+3]
- call isdigit
- je gpi5 ; if good "3 initial" local label
-
- gpi3: stc
- gpi4: mov wptr proc_initials[bp],0
- mov bptr proc_initials[bp+2],0
-
- gpi5: popm si,cx
- ret
- get_proc_initials endp
-
-
- ;; help
- ;
- help proc
- lea ax,help_text
- call puts_dgroup
- ret
- help endp
-
-
- ;; itoa decimal
- ;
- ; entry AX number
- ; ES:DI destination
- ; exit DI updated (points to delimiting 0)
- ; uses AX
- ;
- itoa_decimal proc
- cmp ax,0
- jge ita1 ; if positive
- mov bptr es:[di],'-' ; else "stosb" minus sign
- inc di
- neg ax
-
- ita1: pushm cx,dx
- mov cx,10
- mov dx,-1 ; push sentinal
- ita2: push dx
- mov dx,0
- div cx ; divide digits
- cmp ax,0
- jne ita2
- inc dx
- ita3: xchg ax,dx ; write digits
- add al,'0'-1
- stosb
- pop dx
- inc dx
- jnz ita3 ; if not sentinal
- mov es:[di],dl ; write delimiting 0
- popm dx,cx
- ret
- itoa_decimal endp
-
-
- ;; main
- ;
- main proc
- cmp argc[bp],1
- jbe help ; if no arguments - exit
-
- lds si,argv[bp]
- mov si,[si+2]
-
- call read_entire_file
- jc mai4 ; if file not found or too big
- call malloc_output_bucket
- jc mai4 ; if not enough memory
-
- mai1: mov cx,si ; find start of next procedure
- lea bx,proc_text
- call find_proc_endp
- jc mai2 ; if end of file
-
- xchg cx,si ; output source up to procedure
- sub cx,si
- rep movsb
-
- mov cx,si ; find end of procedure
- lea bx,endp_text
- call find_proc_endp
- jc mai3 ; if endp missing error
-
- mov si,cx ; count lines in procedure body
- call count_proc_lines
- jcxz mai1 ; if empty proc, ignore it
- cmp cx,PROC_LINE_MAX
- ja mai1 ; if procedure too long, ignore it
-
- call get_proc_initials
- jc mai1 ; if unsupported local label syntax
-
- call find_local_labels
- jc mai1 ; if unsupported label syntax
-
- call check_label_sequence
- jnc mai1 ; if label sequence OK
-
- call resequence_proc_labels
-
- mov write_output_flag[bp],-1
- call putchar_proc_name
- jmp mai1
-
- mai2: xchg cx,si ; output source up to procedure
- sub cx,si
- rep movsb
- sub di,wptr output_bucket[bp] ; save output byte count
- mov output_bc[bp],di
-
- call update_asm_source
- jc mai4 ; if any errors updating .asm file
-
- mov al,EXIT_SUCCESS
- ret
-
- mai3: lea ax,ertx_endp_missing
- call set_strerror
- mai4: mov si,NULL_POINTER
- call perror
- mov al,EXIT_FAILURE
- ret
- main endp
-
-
- ;; malloc output bucket
- ;
- ; entry CX file byte count
- ; exit ES:DI output bucket
- ; Cf if file too big or not enough memory
- ; uses AX,CX
- ;
- malloc_output_bucket proc
- add cx,1024 ; allocate oversized output bucket
- jc mob2 ; if file too big
- call malloc
- jc mob1 ; if not enough memory
-
- mov wptr output_bucket[bp],di
- mov wptr output_bucket[bp+2],es
- mob1: ret
-
- mob2: lea ax,ertx_file_too_big
- call set_strerror
- ret
- malloc_output_bucket endp
-
-
- ;; putchar proc name
- ;
- ; entry DS:SI points to endp line
- ; uses AX
- ;
- putchar_proc_name proc
- push si ; display procedure name
- mov al,SPACE_CHAR
- ppn1: call putchar
- lodsb
- cmp al,SPACE_CHAR
- ja ppn1
- pop si
-
- lea ax,resequenced_text ; * resequenced*
- call puts_dgroup
- ret
- putchar_proc_name endp
-
-
- ;; resequence local label
- ;
- ; entry A first character of label
- ; DS:SI points to possible local label
- ; ES:DI output pointer
- ; exit DI,SI updated
- ; uses AX,BX
- ;
- resequence_local_label proc
- mov bx,si
- cmp al,'9'
- jbe rll1 ; if possible OPTASM label
-
- cmp al,proc_initials[bp] ; check for 3 initial label
- jne rll2 ; if not
- mov al,[si+1]
- cmp al,proc_initials[bp+1]
- jne rll2
- mov al,[si+2]
- cmp al,proc_initials[bp+2]
- jne rll2
-
- lea si,[si+3] ; try parsing label index
- call atoi_special
- jc rll2 ; if no index, not label
- call convert_label_index
- jc rll2 ; if unknown label index
-
- xchg bx,si ; copy procedure initials
- movsw
- movsb
- xchg bx,si
-
- call itoa_decimal ; and write new label index
- ret
-
- rll1: call atoi_special ; here for possible OPTASM label
- jc rll2 ; if bad index
- cmp bptr [si],'$'
- jne rll2 ; if dollar suffix missing
- call convert_label_index
- jc rll2 ; if unknown index
- call itoa_decimal
-
- movsb ; copy dollar suffix
- ret
-
- rll2: mov si,bx
- ret
- resequence_local_label endp
-
-
- ;; resequence proc labels
- ;
- ; entry DS:SI procedure body
- ; ES:DI output pointer
- ; CX line count
- ; exit DI,SI updated
- ; uses AX,BX,CX
- ;
- resequence_proc_labels proc
- rpl1: mov al,[si]
- call isalnum
- jne rpl3 ; if not label
- call resequence_local_label ; else resequence it
- jmp rpl3
-
- rpl2: movsb ; skip to next delimiter
- rpl3: mov al,[si]
- cmp al,SPACE_CHAR
- je rpl4
- cmp al,TAB_CHAR
- je rpl4
- cmp al,NL_CHAR
- je rpl5 ; if end of line
- cmp al,';'
- je rpl5 ; if comment
- cmp al,','
- jne rpl2 ; if not delimiter
-
- rpl4: movsb ; delimiter found, skip white space
- mov al,[si]
- cmp al,SPACE_CHAR
- je rpl4 ; if white space
- cmp al,TAB_CHAR
- je rpl4 ; if white space
- cmp al,';'
- je rpl5 ; if comment
- cmp al,NL_CHAR
- je rpl5 ; if end of line
-
- jmp rpl1 ; end of white space, check for label
-
- rpl5: lodsb ; skip to next line
- stosb
- cmp al,NL_CHAR
- jne rpl5
-
- rpl6: loop rpl1 ; loop while more lines left in body
- ret
- resequence_proc_labels endp
-
-
- ;; strcpy new ext
- ;
- ; entry DS:SI asciiz source filename
- ; ES:DI destination pointer
- ; SS:BX new extension
- ; exit DI,SI updated
- ; uses AX
- ;
- strcpy_new_ext proc
- jmp sne2
- sne1: stosb ; copy drive, directories, filename
- sne2: lodsb
- cmp al,NULL_CHAR
- je sne3 ; if end of filename
- cmp al,'.'
- jne sne1 ; if not start of extension
-
- mov al,[si]
- cmp al,'.'
- je sne1 ; if ..
- cmp al,'\'
- je sne1 ; if .\
-
- sne3: mov al,'.' ; write new extension
- stosb
- mov ax,ss:[bx]
- stosw
- mov al,ss:[bx+2]
- mov ah,NULL_CHAR
- stosw
- ret
- strcpy_new_ext endp
-
-
- ;; update asm source
- ;
- ; uses AX,BX,CX,DX,DI,SI,DS,ES
- ;
- update_asm_source proc
- test write_output_flag[bp],-1
- jz uas2 ; if nothing to update
-
- lds si,argv[bp] ; make .bak filename
- mov si,[si+2]
- lea bx,bak_text
- mov es,dgroup_segment[bp]
- lea di,bak_filename
- call strcpy_new_ext
-
- mov ds,dgroup_segment[bp] ; delete old .bak file
- lea si,bak_filename
- call remove ; (ignore errors)
-
- lds si,argv[bp] ; rename .asm to .bak
- mov si,[si+2]
- lea di,bak_filename
- call rename
- jc uas1 ; if rename failed
-
- call open_output_file ; create .asm file
- jc uas1
-
- mov cx,output_bc[bp] ; write .asm file
- les di,output_bucket[bp]
- call write_to_file
-
- call close_file_cf
- uas1: ret
-
- uas2: lea ax,no_update_text
- call puts_dgroup
- ret
- update_asm_source endp
-
- end
-