home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
progjour
/
1991
/
06
/
alibtool
/
order.asm
< prev
next >
Wrap
Assembly Source File
|
1991-08-23
|
14KB
|
701 lines
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