Subject: Re: format line wrap?
From: rpw3@rpw3.org (Rob Warnock)
Date: Wed, 26 Sep 2007 03:20:52 -0500
Newsgroups: comp.lang.lisp
Message-ID: <x7adnerjG_n5i2fbnZ2dnUVZ_hWdnZ2d@speakeasy.net>
Damien Kick  <dkixk@earthlink.net> wrote:
+---------------
| Rob Warnock wrote:
| > O.k., here's a partial repost from what I wrote two weeks ago.
| > First a utility function from my standard personal toolbox:
| > 
| >   (defun \0x (stream arg colon-p at-sign-p &optional mincol padchar)
| >     "Hexadecimal numeric printing for use with the FORMAT ~/.../ directive.
| >     Outputs ARG to STREAM as \"~(0x~mincol,padX~)\" [default
| \"~(0x~8,'0X~)\"].
| >     If COLON-P, the entire output will be capitalized instead of lowercased.
| >     If AT-SIGN-P is true, the \"0x\" prefix will be suppressed."
| >     (let* ((fmt1 "~~~:[~;:@~](~:[0x~;~]~~~:[8~;~:*~a~],'~:[0~;~:*~a~]x~~)")
| >            (fmt2 (format nil fmt1 colon-p at-sign-p mincol padchar)))
| >       (format stream fmt2 arg)))
| 
| I'm not sure if this feeling I'm feeling is awe, fear, or nausea.
+---------------

Come on, CL isn't Scheme, you know!! Neither fear nor nausea is called
for. I do lots of hardware debugging and need to be able to show co-workers
dumps they can read... and none of them read Lisp but thay *all* read C.
Hence a "0" readmacro [so #x123 can be typed in as 0x123] and a "~/0x/"
FORMAT function so when I'm peeking & poking hardware things look like
a C or Tcl programmer expects them to... mostly:

    $ opfr
    opfr> deflex foo "abcde"

    FOO
    opfr> d32 foo
    0x48039998: 0x0000002a 0x00000014 0x64636261 0x00000065
    0x480399a8: 0x4803999f 0x28f0000b 0x4803999f 0x48039993
    0x480399b8: 0x4803999f 0x28f0000b 0x4803996f 0x480399bb
    0x480399c8: 0x48bb1f97 0x480399c3 0x480399cb 0x480399db
    opfr> 

Which, being decoded, is:

                        +-- CMUCL's heap type tag for SIMPLE-BASE-STRING
		        |          +-- (LENGTH "abcde") as a FIXNUM
		        |          |   [Hint: What is (ASH #x14 -2)?
		        |          |    ___ The string ___
		        |          |   /  [Little-Endian] \
    0x48039998: 0x0000002a 0x00000014 0x64636261 0x00000065

Now let's get *really* nasty!!  ;-}  ;-}

    opfr> code-char (r8 (+ 0x48039998 10))

    #\c
    opfr> w8 (+ 0x48039998 10) (char-code #\C) (char-code #\D)

    hwtool> foo

    "abCDe"
    opfr> 


-Rob

[1] OPFR == "Outer-Parenthesis-Free REPL", a trivial wrapper
    around a CL REPL that gives it a Tcl-like flavor as long
    as you're only typing pre-defined functions, variables,
    and literals. And, yes, once you have any sub-expressions
    the underlying Lisp shows through. Turns out not to be a
    biggy, as long as the top-level is paren-free. [I have written
    of the phenomenon at length previously. Google is your friend.]

[2] Yes, I know I'm illegally modifying a literal. It's just a
    quick example. But if you like, replace the first line with:

	deflex foo (copy-seq "abcde")

[3] Here's the D32 function [slightly trimmed]:

      (defun d32 (addr &optional (len #x40) (print-addr addr))
	...[a bunch of error-checking & argument coercion elided,
	    following which ADDR is now an 8-byte-aligned memory address]...
	(loop for i from 0 by 16 below len do
	 (format t "~2/0x/:" (+ print-addr i))
	 (loop for j from i by 4 below (min len (+ i 16)) do
	   (format t " ~/0x/" (r32 (+ addr j))))
	 (format t "~%"))
	 (values)) ; suppress ugly "NIL"

    Yes, the "~2/0x/" could be written as "~(0x~2,'0x~)" and the
    "~/0x/" as ~(0x~8,'0x~)", but I type a lot of one-off hex-output
    FORMATs at the REPL, too, and "~/0x/" is just easier.

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607