home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / source / dcassem.lha / No.15 < prev    next >
Text File  |  1988-05-14  |  5KB  |  134 lines

  1.         SECTION    _printf,CODE
  2.         XREF    _AbsExecBase,_LVOOpenLibrary,_LVOCloseLibrary
  3.         XREF    _LVOOutput,_LVOWrite
  4.  
  5. ;===========================================================================
  6. ; The actual code of the printf function.  Generates a formatted string with
  7. ; a maximum length of 512 bytes and then calls the appropriate text output
  8. ; function.  Text is output as a whole string to speed up the DOS write
  9. ; function which goes real slow on single character output.  Args passed on
  10. ; the stack as: format,arg1,arg2, ... arg8 and it is up to the caller to
  11. ; clean up the stack space used, this is handled by the printf macro.
  12. ;===========================================================================
  13.         XDEF    _printf
  14. _printf        movem.l    d0-d2/a0-a4/a6,-(sp)    save regs
  15.         movea.l    40(sp),a3        a3 points to string
  16.         lea.l    44(sp),a4        a4 points to args
  17.         lea.l    -256(sp),sp        make room for output string
  18.         movea.l    sp,a2            a2 points to output string
  19.  
  20. ; The main loop, copy characters to the output buffer until a % or \ is
  21. ; encountered in which case interpret the characters following in the same
  22. ; manner as C's printf function and put the results into the output stream
  23. ; instead.  A null byte terminates the output.
  24. _printloop    move.b    (a3)+,d0        get a copy of the byte
  25. _possibleend    move.b    d0,(a2)            move to output string
  26.         beq    _printdone        terminating byte
  27.         cmpi.b    #'\',d0            special character byte ?
  28.         beq.s    _specialchar        yes, go see what it is
  29.         cmpi.b    #'%',d0            number or string byte ?
  30.         beq.s    _introchar        yes, go process that
  31. _bumpptr    addq.l    #1,a2            nothing special, bump ptr...
  32.         bra.s    _printloop        ...and go back for the next
  33.  
  34. ; Found a backslash, replace character after with tab or newline (\t or \n)
  35. _specialchar    move.b    (a3)+,d0        get the next character
  36.         beq.s    _possibleend        that could have been nasty!!
  37.         cmpi.b    #'\',d0            did caller want a backslash
  38.         beq.s    _bumpptr        yes, so leave the other
  39.         cmpi.b    #'t',d0            did user want a tab ?
  40.         bne.s    _checkcr        nope, maybe a newline
  41.         move.b    #9,(a2)+        yes, store tab and bump
  42.         bra.s    _printloop        and go for the next char
  43. _checkcr    cmpi.b    #'n',d0            did user want a newline ?
  44.         bne.s    _printloop        nope, ignore all others
  45.         move.b    #13,(a2)+        yes, store cr and bump
  46.         move.b    #10,(a2)+
  47.         bra.s    _printloop        and go for the next char
  48.  
  49. ; Found a percent sign.  Must be introducing a number, string or character
  50. _introchar    move.b    (a3)+,d0        get the next character
  51.         beq.s    _possibleend        another possible oops!
  52.         cmpi.b    #'%',d0            did caller want a percent?
  53.         beq.s    _bumpptr        yes, so leave the last one
  54.         cmpi.b    #'c',d0            print a character ?
  55.         bne.s    _checkstring        nope!
  56.         move.l    (a4)+,d0        get char from arg stack
  57.         move.b    d0,(a2)+        store it and bump ptr
  58.         bra.s    _printloop        and go for the next char
  59. _checkstring    cmpi.b    #'s',d0            print a string ?
  60.         bne.s    _checknumber        nope!
  61.         movea.l    (a4)+,a0        get ptr from arg stack
  62. 10$        move.b    (a0)+,(a2)+        and copy the string
  63.         bne.s    10$
  64.         subq.l    #1,a2            went 1 byte too far
  65.         bra.s    _printloop        go for the next char
  66.  
  67. ; wasn't a string or character code so it has to be a number code here
  68. _checknumber    moveq.l    #0,d2            flag, short (word) number
  69.         cmpi.b    #'l',d0            long version of a number ?
  70.         bne.s    _whatnumber        no, it was a short
  71.         moveq.l    #1,d2            flag, longword number
  72.         move.b    (a3)+,d0        and get the next letter
  73.         beq.s    _possibleend        yet another nasty spot!
  74. _whatnumber    cmpi.b    #'x',d0            hex character ?
  75.         bne.s    _decnumber        nope, must be a decimal
  76.         move.l    (a4)+,d0        get hex value to print
  77.         movea.l    a2,a0            buffer to store to
  78.         tst.w    d2            see what size
  79.         bne.s    _dolonghex        it's a longword
  80.         bsr    bin2hex16        it's a word
  81.         bra.s    _findend        find where number ends
  82. _dolonghex    bsr    bin2hex32
  83.         bra.s    _findend        find where number ends
  84.  
  85. _decnumber    cmpi.b    #'d',d0            really want a decimal ?
  86.         bne    _printloop        nope, illegal character!
  87.         move.l    (a4)+,d0        get decimal value to print
  88.         movea.l    a2,a0            and buffer to store to
  89.         tst.w    d2            see what size
  90.         bne.s    _dolongdec        it's a longword
  91.         bsr    bin2asc16        it's a word
  92.         bra.s    _findend        see what size
  93. _dolongdec    bsr    bin2asc32
  94.  
  95. ; A number has been stored into the buffer, find the end to update A2 ptr
  96. _findend    tst.b    (a2)+            search for null byte
  97.         bne.s    _findend        not there yet
  98.         subq.l    #1,a2            went one byte too far
  99.         bra    _printloop        go for the next char
  100.  
  101. ; We got to the end of the format string and now have a formatted string on
  102. ; the stack that is terminated by a null byte.  Open the dos library to find
  103. ; the current output stream and write the string out.
  104. _printdone    movea.l    _AbsExecBase,a6        need exec library node
  105.         lea.l    DosName(pc),a1
  106.         moveq.l    #0,d0            don't care what version
  107.         jsr    _LVOOpenLibrary(a6)
  108.         tst.l    d0
  109.         beq.s    _cleanup        didn't get the library
  110.         movea.l    d0,a6
  111.  
  112.         jsr    _LVOOutput(a6)        find output handle
  113.         move.l    d0,d1            where we print to
  114.         move.l    sp,d2            where we print from
  115.         suba.l    sp,a2            find length of string
  116.         move.l    a2,d3
  117.         jsr    _LVOWrite(a6)        and write it out
  118.  
  119.         movea.l    a6,a1
  120.         movea.l    _AbsExecBase,a6        finished with dos lib now
  121.         jsr    _LVOCloseLibrary(a6)
  122.  
  123. _cleanup    lea.l    256(sp),sp        fix up the stack pointer
  124.         movem.l    (sp)+,d0-d2/a0-a4/a6    restore regs
  125.         rts                all done
  126.  
  127.         INCLUDE    "numbers.asm"
  128.  
  129. DosName        DC.B    'dos.library',0
  130.         CNOP    0,2
  131.  
  132.         END
  133.  
  134.