start coding wavelist method wf_add_var(), in preparation for future
[gwave-svn.git] / utilities / gwave-doc-snarf.in
blobe8a71f44b8147be6e7b16089db164b3c8e3f0947
1 #!@GUILE@ \
2 -e main -s
3 !#
4
5 ; gwave-doc-snarf - extract embedded documentation from the output of
6 ; the C preprocessor run on C code that uses the xsnarf.h macros
8 (use-modules (ice-9 getopt-long)
9              (ice-9 common-list)
10              (ice-9 format)
11              (ice-9 regex)
12              (srfi srfi-13))
14 (debug-enable 'debug 'backtrace)
15 (read-enable 'positions)
17 ;(display "gwave-doc-snarf running\n")
19 (define opts (getopt-long (program-arguments)
20              `((verbose      (single-char #\v))
21                (debug        (single-char #\x))
22                )))
24 (define opt-verbose
25   (let ((a (assq 'verbose opts)))
26     (if a
27         (cdr a)
28         #f)))
30 (define opt-debug
31   (let ((a (assq 'debug opts)))
32     (if a
33         (cdr a)
34         #f)))
36 (define cmdline-files (pick string? (assq '() opts)))
38 ;-----------------------------------------------------------------------------
40 (define (main a)
41   (for-each 
42    (lambda (f)
43      (if opt-debug (format #t "~a:\n" f))
44      (let ((fp (open-file f "r")))
45        (with-input-from-port fp
46          (lambda ()
47            (process-file f))))
48      )
49    cmdline-files)
52 (define (process-docentry e)
53   (let*((doctype (cadr (assoc 'type e)))
54         (name (cadr (assoc 'fname e)))
55         (doclist (cdr (assoc 'doc e)))
56         (argstr (cadr (assoc 'arglist e)))
57         (src-file (cadr (assoc 'location e)))
58         (src-line (caddr (assoc 'location e)))
59         (arglist (split-arglist argstr))
60         )
61     (if opt-debug (begin
62                     (format #t "name: ~s\n" name)
63                     (format #t "type: ~s\n" doctype)
64                     (format #t "location: ~s\n" (cdr (assoc 'location e)))
65                     (format #t "arglist: ~s\n" argstr)
66                     (format #t "argsig: ~s\n" (cdr (assoc 'argsig e)))
67                     (format #t "doc: ~s\n" doclist)))
68     (display "\f\n")
69     (cond
70      ((eq? doctype 'primitive)
71       (format #t "Procedure: (~a~a)\n" name (string-join arglist " " 'prefix)))
72      ((eq? doctype 'vcell)
73       (format #t "Variable: ~a\n" name))
74      ((eq? doctype 'concept)
75       (format #t "Concept: ~a\n" name))
76      ((eq? doctype 'hook)
77       (format #t "Hook: (~a~a)\n" name (string-join arglist " " 'prefix))))
79     (for-each (lambda (s)
80                 (format #t "~a\n" s))
81               doclist)
82     (format #t "[~a:~d]\n" src-file src-line)))
85 ; Split a string STR into a list of strings, on boundaries determined by
86 ; where the regexp RE matches.
88 (define (split re str)
89   (let ((r (make-regexp re)))
90     (let loop ((s str)
91                (result '()))
92       (let ((m (regexp-exec r s)))
93         (if (not m)
94             (if (< 0 (string-length s))
95                 (reverse! (cons s result))
96                 (reverse! result))
97             (if (< 0 (string-length (match:prefix m)))
98                 (loop (match:suffix m) (cons (match:prefix m) result))
99                 (loop (match:suffix m) result)))
100         ))))
102 ; Use the read-hash-extend facility to add a syntax for constant
103 ; regular expressions that are to be compiled once when read in,
104 ; instead of during the normal flow of execution.   This can let loops
105 ; that repeatedly use a constant regexp be optimized without moving the
106 ; expression's definition far away from its use.
108 ; With this hash-extension, these two expressions behave identicaly:
110 ; (regexp-exec (make-regexp "de+") "abcdeeef"))
111 ; (regexp-exec #+"de+" "abcdeeef")
113 (read-hash-extend #\+ (lambda (c port)
114                   (let ((s (read port)))
115                     (if (string? s)
116                         (make-regexp s)
117                         (error "bad #+ value; string expected")))))
120 ; split the C argument-list string, which looks like "(SCM foo, SCM bar)"
121 ; into a list of strings, each containing the name of one argument.
123 (define (split-arglist s)
124   (let* (
125          (s1 (regexp-substitute/global #f #+"^[ \t]*\\(" s 'post))
126          (s2 (regexp-substitute/global #f #+"\\)[ \t]*$" s1 'pre))
127          (s3 (regexp-substitute/global #f #+"[ \t]*SCM[ \t]*" s2 'pre 'post))
128          )
129       (split "," s3)))
132 (define (process-file fname)
133   (let ((rcaret (make-regexp "^\\^\\^")))
134     (do ((line (read-line) 
135                (read-line)))
136         ((eof-object? line) #f)
137       (if (regexp-exec rcaret line)
138           (begin
139             (call-with-input-string 
140              (string-drop line 2)
141              (lambda (p)
142                (let ((slist (read p)))
143                  (process-docentry slist)
144                  ))))))))
146 ;-----------------------------------------------------------------------------