flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > printf macro for display message

Author
Thread Post new topic Reply to topic
chken



Joined: 24 Feb 2011
Posts: 2
chken 06 May 2011, 22:13
Code:
printf "%s : %d ", "size", 1024
    


compile,display

size : 1024

who can write it.
Post 06 May 2011, 22:13
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 07 May 2011, 00:24
It is something like this:
Code:
; revolution is the author of the next two macros
macro display_decimal value*,put_zeros {
    local leading_zero,digit,divisor,number
    number=value
    if number=1 shl 63
        display '-9223372036854775808'
    else
        if number<0
            number=-number
            display '-'
        end if
        leading_zero=put_zeros+0
        divisor=1000000000000000000
        while divisor>0
            digit=number/divisor
            leading_zero=leading_zero+digit
            if leading_zero | (divisor=1)
                display digit+'0'
                number=number-digit*divisor
            end if
            divisor=divisor/10
        end while
    end if
}
macro display_unsigned value* {
    local number
    number=value
    if number<0
        number=number-10000000000000000000
        if number<0
            number=number+1000000000000000000
            display '9'
            display_decimal number
        else
            display '1'
            display_decimal number,1
        end if
    else
        display_decimal number
    end if
}


; Now my part Very Happy
macro printf fmt*, [args]{
common
local p, s, i, c

   p = 0
   s = 0

   virtual at 0
      db fmt

      repeat $
         load c byte from % - 1

         if ((~s) & (c <> '%')) | ((s) & (c = '%'))
            display c

            s = 0
         else if c = '%'

            s = 1
         else
            i = 0
forward
            if i = p
               if c = 's'
                  display args
               else if c = 'd'
                  display_decimal args, 0
               else
                  err 'Huh! What?!'
               end if
            end if

            i = i + 1
common
            s = 0
            p = p + 1
         end if
      end repeat
  end virtual
}


printf "%s : %d ", "size", 1024    
If you add the missing conversions please share here.
Post 07 May 2011, 00:24
View user's profile Send private message Reply with quote
chken



Joined: 24 Feb 2011
Posts: 2
chken 08 May 2011, 11:02
Very Happy Thank you very much!
Post 08 May 2011, 11:02
View user's profile Send private message Reply with quote
ketmar_



Joined: 19 Jan 2012
Posts: 1
ketmar_ 19 Jan 2012, 04:35
very wordy and lame printf extension. now it understands "%x" and width modifier, so this is perfectly valid: dprintf "%10s %03d %-5d!\n", "str0", 42, 666
note "\n" usage. %-)
Code:
macro printf_display_format_decimal_minint length, zero_fill, lpad {
  local filler, minusok, len
  ;
  minusok = 0
  len = length-20  ; -9223372036854775808
  if (len > 0) & (lpad <> 0)
    if zero_fill > 0
      minusok = 1
      display '-'
      len = len-1
    end if
    while len > 0
      display filler
      len = len-1
    end while
  end if
  if minusok = 0
    len = len-1
    display '-'
  end if
  display "9223372036854775808"
  if (len > 0) & (lpad = 0)
    while len > 0
      display ' '
      len = len-1
    end while
  end if
}


macro printf_display_format_num num, length, zero_fill, lpad, base, alphaupcased {
  local leading_zero, digit, divisor, cnt, filler, minusok, len, number, nn
  ;
  if num = 1 shl 63
    ; special case
    printf_display_format_decimal_minint length, zero_fill, lpad
  else
    len = length
    number = num
    minusok = 0
    ; determine string representation length
    if number < 0
      minusok = 0
      number = -number
      len = len-1
    else
      minusok = 1
    end if
    ;
    cnt = 1
    if number >= base
      divisor = 1
      nn = number/base
      while nn > 0
        cnt = cnt+1
        nn = nn/base
        divisor = divisor*base
      end while
    else
      divisor = base
    end if
    ;
    len = len-cnt  ; compensate size
    ; left fill
    if (len > 0) & (lpad <> 0)
      if zero_fill > 0
        filler = '0'
        if minusok = 0
          minusok = 1
          display '-'
        end if
      else
        filler = ' '
      end if
      while len > 0
        display filler
        len = len-1
      end while
    end if
    ; minus
    if minusok = 0
      display '-'
    end if
    ; number
    while cnt > 0
      digit = number/divisor
      number = number-digit*divisor
      divisor = divisor/base
      cnt = cnt-1
      if digit > 9
        if alphaupcased <> 0
          digit = digit+7
        else
          digit = digit+39
        end if
      end if
      display digit+'0'
    end while
    ; right fill
    if (len > 0) & (lpad = 0)
      while len > 0
        display ' '
        len = len-1
      end while
    end if
  end if
}


