home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / extra / prolib.mac < prev    next >
Text File  |  1988-08-16  |  15KB  |  586 lines

  1.     .TITLE    KERLIB - KERMIT - library
  2.     .SBTTL    S Hecht/D Stevens/RCM/NB
  3.  
  4. ;
  5. ; Kerlib is the library of routines that are common to KERFIL and KERMIT
  6. ;
  7. ; Version
  8. ;
  9.  
  10.     .IDENT    /1.0.04/
  11. ;
  12. ; Directives
  13. ;
  14.     .ENABLE    LC            ; Enable lower case in .ASCIx
  15.     .NLIST    BEX            ; Don't list binary expansions
  16.     .LIBRARY /KERMLB/        ; Kermit macro library
  17.  
  18.     .SBTTL     Revision History
  19.  
  20. ;++
  21. ; 1.0.00    By: Authors            On: Many days
  22. ;        Create this module.
  23. ;
  24. ; 1.0.01    By: Robert C. McQueen        On: 15-Feb-1984
  25. ;        Some module clean up.
  26. ;
  27. ; 1.0.02    By: Robert C. McQueen        On: 5-March-1984
  28. ;        Remove ATTACH and DETACH.
  29. ;
  30. ; 1.0.03    By: Robert C. McQueen        On: 13-March-1984
  31. ;        Remove SMC global location and associated storage.
  32. ;
  33. ; 1.0.04    By: Robert C. McQueen        On: 12-April-1984
  34. ;        Move SY.GENERIC to KERXFR.
  35. ;
  36. ; 1.0.05    By: Robert C. McQueen        On: 16-April-1984
  37. ;        Support KERCON being a seperate task.
  38. ;--
  39.  
  40.  
  41.     .SBTTL    External symbols and RSX directives
  42.  
  43. ; Get the KERMLB definitions
  44.  
  45.     .MCALL    KERDEF
  46.     KERDEF                ; Get the general symbol definitions
  47.  
  48. ; Get the character definitions
  49.  
  50.     .MCALL    CHRDEF            ; Character definition macro
  51.     CHRDEF                ; Define the characters (Ctl-xxxx)
  52.  
  53. ; Bliss interface macros
  54.  
  55.     .MCALL    BLSRTN            ; Allow use of BLISS macros from
  56.     .MCALL    BLSCAL            ;   library
  57.  
  58. ;
  59. ; System routines used in Kerlib
  60. ;
  61.  
  62.     .MCALL    DIR$
  63.     .MCALL    QIO$
  64.     .MCALL    QIOW$
  65.     .MCALL    QIOW$S            ; Output for TERM.DUMP
  66.     .MCALL    ALUN$
  67.     .MCALL    EXIT$S
  68.     .MCALL    WTSE$S
  69.     .MCALL    CLEF$S
  70.  
  71.     .SBTTL    Impure data area
  72.  
  73. ; Set the PSECT to be $OWN$ for the read/write data
  74.  
  75.     .PSECT    $OWN$,  D  
  76.  
  77. ALTLOC:    .BLKW    1            ; Old output routine address.
  78.                     ;   used with ALTBUF
  79. NOSCRN::.BLKW    1            ; No screen output to be done
  80.  
  81.     .SBTTL    Data
  82.  
  83.  
  84. ; Set the PSECT to be $PLIT$ for the read-only data
  85.  
  86.     .PSECT    $PLIT$,  RO ,  D  
  87.  
  88. CSITXT::.BYTE    .CHCSI,.CHNUL
  89.  
  90. M$LFBS:    .BYTE    .CHLFD,.CHBS,.CHSPC,.CHSPC,.CHNUL ; Screen painting
  91.  
  92. M$LFSP:    .BYTE    .CHLFD,.CHSPC,.CHSPC,.CHCRT,.CHNUL ; Screen painting
  93.  
  94. M$RVID:    .ASCIZ    <.CHCSI>/7m/        ; Turn on reverse video
  95. M$BVID::.ASCIZ    <.CHESC>/[1m/        ; Bold video attribute
  96. BVID$L==.-M$BVID
  97. M$NVID::.ASCIZ    <.CHESC>/[0m/        ; Reset video attributes
  98. NVID$L==.-M$NVID
  99. M$HOME:    .ASCIZ    <.CHCSI>/H/        ; Home cursor sequence
  100. CLRESC:    .ASCIZ    <.CHCSI>/2J/        ; Clear screen sequence
  101. CUROFF::.ASCIZ    <.CHCSI>/?25l/        ; Turn the cursor off
  102. CURON::    .ASCIZ    <.CHCSI>/?25h/        ; Turn the cursor on
  103.     .EVEN
  104.  
  105. ;
  106. ; Error routine data
  107. ;
  108.  
  109. ADRERR:: .blkw    1
  110.  
  111.  
  112. FATEM1:    .byte    .CHCR,.CHLF
  113.     .asciz    'Please record the following error information: '
  114.     .even
  115. FATEM2:    .asciz    ', '
  116.     .even
  117. FATEM3:    .BYTE    .CHCR,.CHLF,.CHLF
  118.     .ASCIZ    'Please press RESUME to return to P/OS Main Menu '
  119.     .EVEN
  120.  
  121.     .sbttl    Input Output Macro Calls
  122.  
  123. ;
  124. ; Input/Output control for Kermit
  125. ;
  126. ;    Writes data onto the terminal, 
  127. ;     and reads data off the terminal.
  128. ;
  129. ;    INPUT: Any data to be printed onto screen
  130. ;        Move data into buffer at IOBUFF.
  131. ;
  132. ;    OUTPUT: The data you wanted displayed is put onto the screen.
  133. ;        Control stays with the calling routine.
  134. ;
  135.  
  136. ASSIGN::
  137.     alun$    TERLUN,TI,0        ; Macro to assign the terminal lun.
  138.  
  139.  
  140. READ::    qiow$    io.rvb!tf.esq,TERLUN,ttrefn,,iostat,,<iobuff,400.>
  141.                     ; Macro to read data from the terminal
  142.                     ;   into the iobuffer, a status return 
  143.                     ;   is put into iostat, a wait flag of
  144.                     ;   5 is set when read is completed,
  145.                     ;   the 10. specifies that the task
  146.                     ;   reads data from the terminal.
  147.                     ; TF.ESQ tells the terminal 
  148.                     ;   to recognize escape sequences.
  149. READ1::    qiow$    io.ral,terlun,ttrefn,,iostat,,<iobuff,1.>
  150.                     ; Macro to read a single character
  151.                     ;   from the terminal (passes all 
  152.                     ;   characters including ^C)
  153.  
  154. KILTT::    qiow$    io.kil,TERLUN,ttaefn,,iostat
  155.                     ; Macro to kill all pending I/O
  156.                     ;   related to the terminal
  157.  
  158.     .SBTTL    Module initialization
  159.  
  160. ;++
  161. ; The following routine will initialize this module.  It will return to the
  162. ; caller after the module has been initialized.
  163. ;--
  164.  
  165. INILIB::MOV    #FALSE,NOSCRN        ; Allow TERM.DUMP to output data
  166.     RTS    PC            ; Return to the caller
  167.  
  168.     .SBTTL    Exit routine
  169.  
  170. ;
  171. ; Exit routine
  172. ;This is called from KERMSG in response to a generic logout command.
  173. ;
  174.  
  175.     .PSECT    $CODE$,  RO 
  176.  
  177. SY.LOGOUT::
  178. EXIT::    JSR    PC,S$CLEAR        ; Clear screen
  179.     EXIT$S
  180.  
  181.     .sbttl    Convert to ascii routine
  182.  
  183.  
  184. ;        The contents of Registers:
  185. ;            R2:    Brings down the value to be converted.
  186. ;            R3:    Holds each number to be converted to ascii.
  187. ;            R5:    Brings down the base you want it converted.
  188. ;                  from.
  189. ;        the old contents of register R3 are destroyed
  190. ;        by this subroutine.
  191. ;
  192. ;
  193. CHGOCT::MOV    #8.,R5
  194.     JMP    ASCCHG
  195. CHGDEC::MOV    #10.,R5
  196. ASCCHG::MOV    R2,R3            ; Move the number to be converted.
  197.     BPL    31$            ; If it is a positive number branch.
  198.     NEG    R3            ; Negate the number so it is positive
  199.     BLSCAL    TT.CHAR,#'-        ; Output the minus
  200. 31$:    CLR    R2            ; Clear R2.
  201.     DIV    R5,R2            ; Divide by the base, the remainder
  202.                     ;   goes into R3, the high order
  203.                     ;   word in R2.
  204.     ADD    #'0,R3            ; Make the remainder an ascii character
  205.     MOV    R3,-(SP)        ;   put it into the stack.
  206.     MOV    R2,R3            ; Put the rest back into R3.
  207.     BEQ    32$            ; Have we reached the end of the num
  208.                     ;   if yes then branch.
  209.     JSR    PC,31$            ; Call the routine again
  210. 32$:    BLSCAL    TT.CHAR,(SP)+        ; Get the character and output it
  211.     RTS    PC            ; Return from subroutine.
  212.  
  213.     .SBTTL    Clear screen
  214.  
  215. ;
  216. ; This routine puts the escape sequence needed to clear the screen
  217. ;   into the I/O buffer.
  218. ;
  219. ;    INPUT:    none
  220. ;
  221. ;    OUTPUT:    The escape sequence put into the I/O buffer.
  222. ;
  223.  
  224.     .GLOBL    S$CLEAR
  225. S$CLEAR:
  226. CLRSCR::BLSCAL    TT.TEXT,#CLRESC        ; Get the clear screen text
  227. ;    JMP    S$HOME            ; Home the cursor
  228.  
  229.     .SBTTL    Screen support -- Home the cursor
  230.  
  231. ;++
  232. ; This routine will home the cursor.  It will then return to the caller.
  233. ;
  234. ; Usage:
  235. ;    JSR    PC,S$HOME
  236. ;    (Return)
  237. ;
  238. ;--
  239.  
  240.     .GLOBL    S$HOME
  241.  
  242. S$HOME:    BLSCAL    TT.TEXT,#M$HOME,+    ; Home the cursor
  243.     BLSCAL    TT.OUTPUT,,-        ; Force it out
  244.     RTS    PC            ; Return to the caller
  245.  
  246.     .sbttl    Cursor Positioning Routine
  247.  
  248.  
  249. ;
  250. ; This routine moves the cursor to the position specified by R2 and R5
  251. ;
  252. ;    INPUT:    R5    contains the 'Y' position to move to
  253. ;        R2    contains the 'X' position to move to
  254. ;
  255. ;    OUTPUT:    The code for moving the cursor as specified is placed 
  256. ;        in the I/O buffer.
  257. ;
  258. ;    REGISTERS used:    R2, R3, R5
  259. ;        R2    Temporary value location (destroyed)
  260. ;        R3    Temporary value location (destroyed)
  261. ;        R5    (destroyed)
  262. ;
  263.  
  264. CURABS::
  265.     MOV    R5,YPOS            ; Save the 'Y' position
  266.     MOV    R2,XPOS            ; Save the 'X' position
  267.     BLSCAL    TT.TEXT,#CSITXT,+    ; Output the <Escape>[
  268.     MOV    YPOS,R2            ; Convert the ypos to decimal
  269.     JSR    PC,CHGDEC        ;   and move it to the buffer
  270.     BLSCAL    TT.CHAR,#.CHSEM,+    ; Output the semicolon
  271.     MOV    XPOS,R2            ; Convert the xpos to decimal
  272.     JSR    PC,CHGDEC        ;   and move it to the buffer
  273.     BLSCAL    TT.CHAR,#'H,-        ; Output the character
  274.     RTS    PC            ; Return to sender
  275.  
  276.     .sbttl Error handling global routine
  277.  
  278. ;
  279. ; I/O error handling routine
  280. ;
  281. ;
  282. ;    INPUT:    None
  283. ;
  284. ;    OUTPUT:    The I/O error message is displayed along with giving
  285. ;        a fatal error message.  Control is returned to P/OS
  286. ;        MAIN MENU when RESUME is pressed.
  287. ;
  288.  
  289. IOERR::    MOV    #IOMSG,ADRERR        ; Sets up message to be printed out 
  290.                     ;  when an I/O attempt fails.
  291.     MOV    #8.,BASE        ; Put conversion base into base.
  292.     MOV    IOSTAT,STATUS        ; put iostatus into status.
  293.     MOV    IOSTAT+2,STAT1        ; Put second iostat word into stat1.
  294. ;    jmp    error            ; jump to main error routine.
  295.  
  296. ;
  297. ; Error handling routine
  298. ;
  299.  
  300. ERROR::    JSR    PC,S$CLEAR        ; Clear screen
  301.  
  302.     BLSCAL    TT.TEXT,ADRERR,+    ; Output the error text
  303.     BLSCAL    TT.TEXT,#FATEM1,+    ; Output the second part of the error
  304.     MOV    STATUS,R2        ; Get the status code
  305.     MOV    BASE,R5            ; Set conversion base.
  306.     JSR    PC,ASCCHG        ; Convert to ascii and put in buffer
  307.  
  308.     BLSCAL    TT.TEXT,#FATEM2,+    ; Output the next part of the msg
  309.     MOV    STAT1,R2        ; Get second word of status
  310.     JSR    PC,CHGOCT        ; Convert to ascii and put in buffer
  311.  
  312.     BLSCAL    TT.TEXT,#FATEM3,+    ; And the last part of the message
  313.     BLSCAL    TT.TEXT,#CURON,+    ; Turn the cursor back on
  314.     BLSCAL    TT.OUTPUT,,-        ; Output the text.
  315.     CALL    WTRES            ; Wait for RESUME key
  316.     JMP    EXIT            ; Exit KERMIT
  317.  
  318.     .SBTTL    Support routines -- PAINT - Paint a box
  319.  
  320. ;++
  321. ; This routine will paint a box on the screen with a centered title
  322. ; on the first line.  It uses the normal BLISS calling sequence.
  323. ;
  324. ; Usage:
  325. ; BLISS:
  326. ;    PAINT(Text_address, Text_length, Number_of_lines);
  327. ;
  328. ; Macro:
  329. ;    BLSCAL    PAINT,<#TXTADR,#TXTLEN,#LINES>
  330. ;
  331. ;--
  332.  
  333. BLSRTN    PAINT,2,<TXTADR,TXTLEN,LINES>
  334.  
  335. ; The first thing that we must do is to insure that some silly person
  336. ; didn't cause wrap around to be turned on, so turn it off.
  337.  
  338. ;**
  339.  
  340. ; Tell KERTT to buffer until buffer is full or we call TT.OUTPUT
  341.  
  342.     BLSCAL    TT.HOLD,<#TRUE>,+    ; Start holding data
  343.  
  344. ; Now clear the screen and home the cursor
  345.  
  346.     JSR    PC,S$CLEAR        ; Clear the screen
  347.                     ;  and home the cursor
  348.  
  349. ; How put the screen into reverse video, so that spaces paint the block
  350. ; boundary
  351.  
  352.     BLSCAL    TT.TEXT,<#M$RVID>,+    ; Call the routine
  353.  
  354. ; Compute the number of spaces before and after the centered text.
  355.  
  356.     MOV    TXTLEN+..STKO(SP),R2    ; Get the length of the title
  357.     ASR    R2            ; Divide into two parts
  358.     MOV    #40.,R1            ; Get the number of spaces to print
  359.     SUB    R2,R1            ;  . . .
  360.     SUB    TXTLEN+..STKO(SP),R2    ; Comput number of character after
  361.                     ;  the center of the screen
  362.     ADD    #41.,R2            ; Now number of spaces to print
  363.  
  364. ; At this point we have the following
  365. ;    R1 := Number of spaces before centered text
  366. ;    R2 := Number of spaces after the centered text
  367. ;
  368. ; First output the spaces before the centered text
  369.  
  370.     MOV    #.CHSPC,(SP)        ; Store a space
  371. 10$:    JSR    PC,TT.CHAR        ; Output the spaces
  372.     SOB    R1,10$            ; Output the spaces before text
  373.  
  374. ; Now output the centered text.
  375.  
  376.     BLSCAL    TT.TEXT,<TXTADR+..STKO(SP)>,+ ; Output the text
  377.  
  378. ; Now output the characters after the centered text
  379.  
  380.     MOV    #.CHSPC,(SP)        ; Store a space
  381. 20$:    JSR    PC,TT.CHAR        ; Output the character
  382.     SOB    R2,20$            ; Loop for all of the characters
  383.  
  384. ; At this point we have drawn the top of the box.  We will now go down the
  385. ; right hand side of the screen.  To do this we output: <LF><BS><SP><SP>
  386.  
  387.     MOV    LINES+..STKO(SP),R2    ; Get the number of lines to do
  388.     DEC    R2            ; Less the line on the top
  389.     MOV    #M$LFBS,(SP)        ; Store the argument
  390. 30$:    JSR    PC,TT.TEXT        ; Call the routine
  391.     SOB    R2,30$            ; Loop until done
  392.  
  393. ; Now we have painted the top and the right hand side of the box.  Go back
  394. ; to the top of the screen and paint the left hand side of the box.  The
  395. ; character sequence to paint the other side is: <LF><SP><SP><CR>
  396.  
  397.     BLSCAL    TT.TEXT,#M$HOME,+    ; Home the cursor
  398.     MOV    LINES+..STKO(SP),R2    ; Get the number of lines
  399.     DEC    R2            ; Remove one
  400.     MOV    #M$LFSP,(SP)        ; Store the argument
  401. 40$:    JSR    PC,TT.TEXT        ; Output it
  402.     SOB    R2,40$            ; Loop until done
  403.  
  404.  
  405. ; At this point we have painted the top, right and left sides of the box
  406. ; all that must be done at this point is to do the bottom of the screen.
  407. ; this can be done by just printing 80 spaces.
  408.  
  409.     MOV    #80.,R2            ; Get the number of spaces
  410.     MOV    #.CHSPC,(SP)        ; Store the argument
  411.  
  412. 50$:    JSR    PC,TT.CHAR        ; Output the characters
  413.     SOB    R2,50$            ; Loop for all characters
  414.  
  415. ; Now we must put the cursor back to the top of the screen and turn off
  416. ; reverse video.
  417.  
  418.     BLSCAL    TT.TEXT,<#M$NVID>,+    ; Back to normal video
  419.     BLSCAL    TT.TEXT,#M$HOME,+    ; Home the cursor
  420.     BLSCAL    TT.HOLD,#FALSE,+    ; Can dump whenever it wants now
  421.     BLSCAL    TT.OUTPUT,,-        ; Force the output
  422.     RTS    PC            ; Return to the caller
  423.  
  424.     .SBTTL    Bliss interface -- DBG_DUMP - Dump a terminal buffer
  425.  
  426. ;++
  427. ; This routine will dump a buffer of characters to the terminal.  It will
  428. ; be called with the number of characters and the address of the buffer.  All
  429. ; this routine does is to output the buffer.
  430. ;
  431. ; Usage:
  432. ;
  433. ; Macro:
  434. ;    MOV    #Buffer.address,-(SP)
  435. ;    MOV    #Number.of.character,-(SP)
  436. ;    JSR    PC,DBG.DUMP
  437. ;    (Return - R0 contains the status)
  438. ;
  439. ; Bliss:
  440. ;    Status = DBG_DUMP(Buffer, Number_of_characters);
  441. ;
  442. ;++
  443.  
  444. DBG.DUMP::
  445. ;***** Fall into TERM_DUMP *****
  446.  
  447.     .SBTTL    Bliss interface -- TERM_DUMP - Dump a terminal buffer
  448.  
  449. ;++
  450. ; This routine will dump a buffer of characters to the terminal.  It will
  451. ; be called with the number of characters and the address of the buffer.  All
  452. ; this routine does is to output the buffer.
  453. ;
  454. ; Usage:
  455. ;
  456. ; Macro:
  457. ;    MOV    #Buffer.address,-(SP)
  458. ;    MOV    #Number.of.character,-(SP)
  459. ;    JSR    PC,TERM.DUMP
  460. ;    (Return - R0 contains the status)
  461. ;
  462. ; Bliss:
  463. ;    Status = TERM_DUMP(Buffer, Number_of_characters);
  464. ;
  465. ;++
  466.  
  467.  
  468. BLSRTN    TERM.DUMP,2,<ADDR,LEN>        ; Save R1 and compute offsets
  469.     BIT    #TRUE,CONNECT.FLAG    ; Terminal connected?
  470.     BNE    99$            ; Yes, just exit
  471.     BIT    #TRUE,NOSCRN        ; No screen output?
  472.     BNE    99$            ; Yes, skip this
  473.     MOV    ADDR(SP),R0        ; Get the address of the buffer
  474.     MOV    LEN(SP),R1        ; Get the length
  475.     BEQ    99$            ; If so then branch
  476.     QIOW$S    #IO.WVB,#TERLUN,#TTWEFN,,#IOSTAT,,<R0,R1>
  477. 99$:    MOV    #KNORMAL,R0        ; Return normal
  478.     RTS    PC            ; Return to the caller
  479.  
  480.     .SBTTL    Set alternate type out routines -- Set up
  481.  
  482. ;++
  483. ; This routine will set the alternate type out routine.  It will first
  484. ; make sure that the output has been dumped and then it will set the
  485. ; new output routine.
  486. ;
  487. ; Usage:
  488. ;    JSR    PC,ALTBUF        ; Call the routine
  489. ;
  490. ;--
  491.  
  492.     .GLOBL    ALTBUF
  493.  
  494. ALTBUF:    BLSCAL    TT.OUTPUT        ; Make sure the buffers are output
  495.     BLSCAL    TT.SET.OUTPUT,#ALTOUT    ; Set the character output routine
  496.     MOV    R0,ALTLOC        ;   to ALTOUT and save old routine
  497.     MOV    #IOBUFF,BUFPOS        ; Set the buffer pointer for ALTOUT
  498.     RTS    PC            ; Return to sender
  499.  
  500.     .SBTTL    Set alternate type out routines -- Restore routine
  501.  
  502. ;++
  503. ; This routine will restore the old type out routine.  It assumes that
  504. ; ALTBUF was called some type before
  505. ;
  506. ; Usage:
  507. ;    JSR    PC,ALTRST
  508. ;    (Return)
  509. ;--
  510.  
  511.     .GLOBL    ALTRST
  512.  
  513. ALTRST:    BLSCAL    TT.SET.OUTPUT,ALTLOC    ; Reset output to standard routine
  514.     RTS    PC            ; Return
  515.  
  516.     .SBTTL    Set alternate type out routines -- Output the buffer
  517.  
  518. ;++
  519. ; This routine will cause the buffer to be output and clear some of the
  520. ; initial characters that are in IOBUFF to be cleared.  Required for the
  521. ; menu processing.
  522. ;
  523. ; Usage:
  524. ;    JSR    PC,ALTCLR
  525. ;    (Return)
  526. ;
  527. ;--
  528.     .GLOBL    ALTCLR
  529.  
  530. ALTCLR:    BLSCAL    TT.OUTPUT        ; Dump buffer characters
  531.     MOV    #IOBUFF,R0        ; Get the buffer start address
  532.     RTS    PC            ; Return to sender
  533.  
  534.     .SBTTL    Set alternate type out routines -- Dump the buffer
  535.  
  536. ; Alternate output routine.  Simply buffers the characters.
  537.  
  538.     BLSRTN    ALTOUT,2,<ALTADR,ALTLEN> ; Define routine using macro
  539.     MOV    ALTADR(SP),R0        ; Get the new characters address
  540.     MOV    ALTLEN(SP),R1        ; Get the length of the buffer
  541.     MOV    R1,IOBLEN        ; Store the length
  542.     BEQ    10$            ;   Get out of here
  543. 5$:    MOVB    (R0)+,@BUFPOS        ; Move the characters to the buffer
  544.     INC    BUFPOS            ; Increment buffer pointer
  545.     SOB    R1,5$            ; Decrement character count and branch
  546.                     ;   if not done.  
  547.     CLRB    (R0)+            ; Clear the last byte
  548. 10$:    MOV    #IOBUFF,BUFPOS        ; Reset the buffer pointer
  549.     RTS    PC            ; Return to sender
  550.  
  551.     .SBTTL    FNDOFS - Find offset in a table
  552.  
  553. ;++
  554. ; This routine will find an offset into a table.  It will return the
  555. ; the address in the table or zero if it is not found.
  556. ;
  557. ; Usage:
  558. ;    R0/ Address of the table
  559. ;    R1/ Length of the table
  560. ;    R2/ Item to find
  561. ;    JSR    PC,FNDOFS
  562. ;    (Return)
  563. ;
  564. ; On return:
  565. ;    R0/ Address of entry or zero if not found
  566. ;--
  567.  
  568.     .PSECT    $CODE$,    RO
  569.  
  570.     .GLOBL    FNDOFS
  571.  
  572. FNDOFS:    CMP    R2,(R0)+        ; Is this the entry?
  573.     BEQ    10$            ; Branch if it is it
  574.     SOB    R1,FNDOFS        ; Loop for all entries
  575.     CLR    R0            ; Clear if not found
  576.     RTS    PC            ; Return failure
  577.  
  578. ; Now return the corrected offset to the item
  579.  
  580. 10$:    TST    -(R0)            ; Back up to the entry
  581.     RTS    PC            ; Return to the caller
  582.  
  583.     .SBTTL    End of KERLIB
  584.  
  585.     .END
  586.