1b0c634c59f69f64c3ab0bf38a5e90d94acbf543
[mes.git] / scaffold / mini-mes.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
4  *
5  * This file is part of Mes.
6  *
7  * Mes is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or (at
10  * your option) any later version.
11  *
12  * Mes is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #define MES_MINI 1
22
23 #if __GNUC__
24 #define FIXME_NYACC 1
25 #define  __NYACC__ 0
26 #define NYACC_CAR
27 #define NYACC_CDR
28 #else
29 #define  __NYACC__ 1
30 #define NYACC_CAR nyacc_car
31 #define NYACC_CDR nyacc_cdr
32 #endif
33
34 typedef long size_t;
35 void *malloc (size_t i);
36
37
38 #if __GNUC__
39
40 // #define __NR_restart_syscall 0
41 // #define __NR_exit 1
42 // #define __NR_fork 2
43 // #define __NR_read 3
44 // #define __NR_write 4
45 // #define __NR_open 5
46
47 void
48 exit (int code)
49 {
50   asm (
51        "movl %0,%%ebx\n\t"
52        "movl $1,%%eax\n\t"
53        "int  $0x80"
54        : // no outputs "=" (r)
55        : "" (code)
56        );
57   // not reached
58   exit (0);
59 }
60
61 char const*
62 getenv (char const* p)
63 {
64   return 0;
65 }
66
67 int
68 open (char const *s, int mode)
69 {
70   //return syscall (SYS_open, s, mode);
71   return 0;
72 }
73
74 int
75 read (int fd, int n)
76 {
77   //syscall (SYS_read, 1, 1);
78   return 0;
79 }
80
81 void
82 write (int fd, char const* s, int n)
83 {
84   int r;
85   //syscall (SYS_write, fd, s, n));
86   asm (
87        "mov %0,%%ebx\n\t"
88        "mov %1,%%ecx\n\t"
89        "mov %2,%%edx\n\t"
90
91        "mov $0x4, %%eax\n\t"
92        "int $0x80\n\t"
93        : // no outputs "=" (r)
94        : "" (fd), "" (s), "" (n)
95        : "eax", "ebx", "ecx", "edx"
96        );
97 }
98
99 void *
100 malloc (size_t size)
101 {
102   int *n;
103   int len = size + sizeof (size);
104   //n = mmap (0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );
105   *n = len;
106   return (void*)(n+1);
107 }
108
109 void
110 free (void *p)
111 {
112   int *n = (int*)p-1;
113   //munmap ((void*)p, *n);
114 }
115 #endif // __GNUC__
116
117 #define EOF -1
118 #define STDIN 0
119 #define STDOUT 1
120 #define STDERR 2
121
122 //#include <stdio.h>
123 //#include <string.h>
124 //#include <stdlib.h>
125
126 int g_stdin;
127
128 size_t
129 strlen (char const* s)
130 {
131   int i = 0;
132   while (s[i]) i++;
133   return i;
134 }
135
136 int
137 strcmp (char const* a, char const* b)
138 {
139   while (*a && *b && *a == *b) {a++;b++;}
140   return *a - *b;
141 }
142
143 int
144 getchar ()
145 {
146   return read (g_stdin, 1);
147 }
148
149 int
150 puts (char const* s)
151 {
152   //write (STDOUT, s, strlen (s));
153   //int i = write (STDOUT, s, strlen (s));
154   int i = strlen (s);
155   write (1, s, i);
156   return 0;
157 }
158
159 int
160 eputs (char const* s)
161 {
162   //write (STDERR, s, strlen (s));
163   //int i = write (STDERR, s, strlen (s));
164   int i = strlen (s);
165   write (2, s, i);
166   return 0;
167 }
168
169 char const*
170 itoa (int x)
171 {
172   static char buf[10];
173   char *p = buf+9;
174   *p-- = 0;
175
176   int sign = x < 0;
177   if (sign)
178     x = -x;
179   
180   do
181     {
182       *p-- = '0' + (x % 10);
183       x = x / 10;
184     } while (x);
185
186   if (sign)
187     *p-- = '-';
188
189   return p+1;
190 }
191
192 void
193 assert_fail (char* s)
194 {
195   eputs ("assert fail:");
196   eputs (s);
197   eputs ("\n");
198   *((int*)0) = 0;
199 }
200
201 #if __NYACC__ || FIXME_NYACC
202 #define assert(x) ((x) ? (void)0 : assert_fail(0))
203 // #else
204 // NYACC
205 // #define assert(x) ((x) ? (void)0 : assert_fail(#x))
206 #endif
207 #define false 0
208 #define true 1
209 typedef int bool;
210
211 int ARENA_SIZE = 100000;
212
213 typedef int SCM;
214 #if __NYACC__ || FIXME_NYACC
215 enum type_t {CHAR, CLOSURE, CONTINUATION, FUNCTION, KEYWORD, MACRO, NUMBER, PAIR, REF, SPECIAL, TSTRING, SYMBOL, VALUES, TVECTOR, BROKEN_HEART};
216 #else
217 enum type_t {CHAR, CLOSURE, CONTINUATION, FUNCTION, KEYWORD, MACRO, NUMBER, PAIR, REF, SPECIAL, STRING, SYMBOL, VALUES, VECTOR, BROKEN_HEART};
218 #endif
219 typedef SCM (*function0_t) (void);
220 typedef SCM (*function1_t) (SCM);
221 typedef SCM (*function2_t) (SCM, SCM);
222 typedef SCM (*function3_t) (SCM, SCM, SCM);
223 typedef SCM (*functionn_t) (SCM);
224 typedef struct function_struct {
225   union {
226     function0_t function0;
227     function1_t function1;
228     function2_t function2;
229     function3_t function3;
230     functionn_t functionn;
231   } data;
232   int arity;
233 } function_t;
234 struct scm;
235
236 typedef struct scm_struct {
237   enum type_t type;
238   union {
239     char const *name;
240     SCM string;
241     SCM car;
242     SCM ref;
243     int length;
244   } NYACC_CAR;
245   union {
246     int value;
247     int function;
248     SCM cdr;
249     SCM closure;
250     SCM continuation;
251     SCM macro;
252     SCM vector;
253     int hits;
254   } NYACC_CDR;
255 } scm;
256
257 scm scm_nil = {SPECIAL, "()"};
258 scm scm_f = {SPECIAL, "#f"};
259 scm scm_t = {SPECIAL, "#t"};
260 scm scm_dot = {SPECIAL, "."};
261 scm scm_arrow = {SPECIAL, "=>"};
262 scm scm_undefined = {SPECIAL, "*undefined*"};
263 scm scm_unspecified = {SPECIAL, "*unspecified*"};
264 scm scm_closure = {SPECIAL, "*closure*"};
265 scm scm_circular = {SPECIAL, "*circular*"};
266 scm scm_begin = {SPECIAL, "*begin*"};
267
268
269 //#include "mes.symbols.h"
270 #define cell_nil 1
271 #define cell_f 2
272 #define cell_t 3
273 #define cell_dot 4
274 #define cell_arrow 5
275 #define cell_undefined 6
276 #define cell_unspecified 7
277 #define cell_closure 8
278 #define cell_circular 9
279 #define cell_begin 10
280 #define cell_symbol_dot 11
281 #define cell_symbol_lambda 12
282 #define cell_symbol_begin 13
283 #define cell_symbol_if 14
284 #define cell_symbol_quote 15
285 #define cell_symbol_set_x 16
286
287 #if __GNUC__
288 bool g_debug = false;
289 #endif
290
291 int g_free = 0;
292 scm *g_cells;
293 //scm *g_news = 0;
294 SCM tmp;
295 SCM tmp_num;
296 SCM tmp_num2;
297
298 function_t functions[200];
299 int g_function = 0;
300
301 SCM g_symbols = 0;
302 SCM g_stack = 0;
303 SCM r0 = 0; // a/env
304 SCM r1 = 0; // param 1
305 SCM r2 = 0; // save 2+load/dump
306 SCM r3 = 0; // continuation
307
308 SCM make_cell (SCM type, SCM car, SCM cdr);
309 function_t fun_make_cell = {&make_cell, 3};
310 scm scm_make_cell = {FUNCTION, "make-cell", 0};
311 SCM cell_make_cell;
312
313 SCM cons (SCM x, SCM y);
314 function_t fun_cons = {&cons, 2};
315 scm scm_cons = {FUNCTION, "cons", 0};
316 SCM cell_cons;
317
318 SCM car (SCM x);
319 function_t fun_car = {&car, 1};
320 scm scm_car = {FUNCTION, "car", 0};
321 SCM cell_car;
322
323 SCM cdr (SCM x);
324 function_t fun_cdr = {&cdr, 1};
325 scm scm_cdr = {FUNCTION, "cdr", 0};
326 SCM cell_cdr;
327
328 // SCM eq_p (SCM x, SCM y);
329 // function_t fun_eq_p = {&eq_p, 2};
330 // scm scm_eq_p = {FUNCTION, "eq?", 0};
331 // SCM cell_eq_p;
332
333 #define TYPE(x) (g_cells[x].type)
334
335 #define CAR(x) g_cells[x].car
336 #define LENGTH(x) g_cells[x].length
337 #define STRING(x) g_cells[x].string
338
339 #define CDR(x) g_cells[x].cdr
340 #define VALUE(x) g_cells[x].value
341 #define VECTOR(x) g_cells[x].vector
342
343 #define MAKE_CHAR(n) make_cell (tmp_num_ (CHAR), 0, tmp_num2_ (n))
344 //#define MAKE_CONTINUATION(n) make_cell (tmp_num_ (CONTINUATION), n, g_stack)
345 //#define MAKE_NUMBER(n) make_cell (tmp_num_ (NUMBER), 0, tmp_num2_ (n))
346 //#define MAKE_REF(n) make_cell (tmp_num_ (REF), n, 0)
347
348 #if __NYACC__ || FIXME_NYACC
349 #define MAKE_STRING(x) make_cell (tmp_num_ (TSTRING), x, 0)
350 // #else
351 // #define MAKE_STRING(x) make_cell (tmp_num_ (STRING), x, 0)
352 #endif
353
354 SCM
355 alloc (int n)
356 {
357   assert (g_free + n < ARENA_SIZE);
358   SCM x = g_free;
359   g_free += n;
360   return x;
361 }
362
363 SCM
364 make_cell (SCM type, SCM car, SCM cdr)
365 {
366   SCM x = alloc (1);
367   assert (TYPE (type) == NUMBER);
368   TYPE (x) = VALUE (type);
369   if (VALUE (type) == CHAR || VALUE (type) == NUMBER) {
370     if (car) CAR (x) = CAR (car);
371     if (cdr) CDR(x) = CDR(cdr);
372   } else if (VALUE (type) == FUNCTION) {
373     if (car) CAR (x) = car;
374     if (cdr) CDR(x) = CDR(cdr);
375   } else {
376     CAR (x) = car;
377     CDR(x) = cdr;
378   }
379   return x;
380 }
381
382 SCM
383 tmp_num_ (int x)
384 {
385   VALUE (tmp_num) = x;
386   return tmp_num;
387 }
388
389 SCM
390 tmp_num2_ (int x)
391 {
392   VALUE (tmp_num2) = x;
393   return tmp_num2;
394 }
395
396 SCM
397 cons (SCM x, SCM y)
398 {
399   VALUE (tmp_num) = PAIR;
400   return make_cell (tmp_num, x, y);
401 }
402
403 SCM
404 car (SCM x)
405 {
406 #if MES_MINI
407   //Nyacc
408   //assert ("!car");
409 #else
410   if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_car));
411 #endif
412   return CAR (x);
413 }
414
415 SCM
416 cdr (SCM x)
417 {
418 #if MES_MINI
419   //Nyacc
420   //assert ("!cdr");
421 #else
422   if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_cdr));
423 #endif
424   return CDR(x);
425 }
426
427 SCM
428 gc_push_frame ()
429 {
430   SCM frame = cons (r1, cons (r2, cons (r3, cons (r0, cell_nil))));
431   return g_stack = cons (frame, g_stack);
432 }
433
434 SCM
435 push_cc (SCM p1, SCM p2, SCM a, SCM c) ///((internal))
436 {
437   SCM x = r3;
438   r3 = c;
439   r2 = p2;
440   gc_push_frame ();
441   r1 = p1;
442   r0 = a;
443   r3 = x;
444   return cell_unspecified;
445 }
446
447 SCM caar (SCM x) {return car (car (x));}
448 SCM cadr (SCM x) {return car (cdr (x));}
449 SCM cdar (SCM x) {return cdr (car (x));}
450 SCM cddr (SCM x) {return cdr (cdr (x));}
451
452 SCM
453 gc_peek_frame ()
454 {
455   SCM frame = car (g_stack);
456   r1 = car (frame);
457   r2 = cadr (frame);
458   r3 = car (cddr (frame));
459   r0 = cadr (cddr (frame));
460   return frame;
461 }
462
463 SCM
464 mes_g_stack (SCM a) ///((internal))
465 {
466   r0 = a;
467   r1 = MAKE_CHAR (0);
468   r2 = MAKE_CHAR (0);
469   r3 = MAKE_CHAR (0);
470   g_stack = cons (cell_nil, cell_nil);
471   return r0;
472 }
473
474 //\f Environment setup
475 SCM
476 make_tmps (scm* cells)
477 {
478   tmp = g_free++;
479   cells[tmp].type = CHAR;
480   tmp_num = g_free++;
481   cells[tmp_num].type = NUMBER;
482   tmp_num2 = g_free++;
483   cells[tmp_num2].type = NUMBER;
484 }
485
486 SCM
487 make_symbol_ (SCM s)
488 {
489   VALUE (tmp_num) = SYMBOL;
490   SCM x = make_cell (tmp_num, s, 0);
491   g_symbols = cons (x, g_symbols);
492   return x;
493 }
494
495 SCM
496 make_symbol (SCM s)
497 {
498 #if MES_MINI
499   SCM x = 0;
500 #else
501   SCM x = lookup_symbol_ (s);
502 #endif
503   return x ? x : make_symbol_ (s);
504 }
505
506 SCM
507 cstring_to_list (char const* s)
508 {
509   SCM p = cell_nil;
510   int i = strlen (s);
511   while (i--)
512     p = cons (MAKE_CHAR (s[i]), p);
513   return p;
514 }
515
516 SCM
517 acons (SCM key, SCM value, SCM alist)
518 {
519   return cons (cons (key, value), alist);
520 }
521
522 //\f Jam Collector
523 SCM g_symbol_max;
524
525 SCM
526 gc_init_cells ()
527 {
528   g_cells = (scm *)malloc (2*ARENA_SIZE*sizeof(scm));
529 #if __NYACC__ || FIXME_NYACC
530   TYPE (0) = TVECTOR;
531 // #else
532 //   TYPE (0) = VECTOR;
533 #endif
534   LENGTH (0) = 1000;
535   VECTOR (0) = 0;
536   g_cells++;
537   TYPE (0) = CHAR;
538   VALUE (0) = 'c';
539 }
540
541 // INIT NEWS
542
543 SCM
544 mes_symbols () ///((internal))
545 {
546   gc_init_cells ();
547   //  gc_init_news ();
548
549 #if __GNUC__ && 0
550   //#include "mes.symbols.i"
551 #else
552 g_free++;
553 g_cells[cell_nil] = scm_nil;
554
555 g_free++;
556 g_cells[cell_f] = scm_f;
557
558 g_free++;
559 g_cells[cell_t] = scm_t;
560
561 g_free++;
562 g_cells[cell_dot] = scm_dot;
563
564 g_free++;
565 g_cells[cell_arrow] = scm_arrow;
566
567 g_free++;
568 g_cells[cell_undefined] = scm_undefined;
569
570 g_free++;
571 g_cells[cell_unspecified] = scm_unspecified;
572
573 g_free++;
574 g_cells[cell_closure] = scm_closure;
575
576 g_free++;
577 g_cells[cell_circular] = scm_circular;
578
579 g_free++;
580 g_cells[cell_begin] = scm_begin;
581
582 #endif
583
584   g_symbol_max = g_free;
585   make_tmps (g_cells);
586
587   g_symbols = 0;
588   for (int i=1; i<g_symbol_max; i++)
589     g_symbols = cons (i, g_symbols);
590
591   SCM a = cell_nil;
592
593 #if __GNUC__ && 0
594   //#include "mes.symbol-names.i"
595 #else
596 g_cells[cell_nil].car = cstring_to_list (scm_nil.name);
597 g_cells[cell_f].car = cstring_to_list (scm_f.name);
598 g_cells[cell_t].car = cstring_to_list (scm_t.name);
599 g_cells[cell_dot].car = cstring_to_list (scm_dot.name);
600 g_cells[cell_arrow].car = cstring_to_list (scm_arrow.name);
601 g_cells[cell_undefined].car = cstring_to_list (scm_undefined.name);
602 g_cells[cell_unspecified].car = cstring_to_list (scm_unspecified.name);
603 g_cells[cell_closure].car = cstring_to_list (scm_closure.name);
604 g_cells[cell_circular].car = cstring_to_list (scm_circular.name);
605 g_cells[cell_begin].car = cstring_to_list (scm_begin.name);
606 #endif
607
608   // a = acons (cell_symbol_mes_version, MAKE_STRING (cstring_to_list (VERSION)), a);
609   // a = acons (cell_symbol_mes_prefix, MAKE_STRING (cstring_to_list (PREFIX)), a);
610
611   a = acons (cell_symbol_dot, cell_dot, a); //
612   a = acons (cell_symbol_begin, cell_begin, a);
613   a = acons (cell_closure, a, a);
614
615   // a = acons (cell_symbol_call_with_current_continuation, cell_call_with_current_continuation, a);
616   // a = acons (cell_symbol_sc_expand, cell_f, a);
617
618   return a;
619 }
620
621 SCM
622 mes_environment () ///((internal))
623 {
624   SCM a = mes_symbols ();
625   return mes_g_stack (a);
626 }
627
628 SCM
629 mes_builtins (SCM a)
630 {
631 #if __GNUC__
632 //#include "mes.i"
633
634 // #include "lib.i"
635 // #include "math.i"
636 // #include "posix.i"
637 // #include "reader.i"
638
639 // #include "lib.environment.i"
640 // #include "math.environment.i"
641 // #include "mes.environment.i"
642 // #include "posix.environment.i"
643 // #include "reader.environment.i"
644 #else
645 scm_make_cell.function = g_function;
646 functions[g_function++] = fun_make_cell;
647 cell_make_cell = g_free++;
648 g_cells[cell_make_cell] = scm_make_cell;
649
650 scm_cons.function = g_function;
651 functions[g_function++] = fun_cons;
652 cell_cons = g_free++;
653 g_cells[cell_cons] = scm_cons;
654
655 scm_car.function = g_function;
656 functions[g_function++] = fun_car;
657 cell_car = g_free++;
658 g_cells[cell_car] = scm_car;
659
660 scm_cdr.function = g_function;
661 functions[g_function++] = fun_cdr;
662 cell_cdr = g_free++;
663 g_cells[cell_cdr] = scm_cdr;
664
665 scm_make_cell.string = cstring_to_list (scm_make_cell.name);
666 g_cells[cell_make_cell].string = MAKE_STRING (scm_make_cell.string);
667 a = acons (make_symbol (scm_make_cell.string), cell_make_cell, a);
668
669 scm_cons.string = cstring_to_list (scm_cons.name);
670 g_cells[cell_cons].string = MAKE_STRING (scm_cons.string);
671 a = acons (make_symbol (scm_cons.string), cell_cons, a);
672
673 scm_car.string = cstring_to_list (scm_car.name);
674 g_cells[cell_car].string = MAKE_STRING (scm_car.string);
675 a = acons (make_symbol (scm_car.string), cell_car, a);
676
677 scm_cdr.string = cstring_to_list (scm_cdr.name);
678 g_cells[cell_cdr].string = MAKE_STRING (scm_cdr.string);
679 a = acons (make_symbol (scm_cdr.string), cell_cdr, a);
680 #endif
681   return a;
682 }
683
684 SCM
685 bload_env (SCM a) ///((internal))
686 {
687   g_stdin = open ("module/mes/read-0.mo", 0);
688 #if __GNUC__
689   //g_stdin = g_stdin ? g_stdin : fopen (PREFIX "module/mes/read-0.mo", "r");
690 #endif
691   char *p = (char*)g_cells;
692   assert (getchar () == 'M');
693   assert (getchar () == 'E');
694   assert (getchar () == 'S');
695   g_stack = getchar () << 8;
696   g_stack += getchar ();
697   int c = getchar ();
698   while (c != EOF)
699     {
700       *p++ = c;
701       c = getchar ();
702     }
703   g_free = (p-(char*)g_cells) / sizeof (scm);
704   gc_peek_frame ();
705   g_symbols = r1;
706   g_stdin = STDIN;
707   r0 = mes_builtins (r0);
708   return r2;
709 }
710
711 char const*
712 string_to_cstring (SCM s)
713 {
714   static char buf[1024];
715   char *p = buf;
716   s = STRING(s);
717   while (s != cell_nil)
718     {
719       *p++ = VALUE (car (s));
720       s = cdr (s);
721     }
722   *p = 0;
723   return buf;
724 }
725
726 SCM
727 stderr_ (SCM x)
728 {
729   //SCM write;
730 #if __NYACC__ || FIXME_NYACC
731   if (TYPE (x) == TSTRING)
732 // #else
733 //   if (TYPE (x) == STRING)
734 #endif
735     eputs (string_to_cstring (x));
736   // else if ((write = assq_ref_cache (cell_symbol_write, r0)) != cell_undefined)
737   //   apply (assq_ref_cache (cell_symbol_display, r0), cons (x, cons (MAKE_NUMBER (2), cell_nil)), r0);
738 #if __NYACC__ || FIXME_NYACC
739   else if (TYPE (x) == SPECIAL || TYPE (x) == TSTRING || TYPE (x) == SYMBOL)
740 // #else
741 //   else if (TYPE (x) == SPECIAL || TYPE (x) == STRING || TYPE (x) == SYMBOL)
742 #endif
743     eputs (string_to_cstring (x));
744   else if (TYPE (x) == NUMBER)
745     eputs (itoa (VALUE (x)));
746   else
747     eputs ("display: undefined\n");
748   return cell_unspecified;
749 }
750
751 int
752 main (int argc, char *argv[])
753 {
754 #if __GNUC__
755   //g_debug = getenv ("MES_DEBUG");
756 #endif
757   //if (getenv ("MES_ARENA")) ARENA_SIZE = atoi (getenv ("MES_ARENA"));
758   if (argc > 1 && !strcmp (argv[1], "--help")) return eputs ("Usage: mes [--dump|--load] < FILE");
759   if (argc > 1 && !strcmp (argv[1], "--version")) {eputs ("Mes ");return eputs (VERSION);};
760   g_stdin = STDIN;
761   r0 = mes_environment ();
762
763 #if MES_MINI
764   SCM program = bload_env (r0);
765 #else  
766   SCM program = (argc > 1 && !strcmp (argv[1], "--load"))
767     ? bload_env (r0) : load_env (r0);
768   if (argc > 1 && !strcmp (argv[1], "--dump")) return dump ();
769 #endif
770
771   push_cc (r2, cell_unspecified, r0, cell_unspecified);
772   // r3 = cell_vm_begin;
773   // r1 = eval_apply ();
774   stderr_ (r1);
775
776   eputs ("\n");
777 #if !MES_MINI
778   gc (g_stack);
779 #endif
780 #if __GNUC__
781   if (g_debug)
782     {
783       eputs ("\nstats: [");
784       eputs (itoa (g_free));
785       eputs ("]\n");
786     }
787 #endif
788   puts ("Hello mini-mes!\n");
789   return 0;
790 }
791
792 #if __GNUC__
793 void
794 _start ()
795 {
796   int r;
797   asm (
798        "mov %%ebp,%%eax\n\t"
799        "addl $8,%%eax\n\t"
800        "push %%eax\n\t"
801
802        "mov %%ebp,%%eax\n\t"
803        "addl $4,%%eax\n\t"
804        "movzbl (%%eax),%%eax\n\t"
805        "push %%eax\n\t"
806
807        "call main\n\t"
808        "movl %%eax,%0\n\t"
809        : "=r" (r)
810        : //no inputs "" (&main)
811        );
812   exit (r);
813 }
814 #endif