~ubuntu-branches/ubuntu/lucid/gauche-c-wrapper/lucid

« back to all changes in this revision

Viewing changes to lib/c-wrapper/c-parser.scm

  • Committer: Bazaar Package Importer
  • Author(s): NIIBE Yutaka
  • Date: 2008-04-07 09:15:03 UTC
  • Revision ID: james.westby@ubuntu.com-20080407091503-wu0h414koe95kj4i
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;; -*- coding: utf-8; mode: scheme -*-
 
2
;;
 
3
;; parser.scm
 
4
;; 
 
5
;;  Copyright (c) 2006 KOGURO, Naoki (naoki@koguro.net)
 
6
;; 
 
7
;;  Permission is hereby granted, free of charge, to any person 
 
8
;;  obtaining a copy of this software and associated 
 
9
;;  documentation files (the "Software"), to deal in the 
 
10
;;  Software without restriction, including without limitation 
 
11
;;  the rights to use, copy, modify, merge, publish, distribute, 
 
12
;;  sublicense, and/or sell copies of the Software, and to 
 
13
;;  permit persons to whom the Software is furnished to do so, 
 
14
;;  subject to the following conditions:
 
15
;; 
 
16
;;  The above copyright notice and this permission notice shall 
 
17
;;  be included in all copies or substantial portions of the 
 
18
;;  Software.
 
19
;; 
 
20
;;  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
 
21
;;  KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 
22
;;  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 
23
;;  PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 
 
24
;;  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
 
25
;;  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
 
26
;;  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 
27
;;  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
28
;; 
 
29
;;  $Id: $
 
30
 
 
31
(define-module c-wrapper.c-parser
 
32
  (use srfi-1)
 
33
  (use srfi-13)
 
34
  (use gauche.process)
 
35
  (use gauche.sequence)
 
36
  (use file.util)
 
37
  (use util.match)
 
38
  (use gauche.vport)
 
39
  (use gauche.uvector)
 
40
  (use gauche.regexp)
 
41
  (use gauche.config)
 
42
  (use util.queue)
 
43
  (use c-wrapper.config)
 
44
  (use c-wrapper.c-ffi)
 
45
 
 
46
  (export c-parse)
 
47
 
 
48
  (dynamic-load "c-parser")
 
49
  )
 
50
 
 
51
(select-module c-wrapper.c-parser)
 
52
 
 
53
(debug-print-width #f)
 
54
 
 
55
(define-macro (profiler-on)
 
56
  '(define-syntax profile
 
57
     (syntax-rules ()
 
58
       ((_ . body)
 
59
        (begin
 
60
          (profiler-start)
 
61
          (begin . body)
 
62
          (profiler-stop))))))
 
63
 
 
64
(define-macro (profiler-off)
 
65
  '(define-syntax profile
 
66
     (syntax-rules ()
 
67
       ((_ . body)
 
68
        (begin . body)))))
 
69
 
 
70
(profiler-off)
 
71
 
 
72
(define (warning fmt . args)
 
73
  (apply format
 
74
         (standard-error-port)
 
75
         (string-append "Warning: " fmt "~%")
 
76
         args))
 
77
 
 
78
(define (c-type->class-symbol type)
 
79
  (string->symbol (string-append "<" (symbol->string type) ">")))
 
80
 
 
81
;;
 
82
;;
 
83
;;
 
