home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff339.lzh / PCQ / Runtime.lzh / Runtime / Readers / ReadInt.asm < prev    next >
Assembly Source File  |  1989-11-20  |  3KB  |  125 lines

  1.  
  2. *    ReadInt.asm (of PCQ Pascal runtime library)
  3. *    Copyright (c) 1989 Patrick Quaid
  4.  
  5. *    This routine reads an integer from a text file.
  6.  
  7.     INCLUDE    ":runtime/FileRec.i"
  8.  
  9.     SECTION    ReadInt
  10.  
  11.     XREF    _p%ReadOneChar
  12.     XREF    _p%GetThatChar
  13.     XREF    _p%IOResult
  14.  
  15. * Algorithm for ReadInt:
  16. *
  17. *    save variable address
  18. *    repeat
  19. *        Get the next character
  20. *        if we are at eof
  21. *        set IOResult
  22. *        fix stack
  23. *        return
  24. *        if current character is white space
  25. *        eat it
  26. *    until current character is not white space
  27. *    if the character is a linefeed
  28. *        set IOResult
  29. *        fix stack
  30. *        return
  31. *    if the character is '-' then
  32. *        IsMinus := True
  33. *        eat that character
  34. *        get the next one
  35. *    else
  36. *        IsMinus := False
  37. *    result := 0
  38. *    while the current character is a digit
  39. *        result := result * 10 + value of current character
  40. *        eat the character
  41. *        get the next character
  42. *    correct sign
  43. *    restore variable address
  44. *    return
  45.  
  46.  
  47. * Upon entry, a0 has the address of the variable to be updated.  Since
  48. * this routine will be used to read 32-bit integers as well as 16-bit
  49. * 'shorts', we simply pass a0 back to the caller.  On top of the stack
  50. * is the file record.
  51.  
  52.  
  53.     XDEF    _p%ReadInt
  54. _p%ReadInt
  55.  
  56.     tst.l    _p%IOResult    ; is IO OK?
  57.     bne    Abort
  58.     move.l    a0,-(sp)    ; save the variable address
  59.     move.l    8(sp),a0    ; get the file record
  60. 1$    tst.b    EOF(a0)        ; are we at EOF?
  61.     bne    AbortEOF    ; if so, leave
  62.     jsr    _p%ReadOneChar    ; get the next character
  63.     tst.l    _p%IOResult    ; did it cause an error?
  64.     bne    Abort        ; if so, leave
  65.     cmp.b    #' ',d0        ; is the character a space?
  66.     beq.s    3$        ; if so, stay in loop
  67.     cmp.b    #9,d0        ; is it a tab?
  68.     bne.s    AfterWhiteSpace    ; if not, go on
  69. 3$    jsr    _p%GetThatChar    ; advance the buffer pointer
  70.     bra    1$
  71. AbortEOF
  72.     move.l    #58,_p%IOResult    ; set EOF before first digit
  73. Abort
  74.     move.l    (sp)+,a0    ; get variable address
  75.     moveq.l    #0,d0        ; return 0
  76.     rts
  77.  
  78. AfterWhiteSpace
  79.     cmp.b    #10,d0        ; is the character a linefeed?
  80.     beq    Abort        ; if so, leave
  81.     moveq.w    #0,d2        ; IsMinus := False
  82.     cmp.b    #'-',d0        ; is the character a '-'
  83.     bne.s    3$        ; if not, skip this
  84.     jsr    _p%GetThatChar    ; eat the character
  85.     jsr    _p%ReadOneChar    ; and get the next one
  86.     move.w    #-1,d2        ; IsMinus := True
  87. 3$    cmp.b    #'0',d0        ; is first char a digit?
  88.     blt.s    NoNumber    ; if < 0 then is isn't
  89.     cmp.b    #'9',d0        ; keep checking
  90.     ble.s    DigitOK        ; is <= 9, we're OK
  91. NoNumber
  92.     move.l    #59,_p%IOResult    ; set No Digits for ReadInt
  93.     bra    Abort
  94. DigitOK
  95.     moveq.l    #0,d1        ; Result := 0
  96.     move.w    d2,-(sp)    ; save sign
  97. 5$    cmp.b    #'0',d0        ;
  98.     blt    Leave        ; if < '0' leave now
  99.     cmp.b    #'9',d0
  100.     bgt    Leave        ; if > '9' leave
  101.     sub.b    #'0',d0        ; get digit value
  102.     move.w    d0,-(sp)    ; and save it
  103.     lsl.l    #1,d1        ; d1 := d1 * 2
  104.     move.l    d1,d0        ; d0 := d1 * 2
  105.     lsl.l    #2,d1        ; d1 := d1 * 8
  106.     add.l    d0,d1        ; d1 := d1 * 8 + d1 * 2 = d1 * 10
  107.     move.w    (sp)+,d0    ; retrieve the digit
  108.     and.l    #15,d0        ; no funny business...
  109.     add.l    d0,d1        ; and add to running total
  110.     move.l    d1,-(sp)    ; save the running total
  111.     jsr    _p%GetThatChar    ; eat the current char
  112.     jsr    _p%ReadOneChar    ; get the next character
  113.     move.l    (sp)+,d1    ; get values back
  114.     tst.b    EOF(a0)        ; are we at eof?
  115.     beq    5$        ; if not, continue
  116. Leave
  117.     move.l    d1,d0        ; set up for return
  118.     move.w    (sp)+,d2    ; was it minus?
  119.     beq.s    6$        ; if not, skip this
  120.     neg.l    d0        ; d0 := -d0
  121. 6$    move.l    (sp)+,a0    ; retrieve variable address
  122.     rts
  123.  
  124.     END
  125.