flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
chken 06 May 2011, 22:13
Code: printf "%s : %d ", "size", 1024 compile,display size : 1024 who can write it. |
|||
![]() |
|
chken 08 May 2011, 11:02
![]() |
|||
![]() |
|
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" |
|||
![]() |
|
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. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.
Website powered by rwasa.