mescc: Refactor decl.
[mes.git] / module / language / c99 / compiler.mes
index 3c9e29861db9a2c7238e932a2f404bd718303dc8..4850b3107e9c7ba62ccdb0fd764b7a7dc176de24 100644 (file)
      (type->size info type))
     ((struct-ref (ident ,type))
      (type->size info `("struct" ,type)))
+    (void 4)
+    ((void) 4)
     (_ (let ((type (get-type (.types info) o)))
          (if type (type:size type)
              (error "type->size: unsupported: " o))))))
   (pmatch o
     ((fixed-type ,type) type)
     ((struct-ref (ident ,name)) (list "struct" name))
+    ((struct-def (ident ,name) . ,fields) (list "struct" name))
     ((decl (decl-spec-list (type-spec (struct-ref (ident ,name))))) ;; "scm"
      (list "struct" name)) ;; FIXME
     ((typename ,name) name)
     (,name name)
     (_ (error "decl->type: unsupported: " o))))
 
-(define (expr->global globals)
-  (lambda (o)
-    (pmatch o
-      ((p-expr (string ,string))
-       (let ((g `(#:string ,string)))
-         (or (assoc g globals)
-             (string->global string))))
-      ;;((p-expr (fixed ,value)) (int->global (cstring->number value)))
-      (_ #f))))
-
-(define (initzer->global globals)
-  (lambda (o)
-    (pmatch o
-      ((initzer ,initzer) ((expr->global globals) initzer))
-      (_ #f))))
-
 (define (byte->hex.m1 o)
   (string-drop o 2))
 
 (define (local? o) ;; formals < 0, locals > 0
   (positive? (local:id o)))
 
+(define (ptr-declr->pointer o)
+  (pmatch o
+    ((pointer) 1)
+    ((pointer (pointer)) 2)
+    (_ (error "ptr-declr->pointer unsupported: " o))))
+
+(define (init-declr->name o)
+  (pmatch o
+    ((ident ,name) name)
+    ((ptr-declr ,pointer (ident ,name)) name)
+    (_ (error "init-declr->name unsupported: " o))))
+
+(define (init-declr->pointer o)
+  (pmatch o
+    ((ident ,name) 0)
+    ((ptr-declr ,pointer (ident ,name)) (ptr-declr->pointer pointer))
+    (_ (error "init-declr->pointer unsupported: " o))))
+
 (define (statements->clauses statements)
   (let loop ((statements statements) (clauses '()))
     (if (null? statements) clauses
                        (_ (loop2 (cdr statements) (append c (list s)))))))))
             (_ (error "statements->clauses: unsupported:" s)))))))
 
-(define (ast->info info)
+(define (decl->info info)
   (lambda (o)
     (let ((functions (.functions info))
           (globals (.globals info))
         (if (member name functions) info
             (clone info #:functions (cons (cons name #f) functions))))
       (pmatch o
-        (((trans-unit . _) . _)
-         ((ast-list->info info)  o))
-        ((trans-unit . ,elements)
-         ((ast-list->info info) elements))
-        ((fctn-defn . _) ((function->info info) o))
-        ((cpp-stmt (define (name ,name) (repl ,value)))
-         info)
 
-        ((cast (type-name (decl-spec-list (type-spec (void)))) _)
-         info)
+        ((decl (decl-spec-list (type-spec (typename ,type))) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list . ,param-list)))))
+         (declare name))
 
-        ((break)
-         (let ((label (car (.break info))))
-           (append-text info (wrap-as (i386:jump label)))))
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name))))
+         (clone info #:types (cons (cons name (get-type types type)) types)))
 
-        ((continue)
-         (let ((label (car (.continue info))))
-           (append-text info (wrap-as (i386:jump label)))))
+        ;; int foo ();
+        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list . ,param-list)))))
+         (declare name))
 
-        ;; FIXME: expr-stmt wrapper?
-        (trans-unit info)
-        ((expr-stmt) info)
+        ;; void foo ();
+        ((decl (decl-spec-list (type-spec (void))) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list . ,param-list)))))
+         (declare name))
 
