| 1 | #!/usr/bin/env csi -script # -*-scheme-*- |
|---|
| 2 | ; Print out a list of all typedefs in the src in a format suitable for |
|---|
| 3 | ; using in the indent rule for src/Makefile. Requires chicken scheme. |
|---|
| 4 | ; http://call-with-current-continuation.org or your package manager. |
|---|
| 5 | ; |
|---|
| 6 | ; Written by Raevnos <shawnw@speakeasy.org> for PennMUSH. |
|---|
| 7 | ; |
|---|
| 8 | ; Version 0.9.1. |
|---|
| 9 | ; |
|---|
| 10 | ; Usage: |
|---|
| 11 | ; % csc -O2 -heap-initial-size 768k -o typedefs utils/typedefs.scm |
|---|
| 12 | ; % make etags |
|---|
| 13 | ; % ./typedefs < src/TAGS > indent.defs |
|---|
| 14 | ; % emacs src/Makefile.in indent.defs |
|---|
| 15 | ; edit Makefile.in to modify the indent typedef section |
|---|
| 16 | ; % ./config.status |
|---|
| 17 | ; % make |
|---|
| 18 | ; |
|---|
| 19 | ; You can also use it as an interpreted script: |
|---|
| 20 | ; % csi -script utils/typedefs.scm < src/TAGS > indent.defs |
|---|
| 21 | ; or |
|---|
| 22 | ; % chmod +x typedefs.scm |
|---|
| 23 | ; % ./typedefs.scm < TAGS |
|---|
| 24 | ; |
|---|
| 25 | ; This is just slower to run, thus good for occasional use. |
|---|
| 26 | ; Some rough time trials suggest that the compiled version runs |
|---|
| 27 | ; twice as fast. Of course, it also takes a while to compile it... |
|---|
| 28 | ; |
|---|
| 29 | ; |
|---|
| 30 | ; TODO |
|---|
| 31 | ; Take command-line arguments: The TAGS file and whether or not to |
|---|
| 32 | ; generate output to be included into a Makefile (Lines continued by \) |
|---|
| 33 | ; or into an .indent.pro file. # of columns, tab stops, etc. |
|---|
| 34 | |
|---|
| 35 | ; Optimization and module directives. |
|---|
| 36 | (cond-expand |
|---|
| 37 | ((and chicken compiling) |
|---|
| 38 | (declare |
|---|
| 39 | (fixnum) |
|---|
| 40 | (block) |
|---|
| 41 | (usual-integrations) |
|---|
| 42 | (disable-interrupts) |
|---|
| 43 | (lambda-lift) |
|---|
| 44 | (no-procedure-checks-for-usual-bindings) |
|---|
| 45 | (bound-to-procedure string-between/shared process-line read-typedefs |
|---|
| 46 | copy-typedef emit-typedef) |
|---|
| 47 | (uses utils srfi-1 srfi-13))) |
|---|
| 48 | ((and chicken csi) |
|---|
| 49 | (require-extension utils) |
|---|
| 50 | (require-extension srfi-1) |
|---|
| 51 | (require-extension srfi-13)) |
|---|
| 52 | (else #f)) |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | ; Return what's between the first occurance of fc and the last of lc in |
|---|
| 56 | ; a string. Raises an error if index(fc) > index(lc) or one of the two |
|---|
| 57 | ; doesn't exist. |
|---|
| 58 | (define (string-between/shared str fc lc) |
|---|
| 59 | (let ((first-index (string-index str fc)) |
|---|
| 60 | (last-index (string-index-right str lc))) |
|---|
| 61 | (cond |
|---|
| 62 | ((not (and (integer? first-index) (integer? last-index))) |
|---|
| 63 | (signal 'out-of-range)) |
|---|
| 64 | ((fx>= first-index last-index) |
|---|
| 65 | (signal 'out-of-range)) |
|---|
| 66 | (else |
|---|
| 67 | (substring/shared str (fx+ first-index 1) last-index))))) |
|---|
| 68 | |
|---|
| 69 | ; The special characters that mark the start and end of an identifier |
|---|
| 70 | (define-constant type-start #\x7F) |
|---|
| 71 | (define-constant type-end #\x01) |
|---|
| 72 | |
|---|
| 73 | ; Either return a typedef name or a symbol : 'line-did-not-match or |
|---|
| 74 | ; 'read-more-lines |
|---|
| 75 | (define process-line #f) |
|---|
| 76 | (let* |
|---|
| 77 | ((in-struct-typedef? #f) |
|---|
| 78 | (in-enum-typedef? #f) |
|---|
| 79 | (copy-typedef (lambda (str) |
|---|
| 80 | (string-between/shared str type-start type-end))) |
|---|
| 81 | (pl (lambda (line) |
|---|
| 82 | (handle-exceptions |
|---|
| 83 | exn (if (eq? exn 'out-of-range) |
|---|
| 84 | (begin |
|---|
| 85 | (display |
|---|
| 86 | (format "Unable to extract typedef name from line: ~A\n" |
|---|
| 87 | line) (current-error-port)) |
|---|
| 88 | 'line-did-not-match) |
|---|
| 89 | (abort exn)) |
|---|
| 90 | (cond |
|---|
| 91 | (in-struct-typedef? |
|---|
| 92 | (if (char=? (string-ref line 0) #\}) |
|---|
| 93 | (begin |
|---|
| 94 | (set! in-struct-typedef? #f) |
|---|
| 95 | (copy-typedef line)) |
|---|
| 96 | 'read-more-lines)) |
|---|
| 97 | (in-enum-typedef? |
|---|
| 98 | (if (char=? (string-ref line 0) #\}) |
|---|
| 99 | (begin |
|---|
| 100 | (set! in-enum-typedef? #f) |
|---|
| 101 | (copy-typedef line)) |
|---|
| 102 | 'read-more-lines)) |
|---|
| 103 | ((string-prefix? "typedef struct " line) |
|---|
| 104 | (if (string-index line #\;) |
|---|
| 105 | (copy-typedef line) |
|---|
| 106 | (begin |
|---|
| 107 | ; If the struct is defined here the typedef name |
|---|
| 108 | ; is on the next line starting with }. There are |
|---|
| 109 | ; optional structure member lines between. |
|---|
| 110 | (set! in-struct-typedef? #t) |
|---|
| 111 | 'read-more-lines))) |
|---|
| 112 | ((string-prefix? "typedef enum " line) |
|---|
| 113 | (if (string-index line #\;) |
|---|
| 114 | (copy-typedef line) |
|---|
| 115 | (begin |
|---|
| 116 | ; Skip enum values |
|---|
| 117 | (set! in-enum-typedef? #t) |
|---|
| 118 | 'read-more-lines))) |
|---|
| 119 | ((string-prefix? "typedef " line) |
|---|
| 120 | (copy-typedef line)) |
|---|
| 121 | ((string-prefix? "} " line) |
|---|
| 122 | ; We get this with a typedef of an anonymous struct. |
|---|
| 123 | ; If it then starts an array, some versions of etags |
|---|
| 124 | ; won't record the typedef name and you'll get a warning. |
|---|
| 125 | (copy-typedef line)) |
|---|
| 126 | (else 'line-did-not-match)))))) |
|---|
| 127 | (set! process-line pl)) |
|---|
| 128 | |
|---|
| 129 | (define-macro (prepend! val lst) |
|---|
| 130 | `(set! ,lst (cons ,val ,lst))) |
|---|
| 131 | |
|---|
| 132 | ; Read all typedefs from an inchannel or filename. |
|---|
| 133 | (define (read-typedefs from) |
|---|
| 134 | (let* |
|---|
| 135 | ((typedefs '()) |
|---|
| 136 | (fl-proc (lambda (line) |
|---|
| 137 | (let ((res (process-line line))) |
|---|
| 138 | (if (string? res) (prepend! res typedefs)))))) |
|---|
| 139 | (for-each-line fl-proc from) |
|---|
| 140 | (delete-duplicates (sort typedefs string-ci<) string-ci=))) |
|---|
| 141 | |
|---|
| 142 | ; Control pretty-printing of the typedefs. |
|---|
| 143 | (define-constant max-column-width 75) |
|---|
| 144 | (define-constant tab-stop 8) |
|---|
| 145 | |
|---|
| 146 | ; Print out one typedef to stdout, formated as indent args. |
|---|
| 147 | (define emit-typedef #f) |
|---|
| 148 | (let* |
|---|
| 149 | ((column tab-stop) |
|---|
| 150 | (et (lambda (typedef) |
|---|
| 151 | (let* ((start-of-line? (fx= column tab-stop)) |
|---|
| 152 | (len (fx+ (string-length typedef) |
|---|
| 153 | (if start-of-line? 3 4)))) |
|---|
| 154 | (if (fx>= (fx+ column len) max-column-width) |
|---|
| 155 | (begin |
|---|
| 156 | (display " \\\n\t") |
|---|
| 157 | (set! column tab-stop) |
|---|
| 158 | (set! start-of-line? #t))) |
|---|
| 159 | (if start-of-line? |
|---|
| 160 | (printf "-T ~A" typedef) |
|---|
| 161 | (printf " -T ~A" typedef)) |
|---|
| 162 | (set! column (fx+ column len)))))) |
|---|
| 163 | (set! emit-typedef et)) |
|---|
| 164 | |
|---|
| 165 | ; main |
|---|
| 166 | (let ((typedefs (read-typedefs (current-input-port)))) |
|---|
| 167 | (write-char #\tab) |
|---|
| 168 | (for-each emit-typedef typedefs) |
|---|
| 169 | (newline)) |
|---|