2013年5月23日木曜日

clisp でファイルダンプ

ファイルダンププログラムを clisp でも作成してみた。emacs の初期設定すらもままならない僕にはやはりかなりハードルが高かった。出来上がったソースは lisp らしくないのかもしれないが、とりあえずはじめの一歩を記すことができた。以下、躓いたところを列挙。

  • 本みて理解しているつもりでも、cons,list,push が解ってなかった。目的をもってREPLで試すと少し理解が深まった。
  • どの言語もそうだけれど、1バイト単位の処理方法に意外と苦労する。今回は element-type,read-byte,code-char,char-code の組み合わせかな。
  • while はマクロで実現されているので、自分でマクロを組まなければいけないらしい(初心者には荷が重いので loop に書き換えた)。
  • return は、break のようなもので、二重ループを一気に抜け出たりはしてくれないらしい。
  • format は、独特な世界観で、なかなか覚えられない。そもそもlisp は関数の名前が長めのが多い。
出来上がってみれば、他の言語同様の構造で(lispらしくない?)どこに詰まったのかと思うところが悲しい。
(defun hdmp(adr line len)
  (format t "~8,'0x: " adr)
  (mapc (lambda(c) (format t "~2,'0x " c)) (reverse line))
  (setq zan (- 16 len))
  (if (> zan 0)
      (dotimes(i zan) (princ "   "))))

(defun cdmp(adr line len)
  (princ "| ")
  (mapc (lambda(c)
          (if (or (< c 32) (>= c 127))
              (format t ".")
              (format t "~a" (code-char c))))
        (reverse line))
  (setq zan (- 16 len))
  (if (> zan 0)
      (dotimes(i zan) (princ " ")))
  (princ " |")
  (fresh-line))

(defun dump(name)
  (with-open-file (in name :direction :input :element-type 'unsigned-byte)
    (setq adr 0)
    (setq cnt 0)
    (setq line nil)
    (loop
       (setq c (read-byte in nil nil))
       (if (equal c nil) (return t))

       (if (> cnt 15)
           (progn
             (hdmp adr line cnt)
             (cdmp adr line cnt)
             (setq adr (+ adr cnt))
             (setq cnt 0)
             (setq line nil)))

       (push c line)
       (setq cnt (1+ cnt)))
    (if (> cnt 0)
        (progn
          (hdmp adr line cnt)
          (cdmp adr line cnt))))

0 件のコメント:

コメントを投稿