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)
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))
25 (let ((a (assq 'verbose opts)))
31 (let ((a (assq 'debug opts)))
36 (define cmdline-files (pick string? (assq '() opts)))
38 ;-----------------------------------------------------------------------------
43 (if opt-debug (format #t "~a:\n" f))
44 (let ((fp (open-file f "r")))
45 (with-input-from-port fp
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))
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)))
70 ((eq? doctype 'primitive)
71 (format #t "Procedure: (~a~a)\n" name (string-join arglist " " 'prefix)))
73 (format #t "Variable: ~a\n" name))
74 ((eq? doctype 'concept)
75 (format #t "Concept: ~a\n" name))
77 (format #t "Hook: (~a~a)\n" name (string-join arglist " " 'prefix))))
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)))
92 (let ((m (regexp-exec r s)))
94 (if (< 0 (string-length s))
95 (reverse! (cons s 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)))
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)))
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)
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))
132 (define (process-file fname)
133 (let ((rcaret (make-regexp "^\\^\\^")))
134 (do ((line (read-line)
136 ((eof-object? line) #f)
137 (if (regexp-exec rcaret line)
139 (call-with-input-string
142 (let ((slist (read p)))
143 (process-docentry slist)
146 ;-----------------------------------------------------------------------------