529b79bc53bd4bde736a4f19a2477e3d810934a4
[mes.git] / module / nyacc / lang / c99 / util2.scm
1 ;;; nyacc/lang/c99/util2.scm - C processing code
2 ;;; 
3 ;;; Copyright (C) 2015,2016 Matthew R. Wette
4 ;;;
5 ;;; This program is free software: you can redistribute it and/or modify
6 ;;; it under the terms of the GNU General Public License as published by 
7 ;;; the Free Software Foundation, either version 3 of the License, or 
8 ;;; (at your option) any later version.
9 ;;;
10 ;;; This program is distributed in the hope that it will be useful,
11 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of 
12 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 ;;; GNU General Public License for more details.
14 ;;;
15 ;;; You should have received a copy of the GNU General Public License
16 ;;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 ;; utilities for processing output trees
19
20 ;; The idea is to convert declarations into something like
21 ;; @example
22 ;; const char *args[21];  /* command arguments */
23 ;; @end example
24 ;; @noindent
25 ;; into
26 ;; @example
27 ;; ("args" (comment " command arguments ")
28 ;;  (array-of 21) (pointer-to) (fixed "char"))
29 ;; @end example
30 ;; @noindent
31 ;; or without the comment.  It is a question whether we need the fixed part.
32 ;; In addition, we want to reduce to a set of canonical types.  So something
33 ;; like @code{foo_t} should be expanded.
34
35 ;; KEEPING STRUCTS ENUMS etc
36 ;; if have typename and want to keep it, then change
37 ;;   (typename "foo_t")
38 ;; to
39 ;;   (typename (@ (base "struct")) "foo_t")
40
41 ;; ALSO
42 ;;  (make-proxy comp-udecl) => udecl
43 ;;  (revert-proxy udecl) => comp-udecl
44
45 (define-module (nyacc lang c99 util2)
46   #:export (tree->udict
47             stripdown stripdown-2
48             udecl->mspec
49             udecl->mspec/comm
50
51             unwrap-decl
52             canize-enum-def-list
53             fix-fields
54             fixed-width-int-names
55
56             match-decl match-comp-decl match-param-decl
57             declr->ident
58             expand-decl-typerefs
59             )
60   #:use-module (nyacc lang c99 pprint)
61   #:use-module (ice-9 pretty-print)
62   #:use-module (srfi srfi-1)
63   #:use-module ((sxml fold) #:select (foldts foldts*))
64   #:use-module (sxml match)
65   #:use-module (nyacc lang util)
66   #:use-module (nyacc lang c99 pprint)
67   )
68
69 ;; Use the term @dfn{udecl}, or unit-declaration, for a declaration which has
70 ;; only one decl-item.  That is where,
71 ;; @example
72 ;; @end example
73 ;; (decl (decl-spec-list ...) (init-declr-list (init-declr ...) ...))
74 ;; @noindent
75 ;; has been replaced by
76 ;; (decl (decl-spec-list ...) (init-declr ...))
77 ;; ...
78 ;; @example
79 ;; @end example
80
81 ;; mspec is
82 ;; ("foo" (pointer-to) (array-of 3) (fixed-type "unsigned int"))
83 ;; which can be converted to
84 ;; ("(*foo) (array-of 3) (fixed-type "unsigned int"))
85 ;; which can be converted to
86 ;; (("((*foo)[0])" (fixed-type "unsigned int"))
87 ;;  ("((*foo)[1])" (fixed-type "unsigned int"))
88 ;;  ("((*foo)[2])" (fixed-type "unsigned int"))
89
90 ;; may need to replace (typename "int32_t") with (fixed-type "int32_t")
91
92
93 ;; @deffn declr->ident declr => (ident "name")
94 ;; just match the declarator
95 ;; (init-declr <declr> [<initzer>])
96 ;; See also: declr->id-name in body.scm.
97 (define (declr->ident declr)
98   (sxml-match declr
99     ((init-declr ,declr . ,rest) (declr->ident declr))
100     ((comp-declr ,declr) (declr->ident declr))
101     ((param-declr ,declr) (declr->ident declr))
102     ((ident ,name) declr)
103     ((array-of ,dir-declr ,array-spec) (declr->ident dir-declr))
104     ((array-of ,dir-declr) (declr->ident dir-declr))
105     ((ptr-declr ,pointer ,dir-declr) (declr->ident dir-declr))
106     ((ftn-declr ,dir-declr ,rest ...) (declr->ident dir-declr))
107     ((scope ,declr) (declr->ident declr))
108     (,otherwise (throw 'util-error "c99/util2: unknown declarator: " declr))))
109
110 ;; @deffn unwrap-decl decl seed => seed
111 ;; This is a fold to break up multiple declarators.
112 ;; @example
113 ;; (decl (decl-spec-list ...) (init-declr-list (init-declr ...) ...))
114 ;; =>
115 ;; ((decl (decl-spec-list ...) (init-declr ...))
116 ;;  (decl (decl-spec-list ...) (init-declr ...))
117 ;;  ...)
118 ;; @end example
119 (define (unwrap-decl decl seed)
120   (cond
121    ((not (eqv? 'decl (car decl))) seed)
122    ((< (length decl) 3) seed)           ; this should catch struct-ref etc.
123    (else
124     (let* ((tag (sx-ref decl 0))
125            (attr (sx-attr decl))
126            (spec (sx-ref decl 1))       ; (decl-spec-list ...)
127            (id-l (sx-ref decl 2))       ; (init-declr-list ...)
128            (tail (sx-tail decl 3)))     ; comment
129       (let iter ((res seed) (idl (cdr id-l)))
130         (if (null? idl) res
131             (let* ((declr (sx-ref (car idl) 1))
132                    (ident (declr->ident declr))
133                    (name (cadr ident)))
134               (iter (cons (if attr
135                               (cons* tag attr spec (car idl) tail)
136                               (cons* tag spec (car idl) tail))
137                           res)
138                     (cdr idl)))))))))
139
140
141 ;; @deffn tree->udict tree => udict
142 ;; Turn a C parse tree into a assoc-list of names and definitions.
143 ;; This will unwrap @code{init-declr-list} into list of decls w/
144 ;; @code{init-declr}.
145 ;; BUG: need to add struct and union defn's: struct foo { int x; };
146 ;; how to deal with this
147 ;; lookup '(struct . "foo"), "struct foo", ???
148 ;; wanted "struct" -> dict but that is not great
149 ;; solution: match-decl => '(struct . "foo") then filter to generate
150 ;; ("struct" ("foo" . decl) ..)
151 ;; ("union" ("bar" . decl) ..)
152 (define (tree->udict tree)
153   (if (pair? tree)
154       ;;(reverse (fold match-decl '() (cdr tree)))
155       (fold match-decl '() (cdr tree))
156       '()))
157
158 ;; @deffn match-decl decl seed
159 ;; This procedure is intended to be used with @code{fold}.  It breaks up
160 ;; up the init-declr-list into individual init-declr items and associates
161 ;; with the identifier being declared.  So this is a fold iterator to
162 ;; provide a dictionary of declared names.
163 ;; @example
164 ;; (decl (decl-spec-list ...) (init-declr-list (init-declr ...) ...))
165 ;; @end example
166 ;; @noindent
167 ;; has been replaced by
168 ;; @example
169 ;; (decl (decl-spec-list ...) (init-declr ...))
170 ;; (decl (decl-spec-list ...) ...)
171 ;; @end example
172 ;; Here we generate a dictionary of all declared items:
173 ;; @example
174 ;; (let* ((sx0 (with-input-from-file src-file parse-c))
175 ;;        (sx1 (merge-inc-trees! sx0))
176 ;;        (name-dict (fold match-decl-1 '() (cdr sx1))))
177 ;; @end example
178 (define (match-decl decl seed)
179   (let* ((tag (sx-ref decl 0)) (attr (sx-attr decl)))
180     (case tag
181       ((decl)
182        (let* ((spec (sx-ref decl 1))    ; (decl-spec-list ...)
183               (tbd (sx-ref decl 2)))    ; (init-declr-list ...) OR ...
184          (cond
185           ((or (not tbd) (eqv? 'comment (sx-tag tbd)))
186            (display "ISSUE: some decls have no init-declr-list\n")
187            ;; no init-declr-list => struct or union def or param-decl
188            ;;(display "spec:\n") (pretty-print spec)
189            (sxml-match spec
190              ((decl-spec-list
191                (type-spec
192                 (struct-def (ident ,name) . ,rest2) . ,rest1))
193               (acons `(struct . ,name) decl seed))
194              ((decl-spec-list
195                (type-spec
196                 (union-def (ident ,name) . ,rest2) . ,rest1))
197               (acons `(union . ,name) decl seed))
198              (,otherwise
199               (display "otherwise:\n") (pretty-print (cdr spec))
200               seed)))
201           (else ;; decl with init-declr-list
202            (let* ((id-l tbd) (tail (sx-tail decl 3)))
203              (let iter ((res seed) (idl (cdr id-l)))
204                (if (null? idl) res
205                    (let* ((declr (sx-ref (car idl) 1))
206                           (ident (declr->ident declr))
207                           (name (cadr ident)))
208                      (iter
209                       (acons name
210                              (if attr
211                                  (cons* tag attr spec (car idl) tail)
212                                  (cons* tag spec (car idl) tail))
213                              res)
214                       (cdr idl))))))))))
215       (else seed))))
216
217 ;; @deffn match-comp-decl decl seed
218 ;; This will turn
219 ;; @example
220 ;; (comp-decl (decl-spec-list (type-spec "int"))
221 ;;            (comp-decl-list
222 ;;             (comp-declr (ident "a")) (comp-declr (ident "b"))))
223 ;; @end example
224 ;; @noindent
225 ;; into
226 ;; @example
227 ;; ("a" . (comp-decl (decl-spec-list ...) (comp-declr (ident "a"))))
228 ;; ("b" . (comp-decl (decl-spec-list ...) (comp-declr (ident "b"))))
229 ;; @end example
230 ;; @noindent
231 ;; This is coded to be used with fold-right in order to preserve order
232 ;; in @code{struct} and @code{union} field lists.
233 (define (match-comp-decl decl seed)
234   (if (not (eqv? 'comp-decl (car decl))) seed
235       (let* ((tag (sx-ref decl 0))
236              (attr (sx-attr decl))
237              (spec (sx-ref decl 1))     ; (type-spec ...)
238              (id-l (sx-ref decl 2))     ; (init-declr-list ...)
239              (tail (sx-tail decl 3)))   ; opt comment, different here
240         ;;(simple-format #t "1: ~S\n" id-l)
241         (let iter ((res seed) (idl (cdr id-l)))
242           (if (null? idl) res
243               (let* ((declr (sx-ref (car idl) 1))
244                      (ident (declr->ident declr))
245                      (name (cadr ident)))
246                 ;;(pretty-print `(comp-decl ,spec ,(car idl) . ,tail))
247                 (acons name
248                        (if attr
249                            (cons* tag attr spec (car idl) tail)
250                            (cons* tag spec (car idl) tail))
251                        (iter res (cdr idl)))))))))
252
253 ;; @deffn match-param-decl param-decl seed
254 ;; This will turn
255 ;; @example
256 ;; (param-decl (decl-spec-list (type-spec "int")) (param-declr (ident "a")))
257 ;; @end example
258 ;; @noindent
259 ;; into
260 ;; @example
261 ;; ("a" . (comp-decl (decl-spec-list ...) (comp-declr (ident "a"))))
262 ;; @end example
263 ;; @noindent
264 ;; This is coded to be used with fold-right in order to preserve order
265 ;; in @code{struct} and @code{union} field lists.
266 (define (match-param-decl decl seed)
267   (if (not (eqv? 'param-decl (car decl))) seed
268       (let* ((tag (sx-ref decl 0))
269              (attr (sx-attr decl))
270              (spec (sx-ref decl 1))     ; (type-spec ...)
271              (declr (sx-ref decl 2))    ; (param-declr ...)
272              (ident (declr->ident declr))
273              (name (cadr ident)))
274         (acons name decl seed))))
275         
276 ;; @deffn find-special udecl-alist seed => ..
277 ;; NOT DONE
278 ;; @example
279 ;; '((struct . ("foo" ...) ...)
280 ;;   (union . ("bar" ...) ...)
281 ;;   (enum . ("bar" ...) ...)
282 ;;   seed)
283 ;; @end example
284 (define (find-special udecl-alist seed)
285   (let iter ((struct '()) (union '()) (enum '()) (udal udecl-alist))
286     (if (null? udal) (cons* (cons 'struct struct)
287                           (cons 'union union)
288                           (cons 'enum enum)
289                           seed)
290         '())))
291
292 (define tmap-fmt
293   '(("char" "%hhd")
294     ("unsigned char" "%hhu")
295     ("short int" "%hd")
296     ("unsigned short int" "%hu")
297     ("int" "%d")
298     ("unsigned int" "%u")
299     ("long int" "%ld")
300     ("unsigned long int" "%lu")
301     ("long long int" "%lld")
302     ("unsigned long long int" "%llu")))
303
304 (define fixed-width-int-names
305   '("int8_t" "uint8_t" "int16_t" "uint16_t"
306     "int32_t" "uint32_t" "int64_t" "uint64_t"))
307
308 ;; @deffn typedef-decl? decl)
309 (define (typedef-decl? decl)
310   (sxml-match decl
311     ((decl (decl-spec-list (stor-spec (typedef)) . ,r1) . ,r2) #t)
312     (,otherwise #f)))
313
314 ;; @deffn splice-declarators orig-declr tdef-declr => 
315 ;; Splice the original declarator into the typedef declarator.
316 ;; This is a helper for @code{expand-*-typename-ref} procecures.
317 (define (splice-declarators orig-declr tdef-declr)
318   
319   (define (fD seed tree)                ; => (values seed tree)
320     (sxml-match tree
321       ((param-list . ,rest) (values tree '())) ; don't process
322       ((ident ,name) (values (reverse (cadr orig-declr)) '())) ; replace
323       (,otherwise (values '() tree))))
324
325   (define (fU seed kseed tree)
326     (let ((ktree (case (car kseed)
327                    ((param-list ident) kseed)
328                    (else (reverse kseed)))))
329       (if (null? seed) ktree (cons ktree seed))))
330
331   (define (fH seed tree)
332     (cons tree seed))
333
334   ;; This cons transfers the tag from orig-declr to the result.
335   (cons
336    (car orig-declr)                     ; init-declr or comp-declr
337    (cdr (foldts* fD fU fH '() tdef-declr)))) ; always init-declr
338
339
340 ;; @deffn repl-typespec decl-spec-list replacement
341 ;; This is a helper for expand-decl-typerefs
342 (define (repl-typespec decl-spec-list replacement)
343   (fold-right
344    (lambda (item seed)
345      (cond ((symbol? item) (cons item seed))
346            ((eqv? 'type-spec (car item))
347             (if (pair? (car replacement))
348                 (append replacement seed)
349                 (cons replacement seed)))
350            (else (cons item seed))))
351    '() decl-spec-list))
352
353 ;; @deffn expand-decl-typerefs udecl udecl-dict => udecl
354 ;; Given a declaration or component-declaration, expand all typename,
355 ;; struct, union and enum refs.
356 ;; @example
357 ;; typedef const int  (*foo_t)(int a, double b);
358 ;; extern    foo_t    fctns[2];
359 ;; @noindent
360 ;; This routine should create an init-declarator associated with
361 ;; @end example
362 ;; extern {const int}  (*{fctns[2]})(int a, double b);
363 ;; @end example
364 ;; @noindent
365 ;; Cool. Eh? (but is it done?)
366 (define* (expand-decl-typerefs udecl udecl-dict #:key (keep '()))
367   (display "FIXME: some decls have no init-declr-list\n")
368   ;; between adding (init-declr-list) to those or having predicate
369   ;; (has-init-declr? decl)
370   (let* ((tag (sx-tag udecl))           ; decl or comp-decl
371          (attr (sx-attr udecl))         ; (@ ...)
372          (specl (sx-ref udecl 1))       ; decl-spec-list
373          (declr (or (sx-find 'init-declr udecl)
374                     (sx-find 'comp-declr udecl)))
375          (tail (if declr (sx-tail udecl 3) (sx-tail udecl 2))) ; opt comment
376          (tspec (cadr (sx-find 'type-spec specl))))
377     ;;(simple-format #t "=D> ~S\n" decl-spec-list)
378     ;;(simple-format #t "init-declr: ~S\n" init-declr)
379     (case (car tspec)
380       ((typename)
381        (cond
382         ((member (cadr tspec) keep)
383          udecl)
384         #;((member (cadr tspec) fixed-width-int-names)
385          ;; Convert it to @code{fixed-type}.
386          (let* ((name (cadr tspec))
387                 (fixd-tspec `(type-spec (fixed-type ,name)))
388                 (fixd-specl (repl-typespec specl fixd-tspec))
389                 ;; TODO add attr
390                 (fixed-udecl (cons* tag fixd-specl declr tail)))
391            ;;(expand-decl-typerefs fixed-udecl udecl-dict))) ; not needed ?
392            fixed-udecl))
393         (else
394          ;; splice in the typedef
395          (let* ((name (sx-ref tspec 1))
396                 (decl (assoc-ref udecl-dict name)) ; decl for typename
397                 (tdef-specl (sx-ref decl 1)) ; decl-spec-list for typename
398                 (tdef-declr (sx-ref decl 2)) ; init-declr for typename
399                 ;; splice the typedef specifiers into target:
400                 (fixd-specl (repl-typespec specl (sx-tail tdef-specl 2)))
401                 (fixd-declr (splice-declarators declr tdef-declr))
402                 (fixed-udecl (cons* tag fixd-specl fixd-declr tail)))
403            (expand-decl-typerefs fixed-udecl udecl-dict #:keep keep)))))
404
405       ((struct-ref union-ref)
406        (simple-format (current-error-port)
407                       "+++ c99/util2: struct/union-ref: more to do?\n")
408        ;;(simple-format #t "\nstruct-ref:\n") (pretty-print udecl)
409        udecl)
410
411       ((struct-def union-def)
412        (let* ((ident (sx-find 'ident tspec))
413               (field-list (sx-find 'field-list tspec))
414               (orig-flds (cdr field-list))
415               (unit-flds (map cdr (fold-right match-comp-decl '() orig-flds)))
416               (fixd-flds (map
417                           (lambda (fld)
418                             (expand-decl-typerefs fld udecl-dict #:keep keep))
419                           unit-flds))
420               (fixd-tspec
421                (if #f ;;ident
422                    `(type-spec (struct-def ,ident (field-list ,@fixd-flds)))
423                    `(type-spec (struct-def (field-list ,@fixd-flds)))))
424               (fixd-specl (repl-typespec specl fixd-tspec)))
425          (if declr (cons* tag fixd-specl declr tail)
426              (cons* tag fixd-specl tail))))
427       
428       ((enum-def)
429        (let* ((enum-def-list (sx-find 'enum-def-list tspec))
430               (fixd-def-list (canize-enum-def-list enum-def-list))
431               (fixd-tspec `(type-spec (enum-def ,fixd-def-list)))
432               (fixd-specl (repl-typespec specl fixd-tspec))
433               (fixed-decl (cons* tag fixd-specl declr tail))) ;; !!!
434          fixed-decl))
435
436       ((enum-ref)
437        (simple-format (current-error-port) "chack: enum-ref NOT DONE\n")
438        udecl)
439
440       (else udecl))))
441   
442 ;; @deffn canize-enum-def-list
443 ;; Fill in constants for all entries of an enum list.
444 (define (canize-enum-def-list enum-def-list)
445   (define (get-used edl)
446     (let iter ((uzd '()) (edl edl))
447          (cond
448           ((null? edl) uzd)
449           ((assq-ref (cdar edl) 'p-expr) =>
450            (lambda (x)
451              (iter (cons (string->number (cadar x)) uzd) (cdr edl))))
452           (else
453            (iter uzd (cdr edl))))))
454   (let ((used (get-used (cdr enum-def-list))))
455     (let iter ((rez '()) (ix 0) (edl (cdr enum-def-list)))
456       (cond
457        ((null? edl) (cons (car enum-def-list) (reverse rez)))
458        ((assq-ref (cdar edl) 'p-expr)
459         (iter (cons (car edl) rez) ix (cdr edl)))
460        (else
461         (let* ((ix1 (let iter ((ix (1+ ix)))
462                       (if (memq ix used) (iter (1+ ix)) ix)))
463                (is1 (number->string ix1)))
464           (iter (cons (append (car edl) `((p-expr (fixed ,is1)))) rez)
465                 ix1 (cdr edl))))))))
466
467 ;; @deffn stripdown udecl decl-dict => decl
468 ;; 1) remove stor-spec
469 ;; 2) expand typenames
470 ;; @example
471 ;; typedef int *x_t;
472 ;; x_t a[10];
473 ;; (spec (typename x_t)) (init-declr (array-of 10 (ident a)))
474 ;; (spec (typedef) (fixed-type "int")) (init-declr (pointer) (ident "x_t"))
475 ;; =>
476 ;; [TO BE DOCUMENTED]
477 ;; @end example
478 (define* (stripdown udecl decl-dict #:key (keep '()))
479
480   ;;(define strip-list '(stor-spec type-qual comment))
481   (define strip-list '(stor-spec type-qual))
482
483   (define (fsD seed tree)
484     '())
485
486   (define (fsU seed kseed tree)
487     (if (memq (car tree) strip-list)
488         seed
489         (if (null? seed)
490             (reverse kseed)
491             (cons (reverse kseed) seed))))
492         
493   (define (fsH seed tree)
494     (cons tree seed))
495
496   (let* ((xdecl (expand-decl-typerefs udecl decl-dict #:keep keep))
497          (tag (sx-tag xdecl))
498          (attr (sx-attr xdecl))
499          (specl (sx-ref xdecl 1))
500          (declr (sx-ref xdecl 2))
501          (specl1 (foldts fsD fsU fsH '() specl)))
502     (list tag specl1 declr)))
503
504 ;; This one experimental for guile ffi.
505 (define* (stripdown-2 udecl decl-dict #:key (keep '()))
506
507   ;;(define strip-list '(stor-spec type-qual comment))
508   (define strip-list '(stor-spec type-qual))
509
510   (define (fsD seed tree)
511     '())
512
513   (define (fsU seed kseed tree)
514     (if (memq (car tree) strip-list)
515         seed
516         (if (null? seed)
517             (reverse kseed)
518             (cons (reverse kseed) seed))))
519         
520   (define (fsH seed tree)
521     (cons tree seed))
522
523   (let* ((speclt (sx-tail udecl 1)))    ; decl-spec-list tail
524     ;; don't expand typedefs, structure specs etc,
525     (cond
526      ((and (eqv? 'stor-spec (caar speclt))
527            (eqv? 'typedef (cadar speclt)))
528       udecl)
529      ;; lone struct ref
530      (else
531       (let* ((xdecl (expand-decl-typerefs udecl decl-dict #:keep keep))
532              (tag (sx-tag xdecl))
533              (attr (sx-attr xdecl))
534              (specl (sx-ref xdecl 1))
535              (declr (sx-ref xdecl 2))
536              (specl1 (foldts fsD fsU fsH '() specl)))
537         (list tag specl1 declr))))
538       ))
539
540
541 ;; @deffn udecl->mspec sudecl
542 ;; Turn a stripped-down unit-declaration into an m-spec.
543 ;; This assumes decls have been run through @code{stripdown}.
544 (define (udecl->mspec decl . rest)
545
546   (define (cnvt-array-size size-spec)
547     (simple-format #t "cnvt-array-size\n")
548     (with-output-to-string (lambda () (pretty-print-c99 size-spec))))
549
550   (define (unwrap-specl specl)
551     (let ((tspec (cadadr specl)))
552       ;;(simple-format #t "tspec:\n") (pretty-print tspec)
553       (sxml-match tspec
554         ((xxx-struct-def (field-list . ,rest))
555          `(struct-def ,@rest))
556         (,otherwise
557          tspec))))
558     
559   (define (unwrap-declr declr)
560     (sxml-match declr
561       ((ident ,name)
562        (list name))
563       ((init-declr ,item)
564        (unwrap-declr item))
565       ((comp-declr ,item)
566        (unwrap-declr item))
567       ((ptr-declr (pointer . ,r) ,dir-declr)
568        (cons '(pointer-to) (unwrap-declr dir-declr)))
569       ((array-of ,dir-declr ,size)
570        (cons `(array-of ,(cnvt-array-size size)) (unwrap-declr dir-declr)))
571       ((ftn-declr ,dir-declr ,params)
572        (cons '(function-returning) (unwrap-declr dir-declr)))
573       ((scope ,expr)
574        (unwrap-declr expr))
575       (,otherwise
576        (simple-format #t "unwrap-declr: OTHERWISE\n") (pretty-print otherwise)
577        ;; failed got: (array-of (ident "foo")) FROM const char foo[];
578        #f)))
579
580   (define (find-type-spec decl-spec-list)
581     (let iter ((tsl (cdr decl-spec-list)))
582       (if (eqv? 'type-spec (caar tsl)) (car tsl)
583           (iter (cdr tsl))))) 
584   
585   (let* ((decl-dict (if (pair? rest) (car rest) '()))
586          (specl (sx-ref decl 1))
587          (declr (sx-ref decl 2))
588          (comm (sx-ref decl 3))
589          (m-specl (unwrap-specl specl))
590          (m-declr (unwrap-declr declr))
591          (m-decl (reverse (cons m-specl m-declr))))
592     m-decl))
593
594 (define* (udecl->mspec/comm decl #:optional (dict '()) #:key (def-comm ""))
595   (let* ((comm (sx-ref decl 3))
596          (spec (udecl->mspec decl dict)))
597     (cons* (car spec) (or comm `(comment ,def-comm)) (cdr spec))))
598
599 ;; @deffn fix-fields flds => flds
600 ;; This will take a list of fields from a struct and remove lone comments.
601 ;; If a field following a lone comment has no code-comment, the lone comment
602 ;; will be used.  For example,
603 ;; @example
604 ;;   /* foo */
605 ;;   int x;
606 ;; @end example
607 ;; @noindent
608 ;; will be treated as if it was denereed
609 ;; @example
610 ;;   int x; /* foo */
611 ;; @end example
612 ;; @noindent
613 (define (fix-fields flds)
614   (let iter ((rz '()) (cl '()) (fl flds))
615     ;;(pretty-print fl)
616     (cond
617      ((null? fl) (reverse rz))
618      ((eqv? 'comment (caar fl))
619       (iter rz (cons (cadar fl) cl) (cdr fl)))
620      ((eqv? 'comp-decl (caar fl))
621       (if (eq? 4 (length (car fl)))
622           (iter (cons (car fl) rz) '() (cdr fl))         ; has comment
623           (let* ((cs (apply string-append (reverse cl))) ; add comment
624                  (fd (append (car fl) (list (list 'comment cs)))))
625             (iter (cons fd rz) '() (cdr fl)))))
626      (else
627       (error "bad field")))))
628
629 ;; --- last line ---