-        ((compd-stmt (block-item-list . ,statements)) ((ast-list->info info) statements))
-        
-        ((expr-stmt (fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))
-         (if (equal? name "asm") (let ((arg0 (cadr (cadar expr-list))))
-                                   (append-text info (wrap-as (asm->m1 arg0))))
-             (let* ((info (append-text info (ast->comment o)))
-                    (info ((expr->accu info) `(fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))))
-               (append-text info (wrap-as (i386:accu-zero?))))))
+        ;; void foo (*);
+        ((decl (decl-spec-list (type-spec (void))) (init-declr-list (init-declr (ptr-declr (pointer) (ftn-declr (ident ,name) (param-list . ,param-list))))))
+         (declare name))
 
-        ((if ,test ,then)
-         (let* ((info (append-text info (ast->comment `(if ,test (ellipsis)))))
-                (here (number->string (length text)))
-                (label (string-append (.function info) "_" here "_"))
-                (break-label (string-append label "break"))
-                (else-label (string-append label "else"))
-                (info ((test-jump-label->info info break-label) test))
-                (info ((ast->info info) then))
-                (info (append-text info (wrap-as (i386:jump break-label))))
-                (info (append-text info (wrap-as `((#:label ,break-label))))))
-           (clone info
-                  #:locals locals)))
+        ;; char *strcpy ();
+        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ftn-declr (ident ,name) (param-list . ,param-list))))))
+         (declare name))
 
-        ((if ,test ,then ,else)
-         (let* ((info (append-text info (ast->comment `(if ,test (ellipsis) (ellipsis)))))
-                (here (number->string (length text)))
-                (label (string-append (.function info) "_" here "_"))
-                (break-label (string-append label "break"))
-                (else-label (string-append label "else"))
-                (info ((test-jump-label->info info else-label) test))
-                (info ((ast->info info) then))
-                (info (append-text info (wrap-as (i386:jump break-label))))
-                (info (append-text info (wrap-as `((#:label ,else-label)))))
-                (info ((ast->info info) else))
-                (info (append-text info (wrap-as `((#:label ,break-label))))))
-           (clone info
-                  #:locals locals)))
+        ;; printf (char const* format, ...)
+        ((decl (decl-spec-list ,type) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list ,param-list . (ellipsis))))))
+         (declare name))
 
-        ;; Hmm?
-        ((expr-stmt (cond-expr ,test ,then ,else))
-         (let* ((info (append-text info (ast->comment `(cond-expr ,test (ellipsis) (ellipsis)))))
-                (here (number->string (length text)))
-                (label (string-append (.function info) "_" here "_"))
-                (else-label (string-append label "else"))
-                (break-label (string-append label "break"))
-                (info ((test-jump-label->info info else-label) test))
-                (info ((ast->info info) then))
-                (info (append-text info (wrap-as (i386:jump break-label))))
-                (info (append-text info (wrap-as `((#:label ,else-label)))))
-                (info ((ast->info info) else))
-                (info (append-text info (wrap-as `((#:label ,break-label))))))
-           info))
+        ;; <name> tcc_new
+        ((decl (decl-spec-list ,type) (init-declr-list (init-declr (ptr-declr (pointer) (ftn-declr (ident ,name) (param-list . ,param-list))))))
+         (declare name))
 
-        ((switch ,expr (compd-stmt (block-item-list . ,statements)))
-         (let* ((info (append-text info (ast->comment `(switch ,expr (compd-stmt (block-item-list (ellipsis)))))))
-                (here (number->string (length text)))
-                (label (string-append (.function info) "_" here "_"))
-                (break-label (string-append label "break"))
-                (clauses (statements->clauses statements))
-                (info ((expr->accu info) expr))
-                (info (clone info #:break (cons break-label (.break info))))
-                (info (let loop ((clauses clauses) (i 0) (info info))
-                        (if (null? clauses) info
-                            (loop (cdr clauses) (1+ i) ((clause->info info i label (null? (cdr clauses))) (car clauses))))))
-                (info (append-text info (wrap-as `((#:label ,break-label))))))
-           (clone info
-                  #:locals locals
-                  #:break (cdr (.break info)))))
+        ;; extern type foo ()
+        ((decl (decl-spec-list (stor-spec (extern)) ,type) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list . ,param-list)))))
+         (declare name))
 
-        ((for ,init ,test ,step ,body)
-         (let* ((info (append-text info (ast->comment `(for ,init ,test ,step (ellipsis)))))
-                (here (number->string (length text)))
-                (label (string-append (.function info) "_" here "_"))
-                (break-label (string-append label "break"))
-                (loop-label (string-append label "loop"))
-                (continue-label (string-append label "continue"))
-                (initial-skip-label (string-append label "initial_skip"))
-                (info ((ast->info info) init))
-                (info (clone info #:break (cons break-label (.break info))))
-                (info (clone info #:continue (cons continue-label (.continue info))))
-                (info (append-text info (wrap-as (i386:jump initial-skip-label))))
-                (info (append-text info (wrap-as `((#:label ,loop-label)))))
-                (info ((ast->info info) body))
-                (info (append-text info (wrap-as `((#:label ,continue-label)))))
-                (info ((expr->accu info) step))
-                (info (append-text info (wrap-as `((#:label ,initial-skip-label)))))
-                (info ((test-jump-label->info info break-label) test))
-                (info (append-text info (wrap-as (i386:jump loop-label))))
-                (info (append-text info (wrap-as `((#:label ,break-label))))))
-           (clone info
-                  #:locals locals
-                  #:break (cdr (.break info))
-                  #:continue (cdr (.continue info)))))
+        ;; struct TCCState;
+        ((decl (decl-spec-list (type-spec (struct-ref (ident ,name)))))
+         info)
 
-        ((while ,test ,body)
-         (let* ((info (append-text info (ast->comment `(while ,test (ellipsis)))))
-                (here (number->string (length text)))
-                (label (string-append (.function info) "_" here "_"))
-                (break-label (string-append label "break"))
-                (loop-label (string-append label "loop"))
-                (continue-label (string-append label "continue"))
-                (info (append-text info (wrap-as (i386:jump continue-label))))
-                (info (clone info #:break (cons break-label (.break info))))
-                (info (clone info #:continue (cons continue-label (.continue info))))
-                (info (append-text info (wrap-as `((#:label ,loop-label)))))
-                (info ((ast->info info) body))
-                (info (append-text info (wrap-as `((#:label ,continue-label)))))
-                (info ((test-jump-label->info info break-label) test))
-                (info (append-text info (wrap-as (i386:jump loop-label))))
-                (info (append-text info (wrap-as `((#:label ,break-label))))))
-           (clone info
-                  #:locals locals
-                  #:break (cdr (.break info))
-                  #:continue (cdr (.continue info)))))
+        ;; extern type global;
+        ((decl (decl-spec-list (stor-spec (extern)) ,type) (init-declr-list (init-declr (ident ,name))))
+         info)
 
-        ((do-while ,body ,test)
-         (let* ((info (append-text info (ast->comment `(do-while ,test (ellipsis)))))
-                (here (number->string (length text)))
-                (label (string-append (.function info) "_" here "_"))
-                (break-label (string-append label "break"))
-                (loop-label (string-append label "loop"))
-                (continue-label (string-append label "continue"))
-                (info (clone info #:break (cons break-label (.break info))))
-                (info (clone info #:continue (cons continue-label (.continue info))))
-                (info (append-text info (wrap-as `((#:label ,loop-label)))))
-                (info ((ast->info info) body))
-                (info (append-text info (wrap-as `((#:label ,continue-label)))))
-                (info ((test-jump-label->info info break-label) test))
-                (info (append-text info (wrap-as (i386:jump loop-label))))
-                (info (append-text info (wrap-as `((#:label ,break-label))))))
-           (clone info
-                  #:locals locals
-                  #:break (cdr (.break info))
-                  #:continue (cdr (.continue info)))))
+        ;; ST_DATA struct TCCState *tcc_state;
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
+         info)
 
-        ((labeled-stmt (ident ,label) ,statement)
-         (let ((info (append-text info `(((#:label ,(string-append (.function info) "_label_" label)))))))
-           ((ast->info info) statement)))
+        ;; ST_DATA int ch, tok; -- TCC, why oh why so difficult?
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name)) . ,rest))
+         info)
 
-        ((goto (ident ,label))
-         (append-text info (wrap-as (i386:jump (string-append (.function info) "_label_" label)))))
+        ;; ST_DATA const int *macro_ptr;
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
+         info)
 
-        ((return ,expr)
-         (let ((info ((expr->accu info) expr)))
-           (append-text info (append (wrap-as (i386:ret))))))
+        ;; ST_DATA TokenSym **table_ident;
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (typename ,type))) (init-declr-list (init-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
+         info)
 
-        ;; DECL
+        ;; ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (typename ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name))) . ,rest))
+         info)
 
-        ;; int i;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name))))
-         (if (.function info)
-             (clone info #:locals (add-local locals name type 0))
-             (clone info #:globals (append globals (list (ident->global name type 0 0))))))
+        ;; ST_DATA void **sym_pools;
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (void))) (init-declr-list (init-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
+         info)
 
-        ;; enum e i;
-        ((decl (decl-spec-list (type-spec (enum-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name))))
-         (let ((type "int")) ;; FIXME
-           (if (.function info)
-               (clone info #:locals (add-local locals name type 0))
-               (clone info #:globals (append globals (list (ident->global name type 0 0)))))))
+        ;; ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name)) . ,rest))
+         info)
 
-        ;; int i = 0;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) (initzer (p-expr (fixed ,value))))))
-         (let ((value (cstring->number value)))
-           (if (.function info)
-               (let* ((locals (add-local locals name type 0))
-                      (info (clone info #:locals locals)))
-                 (append-text info ((value->ident info) name value)))
-               (clone info #:globals (append globals (list (ident->global name type 0 value)))))))
+        ;; ST_DATA SValue __vstack[1+/*to make bcheck happy*/ VSTACK_SIZE], *vtop;
+        ;; Yay, let's hear it for the T-for Tiny in TCC!?
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (typename ,type))) (init-declr-list (init-declr (array-of (ident ,name) (add (p-expr (fixed ,a)) (p-expr (fixed ,b))))) (init-declr (ptr-declr (pointer) (ident ,name2)))))
+         info)
 
-        ;; char c = 'A';
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) (initzer (p-expr (char ,value))))))
-         (if (not (.function info)) (error "ast->info: unsupported: " o))
-         (let* ((locals (add-local locals name type 0))
-                (info (clone info #:locals locals))
-                (value (char->integer (car (string->list value)))))
-           (append-text info ((value->ident info) name value))))
+        ;; ST_DATA char *funcname;
+        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
+         info)
 
-        ;; int i = -1;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) (initzer (neg (p-expr (fixed ,value)))))))
-         (let ((value (- (cstring->number value))))
-           (if (.function info)
-               (let* ((locals (add-local locals name type 0))
-                      (info (clone info #:locals locals)))
-                 (append-text info ((value->ident info) name value)))
-               (clone info #:globals (append globals (list (ident->global name type 0 value)))))))
-
-        ;; int i = argc;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) (initzer (p-expr (ident ,local))))))
-         (if (not (.function info)) (error "ast->info: unsupported: " o))
-         (let* ((locals (add-local locals name type 0))
-                (info (clone info #:locals locals)))
-           (append-text info (append ((ident->accu info) local)
-                                     ((accu->ident info) name)))))
-
-        ;; char *p = "foo";
-        ((decl (decl-spec-list (type-spec (fixed-type ,type)) . _) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (p-expr (string ,string))))))
-         (if (.function info)
-             (let* ((locals (add-local locals name type 1))
-                    (globals ((globals:add-string globals) string))
-                    (info (clone info #:locals locals #:globals globals)))
-               (append-text info (append
-                                  (list (i386:label->accu `(#:string ,string)))
-                                  ((accu->ident info) name))))
-             (let* ((globals ((globals:add-string globals) string))
-                    (size 4)
-                    (global (make-global name type 1 (initzer->data `(initzer (p-expr (string ,string))))))
-                    (globals (append globals (list global))))
-               (clone info #:globals globals))))
-        
-        ;; char *p;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type)) . _) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
-         (if (.function info)
-             (let* ((locals (add-local locals name type 1))
-                    (info (clone info #:locals locals)))
-               (append-text info (append (wrap-as (i386:value->accu 0))
-                                         ((accu->ident info) name))))
-             (let ((globals (append globals (list (ident->global name type 1 0)))))
-               (clone info #:globals globals))))
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-ref (ident (,type))))) (init-declr-list (init-declr (ident ,name))))
+         (clone info #:types (cons (cons name (or (get-type types type) `(typedef ("struct" ,type)))) types)))
 
-        ;; char *p = 0;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type)) . _) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (p-expr (fixed ,value))))))
-         (let ((value (cstring->number value)))
-           (if (.function info)
-               (let* ((locals (add-local locals name type 1))
-                      (info (clone info #:locals locals)))
-                 (append-text info (append (wrap-as (i386:value->accu value))
-                                           ((accu->ident info) name))))
-               (clone info #:globals (append globals (list (ident->global name type 1 value)))))))
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name))))
+         (clone info #:types (cons (cons name (or (get-type types type) `(typedef ("struct" ,type)))) types)))
 
-        ;; FILE *p;
-        ((decl (decl-spec-list (type-spec (typename ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
-         (if (.function info)
-             (let* ((locals (add-local locals name type 1))
-                    (info (clone info #:locals locals)))
-               (append-text info (append (wrap-as (i386:value->accu 0))
-                                         ((accu->ident info) name))))
-             (let ((globals (append globals (list (ident->global name type 1 0)))))
-               (clone info #:globals globals))))
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name))))
+         (clone info #:types (cons (cons name (or (get-type types type) `(typedef ("struct" ,type)))) types)))
 
-        ;; FILE *p = 0;
-        ((decl (decl-spec-list (type-spec (typename ,type)) . _) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (p-expr (fixed ,value))))))
-         (let ((value (cstring->number value)))
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name))))
+         (clone info #:types (cons (cons name (or (get-type types type) `(typedef ,type))) types)))
+
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-def ,field-list))) (init-declr-list (init-declr (ident ,name))))
+         (let ((info ((ast->info info) `(decl (decl-spec-list (type-spec (struct-def (ident ,name) ,field-list))) (init-declr-list (init-declr (ident ,name)))))))
+           (clone info #:types (cons (cons name (or (get-type types `("struct" ,name)) `(typedef ,name))) types))))
+
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
+         (let* ((type (get-type types type))
+                (type (make-type name
+                                 (type:type type)
+                                 (type:size type)
+                                 (1+ (type:pointer type))
+                                 (type:description type))))
+           (clone info #:types (cons type types))))
+
+
+        ;; struct foo* bar = expr;
+        ((decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (ref-to (p-expr (ident ,value)))))))
+         (if (.function info) (let* ((locals (add-local locals name (list "struct" type) 1))
+                                     (info (clone info #:locals locals)))
+                                (append-text info (append ((ident-address->accu info) value)
+                                                          ((accu->ident info) name))))
+             (error "ast->info: unsupported global:" o)))
+        ;; END FIXME -- dupe of the below
+
+
+        ;; struct
+        ((decl (decl-spec-list (type-spec (struct-def (ident ,name) (field-list . ,fields)))))
+         (let ((type (struct->type (list "struct" name) (map struct-field fields))))
+           (clone info #:types (cons type types))))
+
+        ;; ;; struct foo {} bar;
+        ((decl (decl-spec-list (type-spec (struct-def (ident ,type) (field-list . ,fields))))
+               (init-declr-list (init-declr (ident ,name))))
+         (let ((info ((ast->info info) `(decl (decl-spec-list (type-spec (struct-def (ident ,type) (field-list . ,fields))))))))
+           ((ast->info info)
+            `(decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name)))))))
+
+
+        ;; TODO
+        ;; enum e i;
+        ((decl (decl-spec-list (type-spec (enum-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name))))
+         (let ((type "int")) ;; FIXME
            (if (.function info)
-               (let* ((locals (add-local locals name type 1))
-                      (info (clone info #:locals locals)))
-                 (append-text info (append (wrap-as (i386:value->accu value))
-                                           ((accu->ident info) name))))
-               (clone info #:globals (append globals (list (ident->global name type 1 value)))))))
+               (clone info #:locals (add-local locals name type 0))
+               (clone info #:globals (append globals (list (ident->global name type 0 0)))))))
 
-        ;; char **p;
+         ;; char **p;
         ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
          (if (.function info)
-             (let* ((locals (add-local locals name type 2))
-                    (info (clone info #:locals locals)))
-               (append-text info (append (wrap-as (i386:value->accu 0))
-                                         ((accu->ident info) name))))
+             (let ((locals (add-local locals name type 2)))
+               (clone info #:locals locals))
              (let ((globals (append globals (list (ident->global name type 2 0)))))
                (clone info #:globals globals))))
 
-        ;; char **p = g_environment;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer (pointer)) (ident ,name)) (initzer (p-expr (ident ,b)))))) ;; FIXME: initzer
-         (if (.function info)
-             (let* ((locals (add-local locals name type 2))
-                    (info (clone info #:locals locals)))
-               (append-text info (append
-                                  ((ident->accu info) b)
-                                  ((accu->ident info) name))))
-             (let* ((value (assoc-ref constants b))
-                    (global (ident->global name type 2 (initzer->data `(p-expr (fixed ,value)))))
-                    (globals (append globals (list global))))
-               (clone info #:globals globals))))
-
         ;; struct foo bar[2];
         ;; char arena[20000];
         ((decl (decl-spec-list (type-spec ,type)) (init-declr-list (init-declr (array-of (ident ,name) (p-expr (fixed ,count))))))
                       (globals (append globals (list array))))
                  (clone info #:globals globals)))))
 
-        ;; struct foo bar;
-        ((decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name))))
-         (if (.function info)
-             (let* ((size (type->size info (list "struct" type)))
-                    (local (car (add-local locals name type 1)))
-                    (local (make-local name `("struct" ,type) -1 (+ (local:id (cdr local)) -1 (quotient (+ size 3) 4))))
-                    (locals (cons local locals)))
-               (clone info #:locals locals))
-             (let* ((size (type->size info (list "struct" type)))
-                    (global (make-global name (list "struct" type) -1 (string->list (make-string size #\nul))))
-                    (globals (append globals (list global)))
-                    (info (clone info #:globals globals)))
-               info)))
-
-        ;;struct scm *g_cells = (struct scm*)arena;
-        ((decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (cast (type-name (decl-spec-list (type-spec (struct-ref (ident ,=type)))) (abs-declr (pointer))) (p-expr (ident ,value)))))))
-         (if (.function info)
-             (let* ((locals (add-local locals name `("struct" ,type) 1))
-                    (info (clone info #:locals locals)))
-               (append-text info (append ((ident->accu info) name)
-                                         ((accu->ident info) value)))) ;; FIXME: deref?
-             (let* ((globals (append globals (list (ident->global name `("struct" ,type) 1 0))))
-                    (info (clone info #:globals globals)))
-               (append-text info (append ((ident->accu info) name)
-                                         ((accu->ident info) value)))))) ;; FIXME: deref?
-
-        ;; SCM tmp;
-        ((decl (decl-spec-list (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name))))
-         (if (.function info)
-             (let ((size (type->size info type)))
-               (if (<= size 4) (clone info #:locals (add-local locals name type 0))
-                   (let* ((local (car (add-local locals name type 1)))
-                          (local (make-local name type -1 (+ (local:id (cdr local)) -1 (quotient (+ size 3) 4))))
-                          (locals (cons local locals)))
-                     (clone info #:locals locals))))
-             (clone info #:globals (append globals (list (ident->global name type 0 0))))))
-
-        ;; SCM g_stack = 0;
-        ((decl (decl-spec-list (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name) (initzer (p-expr (fixed ,value))))))
-         (let ((value (cstring->number value)))
-           (if (.function info)
-               (let* ((locals (add-local locals name type 0))
-                      (info (clone info #:locals locals)))
-                 (append-text info ((value->ident info) name value)))
-               (let ((globals (append globals (list (ident->global name type 0 value)))))
-                 (clone info #:globals globals)))))
-
-        ;; SCM i = argc;
-        ((decl (decl-spec-list (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name) (initzer (p-expr (ident ,local))))))
-         (if (.function info)
-             (let* ((locals (add-local locals name type 0))
-                    (info (clone info #:locals locals)))
-               (append-text info (append ((ident->accu info) local)
-                                         ((accu->ident info) name))))
-             (let* ((globals (append globals (list (ident->global name type 0 0))))
-                    (info (clone info #:globals globals)))
-               (append-text info (append ((ident->accu info) local)
-                                         ((accu->ident info) name))))))
-
         ;; int (*function) (void) = g_functions[g_cells[fn].cdr].function;
         ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ftn-declr (scope (ptr-declr (pointer) (ident ,name))) (param-list . ,param-list)) (initzer ,initzer))))
          (let* ((locals (add-local locals name type 1))
                                            (i386:accu+base))))
                   #:locals locals)))
 
-        ;; char *p = (char*)g_cells;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (cast (type-name (decl-spec-list (type-spec (fixed-type ,=type))) (abs-declr (pointer))) (p-expr (ident ,value)))))))
-         (if (.function info)
-             (let* ((locals (add-local locals name type 1))
-                    (info (clone info #:locals locals)))
-               (append-text info (append ((ident->accu info) value)
-                                         ((accu->ident info) name))))
-             (let ((globals (append globals (list (ident->global name type 1 `(,value #f #f #f))))))
-               (clone info #:globals globals))))
-
         ;; char *p = g_cells;
         ((decl (decl-spec-list (type-spec ,type)) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (p-expr (ident ,value))))))
          (let ((type (decl->type type)))
            ((ast->info info)
             `(decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name)))))))
 
-        ;; struct foo* bar = expr;
-         ((decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (ref-to (p-expr (ident ,value)))))))
-         (if (.function info) (let* ((locals (add-local locals name (list "struct" type) 1))
-                                     (info (clone info #:locals locals)))
-                 (append-text info (append ((ident-address->accu info) value)
-                                           ((accu->ident info) name))))
-             (error "ast->info: unsupported global:" o)))
-         ;; END FIXME -- dupe of the below
-
-
-        ;; struct
-        ((decl (decl-spec-list (type-spec (struct-def (ident ,name) (field-list . ,fields)))))
-         (let ((type (struct->type (list "struct" name) (map struct-field fields))))
-           (clone info #:types (cons type types))))
-
-        ;; struct foo {} bar;
-        ((decl (decl-spec-list (type-spec (struct-def (ident ,type) (field-list . ,fields))))
-               (init-declr-list (init-declr (ident ,name))))
-         (let ((info ((ast->info info) `(decl (decl-spec-list (type-spec (struct-def (ident ,type) (field-list . ,fields))))))))
-           ((ast->info info)
-            `(decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name)))))))
-
-        ;; struct foo* bar = expr;
-         ((decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (ref-to (p-expr (ident ,value)))))))
-         (if (.function info) (let* ((locals (add-local locals name (list "struct" type) 1))
-                                     (info (clone info #:locals locals)))
-                 (append-text info (append ((ident-address->accu info) value)
-                                           ((accu->ident info) name))))
-             (error "ast->info: unsupported global:" o)))
-
-        ;; char *p = &bla;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (ref-to (p-expr (ident ,value)))))))
-         (let ((type (decl->type type)))
-           (if (.function info)
-               (let* ((locals (add-local locals name type 1))
-                      (info (clone info #:locals locals)))
-                 (append-text info (append ((ident-address->accu info) value)
-                                           ((accu->ident info) name))))
-               (error "TODO" o))))
-
-        ;; char **p = &bla;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer (pointer)) (ident ,name)) (initzer (ref-to (p-expr (ident ,value)))))))
-         (let ((type (decl->type type)))
-           (if (.function info)
-               (let* ((locals (add-local locals name type 2))
-                      (info (clone info #:locals locals)))
-                 (append-text info (append ((ident-address->accu info) value)
-                                           ((accu->ident info) name))))
-               (error "TODO" o))))
-
-        ;; char *p = bla[0];
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (array-ref ,index (p-expr (ident ,array)))))))
-         (if (.function info)
-             (let* ((locals (add-local locals name type 1))
-                    (info (clone info #:locals locals))
-                    (info ((expr->accu* info) `(array-ref ,index (p-expr (ident ,array))))))
-               (append-text info ((accu->ident info) name)))
-             (error "TODO" o)))
-
-        ;; char *foo = &bar[0];
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (ref-to (array-ref ,index (p-expr (ident ,array))))))))
-         (if (.function info)
-             (let* ((locals (add-local locals name type 1))
-                    (info (clone info #:locals locals))
-                    (info ((expr->accu* info) `(array-ref ,index (p-expr (ident ,array))))))
-               (append-text info ((accu->ident info) name)))
-             (error "TODO" o)))
-
-        ;; char *p = *bla;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)) (initzer (de-ref (p-expr (ident ,value)))))))
-         (if (.function info)
-             (let* ((locals (add-local locals name type 1))
-                    (info (clone info #:locals locals))
-                    (local (assoc-ref (.locals info) name)))
-               (append-text info (append ((ident->accu info) value)
-                                         (wrap-as (i386:mem->accu))
-                                         ((accu->ident info) name))))
-             (error "TODO" o)))
-
-        ;; DECL
-        ;; char *bla[] = {"a", "b"};
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (array-of (ident ,name))) (initzer (initzer-list . ,initzers)))))
-         (let* ((type (decl->type type))
-                (entries (map (initzer->global globals) initzers))
-                (entry-size 4)
-                (size (* (length entries) entry-size))
-                (initzers (map (initzer->non-const info) initzers)))
-           (if (.function info)
-               (error "TODO: <type> x[] = {};" o)
-               (let* (;;(global (make-global name type 2 (string->list (make-string size #\nul))))
-                      (global (make-global name type 2 (append-map initzer->data initzers)))
-                      (global-names (map car globals))
-                      (entries (filter (lambda (g) (and g (not (member (car g) global-names)))) entries))
-                      (globals (append globals entries (list global))))
-                 (clone info #:globals globals)))))
-
-        ;;
         ;; struct f = {...};
+        ;; LOCALS!
         ((decl (decl-spec-list (type-spec ,type)) (init-declr-list (init-declr (ident ,name) (initzer (initzer-list . ,initzers)))))
          (let* ((info (append-text info (ast->comment o)))
                 (type (decl->type type))
                 (size (type->size info type))
                 (initzers (map (initzer->non-const info) initzers)))
            (if (.function info)
-               (let* ((initzer-globals (filter-map (initzer->global globals) initzers))
+               (let* ((initzer-globals (filter identity (append-map (initzer->globals globals) initzers)))
                       (global-names (map car globals))
                       (initzer-globals (filter (lambda (g) (and g (not (member (car g) global-names)))) initzer-globals))
                       (globals (append globals initzer-globals))
                                        (wrap-as (append (i386:accu->base)))
                                        (.text ((expr->accu empty) initzer))
                                        (wrap-as (i386:accu->base-address+n offset)))))))))
-               (let* ((initzer-globals (filter-map (initzer->global globals) initzers))
+               (let* ((initzer-globals (filter identity (append-map (initzer->globals globals) initzers)))
                       (global-names (map car globals))
                       (initzer-globals (filter (lambda (g) (and g (not (member (car g) global-names)))) initzer-globals))
                       (globals (append globals initzer-globals))
-                      (global (make-global name type 2 (append-map initzer->data initzers)))
+                      (global (make-global name type 2 (append-map (initzer->data info) initzers)))
                       (globals (append globals (list global))))
                  (clone info #:globals globals)))))
 
-        ;;char cc = g_cells[c].cdr;  ==> generic?
-        ((decl (decl-spec-list (type-spec ,type)) (init-declr-list (init-declr (ident ,name) (initzer ,initzer))))
-         (let ((type (decl->type type))
-               (initzer ((initzer->non-const info) initzer))
-               (info (append-text info (ast->comment o))))
+        ;; char *foo[0], *bar;
+        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (array-of (ident ,name) ,index)) . ,rest))
+         (let loop ((inits `((init-declr (array-of (ident ,name) ,index)) ,@rest)) (info info))
+           (if (null? inits) info
+               (loop (cdr inits)
+                     ((ast->info info)
+                      `(decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list ,(car inits))))))))
+
+        ;; DECL
+        ;; char *bla[] = {"a", "b"};
+        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (array-of (ident ,name))) (initzer (initzer-list . ,initzers)))))
+         (let* ((type (decl->type type))
+                (entries (filter identity (append-map (initzer->globals globals) initzers)))
+                (entry-size 4)
+                (size (* (length entries) entry-size))
+                (initzers (map (initzer->non-const info) initzers)))
            (if (.function info)
-               (let* ((locals (add-local locals name type 0))
-                      (info (clone info #:locals locals))
-                      (info ((expr->accu info) initzer)))
-                 (append-text info ((accu->ident info) name)))
-               (let* ((global (make-global name type 2 (initzer->data initzer)))
-                      (globals (append globals (list global))))
+               (error "TODO: <type> x[] = {};" o)
+               (let* ( ;;(global (make-global name type 2 (string->list (make-string size #\nul))))
+                      (global (make-global name type 2 (append-map (initzer->data info) initzers)))
+                      (global-names (map car globals))
+                      (entries (filter (lambda (g) (and g (not (member (car g) global-names)))) entries))
+                      (globals (append globals entries (list global))))
                  (clone info #:globals globals)))))
 
-        ((decl (decl-spec-list (type-spec (typename ,type))) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list . ,param-list)))))
-         (declare name))
-
-        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name))))
-         (clone info #:types (cons (cons name (get-type types type)) types)))
-
-        ;; int foo ();
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list . ,param-list)))))
-         (declare name))
-
-        ;; void foo ();
-        ((decl (decl-spec-list (type-spec (void))) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list . ,param-list)))))
-         (declare name))
-
-        ;; void foo (*);
-        ((decl (decl-spec-list (type-spec (void))) (init-declr-list (init-declr (ptr-declr (pointer) (ftn-declr (ident ,name) (param-list . ,param-list))))))
-         (declare name))
-
-        ;; char *strcpy ();
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ftn-declr (ident ,name) (param-list . ,param-list))))))
-         (declare name))
-
-        ;; printf (char const* format, ...)
-        ((decl (decl-spec-list ,type) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list ,param-list . (ellipsis))))))
-         (declare name))
-
-        ;; <name> tcc_new
-        ((decl (decl-spec-list ,type) (init-declr-list (init-declr (ptr-declr (pointer) (ftn-declr (ident ,name) (param-list . ,param-list))))))
-         (declare name))
-
-        ;; extern type foo ()
-        ((decl (decl-spec-list (stor-spec (extern)) ,type) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list . ,param-list)))))
-         (declare name))
+        ;; SCM tmp;
+        ((decl (decl-spec-list (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name))))
+         (if (.function info)
+             (let ((size (type->size info type)))
+               (if (<= size 4) (clone info #:locals (add-local locals name type 0))
+                   (let* ((local (car (add-local locals name type 1)))
+                          (local (make-local name type -1 (+ (local:id (cdr local)) -1 (quotient (+ size 3) 4))))
+                          (locals (cons local locals)))
+                     (clone info #:locals locals))))
+             (clone info #:globals (append globals (list (ident->global name type 0 0))))))
 
-        ;; struct TCCState;
-        ((decl (decl-spec-list (type-spec (struct-ref (ident ,name)))))
-         info)
+        ((decl (decl-spec-list (type-spec ,type)) (init-declr-list (init-declr ,init . ,initzer)))
+         (let* ((info (type->info info type))
+                (type (decl->type type))
+                (name (init-declr->name init))
+                (pointer (init-declr->pointer init))
+                (initzer-globals (if (null? initzer) '()
+                                     (filter identity (append-map (initzer->globals globals) initzer))))
+                (global-names (map car globals))
+                (initzer-globals (filter (lambda (g) (and g (not (member (car g) global-names)))) initzer-globals))
+                (initzer (if (null? initzer) '() ((initzer->non-const info) initzer)))
+                (info (append-text info (ast->comment o)))
+                (globals (append globals initzer-globals))
+                (info (clone info #:globals globals))
+                (size (type->size info type)))
+           (if (.function info)
+               (let* ((locals (add-local locals name type pointer))
+                      (info (clone info #:locals locals))
+                      (info (if (null? initzer) info ((initzer->accu info) (car initzer))))
+                      (info (if (null? initzer) info (append-text info ((accu->ident info) name)))))
+                 info)
+               (let* ((pointer (if (and (pair? type) (equal? (car type) "struct")) 2 pointer))
+                      (global (make-global name type pointer (if (null? initzer) (string->list (make-string size #\nul))
+                                                                 (append-map (initzer->data info) initzer))))
+                      (globals (append globals (list global))))
+                 (clone info #:globals globals)))))
 
-        ;; extern type global;
-        ((decl (decl-spec-list (stor-spec (extern)) ,type) (init-declr-list (init-declr (ident ,name))))
-         info)
+        ;; int i = 0, j = 0;
+        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) . ,initzer) . ,rest))
+         (let loop ((inits `((init-declr (ident ,name) ,@initzer) ,@rest)) (info info))
+           (if (null? inits) info
+               (loop (cdr inits)
+                     ((ast->info info)
+                      `(decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list ,(car inits))))))))
 
-        ;; ST_DATA struct TCCState *tcc_state;
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
-         info)
 
-        ;; ST_DATA int ch, tok; -- TCC, why oh why so difficult?
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name)) . ,rest))
-         info)
+        ((decl (decl-spec-list (stor-spec (typedef)) ,type) ,name)
+         (format (current-error-port) "SKIP: typedef=~s\n" o)
+         info)        
 
-        ;; ST_DATA const int *macro_ptr;
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
+        ((decl (@ ,at))
+         (format (current-error-port) "SKIP: at=~s\n" o)
          info)
 
-        ;; ST_DATA TokenSym **table_ident;
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (typename ,type))) (init-declr-list (init-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
-         info)
+        ((decl . _) (error "ast->info: unsupported: " o))))))
 
-        ;; ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (typename ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name))) . ,rest))
+(define (ast->info info)
+  (lambda (o)
+    (let ((functions (.functions info))
+          (globals (.globals info))
+          (locals (.locals info))
+          (constants (.constants info))
+          (types (.types info))
+          (text (.text info)))
+      (pmatch o
+        (((trans-unit . _) . _)
+         ((ast-list->info info)  o))
+        ((trans-unit . ,elements)
+         ((ast-list->info info) elements))
+        ((fctn-defn . _) ((function->info info) o))
+        ((cpp-stmt (define (name ,name) (repl ,value)))
          info)
 
-        ;; ST_DATA void **sym_pools;
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (void))) (init-declr-list (init-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
+        ((cast (type-name (decl-spec-list (type-spec (void)))) _)
          info)
 
-        ;; ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name)) . ,rest))
-         info)
+        ((break)
+         (let ((label (car (.break info))))
+           (append-text info (wrap-as (i386:jump label)))))
 
-        ;; ST_DATA SValue __vstack[1+/*to make bcheck happy*/ VSTACK_SIZE], *vtop;
-        ;; Yay, let's hear it for the T-for Tiny in TCC!?
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (typename ,type))) (init-declr-list (init-declr (array-of (ident ,name) (add (p-expr (fixed ,a)) (p-expr (fixed ,b))))) (init-declr (ptr-declr (pointer) (ident ,name2)))))
-         info)
+        ((continue)
+         (let ((label (car (.continue info))))
+           (append-text info (wrap-as (i386:jump label)))))
 
-        ;; ST_DATA char *funcname;
-        ((decl (decl-spec-list (stor-spec (extern)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
-         info)
+        ;; FIXME: expr-stmt wrapper?
+        (trans-unit info)
+        ((expr-stmt) info)
 
-        ;; int i = 0, j = 0;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) . ,initzer) . ,rest))
-         (let loop ((inits `((init-declr (ident ,name) ,@initzer) ,@rest)) (info info))
-           (if (null? inits) info
-               (loop (cdr inits)
-                     ((ast->info info)
-                      `(decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list ,(car inits))))))))
+        ((compd-stmt (block-item-list . ,statements)) ((ast-list->info info) statements))
+        
+        ((expr-stmt (fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))
+         (if (equal? name "asm") (let ((arg0 (cadr (cadar expr-list))))
+                                   (append-text info (wrap-as (asm->m1 arg0))))
+             (let* ((info (append-text info (ast->comment o)))
+                    (info ((expr->accu info) `(fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))))
+               (append-text info (wrap-as (i386:accu-zero?))))))
 
-        ;; char *foo[0], *bar;
-        ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (array-of (ident ,name) ,index)) . ,rest))
-         (let loop ((inits `((init-declr (array-of (ident ,name) ,index)) ,@rest)) (info info))
-           (if (null? inits) info
-               (loop (cdr inits)
-                     ((ast->info info)
-                      `(decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list ,(car inits))))))))
+        ((if ,test ,then)
+         (let* ((info (append-text info (ast->comment `(if ,test (ellipsis)))))
+                (here (number->string (length text)))
+                (label (string-append (.function info) "_" here "_"))
+                (break-label (string-append label "break"))
+                (else-label (string-append label "else"))
+                (info ((test-jump-label->info info break-label) test))
+                (info ((ast->info info) then))
+                (info (append-text info (wrap-as (i386:jump break-label))))
+                (info (append-text info (wrap-as `((#:label ,break-label))))))
+           (clone info
+                  #:locals locals)))
 
+        ((if ,test ,then ,else)
+         (let* ((info (append-text info (ast->comment `(if ,test (ellipsis) (ellipsis)))))
+                (here (number->string (length text)))
+                (label (string-append (.function info) "_" here "_"))
+                (break-label (string-append label "break"))
+                (else-label (string-append label "else"))
+                (info ((test-jump-label->info info else-label) test))
+                (info ((ast->info info) then))
+                (info (append-text info (wrap-as (i386:jump break-label))))
+                (info (append-text info (wrap-as `((#:label ,else-label)))))
+                (info ((ast->info info) else))
+                (info (append-text info (wrap-as `((#:label ,break-label))))))
+           (clone info
+                  #:locals locals)))
 
-        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-ref (ident (,type))))) (init-declr-list (init-declr (ident ,name))))
-         (clone info #:types (cons (cons name (or (get-type types type) `(typedef ("struct" ,type)))) types)))
+        ;; Hmm?
+        ((expr-stmt (cond-expr ,test ,then ,else))
+         (let* ((info (append-text info (ast->comment `(cond-expr ,test (ellipsis) (ellipsis)))))
+                (here (number->string (length text)))
+                (label (string-append (.function info) "_" here "_"))
+                (else-label (string-append label "else"))
+                (break-label (string-append label "break"))
+                (info ((test-jump-label->info info else-label) test))
+                (info ((ast->info info) then))
+                (info (append-text info (wrap-as (i386:jump break-label))))
+                (info (append-text info (wrap-as `((#:label ,else-label)))))
+                (info ((ast->info info) else))
+                (info (append-text info (wrap-as `((#:label ,break-label))))))
+           info))
 
-        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name))))
-         (clone info #:types (cons (cons name (or (get-type types type) `(typedef ("struct" ,type)))) types)))
+        ((switch ,expr (compd-stmt (block-item-list . ,statements)))
+         (let* ((info (append-text info (ast->comment `(switch ,expr (compd-stmt (block-item-list (ellipsis)))))))
+                (here (number->string (length text)))
+                (label (string-append (.function info) "_" here "_"))
+                (break-label (string-append label "break"))
+                (clauses (statements->clauses statements))
+                (info ((expr->accu info) expr))
+                (info (clone info #:break (cons break-label (.break info))))
+                (info (let loop ((clauses clauses) (i 0) (info info))
+                        (if (null? clauses) info
+                            (loop (cdr clauses) (1+ i) ((clause->info info i label (null? (cdr clauses))) (car clauses))))))
+                (info (append-text info (wrap-as `((#:label ,break-label))))))
+           (clone info
+                  #:locals locals
+                  #:break (cdr (.break info)))))
 
-        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ident ,name))))
-         (clone info #:types (cons (cons name (or (get-type types type) `(typedef ("struct" ,type)))) types)))
+        ((for ,init ,test ,step ,body)
+         (let* ((info (append-text info (ast->comment `(for ,init ,test ,step (ellipsis)))))
+                (here (number->string (length text)))
+                (label (string-append (.function info) "_" here "_"))
+                (break-label (string-append label "break"))
+                (loop-label (string-append label "loop"))
+                (continue-label (string-append label "continue"))
+                (initial-skip-label (string-append label "initial_skip"))
+                (info ((ast->info info) init))
+                (info (clone info #:break (cons break-label (.break info))))
+                (info (clone info #:continue (cons continue-label (.continue info))))
+                (info (append-text info (wrap-as (i386:jump initial-skip-label))))
+                (info (append-text info (wrap-as `((#:label ,loop-label)))))
+                (info ((ast->info info) body))
+                (info (append-text info (wrap-as `((#:label ,continue-label)))))
+                (info ((expr->accu info) step))
+                (info (append-text info (wrap-as `((#:label ,initial-skip-label)))))
+                (info ((test-jump-label->info info break-label) test))
+                (info (append-text info (wrap-as (i386:jump loop-label))))
+                (info (append-text info (wrap-as `((#:label ,break-label))))))
+           (clone info
+                  #:locals locals
+                  #:break (cdr (.break info))
+                  #:continue (cdr (.continue info)))))
 
-        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name))))
-         (clone info #:types (cons (cons name (or (get-type types type) `(typedef ,type))) types)))
+        ((while ,test ,body)
+         (let* ((info (append-text info (ast->comment `(while ,test (ellipsis)))))
+                (here (number->string (length text)))
+                (label (string-append (.function info) "_" here "_"))
+                (break-label (string-append label "break"))
+                (loop-label (string-append label "loop"))
+                (continue-label (string-append label "continue"))
+                (info (append-text info (wrap-as (i386:jump continue-label))))
+                (info (clone info #:break (cons break-label (.break info))))
+                (info (clone info #:continue (cons continue-label (.continue info))))
+                (info (append-text info (wrap-as `((#:label ,loop-label)))))
+                (info ((ast->info info) body))
+                (info (append-text info (wrap-as `((#:label ,continue-label)))))
+                (info ((test-jump-label->info info break-label) test))
+                (info (append-text info (wrap-as (i386:jump loop-label))))
+                (info (append-text info (wrap-as `((#:label ,break-label))))))
+           (clone info
+                  #:locals locals
+                  #:break (cdr (.break info))
+                  #:continue (cdr (.continue info)))))
 
-        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-def ,field-list))) (init-declr-list (init-declr (ident ,name))))
-         (let ((info ((ast->info info) `(decl (decl-spec-list (type-spec (struct-def (ident ,name) ,field-list))) (init-declr-list (init-declr (ident ,name)))))))
-           (clone info #:types (cons (cons name (or (get-type types `("struct" ,name)) `(typedef ,name))) types))))
+        ((do-while ,body ,test)
+         (let* ((info (append-text info (ast->comment `(do-while ,test (ellipsis)))))
+                (here (number->string (length text)))
+                (label (string-append (.function info) "_" here "_"))
+                (break-label (string-append label "break"))
+                (loop-label (string-append label "loop"))
+                (continue-label (string-append label "continue"))
+                (info (clone info #:break (cons break-label (.break info))))
+                (info (clone info #:continue (cons continue-label (.continue info))))
+                (info (append-text info (wrap-as `((#:label ,loop-label)))))
+                (info ((ast->info info) body))
+                (info (append-text info (wrap-as `((#:label ,continue-label)))))
+                (info ((test-jump-label->info info break-label) test))
+                (info (append-text info (wrap-as (i386:jump loop-label))))
+                (info (append-text info (wrap-as `((#:label ,break-label))))))
+           (clone info
+                  #:locals locals
+                  #:break (cdr (.break info))
+                  #:continue (cdr (.continue info)))))
 
-        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ptr-declr (pointer) (ident ,name)))))
-         (let* ((type (get-type types type))
-                (type (make-type name
-                                 (type:type type)
-                                 (type:size type)
-                                 (1+ (type:pointer type))
-                                 (type:description type))))
-           (clone info #:types (cons type types))))
+        ((labeled-stmt (ident ,label) ,statement)
+         (let ((info (append-text info `(((#:label ,(string-append (.function info) "_label_" label)))))))
+           ((ast->info info) statement)))
 
-        ((decl (decl-spec-list (stor-spec (typedef)) ,type) ,name)
-         (format (current-error-port) "SKIP: typedef=~s\n" o)
-         info)        
+        ((goto (ident ,label))
+         (append-text info (wrap-as (i386:jump (string-append (.function info) "_label_" label)))))
 
-        ((decl (@ ,at))
-         (format (current-error-port) "SKIP: at=~s\n" o)
-         info)
+        ((return ,expr)
+         (let ((info ((expr->accu info) expr)))
+           (append-text info (append (wrap-as (i386:ret))))))
 
-        ((decl . _) (error "ast->info: unsupported: " o))
+        ((decl . ,decl)
+         ((decl->info info) o))
 
         ;; ...
         ((gt . _) ((expr->accu info) o))
          `(initzer (p-expr (fixed ,(number->string value))))))
       (_ o))))
 
-(define (initzer->data o)
+(define (initzer->data info)
+  (lambda (o)
+    (pmatch o
+      ((initzer (p-expr (ident ,name)))
+       (let ((value (assoc-ref (.constants info) name)))
+         (int->bv32 (or value 0))))
+      ((initzer (p-expr (fixed ,value))) (int->bv32 (cstring->number value)))
+      ((initzer (neg (p-expr (fixed ,value)))) (int->bv32 (- (cstring->number value))))
+      ((initzer (ref-to (p-expr (ident ,name)))) `(,name #f #f #f))
+      ((initzer (p-expr (string ,string))) `((#:string ,string) #f #f #f))
+      ((initzer (initzer-list . ,initzers)) (append-map (initzer->data info) initzers))
+      (() (int->bv32 0))
+      (_ (error "initzer->data: unsupported: " o)))))
+
+(define (initzer->accu info)
+  (lambda (o)
+    (pmatch o
+      ((initzer-list . ,initzers) (append-map (expr->accu info) initzers))
+      ((initzer (initzer-list . ,initzers)) (append-map (expr->accu info) initzers))
+      ((initzer ,initzer) ((expr->accu info) o))
+      (() (append-text info (wrap-as (i386:value->accu 0))))
+      (_ (error "initzer->accu: " o)))))
+
+(define (expr->global globals)
+  (lambda (o)
+    (pmatch o
+      ((p-expr (string ,string))
+       (let ((g `(#:string ,string)))
+         (or (assoc g globals)
+             (string->global string))))
+      ;;((p-expr (fixed ,value)) (int->global (cstring->number value)))
+      (_ #f))))
+
+(define (initzer->globals globals)
+  (lambda (o)
+    (pmatch o
+      ((initzer (initzer-list . ,initzers)) (append-map (initzer->globals globals) initzers))
+      ((initzer ,initzer) (list ((expr->global globals) initzer)))
+      (_ '(#f)))))
+
+(define (type->info info o)
   (pmatch o
-    ((initzer (p-expr (fixed ,value))) (int->bv32 (cstring->number value)))
-    ((initzer (neg (p-expr (fixed ,value)))) (int->bv32 (- (cstring->number value))))
-    ((initzer (ref-to (p-expr (ident ,name)))) `(,name #f #f #f))
-    ((initzer (p-expr (string ,string))) `((#:string ,string) #f #f #f))
-    (_ (error "initzer->data: unsupported: " o))))
+    ((struct-def (ident ,name) (field-list . ,fields))
+     (let ((type (struct->type (list "struct" name) (map struct-field fields))))
+       (clone info #:types (cons type (.types info)))))
+    (_  info)))
 
 (define (.formals o)
   (pmatch o
      1)
     ((param-decl (decl-spec-list . ,decl) (param-declr (ptr-declr (pointer (pointer)) (ident ,name))))
      2)
-    (_
-     (stderr "formal:ptr[~a] => ~a\n" o 0)
-     0)))
+    (_ 0)))
 
 (define (formals->locals o)
   (pmatch o