home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
kermit11.zip
/
k11sub.mac
< prev
next >
Wrap
Text File
|
1989-06-13
|
20KB
|
752 lines
.title k11sub common subroutines for all execs
.ident /8.0.01/
; Brian Nelson 01-Dec-83 13:19:14
;
; Copyright (C) 1983 Change Software, Inc.
;
;
; This software is furnished under a license and may
; be used and copied only in accordance with the
; terms of such license and with the inclusion of
; the above copyright notice. This software or any
; other copies thereof may not be provided or other-
; wise made available to any other person. No title
; to and ownership of the software is hereby trans-
; ferred.
;
; The information in this software is subject to
; change without notice and should not be construed
; as a commitment by the author.
; define macros and things we want for KERMIT-11
.if ndf, K11INC
.ift
.include /IN:K11MAC.MAC/
.endc
.iif ndf, k11inc, .error ; INCLUDE for IN:K11MAC.MAC failed
.psect $code
.enabl gbl
.sbttl cvt$$ basic+ cvt$$ function
.enabl lsb
; calls cvt$$ ,<addr(input),len(input),val(cvtbitpattern)>
;
; returns @ addr(input) trimmed string
; r0 length of whats left
;
; MASK TRIMS
; ---- -----
;
; 1 DISCARD ALL PARITY BITS
; 2 DISCARD ALL SPACES & TABS
; 4 DISCARD CR LF FF ESC RO
; 10 DISCARD LEADING SPACES & TABS
; 20 REDUCE SPACES & TABS TO A SINGLE SPACE
; 40 CONVERT LC TO UC
; 100 CONVERT [ TO ( AND ] TO )
; 200 DISCARD TRAILING SPACES & TABS
; 400 PRESERVE QUOTED SUBSTRINGS
; 1000 MODIFY 4 (IF ON) TO DISCARD ALL CHARACTERS < 40 OR =177
;
c.par = 1
c.spac = 2
c.crlf = 4
c.lspa = 10
c.sspa = 20
c.lcuc = 40
c.brac = 100
c.tspa = 200
c.quot = 400
c.prt = 1000
.asect
. = 0
pat: .blkw 1
inquo: .blkw 1
lastch: .blkw 1
saddr: .blkw 1
lsize = . + 2
.psect
.psect $code
.sbttl the real work of cvt$$
edit$::
cvt$$:: save <r1,r2,r3,r4,r5> ; the scratch registers to use.
sub #lsize ,sp ; allocate some work space
mov sp ,r4 ; point to a local work area
mov (r5)+ ,r2 ; the string address for output
mov r2 ,saddr(r4) ; and save it for a while
mov (r5)+ ,r1 ; get the string length also.
mov (r5)+ ,pat(r4) ; and finally the bit pattern.
clr inquo(r4) ; assume not in a quoted string.
clrb lastch(r4) ; no previous character please.
mov r2 ,r5 ; where to get the input string
tst r1 ; the length
beq 130$ ; nothing to do
10$: clr r3 ; avoind the movb sxt please.
bisb (r5)+ ,r3 ; get the next character .
tstb inquo(r4) ; currently in quoted string?
bne usech ; yes, skip all this junk.
bit #c.par ,pat(r4) ; Do we trim off the parity ?
beq 20$
bicb #200 ,r3 ; yes. clear bit number 7
20$: bit #c.spac!c.lspa,pat(r4) ; How about removing spaces &
bne 25$ ; tabs. if ne, yes
bit #c.sspa ,pat(r4) ; reduce imbedded ones to
beq 30$ ; a single tab/space ?
cmpb r3 ,#11 ; yes. if ch eq tab, then make
bne 21$ ; it into a space first please.
movb #40 ,r3 ; simple
21$: cmpb lastch(r4),#40 ; yes, was the last ch a space
beq 25$ ; or a tab ?
cmpb lastch(r4),#11 ; please check both out
bne 30$ ; no
25$: cmpb r3 ,#40 ; is the current character a
beq skipch ; space ?
cmpb r3 ,#9. ; not a space. try a horz tab
beq skipch ; char was a tab. Then ignore.
bic #c.lspa ,pat(r4) ; For leading spaces and tabs.
30$: bit #c.crlf ,pat(r4) ; try for ignoring form feed,
beq 50$ ; car ret,line feed,esc,null.
mov #junkch ,r0 ; Get the address of the spec
tstb r3 ; is the current ch a null ?
beq skipch ; yes, please skip it then.
40$: tstb @r0 ; anything left in the list ?
beq 50$ ; no
cmpb r3 ,(r0)+ ; see if we have a match. If
beq skipch ; so, we will skip the char.
br 40$ ; no, next check please
50$: bit #c.lcuc ,pat(r4) ; how about converting lower
beq 60$ ; case to upper case ?
cmpb r3 ,#'z!40 ; try against a lower case Z
bhi 60$
cmpb r3 ,#'a!40 ; if less than a lower z,try
blo 60$ ; for ge a lower case a
bicb #40 ,r3 ; char is in range. translate
60$: bit #c.brac ,pat(r4) ; how about convert [ to ( and
beq usech ; and convert ] to )
cmpb r3 ,#'[ ; and so on
bne 70$
movb #'( ,r3 ; convert it. fall thru to next
70$: cmpb r3 ,#']
bne usech
movb #') ,r3
br usech
skipch: br 120$ ; do not want the char, skip it.
.sbttl got a good ch, check for quoted string things
usech: bit #c.quot ,pat(r4) ; what about leaving quoted
beq 110$ ; strings alone ?
tstb inquo(r4) ; currently in a quoted string?
bne 90$ ; yes, check for the stopper.
cmpb r3 ,#'' ; a quote here ?
beq 80$ ; yes
cmpb r3 ,#'" ; alternate for a quote
bne 90$ ; no
80$: movb r3 ,inquo(r4) ; yes, save the terminator
br 110$ ; next please
90$: cmpb r3 ,inquo(r4) ; yes, is this the end of a
bne 110$ ; quoted string ?
clrb inquo(r4) ; yes, turn the flag off then.
110$: bit #c.prt ,pat(r4) ; should we skip nonprintable
beq 115$ ; characters now ?
cmpb r3 ,#40 ; yes, less than a space
blo 120$ ; yes
tstb r3 ; greater than 177 (rubout)
bmi 120$ ; yes
115$: movb r3 ,(r2)+ ; if all ok, return the char.
120$: movb r3 ,lastch(r4) ; please save the last ch
dec r1 ; and go back for some more.
bgt 10$ ; next please
130$: mov r2 ,r0 ; current pointer
sub saddr(r4),r0 ; return the length of what's
ble 160$ ; nothing left to do then.
bit #c.tspa ,pat(r4) ; remove trailing blanks ?
beq 160$ ; no
mov saddr(r4),r1 ; address of the string.
add r0 ,r1 ; point to end of string+1.
140$: cmpb -(r1) ,#40 ; Try for a space first.
beq 150$
cmpb (r1) ,#9. ; Not a space, try a tab.
bne 160$
150$: sob r0 ,140$ ; Tab or space. Check next
160$:
170$: add #lsize ,sp ; pop small work area
unsave <r5,r4,r3,r2,r1> ; pop all temps
return ; and exit
.save
.psect $Pdata,d
junkch: .byte 13.,10.,12.,27.,0,0
.restore
.dsabl lsb
.sbttl l$len get length of .asciz string
; L $ L E N
;
; input: r0 = address of .asciz string
; output: r0 = length of it
l$len:: mov r0 ,-(sp) ; save it for later.
10$: tstb (r0)+ ; look for a null character.
bne 10$ ; keep going
sub (sp)+ ,r0 ; subtract start address from
dec r0 ; current pointer less 1.
return
.sbttl write decimal
l$wrdec::
dfwidth = 6
;
; write a decimal number to KB: passed at 0(r5)
;
;
save <r1,r4,r5>
mov 2(r5) ,r1 ; field width
bgt 10$ ; good positive value.
beq 5$ ; zero, make it 6.
neg r1 ; negative means no space fill
br 10$ ; and skip this
5$: mov #dfwidth,r1 ; finally, we have the width.
10$: mov r1 ,r4 ; save for a moment
add #5 ,r1 ; make it round up to even num.
bic #1 ,r1 ; at last....
mov 2(r5) ,-(sp) ; The real field width please.
mov @r5 ,-(sp) ; And the number to print out.
mov sp ,r5 ; setup the parameter list addr
tst -(r5) ; make room for the buffer on
sub r1 ,sp ; the stack.
mov sp ,@r5 ; insert the buffer address
call l$cvtnum ; and convert the number.
.print @r5 ,r4 ; and print it out
add r1 ,sp ; and fix the stack up.
cmp (sp)+ ,(sp)+ ; rest of stack pop.
unsave <r5,r4,r1> ; thats all for now
return
; write out a decimal number at 2(r5) into the buffer
; address passed at 0(r5). All registers saved.
l$cvti::save <r5> ; call common conversion sub.
clr -(sp) ; setup paramter list first.
mov 2(r5) ,-(sp) ; calls $cvtnum,<@r5,2(r5),#0>
mov @r5 ,-(sp) ; finally the buffer address.
mov sp ,r5 ; the parameter list address.
call l$cvtnum ; convert it please.
add #6 ,sp ; pop stack parameter list.
unsave <r5> ; restore r5
return ; and exit please.
.sbttl the real conversion sub
; input: 0(r5) = buffer address
; 2(r5) = value to print
; 4(r5) = field width ( > 0 ->right, < 0 -> left )
;
; field width: if < zero, string will be left justified
; if > zero, string will be right justified
; if = zero, field will be set to 6.
;
l$cvtnum::
save <r0,r1,r2,r3,r4> ; some scratch registers saved
mov (r5) ,r2 ; the buffer address to use.
mov 4(r5) ,r3 ; the field width to use.
bgt 80$ ; nonzero, it is ok (?)
beq 70$ ; zero
neg r3 ; < 0
br 80$
70$: mov #dfwidth,r3 ; zero, use default width 6.
80$: mov r3 ,r1 ; put it here to clear buffer.
1$: movb #32. ,(r2)+ ; fill the buffer with blanks
sob r1 ,1$
mov r2 ,-(sp) ; save end of buffer here.
mov r3 ,r4 ; save buffer size also.
mov 2(r5) ,r1 ; Get the value to print out.
bpl 2$
neg r1
2$: clr r0 ; set up for the divide by 10.
div #10. ,r0 ; remainder in r1, quotient r0
add #'0 ,r1 ; convert remainder to character
cmp r2 ,@r5 ; overflowed the buffer at all?
beq 100$ ; yes, get out of here !
movb r1 ,-(r2) ; and return the character now.
mov r0 ,r1
beq 3$
sob r3 ,2$ ; go back for more
tst r1 ; something left over by chance?
bne 100$ ; Yes, that's a definite error.
3$: tst 2(r5) ; was this a negative number ?
bpl 90$ ; no, exit
cmp r2 ,@r5 ; yes, room left for a '-' sym.
beq 100$ ; no, flag an error please.
movb #'- ,-(r2) ; yes, insert a minus symbol.
;; br 90$ ; thats all.
90$: tst 4(r5) ; negative field width ?
bpl 4$ ; no, exit.
mov @r5 ,r1 ; start of the buffer here.
95$: movb (r2)+ ,(r1)+ ; move chars to front of buffer.
cmp r2 ,(sp) ; end of the buffer yet ?
bhis 97$ ; no, keep going please.
sob r4 ,95$ ; keep going please
97$: dec r4 ; anything left to zero out?
ble 4$ ; no
98$: movb #40 ,(r1)+ ; yes, zero to end of buffer.
sob r4 ,98$ ; more please
br 4$ ; finally exit this mess.
100$: movb #'* ,@r2 ; field overlfow. place '*' in
; beginning of the buffer.
4$: tst (sp)+ ; pop stack, restore temp regs
unsave <r4,r3,r2,r1,r0>
return ; thats all there is to it.
.sbttl mout print text from message macro
locmout::
tst remote
beq mout
mov (sp)+ ,@sp
return
mout:: save <r0>
mov 4(sp) ,r0
.print r0
unsave <r0>
mov (sp)+ ,@sp
return
.sbttl instr
; I N S T R simple (non-wildcard) version
; input:
;
; (r5) = address of the first string
; 2(r5) = length of the first string .
; 4(r5) = address of the second string, the one to find.
; 6(r5) = length of the second string.
;
; output:
;
; r0 = if > 0 then r0=position of second in first
; else the second is not a substring.
;
instr::
save <r1,r2,r3,r4> ; we use these here, so save.
mov (r5) ,r0 ; the address of first string
mov 4(r5) ,r1 ; the address of second one.
mov 6(r5) ,r2 ; the length of second one.
ble 6$ ; a null string ?
mov 2(r5) ,r4 ; the length of first.
ble 6$ ; a null string ?
sub r2 ,r4 ; convert to looping counter
clr r3 ; the real loop counter.
1$: cmp r3 ,r4 ; are we done yet ?
bgt 6$ ; yes, if r3 > r4 .
cmpb (r0)+ ,(r1) ; see if current character in
bne 5$ ; matches first one in second.
save <r0,r1,r2> ; found first character match.
inc r1 ; point to the next character
dec r2 ; length of pattern thats left
ble 3$ ; in case the len( pattern ) =1
2$: cmpb (r0)+ , (r1)+ ; check the rest of the pattern
bne 4$
sob r2 ,2$ ; loop for len( pattern ) - 1
3$: mov r3 ,r0 ; the current loop count
inc r0
add #6 ,sp ; fix the stack from save < >
br 7$
4$: unsave <r2,r1,r0> ; the match failed. restore the
5$: inc r3 ; pointers and go try the next
br 1$ ; character in the first string
6$: clr r0 ; complete failure if get here
7$: unsave <r4,r3,r2,r1> ; restore the registers we used
return ; and go away.
.sbttl convert rad50 word to 3 ascii bytes and back
;rdtoa
; (r5) = address of where to put ascii chars
; input 2(r5) = the value of rad 50 word
;
;
;
;procedure rd_toa( rval: integer ; var aout: array [1..3] of char ) ;
;
; type rlist = array [0..39] of char ;
; const
; r50ch = rlist(' ','A','B','C','D','E','F','G','H','I','J','K',
; 'L','M','N','O','P','Q','R','S','T','U','V','W',
; 'X','Y','Z','$','.','?','0','1','2','3','4','5',
; '6','7','8','9' );
; var i: integer ;
; begin
; aout[1] := r50ch[ rval div 3100B ]; rval := rval mod 3100B ;
; aout[2] := r50ch[ rval div 50B ] ; aout[3] := r50ch[ rval mod 50B ]
; end ;
rdtoa::
radasc: save <r0,r1,r3> ; same some registers
mov 2(r5) ,r1 ; go get the rad50 character.
mov (r5) ,r3 ; where to put the characters.
com: clr r0 ; prepare for divide
div #3100 ,r0 ; get first char
movb radchr(r0),(r3)+ ; put in buffer
clr r0 ; another divide
div #50 ,r0 ; this one gives char 2
movb radchr(r0),(r3)+ ; put this in buffer
movb radchr(r1),(r3)+ ; and also char 3
unsave <r3,r1,r0> ; restore the registers we used.
return ; bye
.save
.psect $Pdata,d
.nlist bex
radchr: .ascii / ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789:/
.list bex
.even
.restore
.sbttl get decimal number value
; L $ V A L (20-Nov-80)
;
; (r5) = address of .asciz string to convert
;
; r0 = error (-1 for bad number)
; r1 == binary value of the string.
l$val:: save <r2,r3>
clr r1 ; initailize the result.
mov (r5) ,r3 ; the address of the string.
clr -(sp) ; a positive number for now.
clr r0
30$: tstb @r3 ; null. If so, exit please.
beq 5$ ; buy.
cmpb @r3 ,#space ; we will ignore spaces.
beq 50$ ; if equal, then skip.
tst r0 ; past the first space yet ?
bne 40$ ; yes, skip sign checks.
com r0 ; past all the leading spaces.
cmpb @r3 ,#'+ ; positive number ?
beq 50$ ; yes, skip over the character.
cmpb @r3 ,#'- ; negative ?
bne 40$ ; no, try for a digit then.
mov sp ,(sp) ; neg, set a useful flag up.
br 50$ ; and skip it.
40$: cmpb @r3 ,#'0 ; try comparing to '0' .
blo 70$ ; not a digit. time to go
cmpb @r3 ,#'9 ; try comparing to '9' .
bhi 70$ ; not a digit . get out.
clr -(sp) ; clr out the scratch reg.
bisb @r3 ,(sp) ; copy the character over.
sub #48. ,(sp) ; convert char to a digit.
mul #10. ,r1 ; multiply accum by 10 first
bcs 60$ ; oops
add (sp)+ ,r1 ; add on the digit to accum
bvs 70$ ; bye
50$: inc r3 ; pointer := succ( pointer );
br 30$
60$: tst (sp)+ ; came here from multiply overf
70$: clr r0 ; return 0 in case of error.
mov #-1 ,r0 ; ?Illegal number
tst (sp)+ ; pop sign flag from stack.
br 100$
5$: tst (sp)+ ; pop sign flag on tos.
beq 95$ ; positive number ?
tst r1 ; negative 0 (-32768) ?
bne 90$ ; no
bis #100000 ,r1 ; yes, set only the sign bit
br 95$ ; and go away.
90$: neg r1 ; no.
95$: clr r0
100$: unsave <r3,r2>
return ; and time to leave.
.sbttl octval return octal vaule in r1, error in r0
octval::save <r2,r3> ; save temps please
clr r0 ; assume no error
clr r1 ; value := 0
mov @r5 ,r2 ; get the buffer address
10$: movb (r2)+ ,r3 ; get the next character please
beq 100$ ; all done
cmpb r3 ,#'0 ; error if < '0' or > '7'
blo 90$ ; oops
cmpb r3 ,#'7 ; how about the upper limit
bhi 90$ ; oops
sub #'0 ,r3 ; get the value
asl r1 ; accumulated value times 8
asl r1 ; the long way
asl r1 ; r1 = r1 * 8
add r3 ,r1 ; add in the current digit
br 10$ ; next
90$: mov #-1 ,r0 ; illegal number
100$: unsave <r3,r2> ; pop registers and exit
return
.sbttl binary to octal conversion
.enabl lsb
;
; 17-Nov-80 BDN
;
; convert binary number at 2(r5) to ascii string
; at buffer address 0(r5).
;
l$otoa::save <r0,r1,r2,r3> ; save the scratch regs.
mov (r5) ,r2
mov 2(r5) ,r3
add #6 ,r2 ; do it backwards
mov #6 ,r0 ; do it 6 times
10$: mov r3 ,r1 ; get the number
bic #177770 ,r1 ; leave low order 3 bits on
movb 200$(r1),-(r2) ; move an octal digit
ash #-3 ,r3 ; shift three bytes
bic #160000 ,r3 ; zap propagated sign bits
sob r0 ,10$ ; go convert next digit
unsave <r3,r2,r1,r0>
return
.save
.psect $Pdata,D
200$: .ascii \01234567\ ; ascii/octal 200$
.even
.restore
.dsabl lsb
; (r5) = value to write to KB:
l$wroc::save <r0>
sub #10 ,sp
mov sp ,r0 ; use stack for a buffer
calls l$otoa ,<r0,(r5)>
print r0 ,#6.
add #10 ,sp
unsave <r0>
return
.sbttl copyz copyz .asciz string
; C O P Y Z $
;
; input: 6(sp) max len or zero
; 4(sp) source string address
; 2(sp) destination string address
;
; usage: copyz macro, as in copyz #oldfile,#newfile
copyz$::save <r0,r1> ; save registers we may use
tst 4+6(sp) ; see if a maxlen was passed
bne 5$ ; yes
mov #77777 ,4+6(sp) ; no, say we can have MAXINT chars
5$: mov 4+4(sp) ,r0 ; source string address
mov 4+2(sp) ,r1 ; destination string address
10$: movb (r0)+ ,(r1)+ ; copy a byte
beq 20$ ; until a null is found
dec 4+6(sp) ; or we have copied MAXLEN number
bne 10$ ; of characters over
20$: clrb -(r1) ; insure output .asciz please
unsave <r1,r0> ; pop temps
mov @sp ,6(sp) ; move return address up
add #6 ,sp ; fix the stack
return ; and exit
.sbttl formatted byte dump
; input: 4(sp) size
; 2(sp) address
dump$b::save <r0,r1,r2> ; save all please
mov <4+6>(sp),r1 ; size
beq 100$ ; nothing do to today
mov <2+6>(sp),r2 ; address to dump
10$: clr r0 ; get the next byte please
bisb (r2)+ ,r0 ; get it
decout r0 ; and print it
sob r1 ,10$ ; next please
100$: .newline ; a cr/lf
unsave <r2,r1,r0> ; pop all registers we used
mov @sp ,4(sp) ; move return address up
cmp (sp)+ ,(sp)+ ; pop two words for parameter list
return ; and exit
.sbttl strcat and strcpy
; input:
; 0(sp) return address
; 2(sp) dst address
; 4(sp) src address
; output: r0 dest address
strcpy::save <r1> ; save temp registers please
mov 2+2(sp) ,r0 ; destination address
mov 2+4(sp) ,r1 ; source .asciz address
10$: movb (r1)+ ,(r0)+ ; copy until a null
bne 10$ ; not done
mov 2+2(sp) ,r0 ; return the dst address
unsave <r1> ; pop r1 and exit
mov (sp) ,4(sp) ; move return address up now
cmp (sp)+ ,(sp)+ ; pop junk and exit
return
strcat::save <r1> ; save temp registers please
mov 2+2(sp) ,r0 ; destination address
mov 2+4(sp) ,r1 ; source .asciz address
5$: tstb (r0)+ ; look for the end of the dst string
bne 5$ ; not found yet
dec r0 ; found it, fix the pointer
10$: movb (r1)+ ,(r0)+ ; copy until a null
bne 10$ ; not done
mov 2+2(sp) ,r0 ; return the dst address
unsave <r1> ; pop r1 and exit
mov (sp) ,4(sp) ; move return address up now
cmp (sp)+ ,(sp)+ ; pop junk and exit
return
strcmp::mov 2(sp),r0 ;Pick up 'a'
mov 4(sp),r1 ;And 'b'
10$: cmpb (r0)+,(r1) ;Are they the same
bne 20$ ;No
tstb (r1)+ ;At the end of the string
bne 10$ ;No
clr r0 ;Equal return
br 100$
20$: blo 30$ ;Br if a<b
mov #1,r0 ;A>b return
br 100$
30$: mov #-1,r0 ;A<b return
100$: mov (sp) ,4(sp) ; move return address up now
cmp (sp)+ ,(sp)+ ; pop junk and exit
return
malloc::inc r0
bic #1 ,r0
mov r0 ,-(sp)
add @albuff ,(sp)
cmp (sp) ,#alsize
bhis 90$
mov albuff ,r0
add #2 ,r0
add @albuff ,r0
mov (sp)+ ,@albuff
return
90$: clr r0
tst (sp)+
return
global <albuff,alsize>
decryp::
encryp::mov (sp) ,4(sp)
cmp (sp)+ ,(sp)+
return
.end