macro printf_display_helper freevirt, value, fmt, length, zero_fill, lpad {
  local slen, len, filler
  ;
#if 0
  display "[", fmt, "]", 10
  ;
  display " length="
  printf_display_format_unsigned length
  display 10
  ;
  display " zero_fill="
  printf_display_format_unsigned zero_fill
  display 10
  ;
  display " lpad="
  printf_display_format_unsigned lpad
  display 10
  ;
  display " freevirt="
  printf_display_format_unsigned freevirt
  display 10
  ;
  display "==============", 10
end if
  if fmt = 's'
    virtual at freevirt
      db value
      slen = $-freevirt
    end virtual
    len = length-slen
    ;
    if (len > 0) & (lpad <> 0)
      if zero_fill > 0
        filler = '0'
      else
        filler = ' '
      end if
      while len > 0
        display filler
        len = len-1
      end while
    end if
    display value
    if (len > 0) & (lpad = 0)
      while len > 0
        display ' '
        len = len-1
      end while
    end if
  else if fmt = 'd'
    printf_display_format_num value, length, zero_fill, lpad, 10, 0
  else if fmt = 'u'
    ;FIXME!
    printf_display_format_num value, length, zero_fill, lpad, 10, 0
  else if fmt = 'x'
    printf_display_format_num value, length, zero_fill, lpad, 16, 0
  else if fmt = 'X'
    printf_display_format_num value, length, zero_fill, lpad, 16, 1
  else
    display "FATAL: invalid format directive: '", fmt, "'", 10
    err 'Huh! What?!'
  end if
  ;display "|", 10, "--------------", 10
}


macro printf fmt*, [args] {
common
  local curargnum, state, f, curch, fmtlength, fmtzeropad, fmtleftpad, freevirt
  ; state machine:
  ;  0: normal char; check for specials or print
  ;  1: just after '\'
  ;  2: formatting directive just started
  ;  3: parsing formatting directive length
  ;  4: at format directive
  curargnum = 0
  state = 0
  ;display "**************************", 10
  virtual at 0
    db fmt
    freevirt = $+8
    repeat $
      load curch byte from %-1
      ;display "*state: ", state+'0', "; curch=[", curch, "]", 10
      if state = 0
        ; normal
        if curch = '\'
          state = 1
        else if curch = '%'
          state = 2
        else
          display curch
        end if
      else if state = 1
        ; escape
        state = 0
        if curch = 'n'
          display 10
        else if curch = 'r'
          display 13
        else if curch = 't'
          display 9
        else if curch = 'a'
          display 8
        else if curch = 'e'
          display 27
        else
          display curch
        end if
      else if state = 2
        ; first char of format directive
        state = 3
        fmtdir = ' '
        fmtlength = 0
        fmtzeropad = -1
        if curch = '-'
          fmtleftpad = 0
        else if (curch >= '0') & (curch <= '9')
          fmtleftpad = 1
          if curch = '0'
            fmtzeropad = 1
          else
            fmtzeropad = 0
          end if
          fmtlength = curch-'0'
        else if curch = '%'
          state = 0
          display '%'
        else
          state = 0
          f = 0
forward
          ; process all varargs
          if f = curargnum
            printf_display_helper freevirt, args, curch, fmtlength, fmtzeropad, fmtleftpad
          end if
          f = f+1
common
          curargnum = curargnum+1
        end if
      else if state = 3
        ; in length
        if (curch >= '0') & (curch <= '9')
          if fmtzeropad < 0
            if curch = '0'
              fmtzeropad = 1
            else
              fmtzeropad = 0
            end if
          end if
          fmtlength = fmtlength*10+curch-'0'
        else
          state = 0
          f = 0
forward
          ; process all varargs
          if f = curargnum
            printf_display_helper freevirt, args, curch, fmtlength, fmtzeropad, fmtleftpad
          end if
          f = f+1
common
          curargnum = curargnum+1
        end if
      end if
    end repeat
  end virtual
}


printf "%s\n", "size"
printf "%10s: %07d %08x %-10s|\n", "size", -1024, 16385, "str0"
    
Post 19 Jan 2012, 04:35
View user's profile Send private message Reply with quote
gulrak



Joined: 17 Jun 2006
Posts: 1
gulrak 30 Sep 2012, 20:32
I was looking for something like this. Thanks to revolution, LocoDelAssembly and ketmar_ for doing the work, but trying it, I found a bug:

for %d or %x with a value less than the base, if simply prints 0. The reason is

Code:
   if number >= base
      divisor = 1
      nn = number/base
      while nn > 0
        cnt = cnt+1
        nn = nn/base
        divisor = divisor*base
      end while
    else
      divisor = base ; <- this should be divisor = 1
    end if
    


in printf_display_format_num. Setting the divisor for single digit values to base, leaves 0 after the the first digit = number/divisor later in the code.

With that fix it at least worked for my tests.
Post 30 Sep 2012, 20:32
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.