home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / pdp11 / k11sub.mac < prev    next >
Text File  |  2020-01-01  |  19KB  |  752 lines

  1.     .title    k11sub    common subroutines for all execs
  2.     .ident    /8.0.01/
  3.  
  4. ;    Brian Nelson  01-Dec-83  13:19:14
  5. ;
  6.  
  7.  
  8.  
  9.  
  10. ;    Copyright (C) 1983   Change Software, Inc.
  11. ;    
  12. ;    
  13. ;    This software is furnished under a license and may
  14. ;    be  used  and  copied  only in accordance with the
  15. ;    terms of such license and with  the  inclusion  of
  16. ;    the  above copyright notice.  This software or any
  17. ;    other copies thereof may not be provided or other-
  18. ;    wise made available to any other person.  No title
  19. ;    to and ownership of the software is hereby  trans-
  20. ;    ferred.
  21. ;    
  22. ;    The information in this  software  is  subject  to
  23. ;    change  without notice and should not be construed
  24. ;    as a commitment by the author.
  25.  
  26.  
  27.  
  28. ;    define macros and things we want for KERMIT-11
  29.  
  30.  
  31.  
  32.     .if ndf, K11INC
  33.     .ift
  34.     .include    /IN:K11MAC.MAC/
  35.     .endc
  36.  
  37.     .iif ndf, k11inc, .error ; INCLUDE for IN:K11MAC.MAC failed
  38.  
  39.     .psect    $code
  40.     .enabl    gbl
  41.  
  42.  
  43.  
  44.     .sbttl    cvt$$    basic+ cvt$$ function
  45.  
  46.  
  47.     .enabl    lsb
  48.  
  49. ;    calls    cvt$$    ,<addr(input),len(input),val(cvtbitpattern)>
  50. ;
  51. ;    returns    @ addr(input)    trimmed string
  52. ;        r0        length of whats left
  53.  
  54.  
  55. ;
  56. ;    MASK    TRIMS
  57. ;    ----    -----
  58. ;
  59. ;       1    DISCARD ALL PARITY BITS
  60. ;       2    DISCARD ALL SPACES & TABS
  61. ;       4    DISCARD CR LF FF ESC RO
  62. ;      10    DISCARD LEADING SPACES & TABS
  63. ;      20    REDUCE SPACES & TABS TO A SINGLE SPACE
  64. ;      40    CONVERT LC TO UC
  65. ;     100    CONVERT [ TO ( AND ] TO )
  66. ;     200    DISCARD TRAILING SPACES & TABS
  67. ;     400    PRESERVE QUOTED SUBSTRINGS
  68. ;    1000    MODIFY 4 (IF ON) TO DISCARD ALL CHARACTERS < 40 OR =177
  69. ;
  70.     c.par    =    1
  71.     c.spac    =    2
  72.     c.crlf    =    4
  73.     c.lspa    =    10
  74.     c.sspa    =    20
  75.     c.lcuc    =    40
  76.     c.brac    =    100
  77.     c.tspa    =    200
  78.     c.quot    =    400
  79.     c.prt    =    1000
  80.  
  81.  
  82.     .asect
  83.     .    =    0
  84. pat:    .blkw    1
  85. inquo:    .blkw    1
  86. lastch:    .blkw    1
  87. saddr:    .blkw    1
  88.  
  89.     lsize    =    . + 2
  90.  
  91.     .psect
  92.     .psect    $code
  93.  
  94.  
  95.     .sbttl    the real work of cvt$$
  96.  
  97.  
  98. edit$::
  99. cvt$$::    save    <r1,r2,r3,r4,r5>    ; the scratch registers to use.
  100.     sub    #lsize    ,sp        ; allocate some work space
  101.     mov    sp    ,r4        ; point to a local work area
  102.     mov    (r5)+    ,r2        ; the string address for output
  103.     mov    r2    ,saddr(r4)    ; and save it for a while
  104.     mov    (r5)+    ,r1        ; get the string  length  also.
  105.     mov    (r5)+    ,pat(r4)    ; and finally  the bit pattern.
  106.     clr    inquo(r4)        ; assume not in a quoted string.
  107.     clrb    lastch(r4)        ; no previous character please.
  108.     mov    r2    ,r5        ; where to get the input string
  109.     tst    r1            ; the length
  110.     beq    130$            ; nothing to do
  111.  
  112. 10$:    clr    r3            ; avoind the movb sxt please.
  113.     bisb    (r5)+    ,r3        ; get the next character .
  114.     tstb    inquo(r4)        ; currently in quoted string?
  115.     bne    usech            ; yes, skip all this junk.
  116.     
  117.     bit    #c.par    ,pat(r4)    ; Do we trim off the parity  ?
  118.     beq    20$
  119.      bicb    #200    ,r3        ; yes. clear bit number 7
  120.  
  121. 20$:    bit    #c.spac!c.lspa,pat(r4)    ; How about removing spaces &
  122.     bne    25$            ; tabs. if ne, yes
  123.  
  124.     bit    #c.sspa    ,pat(r4)    ; reduce imbedded ones to
  125.     beq    30$            ; a single tab/space ?
  126.     cmpb    r3    ,#11        ; yes. if ch eq tab, then make
  127.     bne    21$            ; it into a space first please.
  128.     movb    #40    ,r3        ; simple
  129. 21$:    cmpb    lastch(r4),#40        ; yes, was the last ch a space
  130.     beq    25$            ; or a tab ?
  131.     cmpb    lastch(r4),#11        ; please check both out
  132.     bne    30$            ; no
  133. 25$:     cmpb    r3    ,#40        ; is the current character a
  134.      beq    skipch            ; space ?
  135.      cmpb    r3    ,#9.        ; not a space. try a horz tab
  136.      beq    skipch            ; char was a tab. Then ignore.
  137.       bic    #c.lspa    ,pat(r4)    ; For leading spaces and tabs.
  138.  
  139. 30$:    bit    #c.crlf    ,pat(r4)    ; try for ignoring form feed,
  140.     beq    50$            ; car ret,line feed,esc,null.
  141.  
  142.     mov    #junkch    ,r0        ; Get the address of the spec
  143.     tstb    r3            ; is the current ch a null ?
  144.     beq    skipch            ; yes, please skip it then.
  145. 40$:    tstb    @r0            ; anything left in the list ?
  146.     beq    50$            ; no
  147.     cmpb    r3    ,(r0)+        ; see if we have a match.  If
  148.     beq    skipch            ; so, we will skip  the char.
  149.     br    40$            ; no, next check please
  150.  
  151. 50$:    bit    #c.lcuc    ,pat(r4)    ; how about converting lower
  152.     beq    60$            ; case to upper case ?
  153.     cmpb    r3    ,#'z!40        ; try against a lower case Z
  154.     bhi    60$
  155.     cmpb    r3    ,#'a!40        ; if less than a lower z,try
  156.     blo    60$            ; for ge a lower case a
  157.      bicb    #40    ,r3        ; char is in range. translate
  158.  
  159. 60$:    bit    #c.brac    ,pat(r4)    ; how about convert [ to ( and
  160.     beq    usech            ; and convert ] to )
  161.     cmpb    r3    ,#'[        ; and so on
  162.     bne    70$
  163.     movb    #'(    ,r3        ; convert it. fall thru to next
  164. 70$:    cmpb    r3    ,#']
  165.     bne    usech
  166.     movb    #')    ,r3
  167.     br    usech
  168. skipch:    br    120$            ; do not want the char, skip it.
  169.  
  170.  
  171.     .sbttl    got a good ch, check for quoted string things
  172.  
  173. usech:    bit    #c.quot    ,pat(r4)    ; what about leaving quoted
  174.     beq    110$            ; strings alone ?
  175.     tstb    inquo(r4)        ; currently in a quoted string?
  176.     bne    90$            ; yes, check for the stopper.
  177.     cmpb    r3    ,#''        ; a quote here ?
  178.     beq    80$            ; yes
  179.     cmpb    r3    ,#'"        ; alternate for a quote
  180.     bne    90$            ; no
  181. 80$:    movb    r3    ,inquo(r4)    ; yes, save the terminator
  182.     br    110$            ; next please
  183.  
  184. 90$:    cmpb    r3    ,inquo(r4)    ; yes, is this the end of a
  185.     bne    110$            ; quoted string ?
  186.     clrb    inquo(r4)        ; yes, turn the flag off then.
  187.  
  188. 110$:    bit    #c.prt    ,pat(r4)    ; should we skip nonprintable
  189.     beq    115$            ; characters now ?
  190.     cmpb    r3    ,#40        ; yes, less than a space
  191.     blo    120$            ; yes
  192.     tstb    r3            ; greater than 177 (rubout)
  193.     bmi    120$            ; yes
  194.  
  195. 115$:    movb    r3    ,(r2)+        ; if all ok, return the  char.
  196. 120$:    movb    r3    ,lastch(r4)    ; please save the last ch
  197.     dec    r1            ; and go back for  some  more.
  198.     bgt    10$            ; next please
  199.  
  200.  
  201. 130$:    mov    r2    ,r0        ; current pointer
  202.     sub    saddr(r4),r0        ; return the length of what's
  203.     ble    160$            ; nothing left to do then.
  204.     bit    #c.tspa    ,pat(r4)    ; remove trailing blanks ?
  205.     beq    160$            ; no
  206.     mov    saddr(r4),r1        ; address of the string.
  207.     add    r0    ,r1        ; point to end of string+1.
  208. 140$:    cmpb    -(r1)    ,#40        ; Try for a space first.
  209.     beq    150$
  210.     cmpb    (r1)    ,#9.        ; Not a space, try a tab.
  211.     bne    160$
  212. 150$:    sob    r0    ,140$        ; Tab or space. Check next
  213. 160$:
  214. 170$:    add    #lsize    ,sp        ; pop small work area 
  215.     unsave    <r5,r4,r3,r2,r1>    ; pop all temps
  216.     return                ; and exit
  217.  
  218.     .save
  219.     .psect    $Pdata,d
  220. junkch:    .byte    13.,10.,12.,27.,0,0
  221.     .restore
  222.  
  223.     .dsabl    lsb
  224.  
  225.  
  226.     .sbttl    l$len    get length of .asciz string
  227.  
  228. ;    L $ L E N
  229. ;
  230. ;    input:    r0    =    address of .asciz string
  231. ;    output:    r0    =    length of it
  232.  
  233. l$len::    mov    r0    ,-(sp)        ; save it for later.
  234. 10$:    tstb    (r0)+            ; look for a null character.
  235.     bne    10$            ; keep going
  236.     sub    (sp)+    ,r0        ; subtract start address from
  237.     dec    r0            ; current pointer less 1.
  238.     return
  239.  
  240.  
  241.     .sbttl    write decimal
  242.  
  243. l$wrdec::
  244.  
  245.     dfwidth    =    6
  246.  
  247. ;
  248. ;    write a decimal number to KB: passed at 0(r5)
  249. ;
  250. ;
  251.     save    <r1,r4,r5>
  252.     mov    2(r5)    ,r1        ; field width
  253.     bgt    10$            ; good positive value.
  254.     beq    5$            ; zero, make it 6.
  255.      neg    r1            ; negative means no space fill
  256.      br    10$            ; and skip this
  257. 5$:    mov    #dfwidth,r1        ; finally, we have the width.
  258. 10$:    mov    r1    ,r4        ; save for a moment
  259.     add    #5    ,r1        ; make it round up to even num.
  260.     bic    #1    ,r1        ; at last....
  261.     mov    2(r5)    ,-(sp)        ; The real field width please.
  262.     mov    @r5    ,-(sp)        ; And the number to print out.
  263.     mov    sp    ,r5        ; setup the parameter list addr
  264.     tst    -(r5)            ; make room for the buffer on
  265.     sub    r1    ,sp        ; the stack. 
  266.     mov    sp    ,@r5        ; insert the buffer address
  267.     call    l$cvtnum        ; and convert the number.
  268.     .print    @r5    ,r4        ; and print it out
  269.     add    r1    ,sp        ; and fix the stack up.
  270.     cmp    (sp)+    ,(sp)+        ; rest of stack pop.
  271.     unsave    <r5,r4,r1>        ; thats all for now
  272.     return
  273.  
  274.  
  275.  
  276. ;    write out a decimal number at 2(r5) into the buffer
  277. ;    address passed at 0(r5). All registers saved.
  278.  
  279. l$cvti::save    <r5>            ; call common conversion sub.
  280.     clr    -(sp)            ; setup paramter list first.
  281.     mov    2(r5)    ,-(sp)        ; calls $cvtnum,<@r5,2(r5),#0>
  282.     mov    @r5    ,-(sp)        ; finally the buffer address.
  283.     mov    sp    ,r5        ; the parameter list address.
  284.     call    l$cvtnum        ; convert it please.
  285.     add    #6    ,sp        ; pop stack parameter list.
  286.     unsave    <r5>            ; restore r5
  287.     return                ; and exit please.
  288.  
  289.  
  290.  
  291.     .sbttl    the real conversion sub
  292.  
  293.  
  294. ;    input:    0(r5)    =    buffer address
  295. ;        2(r5)    =    value to print
  296. ;        4(r5)    =    field width ( > 0 ->right, < 0 -> left )
  297. ;
  298. ;    field width:    if < zero, string will be left justified
  299. ;            if > zero, string will be right justified
  300. ;            if = zero, field will be set to 6.
  301. ;
  302. l$cvtnum::
  303.     save    <r0,r1,r2,r3,r4>    ; some scratch registers saved
  304.     mov    (r5)    ,r2        ; the buffer address to use.
  305.     mov    4(r5)    ,r3        ; the field width to use.
  306.     bgt    80$            ; nonzero, it is ok (?)
  307.     beq    70$            ; zero
  308.      neg    r3            ; < 0
  309.      br    80$
  310. 70$:     mov    #dfwidth,r3        ; zero, use default width 6.
  311. 80$:    mov    r3    ,r1        ; put it here to clear buffer.
  312. 1$:    movb    #32.    ,(r2)+        ; fill the buffer with blanks
  313.     sob    r1    ,1$
  314.     mov    r2    ,-(sp)        ; save end of buffer here.
  315.     mov    r3    ,r4        ; save buffer size also.
  316.     mov    2(r5)    ,r1        ; Get the value to print out.
  317.     bpl    2$
  318.      neg    r1
  319.  
  320. 2$:    clr    r0            ; set up for the divide by 10.
  321.     div    #10.    ,r0        ; remainder in r1, quotient r0
  322.     add    #'0    ,r1        ; convert remainder to character
  323.     cmp    r2    ,@r5        ; overflowed the buffer at all?
  324.     beq    100$            ; yes, get out of here !
  325.     movb    r1    ,-(r2)        ; and return the character now.
  326.     mov    r0    ,r1
  327.     beq    3$
  328.     sob    r3    ,2$        ; go back for more
  329.     tst    r1            ; something left over by chance?
  330.     bne    100$            ; Yes, that's a definite error.
  331.  
  332. 3$:    tst    2(r5)            ; was this a negative number ?
  333.     bpl    90$            ; no, exit
  334.     cmp    r2    ,@r5        ; yes, room left for a '-' sym.
  335.     beq    100$            ; no, flag an error please.
  336.      movb    #'-    ,-(r2)        ; yes, insert a minus symbol.
  337. ;;     br    90$            ; thats all.
  338.  
  339. 90$:    tst    4(r5)            ; negative field width ?
  340.     bpl    4$            ; no, exit.
  341.      mov    @r5    ,r1        ; start of the buffer here.
  342. 95$:     movb    (r2)+    ,(r1)+        ; move chars to front of buffer.
  343.      cmp    r2    ,(sp)        ; end of the buffer yet ?
  344.      bhis    97$            ; no, keep going please.
  345.      sob    r4    ,95$        ; keep going please
  346. 97$:     dec    r4            ; anything left to zero out?
  347.      ble    4$            ; no
  348. 98$:     movb    #40    ,(r1)+        ; yes, zero to end of buffer.
  349.      sob    r4    ,98$        ; more please
  350.      br    4$            ; finally exit this mess.
  351.  
  352. 100$:    movb    #'*    ,@r2        ; field overlfow. place '*' in
  353.                     ; beginning of the buffer.
  354.  
  355. 4$:    tst    (sp)+            ; pop stack, restore temp regs
  356.     unsave    <r4,r3,r2,r1,r0>
  357.     return                ; thats all there is to it.
  358.  
  359.  
  360.  
  361.  
  362.     .sbttl    mout    print text from message macro
  363.  
  364. locmout::
  365.     tst    remote
  366.     beq    mout
  367.     mov    (sp)+    ,@sp
  368.     return
  369.     
  370. mout::    save    <r0>
  371.     mov    4(sp)    ,r0
  372.     .print    r0
  373.     unsave    <r0>
  374.     mov    (sp)+    ,@sp
  375.     return
  376.  
  377.  
  378.  
  379.     .sbttl    instr
  380.  
  381.  
  382. ;    I N S T R    simple (non-wildcard) version
  383.  
  384. ; input:
  385. ;
  386. ;    (r5)    =    address of the first string
  387. ;    2(r5)    =    length of the first string .
  388. ;    4(r5)    =    address of the second string, the one to find.
  389. ;    6(r5)    =    length of the second string.
  390. ;
  391. ; output:
  392. ;
  393. ;    r0    =    if > 0 then r0=position of second in first
  394. ;                   else the second is not a substring.
  395. ;
  396.  
  397. instr::
  398.     save    <r1,r2,r3,r4>        ; we use these here, so save.
  399.     mov    (r5)    ,r0        ; the address of first string
  400.     mov    4(r5)    ,r1        ; the address of second  one.
  401.     mov    6(r5)    ,r2        ; the length of  second  one.
  402.     ble    6$            ; a null string ?
  403.     mov    2(r5)    ,r4        ; the length of  first.
  404.     ble    6$            ; a null string ?
  405.     sub    r2    ,r4        ; convert to looping  counter
  406.     clr    r3            ; the real loop counter.
  407.  
  408. 1$:    cmp    r3    ,r4        ; are we done yet ?
  409.     bgt    6$            ; yes, if r3 > r4 .
  410.  
  411.       cmpb    (r0)+    ,(r1)        ; see if current character in
  412.       bne    5$            ; matches first one in second.
  413.  
  414.         save    <r0,r1,r2>    ; found first character match.
  415.         inc    r1            ; point to the next character
  416.         dec    r2            ; length of pattern thats left
  417.         ble    3$            ; in case the len( pattern ) =1
  418.  
  419. 2$:        cmpb    (r0)+ , (r1)+    ; check the rest of the pattern
  420.         bne    4$
  421.         sob    r2    ,2$        ; loop for len( pattern ) - 1
  422. 3$:        mov    r3    ,r0        ; the current loop  count
  423.         inc    r0
  424.         add    #6    ,sp        ; fix the stack from save <  >
  425.         br    7$
  426.  
  427. 4$:        unsave    <r2,r1,r0>    ; the match failed. restore the
  428. 5$:      inc    r3            ; pointers and go try the  next
  429.     br    1$            ; character in the first string
  430.  
  431.  
  432. 6$:    clr    r0            ; complete failure if  get here
  433. 7$:    unsave    <r4,r3,r2,r1>        ; restore the registers we used
  434.     return                ; and go away.
  435.  
  436.  
  437.     .sbttl    convert rad50 word to 3 ascii bytes and back
  438. ;rdtoa
  439. ;        (r5)    =    address of where to put ascii chars
  440. ;    input    2(r5)    =    the value of rad 50 word
  441. ;
  442. ;
  443. ;
  444. ;procedure rd_toa( rval: integer ; var aout: array [1..3] of char ) ;
  445. ;
  446. ; type rlist = array [0..39] of char ;
  447. ; const
  448. ;      r50ch = rlist(' ','A','B','C','D','E','F','G','H','I','J','K',
  449. ;            'L','M','N','O','P','Q','R','S','T','U','V','W',
  450. ;            'X','Y','Z','$','.','?','0','1','2','3','4','5',
  451. ;            '6','7','8','9' );
  452. ; var i: integer ;
  453. ; begin
  454. ;  aout[1] := r50ch[ rval div 3100B ]; rval := rval mod 3100B ;
  455. ;  aout[2] := r50ch[ rval div 50B ]  ; aout[3] := r50ch[ rval mod 50B ]
  456. ; end ;
  457.  
  458.  
  459. rdtoa::
  460. radasc:    save    <r0,r1,r3>        ; same some registers
  461.     mov    2(r5)    ,r1        ; go get the rad50 character.
  462.     mov    (r5)    ,r3        ; where to put the characters.
  463. com:    clr    r0            ; prepare for divide
  464.     div    #3100    ,r0        ; get first char
  465.     movb    radchr(r0),(r3)+     ; put in buffer
  466.     clr    r0            ; another divide
  467.     div    #50    ,r0        ; this one gives char 2
  468.     movb    radchr(r0),(r3)+     ; put this in buffer
  469.     movb    radchr(r1),(r3)+     ; and also char 3
  470.     unsave    <r3,r1,r0>        ; restore the registers we used.
  471.     return                ; bye
  472.  
  473.     .save
  474.     .psect    $Pdata,d
  475.     .nlist    bex
  476. radchr:    .ascii    / ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789:/
  477.     .list    bex
  478.     .even
  479.     .restore
  480.  
  481.  
  482.     .sbttl    get decimal number value
  483.  
  484.  
  485. ;    L $ V A L    (20-Nov-80)
  486. ;
  487. ;    (r5)    =    address of .asciz string to convert
  488. ;
  489. ;    r0    =    error (-1 for bad number)
  490. ;    r1    ==    binary value of the string.
  491.  
  492.  
  493. l$val::    save    <r2,r3>
  494.     clr    r1            ; initailize the result.
  495.     mov    (r5)    ,r3        ; the address of the string.
  496.     clr    -(sp)            ; a positive number for now.
  497.     clr    r0
  498.  
  499.  
  500. 30$:    tstb    @r3            ; null. If so, exit please.
  501.     beq    5$            ; buy.
  502.     cmpb    @r3    ,#space        ; we will ignore spaces.
  503.     beq    50$            ; if equal,  then  skip.
  504.     tst    r0            ; past the first space yet ?
  505.     bne    40$            ; yes, skip sign checks.
  506.      com    r0            ; past all the leading spaces.
  507.      cmpb    @r3    ,#'+        ; positive number ?
  508.      beq    50$            ; yes, skip over the character.
  509.      cmpb    @r3    ,#'-        ; negative ?
  510.      bne    40$            ; no, try for a digit then.
  511.       mov    sp    ,(sp)        ; neg, set a useful flag up.
  512.       br    50$            ; and skip it.
  513.  
  514. 40$:     cmpb    @r3    ,#'0        ; try comparing to '0' .
  515.      blo    70$            ; not a digit. time to go
  516.      cmpb    @r3    ,#'9        ; try comparing to '9' .
  517.      bhi    70$            ; not a digit . get out.
  518.  
  519.        clr    -(sp)            ; clr out the scratch reg.
  520.        bisb @r3    ,(sp)        ; copy the character over.
  521.        sub    #48.    ,(sp)        ; convert char to a digit.
  522.        mul    #10.    ,r1        ; multiply accum by 10 first
  523.        bcs    60$            ; oops
  524.        add    (sp)+    ,r1        ; add on the digit to accum
  525.        bvs    70$            ; bye
  526.  
  527. 50$:     inc    r3            ; pointer := succ( pointer );
  528.     br    30$
  529.  
  530. 60$:    tst    (sp)+            ; came here from multiply overf
  531. 70$:    clr    r0            ; return 0 in case of error.
  532.     mov    #-1    ,r0        ; ?Illegal number
  533.     tst    (sp)+            ; pop sign flag from stack.
  534.     br    100$
  535.  
  536.  
  537. 5$:    tst    (sp)+            ; pop sign flag on tos.
  538.     beq    95$            ; positive number ?
  539.      tst    r1            ; negative 0 (-32768) ?
  540.      bne    90$            ; no
  541.       bis    #100000    ,r1        ; yes, set only the sign bit
  542.       br    95$            ; and go away.
  543. 90$:      neg    r1            ; no.
  544. 95$:    clr    r0
  545. 100$:    unsave    <r3,r2>
  546.     return                ; and time to leave.
  547.  
  548.  
  549.     .sbttl    octval    return octal vaule in r1, error in r0
  550.  
  551.  
  552. octval::save    <r2,r3>            ; save temps please
  553.     clr    r0            ; assume no error
  554.     clr    r1            ; value := 0
  555.     mov    @r5    ,r2        ; get the buffer address
  556. 10$:    movb    (r2)+    ,r3        ; get the next character please
  557.     beq    100$            ; all done
  558.     cmpb    r3    ,#'0        ; error if < '0' or > '7'
  559.     blo    90$            ; oops
  560.     cmpb    r3    ,#'7        ; how about the upper limit
  561.     bhi    90$            ; oops
  562.     sub    #'0    ,r3        ; get the value
  563.     asl    r1            ; accumulated value times 8
  564.     asl    r1            ; the long way
  565.     asl    r1            ; r1 = r1 * 8
  566.     add    r3    ,r1        ; add in the current digit
  567.     br    10$            ; next
  568.  
  569. 90$:    mov    #-1    ,r0        ; illegal number
  570. 100$:    unsave    <r3,r2>            ; pop registers and exit
  571.     return
  572.  
  573.  
  574.  
  575.     .sbttl    binary to octal conversion
  576.     .enabl    lsb
  577. ;
  578. ;    17-Nov-80  BDN
  579. ;
  580. ;    convert binary number at 2(r5) to ascii string
  581. ;    at buffer address 0(r5).
  582. ;
  583.  
  584. l$otoa::save    <r0,r1,r2,r3>        ; save the scratch regs.
  585.     mov    (r5)    ,r2
  586.     mov    2(r5)    ,r3
  587.     add    #6    ,r2        ; do it backwards
  588.     mov    #6    ,r0        ; do it 6 times
  589. 10$:    mov    r3    ,r1        ; get the number
  590.     bic    #177770    ,r1        ; leave low order 3 bits on
  591.     movb    200$(r1),-(r2)         ; move an octal digit
  592.     ash    #-3    ,r3        ; shift three bytes
  593.     bic    #160000    ,r3        ; zap propagated sign bits
  594.     sob    r0    ,10$        ; go convert next digit
  595.  
  596.     unsave    <r3,r2,r1,r0>
  597.     return
  598.  
  599.     .save
  600.     .psect    $Pdata,D
  601. 200$:    .ascii    \01234567\    ; ascii/octal 200$
  602.     .even
  603.     .restore
  604.     .dsabl    lsb
  605.  
  606.  
  607. ;    (r5)    =    value to write to KB:
  608.  
  609. l$wroc::save    <r0>
  610.     sub    #10    ,sp
  611.     mov    sp    ,r0        ; use stack for a buffer
  612.     calls    l$otoa    ,<r0,(r5)>
  613.     print    r0    ,#6.
  614.     add    #10    ,sp
  615.     unsave    <r0>
  616.     return
  617.  
  618.  
  619.     .sbttl    copyz    copyz .asciz string
  620.  
  621.  
  622.  
  623. ;    C O P Y Z $
  624. ;
  625. ;    input:    6(sp)    max len or zero
  626. ;        4(sp)    source string address
  627. ;        2(sp)    destination string address
  628. ;
  629. ;    usage:    copyz macro, as in    copyz #oldfile,#newfile
  630.  
  631.  
  632. copyz$::save    <r0,r1>            ; save registers we may use
  633.     tst    4+6(sp)            ; see if a maxlen was passed
  634.     bne    5$            ; yes
  635.     mov    #77777    ,4+6(sp)    ; no, say we can have MAXINT chars
  636. 5$:    mov    4+4(sp)    ,r0        ; source string address
  637.     mov    4+2(sp)    ,r1        ; destination string address
  638. 10$:    movb    (r0)+    ,(r1)+        ; copy a byte
  639.     beq    20$            ; until a null is found
  640.     dec    4+6(sp)            ; or we have copied MAXLEN number
  641.     bne    10$            ; of characters over
  642. 20$:    clrb    -(r1)            ; insure output .asciz please
  643.     unsave    <r1,r0>            ; pop temps
  644.     mov    @sp    ,6(sp)        ; move return address up
  645.     add    #6    ,sp        ; fix the stack
  646.     return                ; and exit
  647.  
  648.  
  649.  
  650.  
  651.     .sbttl    formatted byte dump
  652.  
  653. ;    input:    4(sp)    size
  654. ;        2(sp)    address
  655.  
  656.  
  657. dump$b::save    <r0,r1,r2>        ; save all please
  658.     mov    <4+6>(sp),r1        ; size
  659.     beq    100$            ; nothing do to today
  660.     mov    <2+6>(sp),r2        ; address to dump
  661. 10$:    clr    r0            ; get the next byte please
  662.     bisb    (r2)+    ,r0        ; get it
  663.     decout    r0            ; and print it
  664.     sob    r1    ,10$        ; next please
  665. 100$:    .newline            ; a cr/lf
  666.     unsave    <r2,r1,r0>        ; pop all registers we used
  667.     mov    @sp    ,4(sp)        ; move return address up
  668.     cmp    (sp)+    ,(sp)+        ; pop two words for parameter list
  669.     return                ; and exit
  670.  
  671.  
  672.  
  673.     .sbttl    strcat and strcpy
  674.  
  675. ;    input:
  676. ;        0(sp)    return address
  677. ;        2(sp)    dst address
  678. ;        4(sp)    src address
  679. ;    output:    r0    dest address
  680.  
  681.  
  682. strcpy::save    <r1>            ; save temp registers please
  683.     mov    2+2(sp)    ,r0        ; destination address
  684.     mov    2+4(sp)    ,r1        ; source .asciz address
  685. 10$:    movb    (r1)+    ,(r0)+        ; copy until a null
  686.     bne    10$            ; not done
  687.     mov    2+2(sp)    ,r0        ; return the dst address
  688.     unsave    <r1>            ; pop r1 and exit
  689.     mov    (sp)    ,4(sp)        ; move return address up now
  690.     cmp    (sp)+    ,(sp)+        ; pop junk and exit
  691.     return
  692.  
  693.  
  694. strcat::save    <r1>            ; save temp registers please
  695.     mov    2+2(sp)    ,r0        ; destination address
  696.     mov    2+4(sp)    ,r1        ; source .asciz address
  697. 5$:    tstb    (r0)+            ; look for the end of the dst string
  698.     bne    5$            ; not found yet
  699.     dec    r0            ; found it, fix the pointer
  700. 10$:    movb    (r1)+    ,(r0)+        ; copy until a null
  701.     bne    10$            ; not done
  702.     mov    2+2(sp)    ,r0        ; return the dst address
  703.     unsave    <r1>            ; pop r1 and exit
  704.     mov    (sp)    ,4(sp)        ; move return address up now
  705.     cmp    (sp)+    ,(sp)+        ; pop junk and exit
  706.     return
  707.  
  708. strcmp::mov    2(sp),r0    ;Pick up 'a'
  709.     mov    4(sp),r1    ;And 'b'
  710. 10$:    cmpb    (r0)+,(r1)    ;Are they the same
  711.     bne    20$        ;No
  712.     tstb    (r1)+        ;At the end of the string
  713.     bne    10$        ;No
  714.     clr    r0        ;Equal return
  715.     br    100$
  716.  
  717. 20$:    blo    30$        ;Br if a<b
  718.     mov    #1,r0        ;A>b return
  719.     br    100$
  720.  
  721. 30$:    mov    #-1,r0        ;A<b return
  722. 100$:    mov    (sp)    ,4(sp)        ; move return address up now
  723.     cmp    (sp)+    ,(sp)+        ; pop junk and exit
  724.     return
  725.     
  726.  
  727. malloc::inc    r0
  728.     bic    #1    ,r0
  729.     mov    r0    ,-(sp)
  730.     add    @albuff    ,(sp)
  731.     cmp    (sp)    ,#alsize
  732.     bhis    90$
  733.     mov    albuff    ,r0
  734.     add    #2    ,r0
  735.     add    @albuff    ,r0
  736.     mov    (sp)+    ,@albuff
  737.     return
  738. 90$:    clr    r0
  739.     tst    (sp)+
  740.     return
  741.  
  742.     global    <albuff,alsize>
  743.  
  744.  
  745. decryp::
  746. encryp::mov    (sp)    ,4(sp)
  747.     cmp    (sp)+    ,(sp)+
  748.     return
  749.  
  750.  
  751.     .end
  752.