84
(define-class <parse-context> ()
 
85
  (
 
86
   ;; c-parse parameters
 
87
   (import-cond :init-value #f)
 
88
   (export? :init-value #f)
 
89
   (ignore-dlsym-check? :init-value #f)
 
90
   
 
91
   ;; parser states
 
92
   (side-effect? :init-value #f)
 
93
   (use-return? :init-value #f)
 
94
   (use-jump? :init-value #f)
 
95
   (use-iterator? :init-value #f)
 
96
   (typedefed-identifiers :init-form (let ((tbl (make-hash-table)))
 
97
                                       (for-each (cut hash-table-put! tbl <> #t)
 
98
                                                 '(__builtin_va_list
 
99
                                                   char
 
100
                                                   short
 
101
                                                   int
 
102
                                                   long
 
103
                                                   float
 
104
                                                   double
 
105
                                                   void
 
106
                                                   _Bool))
 
107
                                       tbl))
 
108
   (struct-pool :init-form (make-hash-table))
 
109
   (union-pool :init-form (make-hash-table))
 
110
   (value-pool :init-form (make-hash-table))
 
111
   (arg-pool :init-form (make-hash-table))
 
112
   (macro-queue :init-form (make-queue))
 
113
   (import-pool :init-form (make-hash-table 'equal?))
 
114
   (imported-pool :init-form (make-hash-table 'equal?))
 
115
   (code-queue :init-form (let ((tail-cons '(#f)))
 
116
                            (cons tail-cons tail-cons)))
 
117
 
 
118
   ;; lexer states
 
119
   (last-token :init-value #f)
 
120
   (lineno :init-value #f)
 
121
   (filename :init-value #f)
 
122
   (rest-chars :init-value '())
 
123
   (input-port :init-value #f)))
 
124
 
 
125
(define context #f)
 
126
 
 
127
(define-macro (define-context-accessor name)
 
128
  `(define-syntax ,name
 
129
     (syntax-rules ()
 
130
       ((_)
 
131
        (slot-ref context ',name))
 
132
       ((_ val)
 
133
        (slot-set! context ',name val)))))
 
134
 
 
135
(define-context-accessor side-effect?)
 
136
(define-context-accessor use-return?)
 
137
(define-context-accessor use-jump?)
 
138
(define-context-accessor use-iterator?)
 
139
(define-context-accessor import-cond)
 
140
(define-context-accessor export?)
 
141
(define-context-accessor last-token)
 
142
(define-context-accessor lineno)
 
143
(define-context-accessor filename)
 
144
(define-context-accessor rest-chars)
 
145
(define-context-accessor input-port)
 
146
(define-context-accessor typedefed-identifiers)
 
147
(define-context-accessor struct-pool)
 
148
(define-context-accessor union-pool)
 
149
(define-context-accessor value-pool)
 
150
(define-context-accessor arg-pool)
 
151
(define-context-accessor macro-queue)
 
152
(define-context-accessor import-pool)
 
153
(define-context-accessor ignore-dlsym-check?)
 
154
(define-context-accessor imported-pool)
 
155
 
 
156
(define (do-external-declaration decl-specs init-decl-list)
 
157
  (define (extern)
 
158
    (when init-decl-list
 
159
      (for-each (lambda (init-decl)
 
160
                  (emit-define-extern decl-specs init-decl))
 
161
                init-decl-list)))
 
162
  (match decl-specs
 
163
    ((('STRUCT tagname (elem-alist ...)))
 
164
     (emit-init-struct tagname elem-alist)
 
165
     (extern))
 
166
    ((('STRUCT tagname #f))
 
167
     (emit-alloc-struct tagname)
 
168
     (extern))
 
169
    ((('UNION tagname (elem-alist ...)))
 
170
     (emit-init-union tagname elem-alist)
 
171
     (extern))
 
172
    ((('UNION tagname #f))
 
173
     (emit-alloc-union tagname)
 
174
     (extern))
 
175
    ((('ENUM tagname (enum-alist ...)))
 
176
     (emit-define-enum tagname enum-alist)
 
177
     (extern))
 
178
    (('TYPEDEF type ...)
 
179
     (emit-typedef (make-var-list type init-decl-list)))
 
180
    (else
 
181
     (extern))))
 
182
 
 
183
(define (install-arg-pool init-decl-alist)
 
184
  (for-each (lambda (alist)
 
185
              (and-let* ((kv (assq 'identifier alist)))
 
186
                (hash-table-put! (arg-pool) (cadr kv) #t)))
 
187
            init-decl-alist))
 
188
 
 
189
(define (parameter-decl type-spec-list decl)
 
190
  (let ((v (make-var type-spec-list decl)))
 
191
    ;; ISO/IEC 9899:1999 6.7.5.3
 
192
    (match (type-of v)
 
193
      (('c-func ret-type arg-types)
 
194
       (set! (type-of v) `(make-c-func-ptr ,ret-type ,arg-types)))
 
195
      (('c-func-vaargs ret-type arg-types)
 
196
       (set! (type-of v) `(make-c-func-vaargs-ptr ,ret-type ,arg-types)))
 
197
      (else
 
198
       #t))
 
199
    (and-let* ((name (name-of v)))
 
200
      (hash-table-put! (arg-pool) name #t))
 
201
    v))
 
202
 
 
203
(define (declaration specifiers declarator-list)
 
204
  (install-arg-pool declarator-list)
 
205
  (cons specifiers declarator-list))
 
206
 
 
207
(define (decl-identifier v)
 
208
  (list (list 'identifier v)))
 
209
 
 
210
(define (decl-array v)
 
211
  (list (list 'array (and v (%INT v)))))
 
212
 
 
213
(define (decl-func args)
 
214
  (list (cons 'c-func args)))
 
215
 
 
216
(define (decl-func-vaargs args)
 
217
  (list (cons 'c-func-vaargs args)))
 
218
 
 
219
(define (decl-ptr)
 
220
  '((ptr)))
 
221
 
 
222
(define (decl-keyword selector . typename-list)
 
223
  (cons (list (string-append (x->string selector)
 
224
                             (if (null? typename-list) "" ":")))
 
225
        typename-list))
 
226
 
 
227
(define (decl-bitfield decl n)
 
228
  (if decl
 
229
      (cons (list 'bit-field n) decl)
 
230
      (decl-bitfield (decl-identifier (gensym "%")) n)))
 
231
 
 
232
(define (decl-enum identifier lst)
 
233
  (list 'ENUM (or identifier (gensym "%")) lst))
 
234
 
 
235
(define (decl-enumerator identifier expr)
 
236
  (cons identifier expr))
 
237
 
 
238
(define (decl-init-value v)
 
239
  (list 'init-value v))
 
240
 
 
241
(define (combine-decl-keyword decl1 . rest)
 
242
  (let-optionals* rest ((decl2 #f))
 
243
    (if decl2
 
244
        (cons (append (car decl1) (car decl2))
 
245
              (append (cdr decl1) (cdr decl2)))
 
246
        decl1)))
 
247
 
 
248
(define (decl-objc-method ret-type decl-arg)
 
249
  (list (car decl-arg) (cons ret-type (cdr decl-arg))))
 
250
 
 
251
(define (decl-struct-or-union struct-or-union identifier decl-list)
 
252
  (list struct-or-union (or identifier (gensym "%")) decl-list))
 
253
 
 
254
(define (var-id)
 
255
  (make-var '(id) '()))
 
256
 
 
257
(define (%INT v)
 
258
  (if (real? v)
 
259
      (x->integer v)
 
260
      `(cast <integer> ,v)))
 
261
 
 
262
(define (%REAL v)
 
263
  (if (real? v)
 
264
      v
 
265
      `(cast <real> ,v)))
 
266
 
 
267
(define (%SCM-CAST expr)
 
268
  (match expr
 
269
    ((? number? v)
 
270
     v)
 
271
    ((? string? v)
 
272
     v)
 
273
    (('begin (or (? number? v) (? string? v)))
 
274
     v)
 
275
    (('cast _ (? number? v))
 
276
     v)
 
277
    (else
 
278
     `(scm-cast ,expr))))
 
279
 
 
280
(define (%IDENTIFIER v)
 
281
  (if (registered-identifier? v) v #f))
 
282
 
 
283
(define-syntax define-maybe
 
284
  (syntax-rules ()
 
285
    ((_ (name . args) . body)
 
286
     (define (name . args)
 
287
       (if (and . args)
 
288
           (begin . body)
 
289
           #f)))))
 
290
 
 
291
(define-maybe (%MACRO-BODY body)
 
292
  (if (null? (cdr body))
 
293
      (%SCM-CAST (car body))
 
294
      (%SCM-CAST `(begin ,@body))))
 
295
 
 
296
(define-maybe (%FUNCTION-BODY body)
 
297
  `(call/cc (lambda (%return) ,body)))
 
298
 
 
299
(define-maybe (%OBJC-STRING v)
 
300
  `(@ ,v))
 
301
 
 
302
(define-maybe (%EXPR-IN-PARENS expr)
 
303
  (if (symbol? expr)
 
304
      `(identity ,expr)
 
305
      expr))
 
306
 
 
307
(define-maybe (%COMPOUND-STATEMENT statements)
 
308
  `(begin ,@statements))
 
309
 
 
310
(define-maybe (%COMPOUND-STATEMENT-WITH-DECL decl-list statements)
 
311
  (let ((var-list '())
 
312
        (init-list '()))
 
313
    (for-each (lambda (alist)
 
314
                (for-each (lambda (declarator)
 
315
                            (let* ((v (make-var (car alist)
 
316
                                                  declarator))
 
317
                                   (type (type-of v))
 
318
                                   (identifier (name-of v))
 
319
                                   (init-val (value-of v)))
 
320
                              ;; TODO: typedef in compound_statement is not supported
 
321
                              (push! var-list
 
322
                                     `(,identifier (make ,type)))
 
323
                              (when init-val
 
324
                                (push! init-list
 
325
                                       `(set! (ref ,identifier)
 
326
                                              ,init-val)))))
 
327
                          (cdr alist)))
 
328
              decl-list)
 
329
    `(let* ,(reverse var-list)
 
330
       ,@(reverse init-list)
 
331
       ,@statements)))
 
332
 
 
333
(define-maybe (%REF-ARRAY v index)
 
334
  `(ref ,v ,(%INT index)))
 
335
 
 
336
(define-maybe (%FUNCALL func names)
 
337
  (side-effect? #t)
 
338
  (cons (c-lookup-value func) names))
 
339
 
 
340
(define-maybe (%DOT-REF v name)
 
341
  `(raw-ref ,v ',name))
 
342
 
 
343
(define-maybe (%PTR-REF p name)
 
344
  `(raw-ref (deref ,p) ',name))
 
345
 
 
346
(define-maybe (%POST-INC v)
 
347
  (side-effect? #t)
 
348
  `(post++ ,v))
 
349
 
 
350
(define-maybe (%POST-DEC v)
 
351
  (side-effect? #t)
 
352
  `(post-- ,v))
 
353
 
 
354
(define-maybe (%LIST v)
 
355
  (list v))
 
356
 
 
357
(define-maybe (%ADD-LIST lst v)
 
358
  (append lst (list v)))
 
359
 
 
360
(define-maybe (%PRE-INC v)
 
361
  (side-effect? #t)
 
362
  `(pre++ ,v))
 
363
 
 
364
(define-maybe (%PRE-DEC v)
 
365
  (side-effect? #t)
 
366
  `(pre-- ,v))
 
367
 
 
368
(define-maybe (%UNARY op v)
 
369
  (case op
 
370
    ((+) v)
 
371
    ((-) (%SUB 0 v))
 
372
    ((!) (%IF v 0 1))
 
373
    ((~) (%BIT-NOT v))
 
374
    ((&) `(ptr ,v))
 
375
    ((*) `(deref ,v))
 
376
    (else #f)))
 
377
 
 
378
(define-maybe (%BIT-NOT v)
 
379
  (if (integer? v)
 
380
      (lognot v)
 
381
      `(lognot ,(%INT v))))
 
382
 
 
383
(define-maybe (%SIZEOF-EXPR v)
 
384
  `(c-sizeof ,v))
 
385
 
 
386
(define-maybe (%SIZEOF-TYPE v)
 
387
  `(c-sizeof ,(type-of v)))
 
388
 
 
389
(define-maybe (%CAST type-name expr)
 
390
  `(cast ,(type-of type-name) ,expr))
 
391
 
 
392
(define-maybe (%MUL expr1 expr2)
 
393
  (if (and (real? expr1) (real? expr2))
 
394
      (* expr1 expr2)
 
395
      `(* ,(%REAL expr1) ,(%REAL expr2))))
 
396
 
 
397
(define-maybe (%DIV expr1 expr2)
 
398
  (if (and (real? expr1) (real? expr2))
 
399
      (/ expr1 expr2)
 
400
      `(/ ,(%REAL expr1) ,(%REAL expr2))))
 
401
 
 
402
(define-maybe (%MOD expr1 expr2)
 
403
  (if (and (integer? expr1) (integer? expr2))
 
404
      (modulo expr1 expr2)
 
405
      `(modulo ,(%INT expr1) ,(%INT expr2))))
 
406
 
 
407
(define-maybe (%ADD expr1 expr2)
 
408
  (if (and (real? expr1) (real? expr2))
 
409
      (+ expr1 expr2)
 
410
      `(if (is-a? ,expr1 <c-ptr>)
 
411
           (c-ptr+ ,expr1 ,(%REAL expr2))
 
412
           (+ (cast <real> ,expr1) ,(%REAL expr2)))))
 
413
 
 
414
(define-maybe (%SUB expr1 expr2)
 
415
  (if (and (real? expr1) (real? expr2))
 
416
      (- expr1 expr2)
 
417
      `(if (is-a? ,expr1 <c-ptr>)
 
418
           (c-ptr- ,expr1 ,(%REAL expr2))
 
419
           (- (cast <real> ,expr1) ,(%REAL expr2)))))
 
420
 
 
421
(define-maybe (%SHIFT-LEFT expr1 expr2)
 
422
  (if (and (integer? expr1) (integer? expr2))
 
423
      (ash expr1 expr2)
 
424
      `(ash ,(%INT expr1) ,(%INT expr2))))
 
425
 
 
426
(define-maybe (%SHIFT-RIGHT expr1 expr2)
 
427
  (if (and (integer? expr1) (integer? expr2))
 
428
      (ash expr1 (- expr2))
 
429
      `(ash ,(%INT expr1) (- ,(%INT expr2)))))
 
430
 
 
431
(define-maybe (%LT expr1 expr2)
 
432
  (if (and (real? expr1) (real? expr2))
 
433
      (if (< expr1 expr2) 1 0)
 
434
      `(if (< ,(%REAL expr1) ,(%REAL expr2)) 1 0)))
 
435
 
 
436
(define-maybe (%GT expr1 expr2)
 
437
  (if (and (real? expr1) (real? expr2))
 
438
      (if (> expr1 expr2) 1 0)
 
439
      `(if (> ,(%REAL expr1) ,(%REAL expr2)) 1 0)))
 
440
 
 
441
(define-maybe (%LE expr1 expr2)
 
442
  (if (and (real? expr1) (real? expr2))
 
443
      (if (<= expr1 expr2) 1 0)
 
444
      `(if (<= ,(%REAL expr1) ,(%REAL expr2)) 1 0)))
 
445
 
 
446
(define-maybe (%GE expr1 expr2)
 
447
  (if (and (real? expr1) (real? expr2))
 
448
      (if (>= expr1 expr2) 1 0)
 
449
      `(if (>= ,(%REAL expr1) ,(%REAL expr2)) 1 0)))
 
450
 
 
451
(define-maybe (%EQ expr1 expr2)
 
452
  (if (and (real? expr1) (real? expr2))
 
453
      (if (eq? expr1 expr2) 1 0)
 
454
      `(if (equal? ,(%REAL expr1) ,(%REAL expr2)) 1 0)))
 
455
 
 
456
(define-maybe (%NE expr1 expr2)
 
457
  (if (and (real? expr1) (real? expr2))
 
458
      (if (eq? expr1 expr2) 0 1)
 
459
      `(if (equal? ,(%REAL expr1) ,(%REAL expr2)) 0 1)))
 
460
 
 
461
(define-maybe (%BIT-AND expr1 expr2)
 
462
  (if (and (integer? expr1) (integer? expr2))
 
463
      (logand expr1 expr2)
 
464
      `(logand ,(%INT expr1) ,(%INT expr2))))
 
465
 
 
466
(define-maybe (%BIT-XOR expr1 expr2)
 
467
  (if (and (integer? expr1) (integer? expr2))
 
468
      (logxor expr1 expr2)
 
469
      `(logxor ,(%INT expr1) ,(%INT expr2))))
 
470
 
 
471
(define-maybe (%BIT-OR expr1 expr2)
 
472
  (if (and (integer? expr1) (integer? expr2))
 
473
      (logior expr1 expr2)
 
474
      `(logior ,(%INT expr1) ,(%INT expr2))))
 
475
 
 
476
(define-maybe (%LOG-AND expr1 expr2)
 
477
  (let ((v (gensym "%")))
 
478
    `(let ((,v ,(%REAL expr1)))
 
479
       (if (eq? ,v 0) ,v ,expr2))))
 
480
 
 
481
(define-maybe (%LOG-OR expr1 expr2)
 
482
  (let ((v (gensym "%")))
 
483
    `(let ((,v ,(%REAL expr1)))
 
484
       (if (eq? ,v 0) ,expr2 ,v))))
 
485
 
 
486
(define-maybe (%IF test then else)
 
487
  `(if (eq? ,(%REAL test) 0) ,else ,then))
 
488
 
 
489
(define-maybe (%ASSIGN lhs rhs)
 
490
  (side-effect? #t)
 
491
  (match lhs
 
492
    ((? symbol? x)
 
493
     `(let ((%v ,rhs))
 
494
        (set! (ref ,x) %v)
 
495
        %v))
 
496
    (((or 'ref 'raw-ref) x ...)
 
497
     `(let ((%v ,rhs))
 
498
        (set! (ref ,@x) %v)
 
499
        %v))
 
500
    (('deref x)
 
501
     `(let ((%v ,rhs))
 
502
        (set! (deref ,x) %v)
 
503
        %v))
 
504
    (else
 
505
     #f)))
 
506
 
 
507
(define-maybe (%CONCAT-EXPR expr1 expr2)
 
508
  `(begin ,expr1 ,expr2))
 
509
 
 
510
(define-maybe (%FOR init test update body)
 
511
  (use-iterator? #t)
 
512
  `(call/cc (lambda (%break)
 
513
              ,init
 
514
              (let %continue ()
 
515
                ,(%IF test
 
516
                      `(begin
 
517
                         ,body
 
518
                         ,update
 
519
                         (%continue))
 
520
                      '(%break 0))))))
 
521
 
 
522
(define-maybe (%WHILE test statement)
 
523
  (use-iterator? #t)
 
524
  `(call/cc (lambda (%break)
 
525
              (let %continue ()
 
526
                ,(%IF test `(begin ,statement (%continue)) '(%break 0))))))
 
527
 
 
528
(define-maybe (%DO-WHILE test statement)
 
529
  (use-iterator? #t)
 
530
  `(call/cc (lambda (%break)
 
531
              (letrec ((%body (lambda () ,statement (%continue)))
 
532
                       (%continue (lambda ()
 
533
                                    ,(%IF test
 
534
                                          '(%body)
 
535
                                          '(%break 0)))))
 
536
                (%body)))))
 
537
 
 
538
(define (%CONTINUE)
 
539
  (use-jump? #t)
 
540
  '(%continue))
 
541
 
 
542
(define (%BREAK)
 
543
  (use-jump? #t)
 
544
  '(%break 0))
 
545
 
 
546
(define-maybe (%RETURN v)
 
547
  (use-return? #t)
 
548
  `(%return ,v))
 
549
 
 
550
(define-maybe (%QUOTE v)
 
551
  `(',v))
 
552
 
 
553
(define-maybe (%APPEND v1 v2)
 
554
  (append v1 v2))
 
555
 
 
556
(define-maybe (%KEYWORD-ARG selector expr)
 
557
  `(',selector ,expr))
 
558
 
 
559
(define-maybe (%KEYWORD-ARG-WITHOUT-SELECTOR expr)
 
560
  (list : expr))
 
561
 
 
562
(define-maybe (%OBJC-MESSAGE-EXPR receiver args)
 
563
  (side-effect? #t)
 
564
  `(,receiver ,@args))
 
565
 
 
566
(define-maybe (%SELECTOR selector)
 
567
  (side-effect? #t)
 
568
  `(@selector ,selector))
 
569
 
 
570
;;
 
571
 
 
572
(define (lexer-init port)
 
573
  (rest-chars '())
 
574
  (last-token #f)
 
575
  (input-port port))
 
576
 
 
577
(define (clear-arg-pool)
 
578
  (arg-pool (make-hash-table)))
 
579
 
 
580
(define (typedefed? symbol)
 
581
  (hash-table-exists? (typedefed-identifiers) symbol))
 
582
 
 
583
(define (install-type symbol)
 
584
  (hash-table-put! (typedefed-identifiers) symbol #t))
 
585
 
 
586
;;
 
587
 
 
588
(load "c-wrapper/c-lex")
 
589
(load "c-wrapper/c-grammar.yy")
 
590
 
 
591
(define (enqueue-code obj write?)
 
592
  (let ((new-tail (list (cons obj write?)))
 
593
        (queue (slot-ref context 'code-queue)))
 
594
    (set-cdr! (cdr queue) new-tail)
 
595
    (set-cdr! queue new-tail)
 
596
    (car new-tail)))
 
597
 
 
598
(define (code-queue->list)
 
599
  (cdar (slot-ref context 'code-queue)))
 
600
 
 
601
(define (register-identifier name value)
 
602
  (let ((pair (or (hash-table-get (value-pool) name #f)
 
603
                  (cons #f #f))))
 
604
    (set-car! pair value)
 
605
    (hash-table-put! (value-pool) name pair))
 
606
  value)
 
607
 
 
608
(define (c-lookup-value v)
 
609
  (match v
 
610
    (('identity (? symbol? name))
 
611
     (hash-table-get (value-pool) name #f))
 
612
    (else
 
613
     v)))
 
614
 
 
615
(define (register-macro name)
 
616
  (let ((pair (or (hash-table-get (value-pool) name #f)
 
617
                (cons #f #f))))
 
618
    (set-cdr! pair #t)
 
619
    (hash-table-put! (value-pool) name pair)))
 
620
 
 
621
(define (registered-identifier? name)
 
622
  (or (hash-table-exists? (value-pool) name)
 
623
      (hash-table-exists? (arg-pool) name)))
 
624
 
 
625
(define (enqueue-import-pool name data)
 
626
  (hash-table-update! (import-pool) name
 
627
                      (lambda (elem)
 
628
                        (append elem (list data)))
 
629
                      '()))
 
630
 
 
631
(define (dequeue-import-pool name)
 
632
  (let ((result #f))
 
633
    (hash-table-update! (import-pool) name
 
634
                        (lambda (elem)
 
635
                          (if (null? elem)
 
636
                              elem
 
637
                              (begin
 
638
                                (set! result (car elem))
 
639
                                (cdr elem))))
 
640
                        '())
 
641
    result))
 
642
 
 
643
(define (imp-sym v)
 
644
  (do ((data (dequeue-import-pool v) (dequeue-import-pool v)))
 
645
      ((not data))
 
646
    (traverse (cdr data))
 
647
    (set-cdr! (car data) #t)
 
648
    (when (and (export?) v)
 
649
      (enqueue-code `(export ,v) #t))
 
650
    (hash-table-put! (imported-pool) v #t)))
 
651
 
 
652
(define (traverse v)
 
653
  (cond
 
654
   ((null? v)
 
655
    #f)
 
656
   ((list? v)
 
657
    (if (memq (car v) '(c-struct c-union c-enum))
 
658
        (imp-sym v)
 
659
        (map traverse v)))
 
660
   (else
 
661
    (imp-sym v))))
 
662
 
 
663
(define (emit-definition name define-list . rest)
 
664
  (let-optionals* rest ((dependent-symbols define-list))
 
665
    (if (import-cond)
 
666
        (let ((pair (enqueue-code define-list #f)))
 
667
          (enqueue-import-pool name (cons pair dependent-symbols))
 
668
          (when (or (hash-table-exists? (imported-pool) name)
 
669
                    (need-import? name))
 
670
            (imp-sym name)))
 
671
        (begin
 
672
          (enqueue-code define-list #t)
 
673
          (when (and (export?) name)
 
674
            (enqueue-code `(export ,name) #t))))))
 
675
 
 
676
(define-method need-import? (name)
 
677
  (if name
 
678
      (need-import? name (import-cond))
 
679
      #t))
 
680
 
 
681
(define-method need-import? (name (re <regexp>))
 
682
  (re (x->string name)))
 
683
 
 
684
(define-method need-import? (name (col <collection>))
 
685
  (find (cut need-import? name <>) col))
 
686
 
 
687
(define-method need-import? (name (sym <symbol>))
 
688
  (eq? name sym))
 
689
 
 
690
(define-method need-import? (name (str <string>))
 
691
  (need-import? name (string->symbol str)))
 
692
 
 
693
(define-method need-import? (name (proc <procedure>))
 
694
  (apply proc (list (filename) name)))
 
695
 
 
696
(define (make-var type-spec-list qualifiers)
 
697
  (receive (typedef-list ts-list) (partition (cut eq? 'TYPEDEF <>) type-spec-list)
 
698
    (receive (type identifier) (qualified-type (typespec->c-type ts-list)
 
699
                                               qualifiers)
 
700
      (vector identifier
 
701
              type
 
702
              (or (and-let* ((kv (assq 'init-value qualifiers)))
 
703
                                 (cadr kv))
 
704
                               #f)
 
705
              (not (null? typedef-list))))))
 
706
                     
 
707
(define (name-of v)
 
708
  (vector-ref v 0))
 
709
 
 
710
(define type-of (getter-with-setter (lambda (v)
 
711
                                      (vector-ref v 1))
 
712
 
 
713
                                    (lambda (v type)
 
714
                                      (vector-set! v 1 type))))
 
715
 
 
716
(define (value-of v)
 
717
  (vector-ref v 2))
 
718
 
 
719
(define (typedef? v)
 
720
  (vector-ref v 3))
 
721
 
 
722
(define (make-var-list type-spec-list qualifiers-list)
 
723
  (map (cut make-var type-spec-list <>) qualifiers-list))
 
724
 
 
725
(define (qualified-type c-type qualifiers)
 
726
  (let loop ((ret-type c-type)
 
727
             (identifier #f)
 
728
             (rest qualifiers))
 
729
    (match rest
 
730
      (()
 
731
       (values ret-type identifier))
 
732
      ((('ptr) ('c-func args ...) x ...)
 
733
       (values `(c-func-ptr ,(receive (ret-type _) (qualified-type c-type x)
 
734
                                    ret-type)
 
735
                                 ,`(list ,@(map (lambda (v)
 
736
                                                  `(list ',(name-of v)
 
737
                                                         ,(type-of v)))
 
738
                                                args)))
 
739
               identifier))
 
740
      ((('ptr) ('c-func-vaargs args ...) x ...)
 
741
       (values `(c-func-vaargs-ptr ,(receive (ret-type _)
 
742
                                             (qualified-type c-type x)
 
743
                                           ret-type)
 
744
                                        ,`(list ,@(map (lambda (v)
 
745
                                                         `(list ',(name-of v)
 
746
                                                                ,(type-of v)))
 
747
                                                       args)))
 
748
               identifier))
 
749
      ((('c-func args ...) x ...)
 
750
       (values `(c-func ,(receive (ret-type _) (qualified-type c-type x)
 
751
                           ret-type)
 
752
                        ,`(list ,@(map (lambda (v)
 
753
                                         `(list ',(name-of v)
 
754
                                                ,(type-of v)))
 
755
                                       args)))
 
756
               identifier))
 
757
      ((('c-func-vaargs args ...) x ...)
 
758
       (values `(c-func-vaargs ,(receive (ret-type _) (qualified-type c-type x)
 
759
                                ret-type)
 
760
                             ,`(list ,@(map (lambda (v)
 
761
                                              `(list ',(name-of v)
 
762
                                                     ,(type-of v)))
 
763
                                            args)))
 
764
               identifier))
 
765
      ((('ptr) x ...)
 
766
       (values `(ptr ,(receive (ret-type _) (qualified-type c-type x)
 
767
                        ret-type))
 
768
               identifier))
 
769
      ((('array n) x ...)
 
770
       (values `(c-array ,(receive (ret-type _) (qualified-type c-type x)
 
771
                            ret-type)
 
772
                         ,n)
 
773
               identifier))
 
774
      ((('bit-field n) x ...)
 
775
       (loop `(c-bit-field ,ret-type ,n) identifier x))
 
776
      ((('init-value n) x ...)
 
777
       (loop ret-type identifier x))
 
778
      ((('identifier name) x ...)
 
779
       (loop ret-type name x)))))
 
780
 
 
781
(define (typespec->c-type type)
 
782
  (match type
 
783
    (('char) '<c-char>)
 
784
    (('SIGNED 'char) '<c-char>)
 
785
    (('UNSIGNED 'char) '<c-uchar>)
 
786
    (('short) '<c-short>)
 
787
    (('short 'int) '<c-short>)
 
788
    (('SIGNED 'short) '<c-short>)
 
789
    (('SIGNED 'short 'int) '<c-short>)
 
790
    (('UNSIGNED 'short) '<c-ushort>)
 
791
    (('UNSIGNED 'short 'int) '<c-ushort>)
 
792
    (('int) '<c-int>)
 
793
    (('SIGNED 'int) '<c-int>)
 
794
    (('SIGNED) '<c-int>)
 
795
    (('UNSIGNED 'int) '<c-uint>)
 
796
    (('UNSIGNED) '<c-uint>)
 
797
    (('long) '<c-long>)
 
798
    (('long 'int) '<c-long>)
 
799
    (('SIGNED 'long) '<c-long>)
 
800
    (('SIGNED 'long 'int) '<c-long>)
 
801
    (('long 'SIGNED 'int) '<c-long>)
 
802
    (('UNSIGNED 'long) '<c-ulong>)
 
803
    (('UNSIGNED 'long 'int) '<c-ulong>)
 
804
    (('long 'UNSIGNED 'int) '<c-ulong>)
 
805
    (('long 'long) '<c-longlong>)
 
806
    (('long 'long 'int) '<c-longlong>)
 
807
    (('SIGNED 'long 'long) '<c-longlong>)
 
808
    (('SIGNED 'long 'long 'int) '<c-longlong>)
 
809
    (('long 'long 'SIGNED 'int) '<c-longlong>)
 
810
    (('UNSIGNED 'long 'long) '<c-ulonglong>)
 
811
    (('UNSIGNED 'long 'long 'int) '<c-ulonglong>)
 
812
    (('long 'long 'UNSIGNED 'int) '<c-ulonglong>)
 
813
    (('float) '<c-float>)
 
814
    (('double) '<c-double>)
 
815
    (('long 'double) '<c-longdouble>)
 
816
    (('void) '<c-void>)
 
817
    (('_Bool) '<c-int>)
 
818
    (('__builtin_va_list) '(ptr <c-void>))
 
819
    ((('STRUCT tagname (elem-alist ...)))
 
820
     (emit-init-struct tagname elem-alist)
 
821
     `(c-struct ',tagname))
 
822
    ((('STRUCT tagname #f))
 
823
     (emit-alloc-struct tagname)
 
824
     `(c-struct ',tagname))
 
825
    ((('UNION tagname (elem-alist ...)))
 
826
     (emit-init-union tagname elem-alist)
 
827
     `(c-union ',tagname))
 
828
    ((('UNION tagname #f))
 
829
     (emit-alloc-union tagname)
 
830
     `(c-union ',tagname))
 
831
    ((('ENUM tagname (enum-alist ...)))
 
832
     (emit-define-enum tagname enum-alist)
 
833
     `(c-enum ',tagname))
 
834
    (((? symbol? x))
 
835
     (c-type->class-symbol x))))
 
836
 
 
837
(define (make-member-alist elem-list)
 
838
  (map (lambda (elem)
 
839
         `(cons ',(name-of elem) ,(type-of elem)))
 
840
       elem-list))
 
841
 
 
842
(define (emit-alloc-struct tagname)
 
843
  (unless (hash-table-exists? (struct-pool) tagname)
 
844
    (hash-table-put! (struct-pool) tagname #t)
 
845
    (emit-definition `(c-struct ',tagname) `(define-c-struct ,tagname))))
 
846
 
 
847
(define (emit-init-struct tagname member-list)
 
848
  (emit-alloc-struct tagname)
 
849
  (emit-definition `(c-struct ',tagname)
 
850
                 `(init-c-struct! (c-struct ',tagname)
 
851
                                  (list ,@(make-member-alist member-list)))))
 
852
 
 
853
(define (emit-alloc-union tagname)
 
854
  (unless (hash-table-exists? (union-pool) tagname)
 
855
    (hash-table-put! (union-pool) tagname #t)
 
856
    (emit-definition `(c-union ',tagname) `(define-c-union ,tagname))))
 
857
 
 
858
(define (emit-init-union tagname member-list)
 
859
  (emit-alloc-union tagname)
 
860
  (emit-definition `(c-union ',tagname)
 
861
                 `(init-c-union! (c-union ',tagname)
 
862
                                 (list ,@(make-member-alist member-list)))))
 
863
 
 
864
(define (emit-define-enum tagname enum-alist)
 
865
  (fold (lambda (p prev)
 
866
          (let ((v (or (cdr p)
 
867
                       (if (number? prev)
 
868
                           (+ prev 1)
 
869
                           `(+ (scm-cast ,prev) 1)))))
 
870
            (register-identifier (car p) v)
 
871
            (emit-definition (car p) `((with-module c-wrapper define-enum) ,(car p) ,v))
 
872
            v))
 
873
        -1
 
874
        enum-alist)
 
875
  (emit-definition `(c-enum ',tagname)
 
876
                 `(init-c-enum! (c-enum ',tagname)
 
877
                                (list ,@(map car enum-alist)))))
 
878
 
 
879
(define (emit-typedef var-list)
 
880
  (for-each (lambda (v)
 
881
              (let ((obj (match (type-of v)
 
882
                           (('c-func-ptr ret-type ('list ('list _ arg-type) 
 
883
                                                         ...))
 
884
                            `(c-func-ptr ,ret-type (list ,@arg-type)))
 
885
                           (('c-func-vaargs-ptr ret-type 
 
886
                                                     ('list ('list _ arg-type) 
 
887
                                                            ...))
 
888
                            `(c-func-ptr ,ret-type (list ,@arg-type)))
 
889
                           (('c-func ret-type ('list ('list _ arg-type) 
 
890
                                                   ...))
 
891
                            `(c-func ,ret-type (list ,@arg-type)))
 
892
                           (('c-func-vaargs ret-type ('list ('list _ arg-type) 
 
893
                                                          ...))
 
894
                            `(c-func ,ret-type (list ,@arg-type)))
 
895
                           (else
 
896
                            (type-of v)))))
 
897
                (let ((sym (c-type->class-symbol (name-of v))))
 
898
                  (emit-definition sym `(define ,sym ,obj)))
 
899
                (install-type (name-of v))))
 
900
            var-list))
 
901
 
 
902
(define (emit-define-inline type declarator function-body)
 
903
  (define (make-bindings name-list type-list)
 
904
    (let loop ((bindings '())
 
905
               (i 0)
 
906
               (name-rest name-list)
 
907
               (type-rest type-list))
 
908
      (if (null? name-rest)
 
909
          (reverse bindings)
 
910
          (loop (cons `(,(car name-rest) (cast ,(car type-rest)
 
911
                                               (list-ref %args ,i)))
 
912
                      bindings)
 
913
                (+ i 1)
 
914
                (cdr name-rest)
 
915
                (cdr type-rest)))))
 
916
  (receive (c-type identifier)
 
917
      (qualified-type (typespec->c-type type) declarator)
 
918
    (match c-type
 
919
      (('c-func-ptr ret-type ('list ('list ('quote names) types) ...))
 
920
       (warning "'~a' is ignored. It appears in a function definition, but it is a pointer of a function in reality." identifier))
 
921
      (('c-func ret-type ('list ('list ('quote names) types) ...))
 
922
       (register-identifier identifier
 
923
                            `(lambda args
 
924
                               (apply ,identifier args)))
 
925
       (emit-definition identifier
 
926
                        `((with-module c-wrapper define-inline-cfunc)
 
927
                          ,identifier ,ret-type ,names ,types
 
928
                          ,(or function-body
 
929
                               `(errorf "~a is not supported. Try cwcompile if you want to use." ,identifier)))))
 
930
      (((? (lambda (v) (memq v '(c-func-vaargs-ptr func-vaargs))) v)
 
931
        ret-type ('list ('list ('quote names) types) ...))
 
932
       (warning "The inline function '~a' is ignored, because it gets variable arguments" identifier))
 
933
      (else
 
934
       (warning "'~a' is ignored, it is not a function." identifier)))))
 
935
 
 
936
(define (emit-define-extern type init-decl)
 
937
  (receive (c-type identifier)
 
938
      (qualified-type (typespec->c-type type) init-decl)
 
939
    (when (or (ignore-dlsym-check?)
 
940
              (c-lookup-symbol identifier))
 
941
      (and-let* ((obj (match c-type
 
942
                        (('c-func ret-type ('list ('list _ arg-type) ...))
 
943
                         `(make-c-func ',identifier
 
944
                                       ,ret-type
 
945
                                       (list ,@arg-type)))
 
946
                        (('c-func-vaargs ret-type ('list ('list _ arg-type) ...))
 
947
                         `(make-c-func-vaargs ',identifier
 
948
                                              ,ret-type
 
949
                                              (list ,@arg-type)))
 
950
                        (else
 
951
                         `(make-c-var ',identifier ,c-type)))))
 
952
        (register-identifier identifier obj)
 
953
        (emit-definition identifier `(define ,identifier ,obj))))))
 
954
 
 
955
(define (emit-define-objc-class classname-list)
 
956
  (for-each (lambda (classname)
 
957
              (when classname
 
958
                (install-type classname)
 
959
                (let ((sym (c-type->class-symbol classname)))
 
960
                  (emit-definition sym `(define ,sym (c-struct 'objc_object))))
 
961
                (emit-definition classname
 
962
                               `(define ,classname
 
963
                                  (objc-lookup-class ',classname)))))
 
964
            classname-list))
 
965
 
 
966
(define (emit-objc-method keywords type-list)
 
967
  (let ((name (apply string-append keywords)))
 
968
    (emit-definition #f
 
969
                   `(objc-register-method ,name
 
970
                                          (list ,@(map type-of type-list))))))
 
971
 
 
972
(define (emit-define-cmacro name body)
 
973
  (emit-definition name `(define ,name ,body)))
 
974
 
 
975
(define (emit-define-cfunclike-macro name args body)
 
976
  (emit-definition name
 
977
                   `((with-module c-wrapper define-cfunclike-macro)
 
978
                     ,name ,args ,body)))
 
979
 
 
980
(define (macro-parse include-dirs headers options)
 
981
  (call-with-process-io (cpp-command include-dirs headers options #f)
 
982
    (lambda (in out)
 
983
      (profile
 
984
       (let ((identifier-queue (make-queue)))
 
985
         (define (send-macro)
 
986
           (for-each (lambda (macro-def)
 
987
                       (display (car macro-def) out)
 
988
                       (newline out)
 
989
                       (enqueue! identifier-queue (cdr macro-def)))
 
990
                     (queue->list (macro-queue)))
 
991
           (close-output-port out)
 
992
           ;; skip the first line '# 1 "<stdin>"'
 
993
           (read-line in #t)
 
994
           (skip (read-line in #t)))
 
995
         (define (skip line)
 
996
           (cond
 
997
            ((eof-object? line)
 
998
             #f)
 
999
            ((eq? (string-size line) 0)
 
1000
             (skip (read-line in #t)))
 
1001
            ((not (eq? (string-byte-ref line 0) 35)) ;; '#' != 35 (ASCII)
 
1002
             (skip (read-line in #t)))
 
1003
            ((string-incomplete? line)
 
1004
             (skip (read-line in #t)))
 
1005
            ((string=? line "# 1 \"<stdin>\"")
 
1006
             (parse-macro (read-line in #t)))
 
1007
            (else
 
1008
             (skip (read-line in #t)))))
 
1009
         (define (parse-macro line)
 
1010
           (cond
 
1011
            ((eof-object? line)
 
1012
             #f)
 
1013
            ((queue-empty? identifier-queue)
 
1014
             (error "[bug] lost macro body"))
 
1015
            (else
 
1016
             (let ((pos&name&args (dequeue! identifier-queue)))
 
1017
               (filename (caar pos&name&args))
 
1018
               (lineno (cdar pos&name&args))
 
1019
               (parse-macro-body (string->symbol (cadr pos&name&args))
 
1020
                                 (cddr pos&name&args)
 
1021
                                 line))
 
1022
             (parse-macro (read-line in #t)))))
 
1023
         (send-macro))))))
 
1024
 
 
1025
(define (parse-macro-body name args body-str)
 
1026
  (side-effect? #f)
 
1027
  (use-return? #f)
 
1028
  (use-iterator? #f)
 
1029
  (use-jump? #f)
 
1030
  (and-let* ((body (call/cc (lambda (break)
 
1031
                              (clear-arg-pool)
 
1032
                              (when args
 
1033
                                (for-each (lambda (arg)
 
1034
                                            (hash-table-put! (arg-pool) arg #t))
 
1035
                                          args))
 
1036
                              (if body-str
 
1037
                                  (with-input-from-string (string-append body-str
 
1038
                                                                         ";\n")
 
1039
                                    (lambda ()
 
1040
                                      (lexer-init (current-input-port))
 
1041
                                      (let ((first? #t))
 
1042
                                        (c-grammar (lambda ()
 
1043
                                                     (cond
 
1044
                                                      (first?
 
1045
                                                       (set! first? #f)
 
1046
                                                       'START_MACRO)
 
1047
                                                      (else
 
1048
                                                       (c-scan))))
 
1049
                                                   (lambda (msg . _)
 
1050
                                                     (break #f))))))
 
1051
                                  #f)))))
 
1052
    (cond
 
1053
     ((or (and (not (use-iterator?)) (use-jump?))
 
1054
          (use-return?))
 
1055
      #f)
 
1056
     ((and (not args) (not (side-effect?)))
 
1057
      (register-identifier name body)
 
1058
      (emit-define-cmacro name body))
 
1059
     (args
 
1060
      (register-macro name)
 
1061
      (emit-define-cfunclike-macro name args body))
 
1062
     (else
 
1063
      #f))))
 
1064
 
 
1065
;; FIXME!!
 
1066
;; In Linux, /usr/include/sys/types.h uses __attribute__ for these type definitions, 
 
1067
;; but c-wrapper ignores __attribute__.
 
1068
(define (linux?)
 
1069
  (not (not (#/-linux-/ (gauche-config "--arch")))))
 
1070
      
 
1071
(define (cpp-command include-dirs headers options . rest)
 
1072
  (let-optionals* rest ((show-define? #t))
 
1073
    (string-join (append (list GCC "'-D__attribute__(x)=' -E")
 
1074
                         (if (linux?)
 
1075
                             '("-D__int8_t_defined")
 
1076
                             ())
 
1077
                         (if show-define? 
 
1078
                             '("-dD")
 
1079
                             '())
 
1080
                         options
 
1081
                         (map (cut format "-I~a" <>) include-dirs)
 
1082
                         (map (cut format "-include ~a" <>) headers)
 
1083
                         (list "-"))
 
1084
                 " ")))
 
1085
 
 
1086
(define (install-predefined-types)
 
1087
  (when (linux?)
 
1088
    (filename "/usr/include/sys/types.h")
 
1089
    (for-each (lambda (pair)
 
1090
                (emit-typedef (make-var-list (car pair)
 
1091
                                             (%LIST (decl-identifier (cdr pair))))))
 
1092
              '(((SIGNED char) . int8_t)
 
1093
                ((UNSIGNED char) . u_int8_t)
 
1094
                ((SIGNED short) . int16_t)
 
1095
                ((UNSIGNED short) . u_int16_t)
 
1096
                ((SIGNED int) . int32_t)
 
1097
                ((UNSIGNED int) . u_int32_t)
 
1098
                ((SIGNED long long) . int64_t)
 
1099
                ((UNSIGNED long long) . u_int64_t)))))
 
1100
 
 
1101
(define (c-parse include-dirs headers options
 
1102
                 import-cond-arg export?-arg ignore-dlsym-check?-arg)
 
1103
  (set! context (make <parse-context>))
 
1104
  (import-cond import-cond-arg)
 
1105
  (export? export?-arg)
 
1106
  (ignore-dlsym-check? ignore-dlsym-check?-arg)
 
1107
  (call-with-output-string
 
1108
    (lambda (wrapper-out)
 
1109
      (call-with-process-io (cpp-command include-dirs headers options)
 
1110
        (lambda (in out)
 
1111
          (profile
 
1112
           (close-output-port out)
 
1113
           (with-input-from-port in
 
1114
             (lambda ()
 
1115
               (lexer-init in)
 
1116
               (install-predefined-types)
 
1117
               (c-grammar c-scan (lambda (msg . args)
 
1118
                                   (errorf "~a:~a: ~a ~a (last token: ~s)"
 
1119
                                           (filename)
 
1120
                                           (lineno)
 
1121
                                           msg
 
1122
                                           (if (null? args) "" args)
 
1123
                                           (last-token)))))))))
 
1124
      (macro-parse include-dirs headers options)
 
1125
      (when (export?)
 
1126
        (enqueue-code '(export-all) #t))
 
1127
      (for-each (lambda (elem)
 
1128
                  (when (cdr elem)
 
1129
                    (write (car elem) wrapper-out)))
 
1130
                (code-queue->list))
 
1131
      (set! context #f))))
 
1132
 
 
1133
(provide "c-wrapper/c-parser")
 
1134