├── test ├── benz │ ├── expected.txt │ ├── Makefile │ ├── main.c │ └── repl.c ├── nop.c ├── nonreturn.c ├── syntax-error.c ├── test.h ├── cast2.c ├── compound_assign_die.c ├── helloworld.c ├── string-literal4.c ├── array-2d.c ├── cond.c ├── local_static.c ├── unsigned-const.c ├── literal.c ├── not.c ├── numeric_literal.c ├── static-struct.c ├── ident3.c ├── init.c ├── long-short.c ├── array-init.c ├── cond2.c ├── ident1.c ├── neq.c ├── proto.c ├── array-init-global.c ├── addr.c ├── call-fun.c ├── ident2.c ├── ident4.c ├── local_nolink.c ├── local_extern.c ├── union-rec.c ├── 2-param.c ├── const.c ├── div_minus.c ├── mul.c ├── void-pointer.c ├── asm.c ├── bitwise.c ├── while.c ├── volatile.c ├── dowhile.c ├── pre-inc.c ├── assign-to-arg.c ├── postinc.c ├── putchar.c ├── float-const.c ├── shift.c ├── fib-loop.c ├── sizeof_expr.c ├── return.c ├── array-init4.c ├── puts.c ├── string-literal.c ├── struct-init3.c ├── if.c ├── string-literal3.c ├── local_static3.c ├── local_extern2.c ├── logical.c ├── type_spec.c ├── array-vs-pointer.c ├── fib-rec.c ├── pointer.c ├── compound_assign.c ├── pointer-inc.c ├── unsigned-logical.c ├── global.c ├── static-init.c ├── struct2.c ├── struct-init-global.c ├── char-cast.c ├── string-literal2.c ├── struct-in-union.c ├── struct-in-struct.c ├── union-in-union.c ├── rand.c ├── union-in-struct.c ├── break.c ├── char-arg.c ├── fold_const2.c ├── printf.c ├── unsigned-types.c ├── cast-args.c ├── array-pointer.c ├── array.c ├── global-float.c ├── struct4.c ├── overflow.c ├── union-rec2.c ├── assign-float.c ├── calloc.c ├── pointer-sub.c ├── fib-dp.c ├── typedef.c ├── proto2.c ├── shift2.c ├── stdarg.c ├── struct1.c ├── unsigned-divmod.c ├── local_static2.c ├── struct3.c ├── comb.c ├── combination.c ├── isprime.c ├── cast.c ├── cast-return.c ├── muldiv.c ├── struct-init.c ├── compound_assign4.c ├── union.c ├── sizeof.c ├── character.c ├── pointer-postinc.c ├── struct-passing.c ├── goto.c ├── struct5.c ├── function-pointer.c ├── array-init-global2.c ├── array-init3.c ├── setjmp.c ├── pointer-compare.c ├── string-literal-global.c ├── prime.c ├── fold_expr.c ├── compound_assign2.c ├── struct-init2.c ├── compound_assign3.c ├── malloc-fail.c ├── enum.c ├── array-init2.c ├── continue.c ├── array-3d.c ├── fold_const.c ├── sizeof-padding.c ├── xorshift.c ├── variable-assign.c ├── assign.c ├── variadic-cast.c ├── double.c ├── sqrt.c ├── float.c ├── struct-assign.c ├── eratos.c ├── parameter-array.c ├── string.c ├── float-cond.c ├── limits.c ├── unsigned-compare.c ├── _test.pl ├── struct6.c ├── short.c ├── printf2.c ├── unsigned-compare2.c ├── comp.c ├── scope.c ├── list.c ├── fizzbuzz.c ├── switch.c ├── assign-global.c ├── merge-sort.c ├── _malloc.c ├── calculator.c └── miller-rabin.c ├── .proverc ├── .travis.yml ├── bin ├── run └── ucc ├── .gitignore ├── include ├── stddef.h ├── setjmp.h ├── stdbool.h ├── ctype.h ├── stdarg.h ├── assert.h ├── stdlib.h ├── math.h ├── string.h ├── limits.h └── stdio.h ├── .gitmodules ├── travis-ci.sh ├── src ├── parser_helper.ml ├── syntax.ml ├── main.ml ├── util.ml ├── typed_syntax.ml ├── lexer.mll ├── ctype.ml ├── parser.mly └── typing.ml ├── Makefile ├── README.md └── lib ├── libucc.c ├── libm.c └── libc.c /test/benz/expected.txt: -------------------------------------------------------------------------------- 1 | 3628800 2 | -------------------------------------------------------------------------------- /.proverc: -------------------------------------------------------------------------------- 1 | --exec "timeout 20 test/_test.pl" 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | script: bash -ex travis-ci.sh -------------------------------------------------------------------------------- /test/nop.c: -------------------------------------------------------------------------------- 1 | /* 2 | */ 3 | #include "test.h" 4 | int main () { 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /test/nonreturn.c: -------------------------------------------------------------------------------- 1 | /* 2 | */ 3 | #include "test.h" 4 | int f (int x) { 5 | } 6 | int main () { 7 | f(1); 8 | } 9 | -------------------------------------------------------------------------------- /test/syntax-error.c: -------------------------------------------------------------------------------- 1 | /* 2 | DEAD 3 | */ 4 | #include "test.h" 5 | 6 | int main() 7 | { 8 | a 9 | } 10 | -------------------------------------------------------------------------------- /bin/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | dir=`dirname "$0"` 3 | $dir/ucc -o ${1%.*}.out $1 || exit 1 4 | $dir/sim -simple ${1%.*}.out 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.i 3 | *.s 4 | *.out 5 | _build/ 6 | bin/as 7 | bin/cc 8 | bin/sim 9 | test/benz/log.txt 10 | test/benz/build/ 11 | -------------------------------------------------------------------------------- /test/test.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_H_ 2 | #define TEST_H_ 3 | 4 | #include 5 | #define print_int(n) printf("%d\n", n) 6 | 7 | #endif /* test.h */ 8 | -------------------------------------------------------------------------------- /test/cast2.c: -------------------------------------------------------------------------------- 1 | /* 2 | A 3 | */ 4 | 5 | #include "test.h" 6 | 7 | int main() 8 | { 9 | putchar((unsigned char)65); 10 | putchar('\n'); 11 | } 12 | -------------------------------------------------------------------------------- /test/compound_assign_die.c: -------------------------------------------------------------------------------- 1 | /* 2 | DEAD 3 | */ 4 | 5 | #include "test.h" 6 | 7 | int main() 8 | { 9 | int *p, *q; 10 | 11 | p -= q; 12 | } 13 | -------------------------------------------------------------------------------- /test/helloworld.c: -------------------------------------------------------------------------------- 1 | /* 2 | Hello World! 3 | */ 4 | 5 | #include "test.h" 6 | 7 | int main () { 8 | printf("Hello World!\n"); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /test/string-literal4.c: -------------------------------------------------------------------------------- 1 | /* 2 | Hello, World 3 | */ 4 | 5 | #include "test.h" 6 | 7 | int main() 8 | { 9 | printf("Hel" "lo, " "World\n"); 10 | } 11 | -------------------------------------------------------------------------------- /test/array-2d.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | */ 4 | #include "test.h" 5 | 6 | int main () { 7 | int a[2][2]; 8 | a[0][1] = 2; 9 | print_int(a[0][1]); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /include/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_STDDEF_H 2 | #define _UCC_STDDEF_H 3 | 4 | #define NULL 0 5 | typedef unsigned size_t; 6 | typedef int ptrdiff_t; 7 | 8 | #endif /* stddef.h */ 9 | -------------------------------------------------------------------------------- /test/cond.c: -------------------------------------------------------------------------------- 1 | /* 2 | 42 3 | 42 4 | */ 5 | #include "test.h" 6 | 7 | int main() 8 | { 9 | print_int(1 ? 42 : 3); 10 | print_int(0 ? 3 : 42); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /test/local_static.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 3 | */ 4 | 5 | #include "test.h" 6 | 7 | int main() 8 | { 9 | static int a = 3; 10 | 11 | print_int(a); 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /test/unsigned-const.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 0 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int main () { 9 | print_int(-1 < 0); 10 | print_int(-1u < 0); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /test/literal.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 0 4 | */ 5 | 6 | #include 7 | 8 | int main() 9 | { 10 | printf("%d\n", 1L < -3u); 11 | printf("%d\n", -42 < 123ul); 12 | } 13 | -------------------------------------------------------------------------------- /include/setjmp.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_SETJMP_H 2 | #define _UCC_SETJMP_H 3 | 4 | typedef int jmp_buf[4]; 5 | int setjmp(jmp_buf); 6 | void longjmp(jmp_buf, int); 7 | 8 | #endif /* setjmp.h */ 9 | -------------------------------------------------------------------------------- /test/not.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 0 4 | 0 5 | */ 6 | #include "test.h" 7 | 8 | int main() 9 | { 10 | print_int(! 0); 11 | print_int(! 1); 12 | print_int(! 2); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /test/numeric_literal.c: -------------------------------------------------------------------------------- 1 | /* 2 | 171 3 | 83 4 | */ 5 | #include "test.h" 6 | int main () { 7 | int a = 0xab; 8 | int b = 0123; 9 | print_int(a); 10 | print_int(b); 11 | } 12 | -------------------------------------------------------------------------------- /test/static-struct.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | */ 4 | #include "test.h" 5 | 6 | static struct s { 7 | int a; 8 | } x; 9 | 10 | int main () { 11 | x.a = 1; 12 | print_int(x.a); 13 | } 14 | -------------------------------------------------------------------------------- /test/ident3.c: -------------------------------------------------------------------------------- 1 | /* 2 | ok 3 | */ 4 | 5 | #include "test.h" 6 | 7 | enum { foo }; 8 | 9 | struct foo { 10 | int bar; 11 | }; 12 | 13 | int main() 14 | { 15 | printf("ok\n"); 16 | } 17 | -------------------------------------------------------------------------------- /test/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | 6 3 | */ 4 | #include "test.h" 5 | 6 | int main() 7 | { 8 | int a = 1, b = 2, c; 9 | 10 | c = 3; 11 | 12 | print_int(a + b + c); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /test/long-short.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | */ 5 | #include "test.h" 6 | 7 | int main () { 8 | long l = 1; 9 | short b = 2; 10 | print_int(l); 11 | print_int(b); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /test/array-init.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 0 5 | */ 6 | #include "test.h" 7 | int main() { 8 | int a[3] = { 1, 2 }; 9 | print_int(a[0]); 10 | print_int(a[1]); 11 | print_int(a[2]); 12 | } 13 | -------------------------------------------------------------------------------- /test/cond2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2.0000 3 | 3.0000 4 | */ 5 | 6 | #include 7 | 8 | int main() 9 | { 10 | printf("%.4f\n", 2 * (0 ? 1.5 : 1)); 11 | printf("%.4f\n", 2 * (1 ? 1.5 : 1)); 12 | } 13 | -------------------------------------------------------------------------------- /test/ident1.c: -------------------------------------------------------------------------------- 1 | /* 2 | ok 3 | */ 4 | 5 | #include "test.h" 6 | 7 | typedef struct foo foo; 8 | 9 | struct foo { 10 | int bar; 11 | }; 12 | 13 | int main() 14 | { 15 | printf("ok\n"); 16 | } 17 | -------------------------------------------------------------------------------- /include/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_STDBOOL_H 2 | #define _UCC_STDBOOL_H 3 | 4 | #define bool int 5 | #define true 1 6 | #define false 0 7 | #define __bool_true_false_are_defined 1 8 | 9 | #endif /* stdbool.h */ 10 | -------------------------------------------------------------------------------- /test/neq.c: -------------------------------------------------------------------------------- 1 | /* 2 | 42 3 | */ 4 | #include "test.h" 5 | 6 | int main() 7 | { 8 | int a, b; 9 | 10 | a = 0; 11 | b = 1; 12 | if (a != b) { 13 | print_int(42); 14 | } 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/proto.c: -------------------------------------------------------------------------------- 1 | /* 2 | 5 3 | */ 4 | #include "test.h" 5 | 6 | int foo(int, int); 7 | 8 | int foo(int a, int b) 9 | { 10 | return a + b; 11 | } 12 | 13 | int main() 14 | { 15 | print_int(foo(2,3)); 16 | } 17 | -------------------------------------------------------------------------------- /test/array-init-global.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 42 4 | 0 5 | */ 6 | #include "test.h" 7 | int a[1]; 8 | int b[2] = { 42 }; 9 | int main() { 10 | print_int(a[0]); 11 | print_int(b[0]); 12 | print_int(b[1]); 13 | } 14 | -------------------------------------------------------------------------------- /test/addr.c: -------------------------------------------------------------------------------- 1 | /* 2 | 5, 8 3 | */ 4 | 5 | #include 6 | 7 | int main() 8 | { 9 | int a[3][3] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; 10 | 11 | (&printf)("%d, %d\n", (&*a)[1][2], ((int *)(&a + 1))[-1]); 12 | } 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "extlib/gaia"] 2 | path = extlib/gaia 3 | url = https://github.com/b-inary/gaia-software.git 4 | [submodule "extlib/benz-gaia"] 5 | path = extlib/benz-gaia 6 | url = https://github.com/wasabiz/benz-gaia.git 7 | -------------------------------------------------------------------------------- /test/call-fun.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | */ 4 | #include "test.h" 5 | 6 | int f (int x) { 7 | return x+1; 8 | } 9 | 10 | int g(int x) { 11 | return f(x+1); 12 | } 13 | 14 | int main () { 15 | print_int(g(0)); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/ident2.c: -------------------------------------------------------------------------------- 1 | /* 2 | ok 3 | */ 4 | 5 | #include "test.h" 6 | 7 | struct foo { 8 | int bar; 9 | }; 10 | 11 | typedef struct foo bar; 12 | 13 | int main() 14 | { 15 | bar a; 16 | a.bar; 17 | 18 | printf("ok\n"); 19 | } 20 | -------------------------------------------------------------------------------- /test/ident4.c: -------------------------------------------------------------------------------- 1 | /* 2 | ok 3 | */ 4 | 5 | #include "test.h" 6 | 7 | void foo(void) { typedef int hoge; } 8 | void bar(void) { typedef int hoge; } 9 | 10 | int main() 11 | { 12 | foo, bar; 13 | 14 | printf("ok\n"); 15 | } 16 | -------------------------------------------------------------------------------- /test/local_nolink.c: -------------------------------------------------------------------------------- 1 | /* 2 | 7 3 | */ 4 | 5 | #include "test.h" 6 | 7 | int add(int a, int b) 8 | { 9 | return a + b; 10 | } 11 | 12 | int main() 13 | { 14 | int add(int, int); 15 | 16 | printf("%d\n", add(3,4)); 17 | } 18 | -------------------------------------------------------------------------------- /test/local_extern.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 3 | */ 4 | 5 | #include "test.h" 6 | 7 | int main() 8 | { 9 | extern int add(int a, int b); 10 | 11 | print_int(add(1, 2)); 12 | } 13 | 14 | int add(int a, int b) 15 | { 16 | return a + b; 17 | } 18 | -------------------------------------------------------------------------------- /test/union-rec.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | */ 4 | 5 | #include "test.h" 6 | 7 | union foo { 8 | union foo *p; 9 | int x; 10 | }; 11 | 12 | int main() 13 | { 14 | union foo f; 15 | 16 | print_int(1); 17 | 18 | return 0; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /test/2-param.c: -------------------------------------------------------------------------------- 1 | /* 2 | 13 3 | */ 4 | #include "test.h" 5 | 6 | int add(int x, int y){ 7 | if (x==0) { 8 | return y; 9 | } else { 10 | return 1+add(x-1,y); 11 | } 12 | } 13 | 14 | int main () { 15 | print_int(add(3,10)); 16 | } 17 | -------------------------------------------------------------------------------- /test/const.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 0 4 | 0 5 | */ 6 | #include "test.h" 7 | 8 | int main() 9 | { 10 | const int i = 0; 11 | int const * j = 0; 12 | int * const k = 0; 13 | 14 | print_int(i); 15 | print_int(j); 16 | print_int(k); 17 | } 18 | -------------------------------------------------------------------------------- /test/div_minus.c: -------------------------------------------------------------------------------- 1 | /* 2 | 7 3 | -7 4 | -7 5 | 7 6 | */ 7 | #include "test.h" 8 | 9 | int main () { 10 | int x = 23; 11 | print_int(x / 3); 12 | print_int(-x / 3); 13 | print_int(x / -3); 14 | print_int(-x / -3); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /test/mul.c: -------------------------------------------------------------------------------- 1 | /* 2 | -3 3 | -3 4 | 9 5 | */ 6 | #include "test.h" 7 | 8 | int 9 | main() 10 | { 11 | int a, b; 12 | 13 | a = -1; 14 | b = 3; 15 | 16 | print_int(a * b); 17 | print_int(b * a); 18 | 19 | print_int(-3 * -3); 20 | } 21 | -------------------------------------------------------------------------------- /test/void-pointer.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 3 5 | */ 6 | #include "test.h" 7 | 8 | int main () { 9 | long a[3] = {1,2,3}; 10 | int *p; 11 | p = (int*)(void*)a; 12 | print_int(p[0]); 13 | print_int(p[1]); 14 | print_int(p[2]); 15 | } 16 | -------------------------------------------------------------------------------- /test/asm.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | */ 4 | int main () { 5 | __asm("\ 6 | mov r1, 48 \n\ 7 | mov r2, 2 \n\ 8 | add r1, r1, r2 \n\ 9 | write r1 \n\ 10 | mov r1, 10 \n\ 11 | write r1 \n\ 12 | "); 13 | } 14 | -------------------------------------------------------------------------------- /test/bitwise.c: -------------------------------------------------------------------------------- 1 | /* 2 | 4 3 | 15 4 | -14 5 | 11 6 | */ 7 | #include "test.h" 8 | 9 | int main () { 10 | print_int(13 & 6); // 4 11 | print_int(13 | 6); // 15 12 | print_int(~13); // -14 13 | print_int(13 ^ 6); // 11 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /test/while.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | 3 6 | 4 7 | 5 8 | 6 9 | 7 10 | 8 11 | 9 12 | 10 13 | */ 14 | #include "test.h" 15 | 16 | int main () { 17 | int i; 18 | i=0; 19 | while (i<=10) { 20 | print_int(i++); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /travis-ci.sh: -------------------------------------------------------------------------------- 1 | # install ocaml from apt 2 | yes yes | sudo add-apt-repository ppa:avsm/ppa 3 | sudo apt-get update -qq 4 | sudo apt-get install -qq ocaml ocaml-native-compilers 5 | 6 | ocaml -version 7 | 8 | # compile & run tests 9 | make test-all 10 | -------------------------------------------------------------------------------- /test/volatile.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 0 4 | 0 5 | */ 6 | #include "test.h" 7 | 8 | int main() 9 | { 10 | volatile int i = 0; 11 | int volatile * j = 0; 12 | int * volatile k = 0; 13 | 14 | print_int(i); 15 | print_int(j); 16 | print_int(k); 17 | } 18 | -------------------------------------------------------------------------------- /test/dowhile.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | 3 6 | 4 7 | 5 8 | 6 9 | 7 10 | 8 11 | 9 12 | */ 13 | #include "test.h" 14 | 15 | int main () { 16 | int i; 17 | i = 0; 18 | do { 19 | print_int(i); 20 | i++; 21 | } while (i<10); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /test/pre-inc.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 1 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int say_one() 9 | { 10 | print_int(1); 11 | return 1; 12 | } 13 | 14 | int main() 15 | { 16 | int a[3] = {0}; 17 | 18 | ++a[say_one()]; 19 | 20 | print_int(a[1]); 21 | } 22 | -------------------------------------------------------------------------------- /test/assign-to-arg.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | 1 4 | 2 5 | */ 6 | #include "test.h" 7 | 8 | int fun (int x) { 9 | print_int(x); 10 | x -= 1; 11 | print_int(x); 12 | return 0; 13 | } 14 | 15 | int main () { 16 | int a=2; 17 | fun(a); 18 | print_int(a); 19 | } 20 | -------------------------------------------------------------------------------- /test/postinc.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | 3 6 | 2 7 | 1 8 | */ 9 | #include "test.h" 10 | int main () { 11 | int i=0; 12 | print_int(i++); 13 | print_int(i++); 14 | print_int(i++); 15 | print_int(i--); 16 | print_int(i--); 17 | print_int(i--); 18 | } 19 | -------------------------------------------------------------------------------- /test/putchar.c: -------------------------------------------------------------------------------- 1 | /* 2 | Hello! 3 | 42 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int main () { 9 | putchar('H'); 10 | putchar('e'); 11 | putchar('l'); 12 | putchar('l'); 13 | putchar('o'); 14 | putchar('!'); 15 | putchar('\n'); 16 | print_int(42); 17 | } 18 | -------------------------------------------------------------------------------- /test/float-const.c: -------------------------------------------------------------------------------- 1 | /* 2 | -10000.0000 3 | 10000.0000 4 | 0.0012 5 | 3000.0000 6 | */ 7 | 8 | #include 9 | 10 | int main () { 11 | printf("%.4f\n", -1e4f); 12 | printf("%.4f\n", 1.e4); 13 | printf("%.4f\n", 1.2e-3F); 14 | printf("%.4f\n", .3e+4); 15 | } 16 | -------------------------------------------------------------------------------- /test/shift.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | 4 4 | 8 5 | 9 6 | 4 7 | 2 8 | */ 9 | #include "test.h" 10 | 11 | 12 | 13 | int main () { 14 | print_int(1<<1); 15 | print_int(1<<2); 16 | print_int(1<<3); 17 | print_int(18>>1); 18 | print_int(18>>2); 19 | print_int(18>>3); 20 | } 21 | -------------------------------------------------------------------------------- /include/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_CTYPE_H 2 | #define _UCC_CTYPE_H 3 | 4 | int isalnum(int); 5 | int isalpha(int); 6 | int isdigit(int); 7 | int islower(int); 8 | int isspace(int); 9 | int isupper(int); 10 | int tolower(int); 11 | int toupper(int); 12 | 13 | #endif /* ctype.h */ 14 | -------------------------------------------------------------------------------- /test/fib-loop.c: -------------------------------------------------------------------------------- 1 | /* 2 | 832040 3 | */ 4 | #include "test.h" 5 | 6 | int main () { 7 | int a, b, i, n; 8 | a = 0;b = 1;n = 30; 9 | for (i=1; i<=n; i+=1) { 10 | int t; 11 | t = b; 12 | b += a; 13 | a = t; 14 | } 15 | print_int(a); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/sizeof_expr.c: -------------------------------------------------------------------------------- 1 | /* 2 | 256 3 | 4096 4 | 6 5 | */ 6 | 7 | #include "test.h" 8 | 9 | int main() 10 | { 11 | char buf[256]; 12 | struct { int a, b[3]; } buf2[256]; 13 | 14 | print_int(sizeof(buf)); 15 | print_int(sizeof buf2); 16 | print_int(sizeof "abcde"); 17 | } 18 | -------------------------------------------------------------------------------- /test/return.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | 3 4 | 5 5 | */ 6 | 7 | #include "test.h" 8 | 9 | void foo() 10 | { 11 | print_int(3); 12 | return; 13 | print_int(4); 14 | } 15 | 16 | int main() 17 | { 18 | print_int(2); 19 | foo(); 20 | print_int(5); 21 | return 0; 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /include/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_STDARG_H 2 | #define _UCC_STDARG_H 3 | 4 | #define va_arg(ap, type) (*((type *)(ap = (type *)ap + 1) - 1)) 5 | #define va_start(ap, arg) (ap = &(arg) + 1) 6 | #define va_end(ap) ((void) 0) 7 | typedef void *va_list; 8 | 9 | #endif /* stdarg.h */ 10 | -------------------------------------------------------------------------------- /test/array-init4.c: -------------------------------------------------------------------------------- 1 | /* 2 | HelloWorld 3 | */ 4 | 5 | #include "test.h" 6 | 7 | char buf[][5] = { "Hello", "World" }; 8 | 9 | int main() 10 | { 11 | int i; 12 | for (i = 0; i < sizeof buf; ++i) { 13 | putchar(((char*)buf)[i]); 14 | } 15 | putchar('\n'); 16 | } 17 | -------------------------------------------------------------------------------- /test/puts.c: -------------------------------------------------------------------------------- 1 | /* 2 | Hello World! 3 | Hello World! 4 | 1 13 5 | */ 6 | 7 | #include 8 | 9 | int main (){ 10 | int a, b; 11 | 12 | a = fputs("Hello World!\n", stdout); 13 | b = puts("Hello World!"); 14 | 15 | printf("%d %d\n", a, b); 16 | 17 | return 0; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /test/string-literal.c: -------------------------------------------------------------------------------- 1 | /* 2 | 72 3 | 101 4 | 108 5 | 108 6 | 111 7 | 10 8 | 0 9 | */ 10 | #include "test.h" 11 | 12 | int 13 | main() 14 | { 15 | 16 | char a[7] = "Hello\n"; 17 | int i; 18 | 19 | for (i = 0; i < 7; ++i) { 20 | print_int(a[i]); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /test/struct-init3.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 2.000000 3.000000 3 | */ 4 | #include 5 | typedef struct {int x; float a;} foo; 6 | int main() { 7 | foo a = { 1, 2.0}; 8 | foo b = a; 9 | float f = b.a + 1; 10 | 11 | printf("%d %f %f\n", b.x, b.a, f); 12 | 13 | return 0; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /test/if.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 3 | 3 4 | */ 5 | #include "test.h" 6 | 7 | int main() 8 | { 9 | int a = 3; 10 | if (a == 3) 11 | print_int(3); 12 | 13 | if (a == 4) 14 | print_int(5); 15 | else 16 | if (a == 3) 17 | print_int(3); 18 | else 19 | print_int(4); 20 | } 21 | -------------------------------------------------------------------------------- /test/string-literal3.c: -------------------------------------------------------------------------------- 1 | /* 2 | Hello world! 3 | Hello world! 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int main() { 9 | char a[2][10] = { "Hello", "world!" }; 10 | char *p[2] = { "Hello", "world!" }; 11 | printf("%s %s\n", a[0], a[1]); 12 | printf("%s %s\n", p[0], p[1]); 13 | } 14 | -------------------------------------------------------------------------------- /test/local_static3.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | */ 6 | 7 | #include "test.h" 8 | 9 | int foo() 10 | { 11 | static int x; /* no init */ 12 | 13 | return x++; 14 | } 15 | 16 | int main() 17 | { 18 | print_int(foo()); 19 | print_int(foo()); 20 | print_int(foo()); 21 | } 22 | -------------------------------------------------------------------------------- /test/local_extern2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 3 | 5 4 | */ 5 | 6 | #include "test.h" 7 | 8 | void assign5(); 9 | 10 | int main() 11 | { 12 | extern int a; 13 | 14 | print_int(a); 15 | 16 | assign5(); 17 | 18 | print_int(a); 19 | } 20 | 21 | int a = 3; 22 | 23 | void assign5() 24 | { 25 | a = 5; 26 | } 27 | -------------------------------------------------------------------------------- /test/logical.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 1 5 | 1 6 | 0 7 | */ 8 | #include "test.h" 9 | 10 | int main() 11 | { 12 | print_int(1 && 2 && 0 && 3); 13 | print_int(1 && 2 && 3); 14 | 15 | print_int(1 || 2 || 0); 16 | print_int(0 || 2 || 1); 17 | print_int(0 || 0 || 0); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /test/type_spec.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 0 5 | */ 6 | #include 7 | 8 | typedef unsigned long ulong; 9 | int main () { 10 | unsigned int a=0; 11 | unsigned long int b = -1; 12 | ulong c = 2; 13 | printf("%d\n", a); 14 | printf("%d\n", b>c); 15 | printf("%d\n", b=0; i--) { 21 | print_int(*(p--)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/unsigned-logical.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 1 5 | 1 6 | 0 7 | */ 8 | #include "test.h" 9 | 10 | int main () { 11 | unsigned a = 0, b=1, c=2, d=3; 12 | print_int(b && c && a && d); 13 | print_int(b && c && d); 14 | 15 | print_int(b || c || a); 16 | print_int(a || c || b); 17 | print_int(a || a || a); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /test/global.c: -------------------------------------------------------------------------------- 1 | /* 2 | 100 3 | 10 4 | */ 5 | #include "test.h" 6 | 7 | int count = 100; 8 | 9 | int inc () { 10 | count += 1; 11 | return 0; 12 | } 13 | 14 | int main () { 15 | int i; 16 | print_int(count); 17 | count = 0; 18 | for (i=0; i< 10; i++) { 19 | inc (); 20 | } 21 | print_int(count); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /test/static-init.c: -------------------------------------------------------------------------------- 1 | /* 2 | hello 3 | abcd1234 4 | */ 5 | 6 | #include 7 | 8 | char buf[][4] = { "abcd", "1234", "\n" }; 9 | char *p = (char*)buf; 10 | 11 | void foo() 12 | { 13 | printf("hello\n"); 14 | } 15 | 16 | int main() 17 | { 18 | static void (*f)() = foo; 19 | f(); 20 | for (; *p; ++p) putchar(*p); 21 | } 22 | -------------------------------------------------------------------------------- /test/struct2.c: -------------------------------------------------------------------------------- 1 | /* 2 | -2 3 | */ 4 | #include "test.h" 5 | 6 | struct matrix { 7 | int a[2], b[2]; 8 | }; 9 | 10 | int main () { 11 | int det; 12 | struct matrix mat; 13 | mat.a[0] = 1; 14 | mat.a[1] = 2; 15 | mat.b[0] = 3; 16 | mat.b[1] = 4; 17 | det = (mat.a[0]*mat.b[1]) - (mat.a[1]*mat.b[0]); 18 | print_int(det); 19 | } 20 | -------------------------------------------------------------------------------- /test/struct-init-global.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 3 5 | 4 6 | */ 7 | #include "test.h" 8 | 9 | struct foo { 10 | int a; 11 | int b[2]; 12 | int c; 13 | }; 14 | 15 | struct foo f = { 1, { 2, 3 }, 4 }; 16 | 17 | int main() { 18 | print_int(f.a); 19 | print_int(f.b[0]); 20 | print_int(f.b[1]); 21 | print_int(f.c); 22 | } 23 | -------------------------------------------------------------------------------- /include/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_ASSERT_H 2 | #define _UCC_ASSERT_H 3 | 4 | #ifdef NDEBUG 5 | 6 | #define assert(expr) ((void) 0) 7 | 8 | #else 9 | 10 | void __assert_fail(const char *, const char *, int); 11 | #define assert(expr) \ 12 | ((expr) ? (void) 0 : __assert_fail(#expr, __FILE__, __LINE__)) 13 | 14 | #endif 15 | 16 | #endif /* assert.h */ 17 | -------------------------------------------------------------------------------- /test/char-cast.c: -------------------------------------------------------------------------------- 1 | /* 2 | 260 3 | 4 4 | 4 5 | -42 6 | 214 7 | */ 8 | #include 9 | 10 | int main() { 11 | float f = 260, g = -42.5; 12 | int a, b; 13 | char c; 14 | unsigned char uc; 15 | a = f; 16 | b = (char)f; 17 | c = a; 18 | printf("%d\n%d\n%d\n", a, b, c); 19 | c = g; 20 | uc = c; 21 | printf("%d\n%d\n", c, uc); 22 | } 23 | -------------------------------------------------------------------------------- /test/string-literal2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 72 3 | 101 4 | 108 5 | 108 6 | 111 7 | 44 8 | 32 9 | 87 10 | 111 11 | 114 12 | 108 13 | 100 14 | 33 15 | 10 16 | */ 17 | #include "test.h" 18 | 19 | int 20 | main() 21 | { 22 | 23 | char *p = "Hello, World!\n"; 24 | int i = 0; 25 | 26 | while (p[i]) { 27 | print_int(p[i++]); 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /test/struct-in-union.c: -------------------------------------------------------------------------------- 1 | /* 2 | 7 3 | 8 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int main() { 9 | union tag { 10 | int a; 11 | struct { int b; char c; } s; 12 | } x; 13 | union tag y; 14 | x.a = 1; 15 | x.s.b = 2; 16 | y.s.c = 3; 17 | print_int(x.a + x.s.b + y.s.c); 18 | print_int(sizeof(union tag)); 19 | } 20 | -------------------------------------------------------------------------------- /test/struct-in-struct.c: -------------------------------------------------------------------------------- 1 | /* 2 | 6 3 | 12 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int main() { 9 | struct tag { 10 | int a; 11 | struct { int b; char c; } s; 12 | } x; 13 | struct tag y; 14 | x.a = 1; 15 | x.s.b = 2; 16 | y.s.c = 3; 17 | print_int(x.a + x.s.b + y.s.c); 18 | print_int(sizeof(struct tag)); 19 | } 20 | -------------------------------------------------------------------------------- /test/union-in-union.c: -------------------------------------------------------------------------------- 1 | /* 2 | 8 3 | 8 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int main() { 9 | union tag { 10 | int a; 11 | union { int b; int c[2]; } u; 12 | } x; 13 | union tag y; 14 | x.a = 1; 15 | x.u.b = 2; 16 | y.u.c[0] = 3; 17 | print_int(y.a + y.u.b + x.u.c[0]); 18 | print_int(sizeof(union tag)); 19 | } 20 | -------------------------------------------------------------------------------- /test/rand.c: -------------------------------------------------------------------------------- 1 | /* 2 | 479142414 3 | 465566339 4 | 961126155 5 | 1057886067 6 | 1222702060 7 | 1017450741 8 | 1019879755 9 | 72282698 10 | 2048787572 11 | 2058368053 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | int main() 18 | { 19 | int i; 20 | srand(1234); 21 | for (i = 0; i < 10; ++i) 22 | printf("%d\n", rand()); 23 | } 24 | -------------------------------------------------------------------------------- /test/union-in-struct.c: -------------------------------------------------------------------------------- 1 | /* 2 | 6 3 | 12 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int main() { 9 | struct tag { 10 | int a; 11 | union { int b; int c[2]; } u; 12 | } x; 13 | struct tag y; 14 | x.a = 1; 15 | x.u.b = 2; 16 | y.u.c[0] = 3; 17 | print_int(x.a + y.u.b + x.u.c[0]); 18 | print_int(sizeof(struct tag)); 19 | } 20 | -------------------------------------------------------------------------------- /test/break.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 0 4 | 1 5 | 10 6 | 2 7 | 20 8 | */ 9 | #include "test.h" 10 | 11 | 12 | int main () { 13 | int i; 14 | for (i=0;i<3;++i) { 15 | int j; 16 | j=0; 17 | while (1) { 18 | if (j==10*i) { 19 | break; 20 | } 21 | ++j; 22 | } 23 | print_int(i); 24 | print_int(j); 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/char-arg.c: -------------------------------------------------------------------------------- 1 | /* 2 | a b 3 | c d 4 | e f 5 | g h 6 | */ 7 | #include 8 | 9 | int print_chars(char a, char b) 10 | { 11 | printf("%c %c\n", a, b); 12 | 13 | return 0; 14 | } 15 | 16 | int main() 17 | { 18 | int i; 19 | char c[4][2] = { "ab", "cd", "ef", "gh"}; 20 | 21 | for (i = 0; i < 4; ++i) { 22 | print_chars(c[i][0], c[i][1]); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /test/fold_const2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 50 3 | 1 4 | 4 5 | 9 6 | 16 7 | 1 8 | 0 9 | */ 10 | 11 | #include "test.h" 12 | int x = (1+2+3+4)*5; 13 | int a[4] = {1*1, 2*2, 3*3, 4*4}; 14 | int main () { 15 | int b[2] = {1==1, 1==0}; 16 | print_int(x); 17 | print_int(a[0]); 18 | print_int(a[1]); 19 | print_int(a[2]); 20 | print_int(a[3]); 21 | print_int(b[0]); 22 | print_int(b[1]); 23 | } 24 | -------------------------------------------------------------------------------- /test/printf.c: -------------------------------------------------------------------------------- 1 | /* 2 | Hello! UCC 3 | ABC 4 | 1 + 2 = 3 5 | 42 = 0x2a 6 | */ 7 | 8 | #include "test.h" 9 | 10 | int main () { 11 | int a = 1, b = 2; 12 | int num = 42; 13 | char cc[5] = "UCC"; 14 | 15 | printf("Hello! %s\n", cc); 16 | printf("%c%c%c\n", 'A', 'B', 'C'); 17 | printf("%d + %d = %d\n", a, b, a+b); 18 | printf("%d = 0x%x\n", num, num); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /test/unsigned-types.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 1 5 | */ 6 | 7 | #include 8 | 9 | typedef unsigned long ulong; 10 | typedef unsigned int short ushort; 11 | typedef char unsigned uchar; 12 | 13 | int main () { 14 | ulong a; 15 | ushort b; 16 | uchar c; 17 | a = -1; b = 1; c = 3; 18 | printf("%d\n", a 8 | 9 | void 10 | p_float(float f) 11 | { 12 | printf("%.4f\n", f); 13 | } 14 | 15 | void 16 | p_int(int i) 17 | { 18 | printf("%d\n", i); 19 | } 20 | 21 | int 22 | main() 23 | { 24 | float a = 1.5; 25 | int b = 2; 26 | p_float(a); 27 | p_float(b); 28 | p_int(a); 29 | p_int(b); 30 | } 31 | -------------------------------------------------------------------------------- /test/array-pointer.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | 3 6 | 4 7 | 0 8 | 1 9 | 2 10 | 3 11 | 4 12 | */ 13 | #include "test.h" 14 | 15 | int main () { 16 | int a[5], i; 17 | int *p; 18 | p = a; 19 | for (i=0; i<5; i++) { 20 | a[i] = i; 21 | } 22 | for (i=0; i<5; i++) { 23 | print_int(*(a+i)); 24 | } 25 | for (i=0; i<5; i++) { 26 | print_int(*(p+i)); 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /test/array.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | 3 6 | 4 7 | 5 8 | 6 9 | */ 10 | #include "test.h" 11 | 12 | int main () { 13 | int a[3],b[4]; 14 | int i; 15 | for (i=0;i<3;++i) { 16 | a[i] = i; 17 | } 18 | for(i=0;i<4;++i){ 19 | b[i] = i+3; 20 | } 21 | for (i=0;i<3;++i) { 22 | print_int(a[i]); 23 | } 24 | for(i=0;i<4;++i){ 25 | print_int(b[i]); 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/global-float.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3.900 3 | 1.000 4 | 1.000 5 | 7.000 6 | 4.000 7 | */ 8 | #include 9 | 10 | float a = 1.9+2.0; 11 | float b = 1; 12 | float c[] = { 13 | 1, 14 | 1 + 2 * 3, 15 | 3 / 2 * 4.0 16 | }; 17 | 18 | int main () { 19 | printf("%.3f\n", a); 20 | printf("%.3f\n", b); 21 | printf("%.3f\n", c[0]); 22 | printf("%.3f\n", c[1]); 23 | printf("%.3f\n", c[2]); 24 | } 25 | -------------------------------------------------------------------------------- /test/struct4.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 4 5 | 9 6 | 16 7 | 25 8 | 36 9 | 49 10 | 64 11 | 81 12 | */ 13 | #include "test.h" 14 | 15 | struct pair { 16 | int x, y; 17 | }; 18 | 19 | int main () { 20 | int i; 21 | struct pair a[10]; 22 | for (i=0; i<10; i++) { 23 | a[i].x = a[i].y = i; 24 | } 25 | for (i=0; i<10; i++) { 26 | print_int(a[i].x * a[i].y); 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /test/overflow.c: -------------------------------------------------------------------------------- 1 | /* 2 | 00000000 3 | 000000FF 4 | FFFFFFFE 5 | 0000FFFF 6 | */ 7 | 8 | #include 9 | 10 | int main() { 11 | char c = 255; 12 | unsigned char uc = 0; 13 | short s = 32767; 14 | unsigned short us = 0; 15 | c++; 16 | uc -= 1; 17 | s *= 2; 18 | --us; 19 | printf("%08X\n", c); 20 | printf("%08X\n", uc); 21 | printf("%08X\n", s); 22 | printf("%08X\n", us); 23 | } 24 | -------------------------------------------------------------------------------- /test/union-rec2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | */ 4 | 5 | #include "test.h" 6 | 7 | union foo { 8 | union foo *p; 9 | int x; 10 | }; 11 | 12 | struct baz { 13 | union bar { 14 | union bar *b; 15 | int x; 16 | } u; 17 | union bar *x; 18 | struct baz *y; 19 | int z; 20 | }; 21 | 22 | int main() 23 | { 24 | union foo f; 25 | struct baz b; 26 | 27 | print_int(1); 28 | 29 | return 0; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /test/assign-float.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0.5000 3 | 1.5000 4 | 1.7500 5 | 3.5000 6 | 0.8750 7 | */ 8 | #include 9 | 10 | int main() 11 | { 12 | float a = 0.5; 13 | printf("%.4f\n", a); 14 | 15 | a = 1.5; 16 | printf("%.4f\n", a); 17 | 18 | a += 0.25; 19 | printf("%.4f\n", a); 20 | 21 | a *= 2; 22 | printf("%.4f\n", a); 23 | 24 | a /= 4; 25 | printf("%.4f\n", a); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/calloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | OK 3 | */ 4 | #include 5 | #include 6 | #define N 100 7 | typedef struct {int x, y;} foo; 8 | int main () { 9 | unsigned i; 10 | char *c = (char*) calloc(N, sizeof(foo)); 11 | for (i = 0; i < sizeof(foo)*N/sizeof(char); ++i) { 12 | if (c[i] != 0) { 13 | printf("NG\n"); 14 | return 0; 15 | } 16 | } 17 | printf("OK\n"); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/pointer-sub.c: -------------------------------------------------------------------------------- 1 | /* 2 | 5 3 | 3 4 | 1 5 | */ 6 | 7 | #include "test.h" 8 | typedef struct { 9 | int x, y[4], z; 10 | } st; 11 | int main () { 12 | st a, b[10]; 13 | st *p, *q; 14 | int *pi, *qi; 15 | 16 | pi = &a.x; 17 | qi = &a.z; 18 | print_int(qi-pi); 19 | 20 | p = &b[3]; 21 | q = &b[6]; 22 | print_int(q-p); 23 | 24 | p = &b[9]; 25 | print_int((p+1) - p); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/fib-dp.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1134903170 3 | 44 4 | 832040 5 | 44 6 | */ 7 | #include "test.h" 8 | int count; 9 | int dp[50]; 10 | int fib (int x) { 11 | if (x < 2) 12 | return x; 13 | if (dp[x] > 0) 14 | return dp[x]; 15 | count++; 16 | return dp[x] = fib(x-1) + fib(x-2); 17 | } 18 | 19 | int main () { 20 | print_int(fib(45)); 21 | print_int(count); 22 | print_int(fib(30)); 23 | print_int(count); 24 | } 25 | -------------------------------------------------------------------------------- /test/typedef.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | 3 6 | 4 7 | */ 8 | #include "test.h" 9 | 10 | typedef int myInt; 11 | myInt x; 12 | typedef struct { 13 | myInt x, y; 14 | } pair; 15 | pair p; 16 | myInt main () { 17 | pair q; 18 | x = 0; 19 | p.x = 1; 20 | p.y = 2; 21 | q.x = 3; 22 | q.y = 4; 23 | print_int(x ); 24 | print_int(p.x); 25 | print_int(p.y); 26 | print_int(q.x); 27 | print_int(q.y); 28 | } 29 | -------------------------------------------------------------------------------- /include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_STDLIB_H 2 | #define _UCC_STDLIB_H 3 | 4 | #include 5 | 6 | #define RAND_MAX 2147483647 7 | 8 | void abort(void); 9 | int abs(int); 10 | long strtol(const char *, char **, int); 11 | int rand(void); 12 | void srand(unsigned); 13 | void *malloc(size_t); 14 | void *realloc(void *, size_t); 15 | void *calloc(size_t, size_t); 16 | void free(void *); 17 | 18 | #endif /* stdlib.h */ 19 | -------------------------------------------------------------------------------- /test/proto2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 5 3 | 6 4 | */ 5 | 6 | #include "test.h" 7 | 8 | int calc(int (*)(int, int), int, int); 9 | 10 | int add(int a, int b) { 11 | return a + b; 12 | } 13 | 14 | int mul(int a, int b) { 15 | return a * b; 16 | } 17 | 18 | int main() 19 | { 20 | print_int(calc(add, 2, 3)); 21 | print_int(calc(mul, 2, 3)); 22 | } 23 | 24 | int calc(int (*f)(int, int), int a, int b) { 25 | return f(a,b); 26 | } 27 | -------------------------------------------------------------------------------- /test/shift2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 200 3 | 25 4 | -1011703408 5 | 159868227 6 | -39488 7 | -20 8 | */ 9 | 10 | #include 11 | 12 | int main() 13 | { 14 | int i = 100; 15 | unsigned u = 0x98765432; 16 | long l = -1234; 17 | 18 | printf("%d\n", i << 1); 19 | printf("%d\n", i >> 2); 20 | printf("%d\n", u << 3); 21 | printf("%d\n", u >> 4l); 22 | printf("%d\n", l << 5); 23 | printf("%d\n", l >> 6u); 24 | } 25 | -------------------------------------------------------------------------------- /test/stdarg.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 10 4 | 6 5 | */ 6 | #include 7 | #include "test.h" 8 | 9 | int sum (int count, ...) { 10 | int s = 0; 11 | va_list ap; 12 | va_start(ap, count); 13 | while (count-- > 0) { 14 | s += va_arg(ap, int); 15 | } 16 | va_end(ap); 17 | return s; 18 | } 19 | 20 | int main () { 21 | printf("%d\n", sum(0)); 22 | printf("%d\n", sum(1, 10)); 23 | printf("%d\n", sum(3, 1, 2, 3)); 24 | } 25 | -------------------------------------------------------------------------------- /test/struct1.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | */ 8 | #include "test.h" 9 | 10 | struct pair{ 11 | int x, y; 12 | }; 13 | int main () { 14 | struct tri{ 15 | int x, y, z; 16 | }; 17 | struct pair a; 18 | struct tri b; 19 | a.x = 1; 20 | a.y = 2; 21 | b.x = 3; 22 | b.y = 4; 23 | b.z = 5; 24 | print_int(a.x); 25 | print_int(a.y); 26 | print_int(b.x); 27 | print_int(b.y); 28 | print_int(b.z); 29 | } 30 | -------------------------------------------------------------------------------- /test/unsigned-divmod.c: -------------------------------------------------------------------------------- 1 | /* 2 | 12345679 3 | 0 4 | 0 5 | -1406078410 6 | 1 7 | 0 8 | 12345679 9 | 0 10 | */ 11 | 12 | #include "test.h" 13 | 14 | int main() 15 | { 16 | unsigned x = 2888888886, y = x; 17 | print_int(x / 234); 18 | print_int(x % 234); 19 | print_int(x / -1); 20 | print_int(x % -1); 21 | print_int(x / y); 22 | print_int(x % y); 23 | x /= 234; 24 | y %= 234; 25 | print_int(x); 26 | print_int(y); 27 | } 28 | -------------------------------------------------------------------------------- /test/local_static2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | 0 6 | 1 7 | 2 8 | */ 9 | 10 | #include "test.h" 11 | 12 | int foo() 13 | { 14 | static int a = 0; 15 | 16 | return a++; 17 | } 18 | 19 | int bar() 20 | { 21 | static int a = 0; 22 | 23 | return a++; 24 | } 25 | 26 | int main() 27 | { 28 | print_int(foo()); 29 | print_int(foo()); 30 | print_int(foo()); 31 | print_int(bar()); 32 | print_int(bar()); 33 | print_int(bar()); 34 | } 35 | -------------------------------------------------------------------------------- /test/struct3.c: -------------------------------------------------------------------------------- 1 | /* 2 | 12 3 | */ 4 | #include "test.h" 5 | 6 | struct point { 7 | int x, y; 8 | }; 9 | struct rect { 10 | struct point a, b; 11 | }; 12 | 13 | int abs (int a) { 14 | return 0<=a ? a : -a; 15 | } 16 | 17 | int main () { 18 | struct rect sq; 19 | int p; 20 | sq.a.x = 0; 21 | sq.a.y = 2; 22 | sq.b.x = 3; 23 | sq.b.y = 6; 24 | p = abs(sq.a.x-sq.b.x) * abs(sq.a.y-sq.b.y); 25 | print_int(p); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/comb.c: -------------------------------------------------------------------------------- 1 | /* 2 | 210 3 | 455 4 | */ 5 | #include "test.h" 6 | 7 | int dp[20][30]; 8 | 9 | int comb (int a, int b) { 10 | if (dp[a][b] != 0) 11 | return dp[a][b]; 12 | if (a < b) 13 | return -1; 14 | if (a == b || b == 0) { 15 | dp[a][b] = 1; 16 | } else { 17 | dp[a][b] = comb(a-1, b-1) + comb(a-1, b); 18 | } 19 | return dp[a][b]; 20 | } 21 | 22 | int main () { 23 | print_int(comb(10, 4)); 24 | print_int(comb(15, 3)); 25 | } 26 | -------------------------------------------------------------------------------- /include/math.h: -------------------------------------------------------------------------------- 1 | #ifndef _MATH_H 2 | #define _MATH_H 3 | 4 | double sqrt(double); 5 | double fabs(double); 6 | double sin(double); 7 | double cos(double); 8 | double tan(double); 9 | double asin(double); 10 | double acos(double); 11 | double atan(double); 12 | double sinh(double); 13 | double cosh(double); 14 | double tanh(double); 15 | double exp(double); 16 | double log(double); 17 | double pow(double, double); 18 | double floor(double); 19 | 20 | #endif /* math.h */ 21 | -------------------------------------------------------------------------------- /test/combination.c: -------------------------------------------------------------------------------- 1 | /* 2 | 210 3 | 455 4 | */ 5 | #include "test.h" 6 | 7 | int dp[30][30]; 8 | 9 | int comb (int a, int b) { 10 | if (dp[a][b] != 0) 11 | return dp[a][b]; 12 | if (a < b) 13 | return -1; 14 | if (a == b || b == 0) { 15 | dp[a][b] = 1; 16 | } else { 17 | dp[a][b] = comb(a-1, b-1) + comb(a-1, b); 18 | } 19 | return dp[a][b]; 20 | } 21 | 22 | int main () { 23 | print_int(comb(10, 4)); 24 | print_int(comb(15, 3)); 25 | } 26 | -------------------------------------------------------------------------------- /test/isprime.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | 3 4 | 5 5 | 7 6 | 11 7 | 13 8 | */ 9 | #include "test.h" 10 | 11 | int isPrime (int p) { 12 | int i, flg; 13 | flg = 1; 14 | for (i=2; i 5 | 6 | size_t strlen(const char *); 7 | int strcmp(const char *, const char *); 8 | char *strchr(const char *, int); 9 | char *strcpy(char *, const char *); 10 | void *memset(void *, int, size_t); 11 | void *memcpy(void *, const void *, size_t); 12 | int strncmp(const char *, const char *, size_t); 13 | char *strncpy(char *, const char *, size_t); 14 | 15 | #endif /* string.h */ 16 | -------------------------------------------------------------------------------- /test/cast.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | */ 4 | #include "test.h" 5 | 6 | struct foo { 7 | int x; 8 | }; 9 | 10 | struct bar { 11 | int y; 12 | }; 13 | 14 | int main() 15 | { 16 | struct foo *foo; 17 | struct bar *bar; 18 | int i; 19 | 20 | /* int -> ??? */ 21 | i = (int)2; 22 | foo = (struct foo *)2; 23 | 24 | /* ptr -> ??? */ 25 | i = (int)foo; 26 | foo = (struct foo *)foo; 27 | foo = (struct foo *)bar; 28 | 29 | print_int(1); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /test/cast-return.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0.5000 3 | 0.0000 4 | 0 5 | 1 6 | */ 7 | #include 8 | 9 | float 10 | f(float x) 11 | { 12 | return x; 13 | } 14 | 15 | int 16 | g(float x) 17 | { 18 | return x; 19 | } 20 | 21 | unsigned int 22 | h(int x) 23 | { 24 | return x; 25 | } 26 | 27 | int main() 28 | { 29 | float x; 30 | x = f(0.5); 31 | printf("%.4f\n", x); 32 | x = g(0.5); 33 | printf("%.4f\n", x); 34 | printf("%d\n", 1 < -1); 35 | printf("%d\n", 1 < h(-1)); 36 | } 37 | -------------------------------------------------------------------------------- /test/muldiv.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | -15 4 | -120 5 | -15 6 | -1 7 | 15 8 | 0 9 | -7 10 | 3 11 | */ 12 | 13 | #include 14 | 15 | int main() 16 | { 17 | int s = -15; 18 | unsigned u = 123; 19 | 20 | printf("%d\n", s * 0); 21 | printf("%d\n", s * 1); 22 | printf("%d\n", s * 8); 23 | printf("%d\n", s / 1); 24 | printf("%d\n", s / 8); 25 | printf("%d\n", u / 8); 26 | printf("%d\n", s % 1); 27 | printf("%d\n", s % 8); 28 | printf("%d\n", u % 8); 29 | } 30 | -------------------------------------------------------------------------------- /test/struct-init.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 0 5 | 4 6 | 1 7 | 2 8 | 3 9 | 0 10 | */ 11 | #include "test.h" 12 | 13 | struct foo { 14 | int a; 15 | int b[2]; 16 | int c; 17 | }; 18 | 19 | int main() { 20 | struct foo x = { 1, { 2 }, 4 }; 21 | struct foo y = { 1, 2, 3 }; 22 | print_int(x.a); 23 | print_int(x.b[0]); 24 | print_int(x.b[1]); 25 | print_int(x.c); 26 | print_int(y.a); 27 | print_int(y.b[0]); 28 | print_int(y.b[1]); 29 | print_int(y.c); 30 | } 31 | -------------------------------------------------------------------------------- /test/compound_assign4.c: -------------------------------------------------------------------------------- 1 | /* 2 | 4 3 | 9 4 | 6 5 | 24 6 | 12 7 | 4 8 | 15 9 | 24 10 | 168 11 | 56 12 | 0 13 | */ 14 | 15 | #include "test.h" 16 | 17 | int main() 18 | { 19 | int a = 4; 20 | 21 | print_int(a); a += 5; 22 | print_int(a); a -= 3; 23 | print_int(a); a <<= 2; 24 | print_int(a); a >>= 1; 25 | print_int(a); a &= 7; 26 | print_int(a); a |= 15; 27 | print_int(a); a ^= 23; 28 | print_int(a); a *= 7; 29 | print_int(a); a /= 3; 30 | print_int(a); a %= 4; 31 | print_int(a); 32 | } 33 | -------------------------------------------------------------------------------- /test/union.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 2 4 | 42 5 | 20 6 | */ 7 | 8 | #include "test.h" 9 | 10 | typedef struct { 11 | int a; 12 | int b[2]; 13 | } foo; 14 | 15 | typedef struct { 16 | int a[2]; 17 | int b; 18 | } bar; 19 | 20 | typedef union { 21 | foo f; 22 | bar b; 23 | int i[5]; 24 | } uni; 25 | 26 | int main() { 27 | uni u = { 0, { 1, 2 } }; 28 | print_int(u.f.a); 29 | print_int(u.i[2]); 30 | u.b.b = 42; 31 | print_int(u.i[2]); 32 | print_int(sizeof(uni)); 33 | } 34 | -------------------------------------------------------------------------------- /test/sizeof.c: -------------------------------------------------------------------------------- 1 | /* 2 | 4 3 | 4 4 | 20 5 | 24 6 | 4 7 | 12 8 | */ 9 | #include "test.h" 10 | 11 | struct foo { 12 | int a; 13 | int b; 14 | int c[3]; 15 | }; 16 | 17 | struct bar { 18 | struct foo a; 19 | struct foo *b; 20 | }; 21 | 22 | typedef int baz[3]; 23 | 24 | int 25 | main() 26 | { 27 | print_int(sizeof(int)); 28 | print_int(sizeof(unsigned)); 29 | print_int(sizeof(struct foo)); 30 | print_int(sizeof(struct bar)); 31 | print_int(sizeof(struct bar *)); 32 | print_int(sizeof(baz)); 33 | } 34 | -------------------------------------------------------------------------------- /test/character.c: -------------------------------------------------------------------------------- 1 | /* 2 | 32 3 | 65 4 | 97 5 | 48 6 | 47 7 | 126 8 | 0 9 | 10 10 | 39 11 | 92 12 | 27 13 | 27 14 | 25 15 | 51 16 | */ 17 | #include "test.h" 18 | 19 | int main() { 20 | print_int(' '); 21 | print_int('A'); 22 | print_int('a'); 23 | print_int('0'); 24 | print_int('/'); 25 | print_int('~'); 26 | print_int('\0'); 27 | print_int('\n'); 28 | print_int('\''); 29 | print_int('\\'); 30 | print_int('\033'); 31 | print_int('\x1b'); 32 | print_int('z' - 'a'); 33 | print_int('0' + 3); 34 | } 35 | -------------------------------------------------------------------------------- /test/pointer-postinc.c: -------------------------------------------------------------------------------- 1 | /* 2 | OK 3 | */ 4 | #include "test.h" 5 | 6 | struct foo { 7 | int a, b; 8 | }; 9 | 10 | static struct foo fa[100]; 11 | 12 | int main() 13 | { 14 | struct foo *fp; 15 | int i = 0; 16 | 17 | for (fp = fa; fp < fa + 100; fp++) { 18 | fp->a = i++; 19 | fp->b = i++; 20 | } 21 | 22 | i = 0; 23 | 24 | for (fp = fa; fp < fa + 100; fp++) { 25 | if (fp->a != i++) 26 | printf("error"); 27 | if (fp->b != i++) 28 | printf("error"); 29 | } 30 | printf("OK\n"); 31 | } 32 | -------------------------------------------------------------------------------- /test/struct-passing.c: -------------------------------------------------------------------------------- 1 | /* 2 | { 3 | a = 1, 4 | f = {x = 2.000000, y = 3.000000} 5 | } 6 | */ 7 | #include 8 | 9 | typedef struct {float x, y;} foo; 10 | typedef struct {int a; foo f;} bar; 11 | 12 | 13 | void print_foo(foo f) 14 | { 15 | printf(" {x = %f, y = %f}\n", f.x, f.y); 16 | } 17 | 18 | void print_bar(bar b) 19 | { 20 | printf("{\n a = %d,\n f = ", b.a); 21 | print_foo(b.f); 22 | printf("}\n"); 23 | } 24 | 25 | int main() { 26 | bar b = { 1, { 2.0, 3.0}}; 27 | print_bar(b); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /test/goto.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | */ 9 | #include "test.h" 10 | 11 | int foo() 12 | { 13 | goto L1; 14 | L1: 15 | print_int(2); 16 | return 0; 17 | } 18 | 19 | int main() 20 | { 21 | int a = 0; 22 | 23 | goto L1; 24 | L1: 25 | print_int(1); 26 | foo(); 27 | print_int(3); 28 | L2: 29 | if (a == 0) { 30 | print_int(4); 31 | a = 1; 32 | goto L2; 33 | } else { 34 | print_int(5); 35 | goto L3; 36 | } 37 | print_int(0); 38 | L3: 39 | print_int(6); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /test/struct5.c: -------------------------------------------------------------------------------- 1 | /* 2 | 32 3 | */ 4 | #include "test.h" 5 | 6 | 7 | struct tri { 8 | int x, y, z; 9 | }; 10 | 11 | int inner_product (struct tri* a, struct tri* b) { 12 | int ans = 0; 13 | ans += a->x * b->x; 14 | ans += a->y * b->y; 15 | ans += a->z * b->z; 16 | return ans; 17 | } 18 | 19 | int main () { 20 | struct tri p, q; 21 | int ans; 22 | p.x = 1; 23 | p.y = 2; 24 | p.z = 3; 25 | q.x = 4; 26 | q.y = 5; 27 | q.z = 6; 28 | ans = inner_product (&p, &q); 29 | print_int(ans); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /include/limits.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_LIMITS_H 2 | #define _UCC_LIMITS_H 3 | 4 | #define CHAR_BIT 8 5 | #define SCHAR_MAX 127 6 | #define SCHAR_MIN (-128) 7 | #define UCHAR_MAX 255 8 | #define CHAR_MAX 127 9 | #define CHAR_MIN (-128) 10 | #define SHRT_MAX 32767 11 | #define SHRT_MIN (-32768) 12 | #define USHRT_MAX 65535 13 | #define INT_MAX 2147483647 14 | #define INT_MIN (-2147483648) 15 | #define UINT_MAX 4294967295 16 | #define LONG_MAX INT_MAX 17 | #define LONG_MIN INT_MIN 18 | #define ULONG_MAX UINT_MAX 19 | 20 | #endif /* limits.h */ 21 | -------------------------------------------------------------------------------- /test/function-pointer.c: -------------------------------------------------------------------------------- 1 | /* 2 | 5 3 | 6 4 | 5 5 | 6 6 | */ 7 | #include "test.h" 8 | 9 | int (*f)(int a, int b); 10 | 11 | int add(int a, int b) 12 | { 13 | return a + b; 14 | } 15 | 16 | int mul(int a, int b) 17 | { 18 | return a * b; 19 | } 20 | 21 | int main() 22 | { 23 | int (*g)(int a, int b); 24 | 25 | f = add; 26 | 27 | print_int(f(2,3)); 28 | 29 | f = mul; 30 | 31 | print_int(f(2,3)); 32 | 33 | g = add; 34 | 35 | print_int(g(2,3)); 36 | 37 | g = mul; 38 | 39 | print_int(g(2,3)); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /test/array-init-global2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 2 4 | 1 5 | Hello, world! 6 | one two three 7 | 36 8 | 14 9 | 12 10 | */ 11 | 12 | #include "test.h" 13 | 14 | int a[][3] = { { 1 }, { 1, 2 }, { 1, 2, 3 } }; 15 | char s[] = "Hello, world!"; 16 | char *p[] = { "one", "two", "three" }; 17 | 18 | int main() 19 | { 20 | print_int(a[0][2]); 21 | print_int(a[1][1]); 22 | print_int(a[2][0]); 23 | printf("%s\n", s); 24 | printf("%s %s %s\n", p[0], p[1], p[2]); 25 | print_int(sizeof(a)); 26 | print_int(sizeof(s)); 27 | print_int(sizeof(p)); 28 | } 29 | -------------------------------------------------------------------------------- /test/array-init3.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 2 4 | 1 5 | Hello, world! 6 | one two three 7 | 36 8 | 14 9 | 12 10 | */ 11 | 12 | #include "test.h" 13 | 14 | int main() 15 | { 16 | int a[][3] = { { 1 }, { 1, 2 }, { 1, 2, 3 } }; 17 | char s[] = "Hello, world!"; 18 | char *p[] = { "one", "two", "three" }; 19 | 20 | print_int(a[0][2]); 21 | print_int(a[1][1]); 22 | print_int(a[2][0]); 23 | printf("%s\n", s); 24 | printf("%s %s %s\n", p[0], p[1], p[2]); 25 | print_int(sizeof(a)); 26 | print_int(sizeof(s)); 27 | print_int(sizeof(p)); 28 | } 29 | -------------------------------------------------------------------------------- /test/setjmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | sub start 3 | x = 1 4 | main end 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | int x; 11 | jmp_buf buf; 12 | 13 | void sub(void) { 14 | printf("sub start\n"); 15 | longjmp(buf, 123); 16 | printf("sub end\n"); 17 | } 18 | 19 | int main() { 20 | switch (setjmp(buf)) { 21 | case 0: 22 | x = 1; 23 | sub(); 24 | break; 25 | case 123: 26 | printf("x = %d\n", x); 27 | break; 28 | default: 29 | printf("NG\n"); 30 | break; 31 | } 32 | printf("main end\n"); 33 | } 34 | -------------------------------------------------------------------------------- /test/pointer-compare.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 0 4 | 1 5 | 1 6 | 0 7 | 1 8 | 1 9 | 0 10 | 0 11 | 1 12 | */ 13 | 14 | #include "test.h" 15 | 16 | int main () { 17 | int a; 18 | { 19 | int b; 20 | { 21 | int *p = &a, *q = &b; 22 | print_int(p < q); 23 | print_int(p <= q); 24 | print_int(p > q); 25 | print_int(p >= q); 26 | print_int(p == q); 27 | print_int(p != q); 28 | q = &a; 29 | print_int(p == q); 30 | print_int(p != q); 31 | print_int(p == 0); 32 | print_int(p != 0); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/string-literal-global.c: -------------------------------------------------------------------------------- 1 | /* 2 | 72 3 | 101 4 | 108 5 | 108 6 | 111 7 | 44 8 | 32 9 | 87 10 | 111 11 | 114 12 | 108 13 | 100 14 | 33 15 | 10 16 | 72 17 | 101 18 | 108 19 | 108 20 | 111 21 | 44 22 | 32 23 | 87 24 | 111 25 | 114 26 | 108 27 | 100 28 | 33 29 | 10 30 | */ 31 | #include "test.h" 32 | 33 | char a[32] = "Hello, World!\n"; 34 | char *p = "Hello, World!\n"; 35 | 36 | int main() { 37 | int i = 0, j = 0; 38 | 39 | while (a[i]) { 40 | print_int(a[i++]); 41 | } 42 | 43 | while (p[j]) { 44 | print_int(p[j++]); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/prime.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | 3 4 | 5 5 | 7 6 | 11 7 | 13 8 | 17 9 | 19 10 | 23 11 | 29 12 | 31 13 | 37 14 | 41 15 | 43 16 | 47 17 | 53 18 | 59 19 | 61 20 | 67 21 | 71 22 | 73 23 | 79 24 | 83 25 | 89 26 | 97 27 | */ 28 | #include "test.h" 29 | 30 | int main () { 31 | int i, j; 32 | for (i=2; i<=100; i+=1) { 33 | int flg; 34 | flg = 1; 35 | for (j=2; j<=(i-1); j+=1) { 36 | flg = 1; 37 | if (i%j==0) { 38 | flg = 0; 39 | break; 40 | } 41 | } 42 | if (flg == 1) { 43 | print_int(i); 44 | } 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /test/fold_expr.c: -------------------------------------------------------------------------------- 1 | /* 2 | 4095 3 | 42949672 4 | 0 5 | 330 6 | 2 7 | 1 8 | 0 9 | 1 10 | 3 11 | */ 12 | 13 | #include 14 | 15 | typedef struct { int a[4]; } foo; 16 | 17 | int main() 18 | { 19 | static int a[] = { 20 | (unsigned)(-1) >> 20, 21 | (unsigned)(-1) / 100, 22 | (unsigned)(-1) < 1, 23 | (int)((foo *)10 + 20), 24 | (int)((foo *)64 - (foo *)32), 25 | (int)1.23, 26 | 12 && 0, 27 | 12 || 34, 28 | 1 + 2 ? 3 : 4 29 | }; 30 | 31 | int i; 32 | for (i = 0; i < sizeof a / sizeof(int); ++i) { 33 | printf("%d\n", a[i]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/compound_assign2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | */ 4 | 5 | #include "test.h" 6 | 7 | typedef struct { 8 | int fst, snd; 9 | } pair; 10 | 11 | int main() 12 | { 13 | pair P[100]; 14 | pair *p = P; 15 | int i; 16 | int ok = 1; 17 | 18 | for (i = 0; i < 100; ++i) { 19 | P[i].fst = i; 20 | P[i].snd = i; 21 | } 22 | 23 | for (i = 0; i < 100; ++i) { 24 | (*p).fst += i + 42; 25 | p += 1; 26 | } 27 | 28 | for (i = 0; i < 100; ++i) { 29 | if (! (P[i].fst == i * 2 + 42 && P[i].snd == i)) 30 | ok = 0; 31 | } 32 | 33 | print_int(ok); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /test/struct-init2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | 7 9 | 8 10 | */ 11 | #include "test.h" 12 | 13 | struct foo { 14 | int a; 15 | int b[2]; 16 | }; 17 | 18 | struct bar { 19 | struct foo x[2]; 20 | int y[2]; 21 | }; 22 | 23 | int main() { 24 | struct bar b = { { { 1, { 2, 3 } }, { 4, { 5, 6 } } }, { 7, 8 } }; 25 | print_int(b.x[0].a); 26 | print_int(b.x[0].b[0]); 27 | print_int(b.x[0].b[1]); 28 | print_int(b.x[1].a); 29 | print_int(b.x[1].b[0]); 30 | print_int(b.x[1].b[1]); 31 | print_int(b.y[0]); 32 | print_int(b.y[1]); 33 | } 34 | -------------------------------------------------------------------------------- /test/compound_assign3.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | */ 4 | 5 | #include "test.h" 6 | 7 | typedef struct { 8 | int fst, snd; 9 | } pair; 10 | 11 | int main() 12 | { 13 | pair P[100] = {0}; 14 | pair *p = P + 99; 15 | int i, ok = 1; 16 | 17 | for (i = 0; i < 25; ++i) { 18 | p->snd = 42; 19 | p -= 4; 20 | } 21 | 22 | for (i = 0; i < 100; ++i) { 23 | if (P[i].fst != 0) 24 | ok = 0; 25 | if (i % 4 == 3) { 26 | if (P[i].snd != 42) 27 | ok = 0; 28 | } else { 29 | if (P[i].snd != 0) 30 | ok = 0; 31 | } 32 | } 33 | 34 | print_int(ok); 35 | } 36 | -------------------------------------------------------------------------------- /test/malloc-fail.c: -------------------------------------------------------------------------------- 1 | /* 2 | OK 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int i; 11 | char *p[1200]; 12 | 13 | while (i < 1200) { 14 | int s1 = rand() % 0x4000; 15 | int s2 = rand() % 0x4000; 16 | 17 | if (! (p[i] = malloc(s1))) goto end; 18 | p[i++][s1 - 1] = 0; 19 | 20 | if (! (p[i] = malloc(s2))) goto end; 21 | p[i++][s2 - 1] = 0; 22 | 23 | free(p[i / 2]); 24 | } 25 | 26 | printf("NG\n"); 27 | return 0; 28 | 29 | end: 30 | printf(i > 600 ? "OK\n" : "NG\n"); 31 | } 32 | -------------------------------------------------------------------------------- /test/enum.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 3 | 0 4 | 0 5 | 2 6 | 3 7 | 0 8 | 1 9 | 2 10 | */ 11 | 12 | #include "test.h" 13 | 14 | enum udon { 15 | KAKE, KITSUNE, TEMPURA, CURRY, CARBONARA 16 | }; 17 | 18 | enum sushi { 19 | MAGURO, SALMON=2, EBI, IKA=0, WASABI, INARI 20 | }; 21 | 22 | int main () { 23 | enum udon u; 24 | u = CURRY; 25 | printf("%d\n", u); 26 | u = KAKE; 27 | printf("%d\n", u); 28 | 29 | 30 | printf("%d\n", MAGURO); 31 | printf("%d\n", SALMON); 32 | printf("%d\n", EBI); 33 | printf("%d\n", IKA); 34 | printf("%d\n", WASABI); 35 | printf("%d\n", INARI); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /test/array-init2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 0 5 | 4 6 | 5 7 | 6 8 | 7 9 | 0 10 | 0 11 | 10 12 | 11 13 | 12 14 | 13 15 | 0 16 | 0 17 | 16 18 | 17 19 | 18 20 | 19 21 | 20 22 | 21 23 | 22 24 | 0 25 | 0 26 | 25 27 | 0 28 | 0 29 | */ 30 | #include "test.h" 31 | int main() { 32 | int i, j, k; 33 | int a[3][3][3] = { 34 | { { 1, { 2 } }, 4, 5, 6, { 7 } }, 35 | 10, 11, 12, { 13 }, 16, 17, 18, 36 | 19, { 20 }, { 21 }, { 22 }, 25 37 | }; 38 | for (i = 0; i < 3; ++i) 39 | for (j = 0; j < 3; ++j) 40 | for (k = 0; k < 3; ++k) 41 | print_int(a[i][j][k]); 42 | } 43 | -------------------------------------------------------------------------------- /src/parser_helper.ml: -------------------------------------------------------------------------------- 1 | open Ctype 2 | 3 | let rec assoc t = function 4 | | [] -> false 5 | | (x,_)::_ when x=t -> true 6 | | _::xs -> assoc t xs 7 | 8 | (* typedef *) 9 | let typedef_env:(string * ctype) list ref = ref [];; 10 | 11 | let is_typedef_name t = 12 | assoc t !typedef_env 13 | 14 | let typedef (Syntax.Decl (_, typ, name, _)) = 15 | typedef_env := (name, typ) :: !typedef_env 16 | 17 | 18 | (* enum *) 19 | let enum_env:(string * int) list ref = ref [];; 20 | let is_enum_id t = 21 | assoc t !enum_env 22 | let enum_def name v = 23 | enum_env := (name, v) :: !enum_env 24 | let get_enum n = 25 | List.assoc n !enum_env 26 | -------------------------------------------------------------------------------- /test/continue.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 3 4 | 5 5 | 7 6 | 9 7 | 1 8 | 3 9 | 5 10 | 7 11 | 9 12 | 1 13 | 3 14 | 5 15 | 7 16 | 9 17 | */ 18 | #include "test.h" 19 | 20 | int main () { 21 | int i; 22 | i=0; 23 | while (i<10) { 24 | if (i%2 == 0) { 25 | ++i; 26 | continue; 27 | } 28 | print_int(i); 29 | ++i; 30 | } 31 | i=0; 32 | do { 33 | if (i%2 == 0) { 34 | ++i; 35 | continue; 36 | } 37 | print_int(i); 38 | ++i; 39 | } while (i<10); 40 | 41 | for (i=0; i<10; ++i) { 42 | if (i%2 == 0) { 43 | continue; 44 | } 45 | print_int(i); 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /test/array-3d.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 9 4 | 18 5 | 1 6 | 10 7 | 19 8 | 2 9 | 11 10 | 20 11 | 3 12 | 12 13 | 21 14 | 4 15 | 13 16 | 22 17 | 5 18 | 14 19 | 23 20 | 6 21 | 15 22 | 24 23 | 7 24 | 16 25 | 25 26 | 8 27 | 17 28 | 26 29 | */ 30 | #include "test.h" 31 | 32 | int array[3][3][3]; 33 | int main () { 34 | int i,j,k; 35 | for (i=0;i<3;++i) { 36 | for (j=0;j<3;++j) { 37 | for (k=0;k<3;++k) { 38 | array[i][j][k] = i*9 + j*3 + k; 39 | } 40 | } 41 | } 42 | 43 | for (j=0;j<3;++j) { 44 | for (k=0;k<3;++k) { 45 | for (i=0;i<3;++i) { 46 | print_int(array[i][j][k]); 47 | } 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /test/fold_const.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | */ 9 | #include "test.h" 10 | 11 | void fun (int n) { 12 | switch (n) { 13 | case 1 + 2: 14 | print_int(1); 15 | break; 16 | case 3 - 4: 17 | print_int(2); 18 | break; 19 | case 4 == 4: 20 | print_int(3); 21 | break; 22 | case 3 < 1: 23 | print_int(4); 24 | break; 25 | case 6 << 1: 26 | print_int(5); 27 | break; 28 | case 8 >> 2: 29 | print_int(6); 30 | break; 31 | } 32 | } 33 | 34 | int 35 | main() 36 | { 37 | fun(3); 38 | fun(-1); 39 | fun(1); 40 | fun(0); 41 | fun(12); 42 | fun(2); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /test/sizeof-padding.c: -------------------------------------------------------------------------------- 1 | /* 2 | 8 3 | 16 4 | 12 5 | 16 6 | */ 7 | 8 | #include 9 | 10 | int main() 11 | { 12 | struct foo { 13 | char c; 14 | char a[2]; 15 | struct { unsigned char x, y; } s; 16 | } f[2]; 17 | 18 | struct bar { 19 | char c; 20 | short s; 21 | int i; 22 | char d; 23 | }; 24 | 25 | struct baz { 26 | char c; 27 | union { char c; } u; 28 | struct { 29 | short s; 30 | int i; 31 | } s; 32 | }; 33 | 34 | printf("%lu\n", sizeof (struct foo)); 35 | printf("%lu\n", sizeof f); 36 | printf("%lu\n", sizeof (struct bar)); 37 | printf("%lu\n", sizeof (struct baz)); 38 | } 39 | -------------------------------------------------------------------------------- /test/xorshift.c: -------------------------------------------------------------------------------- 1 | /* 2 | -593279510 3 | 458299110 4 | -1794094678 5 | -661847888 6 | 516391518 7 | -1917697722 8 | -1695017917 9 | 717229868 10 | 137866584 11 | 395339113 12 | */ 13 | #include "test.h" 14 | 15 | unsigned xor128(void) { 16 | static unsigned x = 123456789; 17 | static unsigned y = 362436069; 18 | static unsigned z = 521288629; 19 | static unsigned w = 88675123; 20 | unsigned t; 21 | 22 | t = x ^ (x << 11); 23 | x = y; y = z; z = w; 24 | return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); 25 | } 26 | 27 | int main () { 28 | static unsigned a = 12; 29 | int i; 30 | for (i=0; i<10;i++) { 31 | printf("%d\n", xor128()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/variable-assign.c: -------------------------------------------------------------------------------- 1 | /* 2 | 42 3 | Hello!! 4 | FFFFFFFF 5 | 000000FF 6 | FFFFABCD 7 | 0000ABCD 8 | 1 2 9 | */ 10 | 11 | #include 12 | 13 | char str[] = "Hello!"; 14 | unsigned short ss[] = {0xabcd, 0}; 15 | 16 | int main() { 17 | int a; 18 | char c1, c2, *p; 19 | unsigned char uc; 20 | short s; 21 | struct {short a; int b;} v1 = { 1, 2}, v2; 22 | a = 42; 23 | p = str; c1 = str[5]; 24 | uc = 255; c2 = uc; 25 | s = ss[0]; ss[0] = s; 26 | v2 = v1; 27 | printf("%d\n", a); 28 | printf("%s%c\n", p, c1); 29 | printf("%08X\n%08X\n", c2, uc); 30 | printf("%08X\n", s); 31 | printf("%08X\n", ss[0]); 32 | printf("%d %d\n", v2.a, v2.b); 33 | } 34 | -------------------------------------------------------------------------------- /test/assign.c: -------------------------------------------------------------------------------- 1 | /* 2 | 9 3 | 9 4 | 4 5 | 4 6 | 1 7 | 1 8 | 5 9 | 5 10 | 4 11 | 4 12 | 16 13 | 16 14 | 8 15 | 8 16 | 8 17 | 8 18 | 14 19 | 14 20 | 4 21 | 4 22 | */ 23 | #include "test.h" 24 | 25 | #define TEST(op, op2, arg) \ 26 | print_int(a op arg); \ 27 | a op2 arg; \ 28 | print_int(a) 29 | 30 | int main() 31 | { 32 | int a = 3; 33 | 34 | TEST(*, *=, 3); 35 | TEST(/, /=, 2); 36 | TEST(%, %=, 3); 37 | TEST(+, +=, 4); 38 | TEST(-, -=, 1); 39 | TEST(<<, <<=, 2); 40 | TEST(>>, >>=, 1); 41 | TEST(&, &=, 24); 42 | TEST(|, |=, 6); 43 | TEST(^, ^=, 10); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /test/variadic-cast.c: -------------------------------------------------------------------------------- 1 | /* 2 | apple orange grape 3 | Alice Bob Carol Dave Eva 4 | */ 5 | #include 6 | #include 7 | void print_words(int num, ...) { 8 | va_list ap; 9 | int i; 10 | char *s; 11 | 12 | va_start(ap, num); 13 | 14 | for (i = 0; i < num; ++i) { 15 | s = va_arg(ap, char *); 16 | printf("%s", s); 17 | if (i != num-1) 18 | putchar(' '); 19 | } 20 | 21 | putchar('\n'); 22 | 23 | va_end(ap); 24 | 25 | } 26 | 27 | int main() { 28 | double d = 5.0; 29 | 30 | print_words(3, "apple", "orange", "grape"); 31 | 32 | /* implicit conversion */ 33 | print_words(d, "Alice", "Bob", "Carol", "Dave", "Eva"); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /test/double.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0.5000 3 | -0.5000 4 | -1.2500 5 | 1.2500 6 | -0.7500 7 | 1.7500 8 | -2.2500 9 | -0.6250 10 | -0.4000 11 | -2.5000 12 | 0 13 | -1 14 | 0 15 | 1 16 | 0.0120 17 | */ 18 | #include 19 | int main() { 20 | double a=0.5, b=-1.25, c=0.012; 21 | printf("%.4f\n", a); 22 | printf("%.4f\n", -a); 23 | printf("%.4f\n", b); 24 | printf("%.4f\n", -b); 25 | printf("%.4f\n", a+b); 26 | printf("%.4f\n", a-b); 27 | printf("%.4f\n", b-1); 28 | printf("%.4f\n", a*b); 29 | printf("%.4f\n", a/b); 30 | printf("%.4f\n", b/a); 31 | printf("%d\n", (int)a); 32 | printf("%d\n", (int)b); 33 | printf("%d\n", (int)-a); 34 | printf("%d\n", (int)-b); 35 | printf("%.4f\n", c); 36 | } 37 | -------------------------------------------------------------------------------- /test/sqrt.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1.414 3 | 1.732 4 | 2.236 5 | 3.162 6 | */ 7 | 8 | #include 9 | #define EPS 0.00001 10 | 11 | float myfabs(float a, float b) { 12 | return a < b ? b-a : a-b; 13 | } 14 | 15 | /* 16 | calculate square-root by Newton Method 17 | */ 18 | float mysqrt(float a) { 19 | float x0, x1; 20 | x0 = 1.0; 21 | x1 = 0; 22 | while (myfabs(x0, x1) > EPS) { 23 | float f, fd; 24 | f = x0 * x0 - a; 25 | fd = 2 * x0; 26 | x1 = x0; 27 | x0 -= f/fd; 28 | } 29 | return x0; 30 | } 31 | 32 | int main() { 33 | printf("%.3f\n", mysqrt(2)); 34 | printf("%.3f\n", mysqrt(3)); 35 | printf("%.3f\n", mysqrt(5)); 36 | printf("%.3f\n", mysqrt(10)); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /test/float.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0.5000 3 | -0.5000 4 | -1.2500 5 | 1.2500 6 | -0.7500 7 | 1.7500 8 | -2.2500 9 | -0.6250 10 | -0.4000 11 | -2.5000 12 | 0 13 | -1 14 | 0 15 | 1 16 | 0.0120 17 | */ 18 | #include "test.h" 19 | 20 | int main () { 21 | float a=0.5, b=-1.25, c=0.012; 22 | printf("%.4f\n", a); 23 | printf("%.4f\n", -a); 24 | printf("%.4f\n", b); 25 | printf("%.4f\n", -b); 26 | printf("%.4f\n", a+b); 27 | printf("%.4f\n", a-b); 28 | printf("%.4f\n", b-1); 29 | printf("%.4f\n", a*b); 30 | printf("%.4f\n", a/b); 31 | printf("%.4f\n", b/a); 32 | printf("%d\n", (int)a); 33 | printf("%d\n", (int)b); 34 | printf("%d\n", (int)-a); 35 | printf("%d\n", (int)-b); 36 | printf("%.4f\n", c); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /test/struct-assign.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2, 3, 4 4 | 1, 3, 4 5 | 2 6 | */ 7 | 8 | #include 9 | 10 | int main() 11 | { 12 | typedef struct { int x; } foo_t; 13 | typedef struct { int x, y, z; } bar_t; 14 | typedef union { bar_t x; int y; } baz_t; 15 | 16 | foo_t foo; 17 | bar_t bar; 18 | baz_t baz; 19 | 20 | foo_t a = { 1 }; 21 | bar_t b = { 2, 3, 4 }; 22 | baz_t c = { { 5, 6, 7 } }; 23 | 24 | foo = a; 25 | bar = b; 26 | baz = c; 27 | 28 | c.x = (&baz)->x = *(&b); 29 | baz.y = foo.x; 30 | 31 | printf("%d\n", foo.x); 32 | printf("%d, %d, %d\n", bar.x, bar.y, bar.z); 33 | printf("%d, %d, %d\n", baz.x.x, baz.x.y, baz.x.z); 34 | printf("%d\n", c.x.x); 35 | } 36 | -------------------------------------------------------------------------------- /test/eratos.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | 3 4 | 5 5 | 7 6 | 11 7 | 13 8 | 17 9 | 19 10 | 23 11 | 29 12 | 31 13 | 37 14 | 41 15 | 43 16 | 47 17 | 53 18 | 59 19 | 61 20 | 67 21 | 71 22 | 73 23 | 79 24 | 83 25 | 89 26 | 97 27 | */ 28 | #include "test.h" 29 | 30 | #define N 100 31 | 32 | int main () { 33 | int isprime[N]; 34 | int i; 35 | 36 | for (i=0; i log.txt 5 | diff expected.txt log.txt 6 | 7 | build/benz.out: 8 | mkdir -p build 9 | cp $(UCCDIR)/extlib/benz-gaia/*.c build/ 10 | cp -r $(UCCDIR)/extlib/benz-gaia/include build/ 11 | rm build/main.c 12 | $(UCCDIR)/bin/ucc -Wa=-Wno-unused-label -I./build/include build/*.c main.c 13 | mv a.out build/benz.out 14 | 15 | build/repl.out: repl.c 16 | mkdir -p build 17 | cp $(UCCDIR)/extlib/benz-gaia/*.c build/ 18 | cp -r $(UCCDIR)/extlib/benz-gaia/include build/ 19 | rm build/main.c 20 | $(UCCDIR)/bin/ucc -Wa=-Wno-unused-label -I./build/include build/*.c repl.c 21 | mv a.out build/repl.out 22 | 23 | clean: 24 | rm -rf build/ log.txt *~ 25 | -------------------------------------------------------------------------------- /test/parameter-array.c: -------------------------------------------------------------------------------- 1 | /* 2 | hello 3 | world 4 | hello 5 | world 6 | hello 7 | world 8 | apple 9 | orange 10 | grape 11 | */ 12 | 13 | #include "test.h" 14 | 15 | void f1 (char s[][6]) { 16 | printf("%s\n", s[0]); 17 | printf("%s\n", s[1]); 18 | } 19 | void f2 (char s[2][6]) { 20 | printf("%s\n", s[0]); 21 | printf("%s\n", s[1]); 22 | } 23 | void g (char (*s)[6]) { 24 | printf("%s\n", s[0]); 25 | printf("%s\n", s[1]); 26 | } 27 | void h (char *s[], int n) { 28 | int i; 29 | for (i=0; i 15 | #include 16 | 17 | int main() 18 | { 19 | char *s = "abcde"; 20 | char a[10]; 21 | 22 | printf("%d\n", strlen("")); 23 | printf("%d\n", strlen("abc")); 24 | printf("%d\n", strcmp("abc", "abcd")); 25 | printf("%d\n", strcmp("abcd", "abcd")); 26 | printf("%d\n", strcmp("abcde", "abcd")); 27 | printf("%d\n", strchr(s, 'c') - s); 28 | printf("%d\n", strchr(s, '\0') - s); 29 | 30 | strcpy(a, s); 31 | printf("%s\n", a); 32 | 33 | memset(a, 'a', 4); 34 | printf("%s\n", a); 35 | 36 | memcpy(a, s, 3); 37 | printf("%s\n", a); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /test/float-cond.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 0 4 | 1 5 | 1 6 | 0 7 | OK 8 | OK 9 | OK 10 | OK 11 | OK 12 | */ 13 | 14 | #include 15 | 16 | int main() 17 | { 18 | float t = 0.1; 19 | float f = -0.0; 20 | int ti = (0 == 0.0 * -1.0); 21 | printf("%d\n", 0.0 ? 1 : 0); 22 | printf("%d\n", -0.0 ? 1 : 0); 23 | printf("%d\n", 0.1 ? 1 : 0); 24 | printf("%d\n", t ? 1 : 0); 25 | printf("%d\n", f ? 1 : 0); 26 | if ( 0.0) printf("NG\n"); 27 | if (-0.0) printf("NG\n"); 28 | if ( 0.1) printf("OK\n"); 29 | if (t) printf("OK\n"); 30 | if (f) printf("NG\n"); 31 | if (0.0 == -0.0) printf("OK\n"); 32 | if (0.0 != -0.0) printf("NG\n"); 33 | if (0.0 == 0.0 * -1.0) printf("OK\n"); 34 | if (0.0 != -0.0) printf("NG\n"); 35 | if (ti) printf("OK\n"); 36 | } 37 | -------------------------------------------------------------------------------- /test/limits.c: -------------------------------------------------------------------------------- 1 | /* 2 | 8 3 | 127 4 | -128 5 | 255 6 | 127 7 | -128 8 | 32767 9 | -32768 10 | 65535 11 | 2147483647 12 | -2147483648 13 | 4294967295 14 | 2147483647 15 | -2147483648 16 | 4294967295 17 | */ 18 | 19 | #include 20 | #include "test.h" 21 | int main () { 22 | printf("%d\n", CHAR_BIT); 23 | printf("%d\n", SCHAR_MAX); 24 | printf("%d\n", SCHAR_MIN); 25 | printf("%d\n", UCHAR_MAX); 26 | printf("%d\n", CHAR_MAX); 27 | printf("%d\n", CHAR_MIN); 28 | printf("%d\n", SHRT_MAX); 29 | printf("%d\n", SHRT_MIN); 30 | printf("%d\n", USHRT_MAX); 31 | printf("%d\n", INT_MAX); 32 | printf("%d\n", INT_MIN); 33 | printf("%u\n", UINT_MAX); 34 | printf("%ld\n", LONG_MAX); 35 | printf("%ld\n", LONG_MIN); 36 | printf("%lu\n", ULONG_MAX); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | LIBS = lib/libucc.s lib/libc.s lib/libm.s 3 | 4 | all: bin/cc $(LIBS) bin/sim bin/as 5 | 6 | bin/cc: FORCE 7 | ocamlbuild src/main.native 8 | mv main.native bin/cc 9 | 10 | %.s: %.c bin/cc 11 | bin/ucc -s -o $@ $< 12 | 13 | bin/sim: 14 | git submodule update --init 15 | $(MAKE) -C extlib/gaia 16 | cp extlib/gaia/sim bin/sim 17 | $(MAKE) -C extlib/gaia clean 18 | 19 | bin/as: 20 | cp extlib/gaia/asm.py bin/as 21 | 22 | test: all test/*.c 23 | prove -j 4 test/*.c 24 | 25 | test-benz: 26 | git submodule update --init 27 | $(MAKE) -C test/benz test 28 | 29 | test-all: test test-benz 30 | 31 | clean: 32 | ocamlbuild -clean 33 | rm -f *~ test/*~ test/*.i test/*.s test/*.out bin/cc bin/sim bin/as lib/*.s 34 | $(MAKE) -C test/benz clean 35 | 36 | FORCE: 37 | .PHONY: FORCE clean all test 38 | -------------------------------------------------------------------------------- /test/unsigned-compare.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 1 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 1 10 | 1 11 | 0 12 | 0 13 | 1 14 | 0 15 | 1 16 | 1 17 | */ 18 | 19 | #include "test.h" 20 | 21 | int main () { 22 | int a = -1; 23 | int b = 2; 24 | print_int( a < b); 25 | print_int( a <= b); 26 | print_int( a > b); 27 | print_int( a >= b); 28 | print_int( a == b); 29 | 30 | print_int((unsigned)a < (unsigned)b); 31 | print_int((unsigned)a <= (unsigned)b); 32 | print_int((unsigned)a > (unsigned)b); 33 | print_int((unsigned)a >= (unsigned)b); 34 | print_int((unsigned)a == (unsigned)b); 35 | 36 | print_int((unsigned)a < (unsigned)a); 37 | print_int((unsigned)a <= (unsigned)a); 38 | print_int((unsigned)a > (unsigned)a); 39 | print_int((unsigned)a >= (unsigned)a); 40 | print_int((unsigned)a == (unsigned)a); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef _UCC_STDIO_H 2 | #define _UCC_STDIO_H 3 | 4 | #include 5 | #include 6 | 7 | #define EOF (-1) 8 | 9 | typedef struct { 10 | int (*read)(void); 11 | int (*write)(int); 12 | } FILE; 13 | 14 | extern FILE *stdin; 15 | extern FILE *stdout; 16 | extern FILE *stderr; 17 | 18 | int putchar(int); 19 | int getchar(void); 20 | int putc(int, FILE *); 21 | int fputc(int, FILE *); 22 | int getc(FILE *); 23 | int fgetc(FILE *); 24 | int puts(char *); 25 | int fputs(char *, FILE *); 26 | char *fgets(char *, int, FILE *); 27 | char *gets(char *); 28 | 29 | 30 | int printf(const char *, ...); 31 | int fprintf(FILE *, const char *, ...); 32 | int sprintf(char *, const char *, ...); 33 | int vprintf(const char *, va_list); 34 | int vfprintf(FILE *, const char *, va_list); 35 | int vsprintf(char *, const char *, va_list); 36 | 37 | #endif /* stdio.h */ 38 | -------------------------------------------------------------------------------- /test/_test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use strict; 3 | 4 | use File::Temp 'tempfile'; 5 | use File::Basename; 6 | use Test::Simple tests => 1; 7 | 8 | my $dir = dirname $0; 9 | $dir .= "/.."; 10 | my $bin = "$dir/bin"; 11 | 12 | my ($file) = @ARGV 13 | or die "no args"; 14 | 15 | open FH, "<", $file 16 | or die "cannot open file '$file'"; 17 | 18 | undef $/; 19 | my $content = ; 20 | 21 | my ($expected) = $content =~ m{/\*\n(|.*?\n)\*/}s 22 | or die "expected output not given in '$file'"; 23 | 24 | my (undef, $outfile) = tempfile; 25 | 26 | system "$bin/ucc -o $outfile $file 2> /dev/null"; 27 | 28 | if ($? != 0) { 29 | ok $expected eq "DEAD\n", "ok"; 30 | exit; 31 | } 32 | 33 | open PIPE, "$bin/sim -simple $outfile 2> /dev/null |" 34 | or die "could not run simulator with $outfile"; 35 | 36 | undef $/; 37 | my $output = ; 38 | 39 | ok $output eq $expected, 'ok'; 40 | -------------------------------------------------------------------------------- /test/struct6.c: -------------------------------------------------------------------------------- 1 | /* 2 | 10 3 | 1 4 | 11 5 | -1 6 | 3 7 | 31 8 | */ 9 | #include "test.h" 10 | 11 | struct pair{ 12 | int x, y; 13 | }; 14 | 15 | struct tag_pair{ 16 | int tag; 17 | struct pair *p; 18 | }; 19 | 20 | struct bogo_pair{ 21 | int bogo; 22 | struct tag_pair *q; 23 | }; 24 | 25 | int read_struct(struct pair *p, int none, struct bogo_pair *bp){ 26 | print_int(none); 27 | 28 | print_int(p->x); 29 | print_int(p->y); 30 | 31 | print_int(bp->bogo); 32 | print_int(bp->q->p->x); 33 | print_int(((bp->q)->p)->y); 34 | 35 | return 0; 36 | } 37 | 38 | int main(){ 39 | struct pair p0, p1; 40 | struct tag_pair tp0; 41 | struct bogo_pair bg0; 42 | 43 | p0.x = 1; 44 | p0.y = 11; 45 | p1.x = 3; 46 | p1.y = 31; 47 | 48 | tp0.tag = 55; 49 | tp0.p = &p1; 50 | 51 | bg0.bogo = -1; 52 | bg0.q = &tp0; 53 | 54 | read_struct(&p0,10,&bg0); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /test/short.c: -------------------------------------------------------------------------------- 1 | /* 2 | 2 3 | 10 4 | 0000abcd 5 | 2 6 | 2 7 | 2 8 | FFFFFF9C 9 | FF9C 10 | 0 11 | 1 12 | 2 13 | 3 14 | 4 15 | */ 16 | 17 | #include 18 | 19 | short a = 1; 20 | 21 | int main() { 22 | short b; 23 | static short c; 24 | short ss[5] = {0}; 25 | int i; 26 | signed char sc = -100; 27 | unsigned short us; 28 | union {short s; unsigned u;} uni; 29 | 30 | printf("%ld\n", sizeof(short)); 31 | printf("%ld\n", sizeof(ss)); 32 | 33 | uni.u = 0; 34 | uni.s = 0xabcd; 35 | printf("%08x\n", uni.u); 36 | 37 | 38 | b = a; 39 | c = b++; 40 | a = ++c; 41 | printf("%d\n", a); 42 | printf("%d\n", b); 43 | printf("%d\n", c); 44 | 45 | b = sc; 46 | us = sc; 47 | printf("%X\n", b); 48 | printf("%X\n", us); 49 | 50 | for (i = 1; i < 5; ++i) { 51 | ss[i] = ss[i-1] + 1; 52 | } 53 | for (i = 0; i < 5; ++i) { 54 | printf("%d\n", ss[i]); 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /test/printf2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 42 3 | +0000000042 4 | 0x00ffffffff 5 | 10.2300 6 | INF 7 | Hello, world! 8 | Hello, world! 9 | Hello, wor $ 10 | 1 10 100 11 | 123: Hello, world! 12 | 10000000.000000, 1.000000e+07, 1e+07 13 | 4275817112, 012 14 | */ 15 | 16 | #include 17 | 18 | int main() 19 | { 20 | float inf = 1.0 / 0.0; 21 | char *str = "Hello, world!"; 22 | char buf[32]; 23 | 24 | printf("%d\n", 42); 25 | printf("%+20.10d\n", 42); 26 | printf("%#012x\n", 0xffffffffu); 27 | printf("%#.6g\n", 10.23); 28 | printf("%F\n", inf); 29 | printf("%s\n", str); 30 | printf("%20s\n", str); 31 | printf("%-20.10s$\n", str); 32 | printf("%*d%*d%*d\n", 4, 1, 4, 10, 4, 100); 33 | 34 | sprintf(buf, "%d: %s", 123, str); 35 | printf("%s\n", buf); 36 | 37 | fprintf(stdout, "%f, %e, %g\n", 1e7, 1e7, 1e7); 38 | fprintf(stderr, "%u, %#.3o\n", 0xfedbca98, 012); 39 | } 40 | -------------------------------------------------------------------------------- /test/unsigned-compare2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 0 5 | 1 6 | 1 7 | 1 8 | 1 9 | 0 10 | 0 11 | 0 12 | 1 13 | 1 14 | 0 15 | 0 16 | 0 17 | 1 18 | 1 19 | 0 20 | 0 21 | 0 22 | 0 23 | 0 24 | 1 25 | 1 26 | 0 27 | 0 28 | 1 29 | 0 30 | 1 31 | 1 32 | 1 33 | 1 34 | 0 35 | 0 36 | 0 37 | 1 38 | 1 39 | 0 40 | 0 41 | 0 42 | 0 43 | 0 44 | 1 45 | 1 46 | 0 47 | 0 48 | 0 49 | 1 50 | 1 51 | 0 52 | 0 53 | 1 54 | 0 55 | 1 56 | 1 57 | 1 58 | 1 59 | 0 60 | 0 61 | 0 62 | 0 63 | 0 64 | 1 65 | 1 66 | 0 67 | 0 68 | 0 69 | 1 70 | 1 71 | 0 72 | 0 73 | 0 74 | 1 75 | 1 76 | 0 77 | 0 78 | 1 79 | 0 80 | 1 81 | 1 82 | */ 83 | 84 | #include "test.h" 85 | 86 | int main() { 87 | unsigned a[4] = {2, 3, 1<<17, (1<<17)+1}; 88 | int i; 89 | for (i=0;i<4;i++) { 90 | int j; 91 | for (j=0;j<4;j++) { 92 | print_int(a[i] < a[j]); 93 | print_int(a[i] <= a[j]); 94 | print_int(a[i] > a[j]); 95 | print_int(a[i] >= a[j]); 96 | print_int(a[i] == a[j]); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /test/comp.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 1 4 | 0 5 | 0 6 | 0 7 | 1 8 | 0 9 | 1 10 | 1 11 | 1 12 | 0 13 | 0 14 | 1 15 | 1 16 | 0 17 | 0 18 | 0 19 | 0 20 | 1 21 | 1 22 | 0 23 | 0 24 | 1 25 | 1 26 | 0 27 | 0 28 | 1 29 | 1 30 | 0 31 | 1 32 | 0 33 | 1 34 | */ 35 | #include "test.h" 36 | 37 | int main () { 38 | print_int(1< 2); 39 | print_int(1<=2); 40 | print_int(1> 2); 41 | print_int(1>=2); 42 | print_int(1< 1); 43 | print_int(1<=1); 44 | print_int(1> 1); 45 | print_int(1>=1); 46 | 47 | print_int(-1< 2); 48 | print_int(-1<=2); 49 | print_int(-1> 2); 50 | print_int(-1>=2); 51 | print_int(-1< 1); 52 | print_int(-1<=1); 53 | print_int(-1> 1); 54 | print_int(-1>=1); 55 | 56 | print_int(1< -2); 57 | print_int(1<=-2); 58 | print_int(1> -2); 59 | print_int(1>=-2); 60 | print_int(1< -1); 61 | print_int(1<=-1); 62 | print_int(1> -1); 63 | print_int(1>=-1); 64 | 65 | print_int(-1< -2); 66 | print_int(-1<=-2); 67 | print_int(-1> -2); 68 | print_int(-1>=-2); 69 | print_int(-1< -1); 70 | print_int(-1<=-1); 71 | print_int(-1> -1); 72 | print_int(-1>=-1); 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /test/scope.c: -------------------------------------------------------------------------------- 1 | /* 2 | 12, 8, 12, 4, 8, 4 3 | 0, 42 4 | 123, 0 5 | 12, 42 6 | 12, 8 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | typedef struct foo foo; 13 | typedef union bar bar; 14 | 15 | struct foo { 16 | foo *p; 17 | bar *q; 18 | union { int a; float b; } u; 19 | }; 20 | 21 | union bar { 22 | foo *p; 23 | bar *q; 24 | struct { int a; float b; } s; 25 | }; 26 | 27 | enum { baz }; 28 | 29 | void test() 30 | { 31 | int s1 = sizeof (foo); 32 | int s2 = sizeof (bar); 33 | 34 | struct foo { int a; }; 35 | union bar { int a; }; 36 | 37 | int s3 = sizeof (foo); 38 | int s4 = sizeof (struct foo); 39 | int s5 = sizeof (bar); 40 | int s6 = sizeof (union bar); 41 | 42 | int x = baz; 43 | int baz = 42; 44 | 45 | printf("%d, %d, %d, %d, %d, %d\n", s1, s2, s3, s4, s5, s6); 46 | printf("%d, %d\n", x, baz); 47 | 48 | { 49 | foo foo = { NULL, NULL, { 123 } }; 50 | enum { baz }; 51 | 52 | printf("%d, %d\n", foo.u.a, baz); 53 | } 54 | 55 | printf("%d, %d\n", sizeof (foo), baz); 56 | } 57 | 58 | int main() 59 | { 60 | test(); 61 | 62 | printf("%d, %d\n", sizeof (struct foo), sizeof (union bar)); 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UCC - Udon C Compiler [![Build Status](https://travis-ci.org/kw-udon/ucc.svg?branch=master)](https://travis-ci.org/kw-udon/ucc) 2 | 3 | C compiler for [GAIA](https://github.com/wasabiz/GAIA3) CPU written in OCaml. 4 | 5 | Requirement 6 | ============== 7 | * OCaml >= 4.0.1 8 | * ocamlbuild >= 4.0.1 9 | * Clang (for preprocessing and syntax check) 10 | 11 | Build 12 | ============== 13 | ``make`` 14 | 15 | To run the tests, use the following command. 16 | 17 | ``make test`` 18 | 19 | Example 20 | ========== 21 | You can compile C file by the following command. 22 | 23 | ``./bin/ucc ./test/printf.c`` 24 | 25 | Then, `a.out` will be created. It runs on the simulator. 26 | 27 | 28 | ``./bin/sim -simple a.out`` 29 | 30 | You can check generated assembly by `-S` option. 31 | 32 | ``./bin/ucc -S ./test/printf.c`` 33 | 34 | If you want to see other options, please use `-h` option. 35 | 36 | In addition, UCC can compile [xv6 ported to GAIA](https://github.com/wasabiz/xv6), a simple Unix-like OS. 37 | Please use this [Makefile](https://gist.github.com/kw-udon/0fcedda2d29c81a2d1be) to try it. 38 | 39 | Article 40 | ========= 41 | * http://kw-udon.hatenablog.com/entry/2015/03/19/171921 (written in Japanese) 42 | -------------------------------------------------------------------------------- /test/list.c: -------------------------------------------------------------------------------- 1 | /* 2 | 0 3 | 1 4 | 2 5 | 3 6 | 4 7 | 4 8 | 3 9 | 2 10 | 1 11 | 0 12 | */ 13 | 14 | #include "test.h" 15 | 16 | struct list { 17 | int car; 18 | struct list *cdr; 19 | } heap[1024]; 20 | 21 | int i; 22 | 23 | struct list *alloc() { 24 | return heap + i++; 25 | } 26 | 27 | struct list *cons(int car, struct list *cdr) { 28 | struct list *x; 29 | 30 | x = alloc(); 31 | x->car = car; 32 | x->cdr = cdr; 33 | return x; 34 | } 35 | 36 | struct list *rev(struct list *list, struct list *acc) { 37 | if (list == 0) { 38 | return acc; 39 | } 40 | else { 41 | struct list *tail = alloc(); 42 | 43 | tail->car = list->car; 44 | tail->cdr = acc; 45 | return rev(list->cdr, tail); 46 | } 47 | } 48 | 49 | void print_list(struct list *list) { 50 | if (list == 0) 51 | return; 52 | print_int(list->car); 53 | print_list(list->cdr); 54 | } 55 | 56 | /* list of [s,e) */ 57 | struct list *iota(int s, int e) { 58 | if (s == e) { 59 | return 0; 60 | } else { 61 | return cons(s, iota(s + 1, e)); 62 | } 63 | } 64 | 65 | int main() 66 | { 67 | struct list *e; 68 | 69 | e = iota(0, 5); 70 | 71 | print_list(e); 72 | 73 | e = rev(e, 0); 74 | 75 | print_list(e); 76 | } 77 | -------------------------------------------------------------------------------- /test/fizzbuzz.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | -1 5 | 4 6 | -2 7 | -1 8 | 7 9 | 8 10 | -1 11 | -2 12 | 11 13 | -1 14 | 13 15 | 14 16 | -3 17 | 16 18 | 17 19 | -1 20 | 19 21 | -2 22 | -1 23 | 22 24 | 23 25 | -1 26 | -2 27 | 26 28 | -1 29 | 28 30 | 29 31 | -3 32 | 31 33 | 32 34 | -1 35 | 34 36 | -2 37 | -1 38 | 37 39 | 38 40 | -1 41 | -2 42 | 41 43 | -1 44 | 43 45 | 44 46 | -3 47 | 46 48 | 47 49 | -1 50 | 49 51 | -2 52 | -1 53 | 52 54 | 53 55 | -1 56 | -2 57 | 56 58 | -1 59 | 58 60 | 59 61 | -3 62 | 61 63 | 62 64 | -1 65 | 64 66 | -2 67 | -1 68 | 67 69 | 68 70 | -1 71 | -2 72 | 71 73 | -1 74 | 73 75 | 74 76 | -3 77 | 76 78 | 77 79 | -1 80 | 79 81 | -2 82 | -1 83 | 82 84 | 83 85 | -1 86 | -2 87 | 86 88 | -1 89 | 88 90 | 89 91 | -3 92 | 91 93 | 92 94 | -1 95 | 94 96 | -2 97 | -1 98 | 97 99 | 98 100 | -1 101 | */ 102 | #include "test.h" 103 | 104 | int main () { 105 | int i; 106 | for (i=1;i<100; ++i) { 107 | if (i%15==0) { 108 | print_int(-3); 109 | } else if (i%3==0) { 110 | print_int(-1); 111 | } else if (i%5==0) { 112 | print_int(-2); 113 | } else { 114 | print_int(i); 115 | } 116 | } 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /test/switch.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 2 4 | 2 5 | 1 6 | 1 7 | 2 8 | 1 9 | 2 10 | 5 11 | */ 12 | #include "test.h" 13 | 14 | int 15 | main() 16 | { 17 | switch (1) { 18 | case 0: 19 | print_int(0); 20 | case 1: 21 | print_int(1); 22 | case 2: 23 | print_int(2); 24 | } 25 | 26 | /* w/default */ 27 | switch (3) { 28 | case 0: 29 | print_int(0); 30 | case 1: 31 | print_int(1); 32 | default: 33 | print_int(2); 34 | } 35 | 36 | /* w/break */ 37 | switch (1) { 38 | case 0: 39 | print_int(0); 40 | case 1: 41 | print_int(1); 42 | break; 43 | default: 44 | print_int(2); 45 | } 46 | 47 | /* cases inside nested block */ 48 | switch (1) { 49 | do { 50 | case 0: 51 | print_int(0); 52 | case 1: 53 | print_int(1); 54 | } while (0); 55 | default: 56 | print_int(2); 57 | } 58 | 59 | /* nested switches */ 60 | switch (1) { 61 | case 0: 62 | print_int(0); 63 | case 1: 64 | print_int(1); 65 | switch (0) { 66 | case 0: 67 | print_int(2); 68 | break; 69 | case 1: 70 | print_int(3); 71 | break; 72 | default: 73 | print_int(4); 74 | break; 75 | } 76 | default: 77 | print_int(5); 78 | break; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/syntax.ml: -------------------------------------------------------------------------------- 1 | open Ctype 2 | 3 | type value = 4 | | VInt of int 5 | | VFloat of float 6 | | VStr of int list 7 | 8 | type expr = 9 | | EConst of value 10 | | EVar of name 11 | | EComma of expr * expr 12 | | EAssign of arith_bin option * expr * expr 13 | | EUnary of unary * expr 14 | | EArith of arith_bin * expr * expr 15 | | ERel of rel_bin * expr * expr 16 | | EEq of eq_bin * expr * expr 17 | | ELog of logical_bin * expr * expr 18 | | ECall of expr * (expr list) 19 | | EPtr of expr 20 | | EAddr of expr 21 | | ECond of expr * expr * expr 22 | | EDot of expr * name 23 | | ECast of ctype * expr 24 | | ESizeof of expr 25 | 26 | type init = 27 | | IScal of expr 28 | | IVect of init list 29 | 30 | type decl = 31 | | Decl of linkage * ctype * name * (init option) 32 | 33 | type stmt = 34 | | SNil 35 | | SBlock of decl list * stmt list 36 | | SWhile of expr * stmt 37 | | SDoWhile of stmt * expr 38 | | SFor of (expr option) * (expr option) * (expr option) * stmt 39 | | SIfElse of expr * stmt * stmt 40 | | SReturn of expr option 41 | | SContinue 42 | | SBreak 43 | | SLabel of string * stmt 44 | | SGoto of string 45 | | SSwitch of expr * stmt 46 | | SCase of expr 47 | | SDefault 48 | | SExpr of expr 49 | 50 | type def = 51 | | DefFun of decl * (decl list) * stmt 52 | | DefVar of decl 53 | -------------------------------------------------------------------------------- /test/assign-global.c: -------------------------------------------------------------------------------- 1 | /* 2 | A 42 3 | {1, f} 4 | {b, a, r, {2, g}} 5 | A 84 6 | {1, f} 7 | {b, a, r, {2, g}} 8 | B 126 9 | {1, f} 10 | {b, a, r, {2, g}} 11 | */ 12 | 13 | #include 14 | 15 | char g_char; 16 | int g_int; 17 | 18 | struct foo { 19 | int a; 20 | char b; 21 | } g_foo; 22 | 23 | struct bar { 24 | char c, d, e; 25 | struct foo f; 26 | } g_bar; 27 | 28 | 29 | int main() { 30 | char c = 'A'; 31 | int a = 42; 32 | struct foo f = { 1, 'f'}; 33 | struct bar b = {'b', 'a', 'r', {2, 'g'}}; 34 | 35 | g_char = c; 36 | g_int = a; 37 | 38 | g_foo = f; 39 | g_bar = b; 40 | 41 | printf("%c %d\n", g_char, g_int); 42 | printf("{%d, %c}\n", g_foo.a, g_foo.b); 43 | printf("{%c, %c, %c, {%d, %c}}\n", 44 | g_bar.c, g_bar.d, g_bar.e, g_bar.f.a, g_bar.f.b); 45 | 46 | 47 | g_char = g_char; 48 | g_int += g_int; 49 | g_foo = g_foo; 50 | g_bar = g_bar; 51 | 52 | printf("%c %d\n", g_char, g_int); 53 | printf("{%d, %c}\n", g_foo.a, g_foo.b); 54 | printf("{%c, %c, %c, {%d, %c}}\n", 55 | g_bar.c, g_bar.d, g_bar.e, g_bar.f.a, g_bar.f.b); 56 | 57 | 58 | c = g_char + 1; 59 | a += g_int; 60 | 61 | f = g_foo; 62 | b = g_bar; 63 | 64 | printf("%c %d\n", c, a); 65 | printf("{%d, %c}\n", f.a, f.b); 66 | printf("{%c, %c, %c, {%d, %c}}\n", 67 | b.c, b.d, b.e, b.f.a, b.f.b); 68 | 69 | 70 | return 0; 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main.ml: -------------------------------------------------------------------------------- 1 | 2 | (* the name of the file which contains the expressions *) 3 | 4 | let out_file fname = 5 | let fnlen = String.length fname in 6 | let suffix = if 2 < fnlen then String.sub fname (fnlen - 2) 2 else "" in 7 | if suffix = ".c" || suffix = ".i" then 8 | Printf.sprintf "%s.s" (String.sub fname 0 (fnlen - 2)) 9 | else 10 | Printf.sprintf "%s.s" fname 11 | 12 | let show_pos fname filebuf = 13 | let pos = filebuf.Lexing.lex_start_p in 14 | Printf.eprintf "File \"%s\", line %d, character %d:\n" 15 | fname 16 | pos.Lexing.pos_lnum 17 | (pos.Lexing.pos_cnum - pos.Lexing.pos_bol + 1) 18 | 19 | let show_error fmt = 20 | let go str = 21 | Printf.eprintf "error: %s\n" str; 22 | exit 1 in 23 | Printf.ksprintf go fmt 24 | 25 | let () = 26 | let argc = Array.length Sys.argv in 27 | if argc != 2 then Format.printf "Usage: ./cc [filename]\n" else 28 | let fname = Sys.argv.(1) in 29 | let inchan = open_in fname in 30 | let filebuf = Lexing.from_channel inchan in 31 | try 32 | let parse = Parser.main Lexer.token filebuf in 33 | let typing = Typing.main parse in 34 | let outchan = open_out (out_file fname) in 35 | Emitter.main outchan typing; 36 | with 37 | | Lexer.LexerError msg -> 38 | show_pos fname filebuf; 39 | show_error "lex: %s" msg 40 | | Failure "parse error" -> 41 | show_pos fname filebuf; 42 | show_error "parser: syntax error near '%s'" (Lexing.lexeme filebuf) 43 | -------------------------------------------------------------------------------- /src/util.ml: -------------------------------------------------------------------------------- 1 | let sum_of = List.fold_left (+) 0 2 | let max_of = List.fold_left max 0 3 | 4 | let (<<) f g = fun x -> f (g x) 5 | let (>>) f g = fun x -> g (f x) 6 | 7 | let push stack x = stack := x :: !stack 8 | let peek stack = List.hd !stack 9 | let pop stack = stack := List.tl !stack 10 | 11 | let id x = x 12 | let const x _ = x 13 | 14 | let rec rep x = function 15 | | 0 -> [] 16 | | n -> x :: rep x (n-1) 17 | 18 | let rec take = function 19 | | 0 -> const [] 20 | | i -> function 21 | | [] -> failwith "take" 22 | | x::xs -> x::take (i-1) xs 23 | 24 | let rec list_set = function 25 | | [] -> const (const []) 26 | | x :: xs -> function 27 | | 0 -> 28 | fun y -> y :: xs 29 | | i -> 30 | fun y -> x :: list_set xs (i - 1) y 31 | 32 | let is_none x = 33 | x = None 34 | 35 | let is_some x = 36 | not (is_none x) 37 | 38 | let from_some = function 39 | | Some x -> x 40 | | None -> failwith "from_some" 41 | 42 | let opMap f = function 43 | | Some x -> Some (f x) 44 | | None -> None 45 | 46 | let opMap2 f a b = 47 | match (a, b) with 48 | | (Some x, Some y) -> 49 | Some (f x y) 50 | | _ -> None 51 | 52 | module String = struct 53 | include String 54 | let slice str s e = 55 | let s = if s < 0 then length str + s else s in 56 | let s = max 0 (min (length str) s) in 57 | let e = if e < 0 then length str + e else e in 58 | let e = max s (min (length str) e) in 59 | sub str s (e - s) 60 | end 61 | -------------------------------------------------------------------------------- /test/merge-sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | -97 3 | -88 4 | -84 5 | -78 6 | -76 7 | -59 8 | -52 9 | -28 10 | -22 11 | -17 12 | -10 13 | 10 14 | 12 15 | 13 16 | 18 17 | 20 18 | 21 19 | 32 20 | 33 21 | 46 22 | 48 23 | 53 24 | 59 25 | 68 26 | 72 27 | 73 28 | 78 29 | 82 30 | 84 31 | 96 32 | */ 33 | 34 | #include "test.h" 35 | #define N 30 36 | int xor128(); 37 | void mergeSort (int x[], int left, int right); 38 | 39 | int main () { 40 | int a[N]; 41 | int i; 42 | for (i=0; i> 19)) ^ (t ^ (t >> 8))); 64 | } 65 | 66 | void mergeSort (int x[], int l, int r) { 67 | int temp[N], i, j, k; 68 | int mid; 69 | if (l >= r-1) 70 | return; 71 | mid = (l + r) / 2; 72 | mergeSort(x, l, mid); 73 | mergeSort(x, mid, r); 74 | for (i=l; i 9 | #include 10 | 11 | #define N 10000 12 | 13 | #define check(c) \ 14 | do { \ 15 | if (c) \ 16 | printf("OK\n"); \ 17 | else \ 18 | printf("NG\n"); \ 19 | } while (0) 20 | 21 | 22 | int 23 | my_rand(int mod) 24 | { 25 | static int seed = 876543; 26 | 27 | return seed = (seed * 11 + 5) % mod; 28 | } 29 | 30 | 31 | int 32 | test(int *list[N]) 33 | { 34 | int i, j; 35 | for (i = 0; i < N; ++i) { 36 | int s; 37 | if (list[i] == NULL) { 38 | continue; 39 | } 40 | s = list[i][0]; 41 | for (j = 0; j < s; ++j) { 42 | if (s != list[i][j]) { 43 | return 0; 44 | } 45 | } 46 | } 47 | return 1; 48 | } 49 | 50 | 51 | 52 | int main() 53 | { 54 | int i, j; 55 | int *list[N]; 56 | 57 | // initialize 58 | for (i = 0; i < N; ++i) { 59 | int s = my_rand(100); 60 | list[i] = malloc((s + 1) * sizeof(int)); 61 | for (j = 0; j < s; ++j) { 62 | list[i][j] = s; 63 | } 64 | } 65 | 66 | check(test(list)); 67 | 68 | for (i = 0; i < N; i+=3) { 69 | free(list[i]); 70 | list[i] = NULL; 71 | } 72 | 73 | check(test(list)); 74 | 75 | for (i = 1; i < N; i+=3) { 76 | free(list[i]); 77 | list[i] = NULL; 78 | } 79 | 80 | check(test(list)); 81 | 82 | for (i = 2; i < N; i+=3) { 83 | free(list[i]); 84 | list[i] = NULL; 85 | } 86 | 87 | check(test(list)); 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /lib/libucc.c: -------------------------------------------------------------------------------- 1 | 2 | int __mul(int a, int b) { 3 | __asm("\ 4 | mov r1, [rbp + 4] \n\ 5 | mov r2, [rbp + 8] \n\ 6 | xor r3, r1, r2 \n\ 7 | sar r4, r1, 31 \n\ 8 | sar r5, r2, 31 \n\ 9 | xor r1, r1, r4 \n\ 10 | xor r2, r2, r5 \n\ 11 | sub r1, r1, r4 \n\ 12 | sub r2, r2, r5 \n\ 13 | mov r4, 0 \n\ 14 | cmplt r5, r1, r2 \n\ 15 | bz r5, __mul_L1 \n\ 16 | mov r5, r1 \n\ 17 | mov r1, r2 \n\ 18 | mov r2, r5 \n\ 19 | __mul_L1: \n\ 20 | and r5, r2, 1 \n\ 21 | bz r5, __mul_L2 \n\ 22 | add r4, r4, r1 \n\ 23 | __mul_L2: \n\ 24 | add r1, r1, r1 \n\ 25 | shr r2, r2, 1 \n\ 26 | bnz+ r2, __mul_L1 \n\ 27 | cmplt r3, r3, 0 \n\ 28 | neg r3, r3 \n\ 29 | xor r1, r4, r3 \n\ 30 | sub r1, r1, r3 \n\ 31 | ret \n\ 32 | "); 33 | } 34 | 35 | static void signed_divmod(int n, int d, int *qp, int *rp) { 36 | int is_neg = (n ^ d) < 0; 37 | int i, q = 0, r = 0; 38 | if (n < 0) n = -n; 39 | if (d < 0) d = -d; 40 | for (i = 31; i >= 0; --i) { 41 | r <<= 1; 42 | r += (n >> i) & 1; 43 | if (r >= d) { 44 | q += 1 << i; 45 | r -= d; 46 | } 47 | } 48 | *qp = is_neg ? -q : q; 49 | *rp = is_neg ? -r : r; 50 | } 51 | 52 | static void unsigned_divmod(unsigned n, unsigned d, unsigned *qp, unsigned *rp) { 53 | int i; 54 | unsigned q = 0, r = 0; 55 | for (i = 31; i >= 0; --i) { 56 | r <<= 1; 57 | r += (n >> i) & 1; 58 | if (r >= d) { 59 | q += 1 << i; 60 | r -= d; 61 | } 62 | } 63 | *qp = q; 64 | *rp = r; 65 | } 66 | 67 | int __signed_div(int n, int d) { 68 | int p, q; 69 | signed_divmod(n, d, &p, &q); 70 | return p; 71 | } 72 | 73 | int __signed_mod(int n, int d) { 74 | int p, q; 75 | signed_divmod(n, d, &p, &q); 76 | return q; 77 | } 78 | 79 | unsigned __unsigned_div(unsigned n, unsigned d) { 80 | unsigned p, q; 81 | unsigned_divmod(n, d, &p, &q); 82 | return p; 83 | } 84 | 85 | unsigned __unsigned_mod(unsigned n, unsigned d) { 86 | unsigned p, q; 87 | unsigned_divmod(n, d, &p, &q); 88 | return q; 89 | } 90 | -------------------------------------------------------------------------------- /test/benz/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * See Copyright Notice in picrin.h 3 | */ 4 | 5 | #include "picrin.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | int 12 | xf_file_read(void *cookie, char *ptr, int size) 13 | { 14 | int s = size; 15 | while (s-- > 0) { 16 | *ptr++ = getchar(); 17 | } 18 | return size; 19 | } 20 | 21 | int 22 | xf_file_write(void *cookie, const char *ptr, int size) 23 | { 24 | int s = size; 25 | while (s-- > 0) { 26 | putchar(*ptr++); 27 | } 28 | return size; 29 | } 30 | 31 | long 32 | xf_file_seek(void *cookie, long pos, int whence) 33 | { 34 | return 0; 35 | } 36 | 37 | int 38 | xf_file_flush(void *cookie) 39 | { 40 | return 0; 41 | } 42 | 43 | int 44 | xf_file_close(void *cookie) 45 | { 46 | return 0; 47 | } 48 | 49 | xFILE * 50 | xfopen() 51 | { 52 | xFILE *file; 53 | 54 | file = xfunopen(NULL, xf_file_read, xf_file_write, xf_file_seek, xf_file_flush, xf_file_close); 55 | if (! file) { 56 | return NULL; 57 | } 58 | 59 | return file; 60 | } 61 | 62 | static void * 63 | pic_default_allocf(void *ptr, size_t size) 64 | { 65 | if (size == 0) { 66 | if (ptr) { 67 | free(ptr); 68 | } 69 | return NULL; 70 | } 71 | if (ptr) { 72 | return realloc(ptr, size); 73 | } else { 74 | return malloc(size); 75 | } 76 | } 77 | 78 | static void 79 | pic_default_abortf() 80 | { 81 | abort(); 82 | } 83 | 84 | /* Simple REPL program */ 85 | 86 | const char* sample_expr = "\ 87 | (letrec ((fact \ 88 | (lambda (n) \ 89 | (if (= n 1) \ 90 | 1 \ 91 | (* n (fact (- n 1))))))) \ 92 | (fact 10)) \ 93 | "; 94 | 95 | int 96 | main() 97 | { 98 | pic_state *pic; 99 | pic_value expr; 100 | 101 | pic = pic_open(pic_default_allocf, pic_default_abortf, sizeof(jmp_buf), 0, NULL, NULL, xfopen(), xfopen(), xfopen()); 102 | 103 | expr = pic_read_cstr(pic, sample_expr); 104 | 105 | pic_printf(pic, "~s\n", pic_eval(pic, expr, pic->lib)); 106 | 107 | pic_close(pic); 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /test/calculator.c: -------------------------------------------------------------------------------- 1 | /* 2 | 100 3 | 100 4 | 2014 5 | 2015 6 | */ 7 | 8 | #include "test.h" 9 | 10 | #define BUF_SIZE 256 11 | 12 | int pos; 13 | char str[BUF_SIZE]; 14 | int is_error; 15 | 16 | int isdigit(char c) 17 | { 18 | return '0' <= c && c <= '9'; 19 | } 20 | 21 | int parse0() 22 | { 23 | int res = 0; 24 | if (!isdigit(str[pos])) is_error = 1; 25 | while (isdigit(str[pos])) 26 | res = res * 10 + (str[pos++] - '0'); 27 | return res; 28 | } 29 | 30 | int parse4(); 31 | int parse1() 32 | { 33 | if (str[pos] == '(') { 34 | int res; 35 | ++pos; 36 | res = parse4(); 37 | if (str[pos++] != ')') is_error = 1; 38 | return res; 39 | } 40 | return parse0(); 41 | } 42 | 43 | int parse2() 44 | { 45 | if (str[pos] == '-') { 46 | ++pos; 47 | return -parse1(); 48 | } 49 | return parse1(); 50 | } 51 | 52 | int parse3() 53 | { 54 | int res = parse2(); 55 | while (str[pos] == '*' || str[pos] == '/') { 56 | char op = str[pos++]; 57 | int tmp = parse2(); 58 | op == '*' ? (res *= tmp) : (res /= tmp); 59 | } 60 | return res; 61 | } 62 | 63 | int parse4() 64 | { 65 | int res = parse3(); 66 | while (str[pos] == '+' || str[pos] == '-') { 67 | char op = str[pos++]; 68 | int tmp = parse3(); 69 | op == '+' ? (res += tmp) : (res -= tmp); 70 | } 71 | return res; 72 | } 73 | 74 | int parse(char *p) 75 | { 76 | int i, sz = 0; 77 | int res; 78 | pos = is_error = 0; 79 | for (i = 0; p[i] && sz < BUF_SIZE; ++i) 80 | if (p[i] != ' ') str[sz++] = p[i]; 81 | if (sz == BUF_SIZE) { 82 | is_error = 1; 83 | return 0; 84 | } 85 | str[sz] = '$'; 86 | res = parse4(); 87 | if (pos != sz) is_error = 1; 88 | return res; 89 | } 90 | 91 | void calc(char *p) 92 | { 93 | int res = parse(p); 94 | if (is_error) 95 | printf("parse error\n"); 96 | else 97 | printf("%d\n", res); 98 | } 99 | 100 | int main() 101 | { 102 | calc("123 - 45 - 67 + 89"); 103 | calc("-12 + 3 * 4 * 5 + 6 * 78 / 9"); 104 | calc("-1 + 2 + 3 * (-4 * 5 * (6 * -7 + 8) - 9)"); 105 | calc("((1 + 2) / 3 + 4 * (56 + 7)) * 8 - 9"); 106 | } 107 | -------------------------------------------------------------------------------- /src/typed_syntax.ml: -------------------------------------------------------------------------------- 1 | open Ctype 2 | 3 | type value = 4 | | VInt of int 5 | | VFloat of float 6 | | VStr of int list 7 | 8 | type expr = 9 | | ENil 10 | | EArith of ctype * arith_bin * expr * expr 11 | | EFArith of ctype * arith_bin * expr * expr 12 | | EPAdd of ctype * expr * expr 13 | | EPDiff of ctype * expr * expr 14 | | ERel of ctype * rel_bin * expr * expr 15 | | EURel of ctype * rel_bin * expr * expr 16 | | EFRel of ctype * rel_bin * expr * expr 17 | | EEq of ctype * eq_bin * expr * expr 18 | | EFEq of ctype * eq_bin * expr * expr 19 | | ELog of ctype * logical_bin * expr * expr 20 | | EUnary of ctype * unary * expr 21 | | EFUnary of ctype * unary * expr 22 | | EPPost of ctype * inc * expr 23 | | EConst of ctype * value 24 | | EVar of ctype * name 25 | | EComma of ctype * expr * expr 26 | | EAssign of ctype * arith_bin option * expr * expr 27 | | EFAssign of ctype * arith_bin option * expr * expr 28 | | ECall of ctype * expr * (expr list) 29 | | EAddr of ctype * expr 30 | | EPtr of ctype * expr 31 | | ECond of ctype * expr * expr * expr 32 | | EDot of ctype * expr * name 33 | | ECast of ctype * ctype * expr 34 | | EAsm of ctype * (int list) 35 | | ESpace of ctype 36 | 37 | type decl = 38 | | Decl of linkage * ctype * name * (expr list) 39 | 40 | type stmt = 41 | | SNil 42 | | SBlock of decl list * stmt list 43 | | SWhile of expr * stmt 44 | | SDoWhile of stmt * expr 45 | | SFor of (expr option) * (expr option) * (expr option) * stmt 46 | | SIfElse of expr * stmt * stmt 47 | | SReturn of expr option 48 | | SContinue 49 | | SBreak 50 | | SLabel of string * stmt 51 | | SGoto of string 52 | | SSwitch of expr * stmt 53 | | SCase of int 54 | | SDefault 55 | | SExpr of expr 56 | 57 | type def = 58 | | DefFun of decl * (decl list) * stmt 59 | | DefVar of decl 60 | 61 | let typeof = function 62 | | EArith (t, _, _, _) -> t 63 | | EFArith (t, _, _, _) -> t 64 | | ERel (t, _, _, _) -> t 65 | | EURel (t, _, _, _) -> t 66 | | EFRel (t, _, _, _) -> t 67 | | EPAdd (t, _, _) -> t 68 | | EPDiff (t, _, _) -> t 69 | | EEq (t, _, _, _) -> t 70 | | EFEq (t, _, _, _) -> t 71 | | ELog (t, _, _, _) -> t 72 | | EUnary (t, _, _) -> t 73 | | EFUnary (t, _, _) -> t 74 | | EPPost (t, _, _) -> t 75 | | EConst (t, _) -> t 76 | | EVar (t, _) -> t 77 | | EComma (t, _, _) -> t 78 | | EAssign (t, _, _, _) -> t 79 | | EFAssign(t, _, _, _) -> t 80 | | ECall (t, _, _) -> t 81 | | EAddr (t, _) -> t 82 | | EPtr (t, _) -> t 83 | | ECond (t, _, _, _) -> t 84 | | EDot (t, _, _) -> t 85 | | ECast (t, _, _) -> t 86 | | EAsm (t, _) -> t 87 | | ENil -> failwith "typeof ENil" 88 | | ESpace _ -> failwith "typeof ESpace" 89 | -------------------------------------------------------------------------------- /test/benz/repl.c: -------------------------------------------------------------------------------- 1 | /** 2 | * See Copyright Notice in picrin.h 3 | */ 4 | 5 | #include "picrin.h" 6 | #include "picrin/error.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | int 13 | xf_file_read(void *cookie, char *ptr, int size) 14 | { 15 | int s = size; 16 | while (s-- > 0) { 17 | char c = getchar(); 18 | putchar(c); 19 | *ptr++ = c; 20 | } 21 | return size; 22 | } 23 | 24 | int 25 | xf_file_write(void *cookie, const char *ptr, int size) 26 | { 27 | int s = size; 28 | while (s-- > 0) { 29 | putchar(*ptr++); 30 | } 31 | return size; 32 | } 33 | 34 | long 35 | xf_file_seek(void *cookie, long pos, int whence) 36 | { 37 | return 0; 38 | } 39 | 40 | int 41 | xf_file_flush(void *cookie) 42 | { 43 | return 0; 44 | } 45 | 46 | int 47 | xf_file_close(void *cookie) 48 | { 49 | return 0; 50 | } 51 | 52 | xFILE * 53 | xfopen() 54 | { 55 | xFILE *file; 56 | 57 | file = xfunopen(NULL, xf_file_read, xf_file_write, xf_file_seek, xf_file_flush, xf_file_close); 58 | if (! file) { 59 | return NULL; 60 | } 61 | 62 | return file; 63 | } 64 | 65 | static void * 66 | pic_default_allocf(void *ptr, size_t size) 67 | { 68 | if (size == 0) { 69 | if (ptr) { 70 | free(ptr); 71 | } 72 | return NULL; 73 | } 74 | if (ptr) { 75 | return realloc(ptr, size); 76 | } else { 77 | return malloc(size); 78 | } 79 | } 80 | 81 | static void 82 | pic_default_abortf() 83 | { 84 | abort(); 85 | } 86 | 87 | /* Simple REPL program */ 88 | 89 | const char* sample_expr = "\ 90 | (letrec ((fact \ 91 | (lambda (n) \ 92 | (if (= n 1) \ 93 | 1 \ 94 | (* n (fact (- n 1))))))) \ 95 | (fact 10)) \ 96 | "; 97 | 98 | #include 99 | 100 | #define NL "\r\n" 101 | 102 | const char *msg = 103 | NL 104 | " _ _ _ ____ _ ____ ____ _ _ ____ ___ ____" NL 105 | " | | | |___ | | | | |\\/| |___ | | |" NL 106 | " |_|_| |___ |___ |___ |__| | | |___ | |__|" NL 107 | "" NL 108 | "" NL 109 | " .g8\"\"\"bgd db `7MMF\' db" NL 110 | " .dP\' `M ;MM: MM ;MM:" NL 111 | " dM\' ` ,V^MM. MM ,V^MM." NL 112 | " MM ,M `MM MM ,M `MM" NL 113 | " MM. `7MMF\' AbmmmqMA MM AbmmmqMA" NL 114 | " `Mb. MM A' VML MM A\' VML" NL 115 | " `\"bmmmdPY .AMA. .AMMA..JMML..AMA. .AMMA." NL 116 | NL; 117 | 118 | void 119 | sleep() 120 | { 121 | int n = 0x100; 122 | 123 | while (n--) 124 | ; 125 | } 126 | 127 | void title() 128 | { 129 | const char *c = msg; 130 | while (*c) { 131 | putchar(*c++); 132 | sleep(); 133 | } 134 | } 135 | 136 | int 137 | main() 138 | { 139 | pic_state *pic; 140 | pic_value expr; 141 | xFILE *stderr = xfopen(); 142 | 143 | title(); 144 | 145 | pic = pic_open(pic_default_allocf, pic_default_abortf, sizeof(jmp_buf), 0, NULL, NULL, xfopen(), xfopen(), stderr); 146 | 147 | while (1) { 148 | pic_try { 149 | pic_printf(pic, "> "); 150 | 151 | expr = pic_read(pic, pic->xSTDIN); 152 | 153 | pic_printf(pic, "\r\n"); 154 | 155 | if (pic_eof_p(expr)) 156 | break; 157 | 158 | pic_printf(pic, "~s\r\n", pic_eval(pic, expr, pic->lib)); 159 | } 160 | pic_catch { 161 | pic_print_backtrace(pic, stderr); 162 | } 163 | } 164 | 165 | pic_close(pic); 166 | 167 | pic_printf(pic, "halting now..."); 168 | 169 | return 0; 170 | } 171 | -------------------------------------------------------------------------------- /test/miller-rabin.c: -------------------------------------------------------------------------------- 1 | /* 2 | 1 3 | 1 4 | 1 5 | 1 6 | 1 7 | 1 8 | 1 9 | 1 10 | 1 11 | 1 12 | 1 13 | 0 14 | */ 15 | 16 | #include "test.h" 17 | 18 | typedef struct { 19 | unsigned d[4]; 20 | } ull; 21 | 22 | void assign(ull *n, ull *x) 23 | { 24 | n->d[0] = x->d[0]; 25 | n->d[1] = x->d[1]; 26 | n->d[2] = x->d[2]; 27 | n->d[3] = x->d[3]; 28 | } 29 | 30 | void assign_digit(ull *n, unsigned x) 31 | { 32 | n->d[0] = x; 33 | n->d[1] = n->d[2] = n->d[3] = 0; 34 | } 35 | 36 | int cmp(ull *n, ull *m) 37 | { 38 | int i; 39 | for (i = 3; i >= 0; --i) 40 | if (n->d[i] != m->d[i]) 41 | return n->d[i] > m->d[i] ? 1 : -1; 42 | return 0; 43 | } 44 | 45 | int cmp_digit(ull *n, unsigned x) 46 | { 47 | if (n->d[3] || n->d[2] || n->d[1] || n->d[0] > x) 48 | return 1; 49 | return n->d[0] == x ? 0 : -1; 50 | } 51 | 52 | int test_bit(ull *n, int b) 53 | { 54 | return (n->d[(b >> 4) & 3] >> (b & 15)) & 1; 55 | } 56 | 57 | void add(ull *n, ull *x, ull *y) 58 | { 59 | int i, tmp = 0; 60 | for (i = 0; i < 4; ++i) { 61 | tmp += x->d[i] + y->d[i]; 62 | n->d[i] = tmp & 0xffff; 63 | tmp >>= 16; 64 | } 65 | } 66 | 67 | void sub(ull *n, ull *x, ull *y) 68 | { 69 | int i, tmp = 0; 70 | for (i = 0; i < 4; ++i) { 71 | tmp += x->d[i] - y->d[i]; 72 | n->d[i] = tmp & 0xffff; 73 | tmp = -(tmp < 0); 74 | } 75 | } 76 | 77 | void sub_digit(ull *n, ull *x, unsigned y) 78 | { 79 | int i, carry; 80 | n->d[0] = x->d[0] - y; 81 | for (i = 1; i < 4; ++i) { 82 | carry = n->d[i - 1] >= 0x10000; 83 | if (carry) n->d[i - 1] += 0x10000; 84 | n->d[i] = x->d[i] - carry; 85 | } 86 | } 87 | 88 | void modmul(ull *n, ull *x, ull *y, ull *mod) 89 | { 90 | int i; 91 | ull res, tmp; 92 | assign_digit(&res, 0); 93 | assign(&tmp, x); 94 | for (i = 0; i < 64; ++i) { 95 | if (test_bit(y, i)) { 96 | add(&res, &res, &tmp); 97 | if (cmp(&res, mod) > 0) 98 | sub(&res, &res, mod); 99 | } 100 | add(&tmp, &tmp, &tmp); 101 | if (cmp(&tmp, mod) > 0) 102 | sub(&tmp, &tmp, mod); 103 | } 104 | assign(n, &res); 105 | } 106 | 107 | void modpow(ull *n, ull *x, ull *y, ull *mod) 108 | { 109 | int i; 110 | ull res, tmp; 111 | assign_digit(&res, 1); 112 | assign(&tmp, x); 113 | for (i = 0; i < 64; ++i, modmul(&tmp, &tmp, &tmp, mod)) 114 | if (test_bit(y, i)) modmul(&res, &res, &tmp, mod); 115 | assign(n, &res); 116 | } 117 | 118 | void shift_right(ull *n, ull *x, int y) 119 | { 120 | int i; 121 | int a = (y >> 4) & 3, b = y & 15; 122 | for (i = 0; i < 4 - a; ++i) 123 | n->d[i] = x->d[i + a] >> b; 124 | for (i = 0; i < 3 - a; ++i) 125 | n->d[i] |= (x->d[i + a + 1] << (16 - b)) & 0xffff; 126 | } 127 | 128 | int miller_rabin(ull *n, int base) 129 | { 130 | int i, s; 131 | ull d, x, nm1; 132 | if (cmp_digit(n, 2) < 0 || test_bit(n, 0) == 0) 133 | return cmp_digit(n, 2) == 0; 134 | for (s = 1; test_bit(n, s) == 0; ++s); 135 | shift_right(&d, n, s); 136 | sub_digit(&nm1, n, 1); 137 | assign_digit(&x, base); 138 | modpow(&x, &x, &d, n); 139 | if (cmp_digit(&x, 1) == 0 || cmp(&x, &nm1) == 0) 140 | return 1; 141 | for (i = 0; i < s - 1; ++i) { 142 | modmul(&x, &x, &x, n); 143 | if (cmp(&x, &nm1) == 0) return 1; 144 | } 145 | return 0; 146 | } 147 | 148 | int main() 149 | { 150 | ull n; 151 | 152 | /* assign 3825123056546413051 */ 153 | n.d[0] = 63995; 154 | n.d[1] = 20378; 155 | n.d[2] = 37159; 156 | n.d[3] = 13589; 157 | 158 | print_int(miller_rabin(&n, 2)); 159 | print_int(miller_rabin(&n, 3)); 160 | print_int(miller_rabin(&n, 5)); 161 | print_int(miller_rabin(&n, 7)); 162 | print_int(miller_rabin(&n, 11)); 163 | print_int(miller_rabin(&n, 13)); 164 | print_int(miller_rabin(&n, 17)); 165 | print_int(miller_rabin(&n, 19)); 166 | print_int(miller_rabin(&n, 23)); 167 | print_int(miller_rabin(&n, 29)); 168 | print_int(miller_rabin(&n, 31)); 169 | print_int(miller_rabin(&n, 37)); 170 | } 171 | -------------------------------------------------------------------------------- /bin/ucc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | 3 | import os.path 4 | import sys 5 | import subprocess 6 | import argparse 7 | 8 | BIN_DIR = os.path.dirname(__file__) 9 | 10 | CC = BIN_DIR + '/cc' 11 | AS = BIN_DIR + '/as' 12 | 13 | MACROS = ['__UCC__', 'inline='] 14 | INCDIRS = [BIN_DIR + '/../include'] 15 | CPPOPTS = ['-undef', '-nostdinc'] 16 | CHKOPTS = ['-fsyntax-only', '-w', '-ansi', '-pedantic-errors', '-Werror=implicit', 17 | '-Werror=aggregate-return', '-Wno-overlength-strings', '-fno-builtin'] 18 | LIBS = ['ucc', 'c'] 19 | ASOPTS = ['-f__UCC_HEAP_START'] 20 | 21 | ASMS = [] 22 | 23 | # parse command line arguments 24 | argparser = argparse.ArgumentParser( 25 | usage='%(prog)s [options] file...', formatter_class=argparse.RawTextHelpFormatter) 26 | argparser.add_argument('inputs', 27 | nargs='*', help='input files', metavar='file...') 28 | argparser.add_argument('-D', 29 | help='predefine when preprocessing', metavar='', action='append', default=MACROS) 30 | argparser.add_argument('-I', 31 | help='add to include search path', metavar='', action='append', default=[]) 32 | argparser.add_argument('-l', 33 | help='search when linking', metavar='', action='append', default=LIBS) 34 | argparser.add_argument('-nostdlib', 35 | help='do not use standard libraries when linking', action='store_true') 36 | argparser.add_argument('-o', 37 | help='set output file name', metavar='') 38 | argparser.add_argument('-S', '-s', 39 | help='compile only; do not assemble or link', action='store_true') 40 | argparser.add_argument('-Wa', 41 | help=' pass comma-separated to the assembler', metavar='\b=') 42 | argparser.add_argument('-Wc', 43 | help=' pass comma-separated to the clang', metavar='\b=') 44 | argparser.add_argument('-Wp', 45 | help=' pass comma-separated to the preprocessor', metavar='\b=') 46 | 47 | args = argparser.parse_args() 48 | 49 | if args.inputs == []: 50 | argparser.print_help(sys.stderr) 51 | exit(1) 52 | 53 | if len(args.inputs) > 1 and args.S and args.o: 54 | print >> sys.stderr, 'ucc: error: cannot specify -o when generating multiple output files' 55 | exit(1) 56 | 57 | def comma_sep_list(arg): 58 | if not arg: 59 | return [] 60 | return filter(None, map(str.strip, arg.split(','))) 61 | 62 | args.D = map(lambda s: '-D' + s, args.D) 63 | args.I = map(lambda s: '-I' + s, args.I + INCDIRS) 64 | args.l = map(lambda s: '-l{}/../lib/lib{}.s'.format(BIN_DIR, s), args.l) 65 | 66 | args.Wa = ASOPTS + args.l + comma_sep_list(args.Wa) 67 | args.Wc = CHKOPTS + comma_sep_list(args.Wc) 68 | args.Wp = CPPOPTS + args.D + args.I + comma_sep_list(args.Wp) 69 | 70 | if args.nostdlib: 71 | args.Wa.remove('-f__UCC_HEAP_START') 72 | args.Wa.remove('-l{}/../lib/libc.s'.format(BIN_DIR)) 73 | 74 | def abort(): 75 | subprocess.call(['rm', '-f'] + filter(lambda s: s.endswith('.tmp.s'), ASMS)) 76 | exit(1) 77 | 78 | def call(*cmd): 79 | try: 80 | if subprocess.call(cmd): 81 | abort() 82 | except Exception as e: 83 | print >> sys.stderr, e 84 | print >> sys.stderr, ' '.join(cmd) 85 | abort() 86 | 87 | def move_asm(fname): 88 | if args.S: 89 | if args.o: 90 | call('mv', '-f', fname + '.tmp.s', args.o) 91 | else: 92 | call('mv', '-f', fname + '.tmp.s', os.path.basename(fname) + '.s') 93 | else: 94 | ASMS.append(fname + '.tmp.s') 95 | 96 | for filename in args.inputs: 97 | if not os.path.isfile(filename): 98 | print >> sys.stderr, 'ucc: error: file does not exist:', filename 99 | abort() 100 | fname, ext = os.path.splitext(filename) 101 | if ext == '.c': 102 | call('clang', '-E', filename, '-o', fname + '.tmp.i', *args.Wp) 103 | call('clang', fname + '.tmp.i', *args.Wc) 104 | call(CC, fname + '.tmp.i') 105 | call('rm', '-f', fname + '.tmp.i') 106 | move_asm(fname) 107 | elif ext == '.S': 108 | call('clang', '-E', filename, '-o', fname + '.tmp.s', *args.Wp) 109 | move_asm(fname) 110 | elif ext == '.s': 111 | ASMS.append(filename) 112 | else: 113 | print >> sys.stderr, 'ucc: error: unknown extension:', ext 114 | abort() 115 | 116 | if args.S: 117 | exit(0) 118 | 119 | if not args.o: 120 | args.o = 'a.out' 121 | 122 | call(AS, '-o', args.o, *(args.Wa + ASMS)) 123 | call('rm', '-f', *filter(lambda s: s.endswith('.tmp.s'), ASMS)) 124 | -------------------------------------------------------------------------------- /src/lexer.mll: -------------------------------------------------------------------------------- 1 | { 2 | open Parser 3 | open Parser_helper 4 | open String 5 | 6 | exception LexerError of string 7 | 8 | let cast_char_to_int s = 9 | let table = [ 10 | ('a', 7); ('b', 8); ('t', 9); ('n', 10); 11 | ('v', 11); ('f', 12); ('r', 13); ('"', 34); 12 | ('\'', 39); ('?', 63); ('\\', 92); 13 | ] in 14 | if s.[0] <> '\\' then 15 | Char.code s.[0] 16 | else try 17 | List.assoc s.[1] table 18 | with Not_found -> 19 | let len = String.length s in 20 | if s.[1] = 'x' then 21 | int_of_string ("0x" ^ String.sub s 2 (len - 2)) 22 | else 23 | int_of_string ("0o" ^ String.sub s 1 (len - 1)) 24 | 25 | let stoi s = 26 | if String.length s >= 2 && s.[0] = '0' && s.[1] < '8' then 27 | int_of_string ("0o" ^ s) 28 | else 29 | int_of_string s 30 | } 31 | 32 | let digit = ['0'-'9'] 33 | let dec = ['1'-'9'] digit* 34 | let hex = '0' ['x' 'X'] ['0'-'9' 'a'-'f' 'A'-'F']+ 35 | let oct = '0' ['0'-'7']* 36 | let integer = dec | hex | oct 37 | let exp = ['E' 'e'] ['+' '-']? digit+ 38 | let float1 = digit+ exp 39 | let float2 = digit* '.' digit+ exp? 40 | let float3 = digit+ '.' digit* exp? 41 | let fnum = float1 | float2 | float3 42 | let space = [' ' '\t' '\r'] 43 | let alpha = ['a'-'z' 'A'-'Z' '_' ] 44 | let ident = alpha (alpha | digit)* 45 | let escapes = ['a' 'b' 't' 'n' 'v' 'f' 'r' '"' '\'' '?' '\\'] 46 | let char = [^'\\'] | '\\' (escapes | ['0'-'7']+ | 'x' ['0'-'9' 'a'-'f' 'A'-'F']+) 47 | 48 | rule token = parse 49 | | space 50 | { token lexbuf } 51 | | '\n' 52 | { Lexing.new_line lexbuf; token lexbuf } 53 | | ';' 54 | { SEMICOLON } 55 | | ',' 56 | { COMMA } 57 | | "int" 58 | { TINT } 59 | | "long" 60 | { TLONG } 61 | | "short" 62 | { TSHORT } 63 | | "signed" 64 | { TSIGNED } 65 | | "unsigned" 66 | { TUNSIGNED } 67 | | "char" 68 | { TCHAR } 69 | | "float" 70 | { TFLOAT } 71 | | "double" 72 | { TDOUBLE } 73 | | "void" 74 | { TVOID } 75 | | "struct" 76 | { STRUCT } 77 | | "union" 78 | { UNION } 79 | | "enum" 80 | { ENUM } 81 | | "typedef" 82 | { TYPEDEF } 83 | | "static" 84 | { STATIC } 85 | | "extern" 86 | { EXTERN } 87 | | "const" 88 | { token lexbuf } 89 | | "volatile" 90 | { token lexbuf } 91 | | "if" 92 | { IF } 93 | | "else" 94 | { ELSE } 95 | | "while" 96 | { WHILE } 97 | | "do" 98 | { DO } 99 | | "for" 100 | { FOR } 101 | | "return" 102 | { RETURN } 103 | | "continue" 104 | { CONTINUE } 105 | | "break" 106 | { BREAK } 107 | | "goto" 108 | { GOTO } 109 | | "switch" 110 | { SWITCH } 111 | | "case" 112 | { CASE } 113 | | "default" 114 | { DEFAULT } 115 | | '+' 116 | { PLUS } 117 | | "++" 118 | { INC } 119 | | '-' 120 | { MINUS } 121 | | '!' 122 | { NOT } 123 | | '?' 124 | { COND } 125 | | ':' 126 | { COLON } 127 | | "--" 128 | { DEC } 129 | | '*' 130 | { STAR } 131 | | '/' 132 | { SLASH } 133 | | '%' 134 | { MOD } 135 | | "<<" 136 | { LSHIFT } 137 | | ">>" 138 | { RSHIFT } 139 | | '.' 140 | { DOT } 141 | | "->" 142 | { ARROW } 143 | | '&' 144 | { AMP } 145 | | '^' 146 | { HAT } 147 | | '|' 148 | { BAR } 149 | | "&&" 150 | { AND } 151 | | "||" 152 | { OR } 153 | | '~' 154 | { TILDE } 155 | | "==" 156 | { EQ } 157 | | "!=" 158 | { NEQ } 159 | | "=" 160 | { ASSIGN } 161 | | "+=" 162 | { PLUS_ASSIGN } 163 | | "-=" 164 | { MINUS_ASSIGN } 165 | | "*=" 166 | { STAR_ASSIGN } 167 | | "/=" 168 | { SLASH_ASSIGN } 169 | | "%=" 170 | { MOD_ASSIGN } 171 | | "<<=" 172 | { LSHIFT_ASSIGN } 173 | | ">>=" 174 | { RSHIFT_ASSIGN } 175 | | "&=" 176 | { AMP_ASSIGN } 177 | | "^=" 178 | { HAT_ASSIGN } 179 | | "|=" 180 | { BAR_ASSIGN } 181 | | "<" 182 | { LT } 183 | | ">" 184 | { GT } 185 | | "<=" 186 | { LE } 187 | | ">=" 188 | { GE } 189 | | '(' 190 | { LPAREN } 191 | | ')' 192 | { RPAREN } 193 | | '{' 194 | { LBRACE } 195 | | '}' 196 | { RBRACE } 197 | | '[' 198 | { LBRACKET } 199 | | ']' 200 | { RBRACKET } 201 | | "sizeof" 202 | { SIZEOF } 203 | | "..." 204 | { DOTS } 205 | | "//" 206 | { commentbis lexbuf } 207 | | "#" 208 | { commentbis lexbuf } 209 | | "/*" 210 | { comment lexbuf } 211 | | integer as i 212 | { INT (stoi i) } 213 | | (integer as i) ['u' 'U'] 214 | { UINT (stoi i) } 215 | | (integer as i) ['l' 'L'] 216 | { LINT (stoi i) } 217 | | (integer as i) ("ul" | "UL") 218 | { ULINT (stoi i) } 219 | | '\'' (char as c) '\'' 220 | { INT (cast_char_to_int c) } 221 | | (fnum as f) [ 'f' 'F' ]? 222 | { FLOAT (float_of_string f) } 223 | | (fnum as f) [ 'l' 'L' ] 224 | { DOUBLE (float_of_string f) } 225 | | '\"' 226 | { STR (string_elements lexbuf) } 227 | | ident as n 228 | { 229 | if is_typedef_name n then 230 | TYPEDEF_NAME n 231 | else if is_enum_id n then 232 | ENUM_ID n 233 | else 234 | ID n 235 | } 236 | | eof 237 | { EOF } 238 | | _ 239 | { raise (LexerError ("illegal token '%s'" ^ Lexing.lexeme lexbuf)) } 240 | 241 | and string_elements = parse 242 | | '\"' 243 | { [] } 244 | | char as c 245 | { (cast_char_to_int c)::(string_elements lexbuf) } 246 | 247 | and comment = parse 248 | | "*/" 249 | { token lexbuf } 250 | | '\n' 251 | { Lexing.new_line lexbuf; comment lexbuf } 252 | | eof 253 | { raise (LexerError "unterminated comment") } 254 | | _ 255 | { comment lexbuf } 256 | 257 | and commentbis = parse 258 | | '\n' 259 | { Lexing.new_line lexbuf; token lexbuf } 260 | | eof 261 | { EOF } 262 | | _ 263 | { commentbis lexbuf } 264 | -------------------------------------------------------------------------------- /src/ctype.ml: -------------------------------------------------------------------------------- 1 | open Util 2 | open Printf 3 | 4 | exception TODO of string 5 | 6 | type size = int 7 | 8 | type name = string 9 | 10 | type ctype = 11 | | TInt | TShort | TLong | TChar 12 | | TUInt | TUShort | TULong | TUChar 13 | | TFloat| TDouble 14 | | TVoid 15 | | TStruct of int 16 | | TUnion of int 17 | | TPtr of ctype 18 | | TArray of ctype * int 19 | | TFun of ctype * (ctype list) 20 | 21 | type linkage = 22 | | Static 23 | | Extern 24 | | NoLink 25 | 26 | let struct_env : (string * ctype) list list ref = ref [] 27 | let union_env : (string * ctype) list list ref = ref [] 28 | 29 | let rev_table_struct : (int * string) list ref = ref [] 30 | let rev_table_union : (int * string) list ref = ref [] 31 | 32 | let rec align = function 33 | | TChar | TUChar -> 1 34 | | TShort | TUShort -> 2 35 | | TInt | TLong 36 | | TUInt | TULong 37 | | TFloat | TDouble | TPtr _ -> 4 38 | | TStruct _ 39 | | TUnion _ -> 4 40 | | TArray (ty, _) -> align ty 41 | | TFun _ -> failwith "align function" 42 | | TVoid -> failwith "align void" 43 | 44 | let aligned ty n = 45 | let a = align ty in 46 | (n + a - 1) / a * a 47 | 48 | let rec sizeof = function 49 | | TChar | TUChar -> 1 50 | | TShort | TUShort -> 2 51 | | TInt | TLong 52 | | TUInt | TULong 53 | | TFloat | TDouble | TPtr _ -> 4 54 | | TStruct s_id as ty -> 55 | s_id |> List.nth !struct_env 56 | |> List.map snd 57 | |> List.fold_left (fun n t -> aligned t n + sizeof t) 0 58 | |> aligned ty 59 | | TUnion u_id as ty -> 60 | u_id |> List.nth !union_env 61 | |> List.map (snd >> sizeof) 62 | |> Util.max_of 63 | |> aligned ty 64 | | TArray (ty, sz) -> (sizeof ty) * sz 65 | | TFun _ -> failwith "sizeof function" 66 | | TVoid -> failwith "sizeof void" 67 | 68 | let promote = function 69 | | TChar | TUChar 70 | | TInt | TShort | TLong -> TInt 71 | | TUInt | TUShort | TULong -> TUInt 72 | | TFloat| TDouble -> TDouble 73 | | ty -> failwith "promote" 74 | 75 | 76 | (* operator definitions *) 77 | 78 | type arith_bin = 79 | | Add | Sub 80 | | Mul | Div | Mod 81 | | LShift | RShift 82 | | BitAnd | BitXor | BitOr 83 | 84 | type logical_bin = LogAnd | LogOr 85 | 86 | type rel_bin = Lt | Le | Gt | Ge 87 | 88 | type eq_bin = Eq | Ne 89 | 90 | type unary = Plus | Minus | BitNot | PostInc | PostDec 91 | 92 | type inc = Inc | Dec 93 | 94 | 95 | let is_integral = function 96 | | TInt | TShort | TLong | TChar 97 | | TUInt | TUShort | TULong | TUChar -> true 98 | | _ -> false 99 | 100 | let is_real = function 101 | | TFloat | TDouble -> true 102 | | _ -> false 103 | 104 | let is_unsigned = function 105 | | TUInt | TUShort | TULong | TUChar -> true 106 | | _ -> false 107 | 108 | let is_arith t = is_integral t || is_real t 109 | 110 | let is_pointer = function 111 | | TPtr _ -> true 112 | | _ -> false 113 | 114 | let is_scalar t = is_arith t || is_pointer t 115 | 116 | let is_funty = function 117 | | TFun _ -> true 118 | | _ -> false 119 | 120 | let deref_pointer = function 121 | | TPtr ty -> ty 122 | | _ -> failwith "deref_pointer" 123 | 124 | 125 | (* functions for fold-expression *) 126 | 127 | let uint_of_int x = 128 | if x < 0 then x + 0x100000000 else x 129 | 130 | let arith2fun ty = function 131 | | Add -> (+) 132 | | Sub -> (-) 133 | | Mul -> ( * ) 134 | | Div -> 135 | if is_unsigned ty then 136 | fun x y -> uint_of_int x / uint_of_int y 137 | else (/) 138 | | Mod -> 139 | if is_unsigned ty then 140 | fun x y -> uint_of_int x mod uint_of_int y 141 | else (mod) 142 | | LShift -> (lsl) 143 | | RShift -> 144 | if is_unsigned ty then 145 | fun x y -> (x land 0xffffffff) lsr y 146 | else (asr) 147 | | BitAnd -> (land) 148 | | BitXor -> (lxor) 149 | | BitOr -> (lor) 150 | 151 | let farith2fun = function 152 | | Add -> (+.) 153 | | Sub -> (-.) 154 | | Mul -> ( *. ) 155 | | Div -> (/.) 156 | | _ -> failwith "farith2fun" 157 | 158 | let rel2fun rel = 159 | let op = 160 | match rel with 161 | | Lt -> (<) 162 | | Le -> (<=) 163 | | Gt -> (>) 164 | | Ge -> (>=) in 165 | (fun a b -> if (op a b) then 1 else 0) 166 | 167 | let urel2fun rel = 168 | let op = 169 | match rel with 170 | | Lt -> (<) 171 | | Le -> (<=) 172 | | Gt -> (>) 173 | | Ge -> (>=) in 174 | (fun a b -> if (op (uint_of_int a) (uint_of_int b)) then 1 else 0) 175 | 176 | let eq2fun eq = 177 | let op = 178 | match eq with 179 | | Eq -> (=) 180 | | Ne -> (<>) in 181 | (fun a b -> if (op a b) then 1 else 0) 182 | 183 | let unary2fun = function 184 | | Plus -> (+) 0 185 | | Minus -> (-) 0 186 | | BitNot -> (lnot) 187 | | _ -> failwith "unary2fun: PostInc/PostDec" 188 | 189 | 190 | (* pretty-printing *) 191 | 192 | let rec pp_struct id = 193 | try 194 | let s = List.assoc id !rev_table_struct in 195 | sprintf "struct %s" s 196 | with 197 | Not_found -> 198 | let m = (List.nth !struct_env id) in 199 | let ms = String.concat "; " 200 | (List.map (fun (_, ty) -> pp_type ty) m) in 201 | sprintf "struct {%s;}" ms 202 | and pp_union id = 203 | try 204 | let s = List.assoc id !rev_table_struct in 205 | sprintf "union %s" s 206 | with 207 | Not_found -> 208 | let m = (List.nth !union_env id) in 209 | let ms = String.concat "; " 210 | (List.map (fun (_, ty) -> pp_type ty) m) in 211 | sprintf "union {%s;}" ms 212 | and pp_type ty = 213 | let rec go str = function 214 | | TInt -> "int" ^ str 215 | | TShort -> "short" ^ str 216 | | TLong -> "long" ^ str 217 | | TChar -> "char" ^ str 218 | | TUInt -> "unsigned" ^ str 219 | | TUShort -> "unsigned short" ^ str 220 | | TULong -> "unsigned long" ^ str 221 | | TUChar -> "unsigned char" ^ str 222 | | TFloat -> "float" ^ str 223 | | TDouble -> "double" ^ str 224 | | TVoid -> "void" ^ str 225 | | TStruct id -> 226 | sprintf "%s%s" (pp_struct id) str 227 | | TUnion id -> 228 | sprintf "%s%s" (pp_union id) str 229 | | TPtr ty -> 230 | let s = match ty with 231 | | TArray _ | TFun _ -> 232 | sprintf "(*%s)" str 233 | | TPtr _ -> 234 | sprintf "*%s" str 235 | | _ -> 236 | sprintf " *%s" str in 237 | go s ty 238 | | TArray (ty, sz) -> 239 | go (str ^ "[]") ty 240 | | TFun (ty, args)-> 241 | let a = String.concat ", " (List.map (go "") args) in 242 | go (sprintf "%s(%s)" str a) ty 243 | in 244 | go "" ty 245 | -------------------------------------------------------------------------------- /lib/libm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * math.h 3 | */ 4 | 5 | static double __pow_fi(double a,int n){ 6 | // return a^x 7 | double r = 1.0; 8 | while(n-- > 0) r *= a; 9 | return r; 10 | } 11 | 12 | 13 | /* 14 | * sqrt 15 | * fabs 16 | * 17 | */ 18 | double sqrt(double x){ 19 | __asm("\ 20 | mov r1, [rbp + 4] \n\ 21 | fsqrt r1, r1 \n\ 22 | ret\n"); 23 | } 24 | 25 | double fabs(double x){ 26 | return x < 0 ? -x : x; 27 | } 28 | 29 | /* 30 | * kernel sin 31 | * kernel cos 32 | * 33 | * x is in range [-pi/4, pi/4] 34 | * 35 | */ 36 | static double __kernel_sin(double x){ 37 | double a1, a2, a3, a4; 38 | 39 | a1 = 0.1666667; 40 | a2 = 0.0500000; 41 | a3 = 0.0238095; 42 | a4 = 0.0138888; 43 | 44 | return x*(1-a1*x*x*(1-a2*x*x*(1-a3*x*x*(1-a4*x*x)))); 45 | } 46 | static double __kernel_cos(double x){ 47 | double a1, a2, a3, a4; 48 | 49 | a1 = 0.5000000; 50 | a2 = 0.0833333; 51 | a3 = 0.0333333; 52 | a4 = 0.0178571; 53 | 54 | return (1-a1*x*x*(1-a2*x*x*(1-a3*x*x*(1-a4*x*x)))); 55 | } 56 | 57 | /* 58 | * __frem_for_triangle 59 | * 60 | * i is a quotient, x = pi/4 * i + (return value) 61 | * 62 | */ 63 | static double __frem_for_triangle(double x, int *i){ 64 | double pi4; 65 | 66 | *i=0; 67 | pi4 = 0.7853981; // const value 68 | 69 | while(x - (*i)*pi4 >= 0) (*i) += 1; 70 | *i -= 1; 71 | 72 | return (x - (*i)*pi4); 73 | } 74 | 75 | /* 76 | * sin 77 | * sin(x) = -sin(-x) 78 | * cos 79 | * cos(x) = cos(-x) 80 | * tan 81 | * tan(x) = tan(x + pi/2) 82 | */ 83 | double sin(double x){ 84 | int i, neg; 85 | double y; 86 | 87 | neg = x > 0 ? 1 : -1; 88 | x = x > 0 ? x : -x; 89 | y = __frem_for_triangle(x, &i); 90 | 91 | if(i%8 >= 4 && neg == 1) neg = -1; 92 | else if(i%8 >= 4 && neg == -1) neg = 1; 93 | 94 | switch(i%4){ 95 | case 0: 96 | return neg * __kernel_sin(y); 97 | case 1: 98 | return neg * __kernel_cos(0.7853981 - y); 99 | case 2: 100 | return neg * __kernel_cos(y); 101 | default: 102 | return neg * __kernel_sin(0.7853981 - y); 103 | } 104 | } 105 | double cos(double x){ 106 | int i; 107 | double y; 108 | 109 | x = x > 0 ? x : -x; 110 | y = __frem_for_triangle(x, &i); 111 | 112 | switch(i%8){ 113 | case 0: 114 | return __kernel_cos(y); 115 | case 1: 116 | return __kernel_sin(0.7853981 - y); 117 | case 2: 118 | return - __kernel_sin(y); 119 | case 3: 120 | return - __kernel_cos(0.7853981 - y); 121 | case 4: 122 | return - __kernel_cos(y); 123 | case 5: 124 | return - __kernel_sin(0.7853981 - y); 125 | case 6: 126 | return __kernel_sin(y); 127 | default: 128 | return __kernel_cos(0.7853981 - y); 129 | } 130 | } 131 | double tan(double x){ 132 | return sin(x)/cos(x); 133 | } 134 | 135 | static double __arctan_sub(double x){ 136 | return x*(1.0 - 0.33333333*x*x*(1.0 - 0.60*x*x*(1.0 - 2.1428571*x*x))); 137 | } 138 | 139 | /* 140 | * arctan 141 | * 142 | * arctan(x) = - arctan(-x) 143 | * 144 | * Algorithm: 145 | * 0 <= x <= sqrt(2) - 1: 146 | * x - 1/3 x^3 + 1/5 x^5 + ... 147 | * sqrt(2) - 1 < x < 1 148 | * pi/4 - arctan((1-x)/(1+x)) 149 | * 1 <= x < 1 + sqrt(2) 150 | * z = 1/x 151 | * arctan(x) = pi/2 - arctan(z) 152 | * 1 + sqrt(2) <= x 153 | * z = 1/x 154 | * arctan(x) = pi/2 - arctan(z) 155 | * 156 | */ 157 | double atan(double x){ 158 | int sign; 159 | 160 | sign = x >= 0 ? 1 : -1; 161 | x = x >= 0 ? x : -x; 162 | 163 | if(0.0 <= x && x <= 0.41421356){ 164 | return sign * __arctan_sub(x); 165 | }else if(0.41421356 < x && x <= 1.0){ 166 | double tmp; 167 | tmp = (1.0 - x) / (1.0 + x); 168 | return sign * (0.7853981 - __arctan_sub(tmp)); 169 | }else if(1.0 <= x && x <= 2.41421356){ 170 | double tmp; 171 | tmp = (x - 1.0)/(x + 1.0); 172 | return sign * (0.7853981 + __arctan_sub(tmp)); 173 | }else{ 174 | double tmp; 175 | tmp = 1.0/x; 176 | return sign * (1.5707963 - __arctan_sub(tmp)); 177 | } 178 | } 179 | 180 | double asin(double x){ 181 | if(x < -1.0 || x > 1.0) return -1024; // error 182 | if(x == -1.0) return -1.5707963; 183 | if(x == 1.0) return 1.5707963; 184 | 185 | if(x > 0.816){ 186 | return atan(x/sqrt((1+x)*(1-x))); 187 | }else{ 188 | return atan(x/sqrt(1-x*x)); 189 | } 190 | } 191 | double acos(double x){ 192 | if(x < -1.0 || x > 1.0) return -1024; // error 193 | if(x == -1.0) return 3.14159265; 194 | if(x == 1.0) return 0.0; 195 | 196 | if(x > 0.816){ 197 | return 1.5707963 - atan(x/sqrt((1+x)*(1-x))); 198 | }else{ 199 | return 1.5707963 - atan(x/sqrt(1-x*x)); 200 | } 201 | } 202 | 203 | static double __exp_sub(double x){ 204 | int i, j; 205 | double res, a; 206 | 207 | res = 0; 208 | for(i=0; i<10; i++){ 209 | a=1.0; 210 | for(j=1; j<=i; j++){ 211 | a *= x/(double)j; 212 | } 213 | res += a; 214 | } 215 | return res; 216 | } 217 | static double __frem_for_exp(double x, int *i){ 218 | double log2; 219 | 220 | *i=0; 221 | log2 = 0.693147180; // const value 222 | 223 | while(x - (*i)*log2 >= 0) (*i) += 1; 224 | *i -= 1; 225 | 226 | return (x - (*i)*log2); 227 | } 228 | 229 | /* 230 | * exp 231 | * 232 | * Algorithm: 233 | * 0 <= x < log_e(2): 234 | * 1 + x + x^2/2 + ... 235 | * log_e(2) <= x 236 | * x = m*log_e(2) + z 237 | * e^x = e^z * 2^m 238 | * x < 0 239 | * z = -x 240 | * exp(x) = 1.0/exp(z) 241 | * 242 | */ 243 | double exp(double x){ 244 | if(x < 0){ 245 | return 1.0/exp(-x); 246 | }else if(x < 0.693147180){ 247 | return __exp_sub(x); 248 | }else{ 249 | int d, m; 250 | double z; 251 | 252 | z = __frem_for_exp(x, &m); 253 | 254 | d = 1; 255 | while(m-- > 0) d *= 2; 256 | 257 | return d * __exp_sub(z); 258 | } 259 | } 260 | 261 | /* 262 | * log(log_e) 263 | * log(x) = -1 if x <= 0 264 | * generally, return nan (x < 0) and -inf (x = 0) 265 | * 266 | * Algorithm: 267 | * x = 2^m * z (1 <= z < 2) 268 | * y = (z-1)/(z+1) 269 | * log((1+x)/(1-x)) = 2(x + x^3/3 + ...) 270 | * -> log z = log((1+y)/(1-y)) 271 | * log x = log z + m*log(2) 272 | * 273 | * pow 274 | * use exp and log 275 | * a^x = exp(x * log_e(a)) 276 | */ 277 | double log(double x){ 278 | int i, m; 279 | double z, y, t; 280 | 281 | if(x <= 0) 282 | return -1; 283 | 284 | m = 0; 285 | z = x/__pow_fi(2.0, m); 286 | while(2.0 <= z){ 287 | m++; 288 | z = x/__pow_fi(2.0, m); 289 | } 290 | 291 | y = (z-1)/(z+1); 292 | t = 0; 293 | 294 | for(i=0; i<10; i++){ 295 | t += __pow_fi(y, 2*i+1)/(2*i + 1); 296 | } 297 | 298 | return (2.0*t + m*0.693147180); 299 | } 300 | double pow(double a, double x){ 301 | return exp(x * log(a)); 302 | } 303 | 304 | /* 305 | * hyperbolic function 306 | * 307 | */ 308 | double sinh(double x){ 309 | return (exp(x) - exp(-x))/2.0; 310 | } 311 | double cosh(double x){ 312 | return (exp(x) + exp(-x))/2.0; 313 | } 314 | double tanh(double x){ 315 | return sinh(x)/cosh(x); 316 | } 317 | 318 | /* 319 | * floor 320 | */ 321 | 322 | double floor(double x) { 323 | __asm("\ 324 | mov r1, [rbp + 4] \n \ 325 | floor r1, r1 \n \ 326 | ret \n \ 327 | "); 328 | } 329 | -------------------------------------------------------------------------------- /src/parser.mly: -------------------------------------------------------------------------------- 1 | %{ 2 | open Syntax 3 | open Ctype 4 | open Parser_helper 5 | open Util 6 | 7 | exception ParserError of string 8 | 9 | type declarator = 10 | | DeclPtr of declarator 11 | | DeclIdent of name 12 | | DeclArray of declarator * size 13 | | DeclFun of declarator * (decl list) 14 | 15 | let struct_table : (string * (int * int)) list ref = ref [] 16 | let union_table : (string * (int * int)) list ref = ref [] 17 | 18 | let scope_stack = ref [] 19 | 20 | let get_namety = function 21 | | Decl (_, ty, name, _) -> (name, ty) 22 | 23 | let add_struct_decl name_opt decl = 24 | let id = List.length !struct_env in 25 | if is_some name_opt then begin 26 | let depth = List.length !scope_stack in 27 | push struct_table (from_some name_opt, (id, depth)); 28 | push rev_table_struct (id, from_some name_opt) 29 | end; 30 | struct_env := !struct_env @ [List.map get_namety decl]; 31 | TStruct id 32 | 33 | let add_union_decl name_opt decl = 34 | let id = List.length !union_env in 35 | if is_some name_opt then begin 36 | let depth = List.length !scope_stack in 37 | push union_table (from_some name_opt, (id, depth)); 38 | push rev_table_struct (id, from_some name_opt) 39 | end; 40 | union_env := !union_env @ [List.map get_namety decl]; 41 | TUnion id 42 | 43 | let get_ty = function 44 | | Decl (_, TArray (ty, sz), _, _) -> 45 | TPtr ty 46 | | Decl (_, ty, _, _) -> 47 | ty 48 | 49 | let make_decl ln ty (decl, exp) = 50 | let name = ref "" in 51 | let rec go k = function 52 | | DeclIdent n -> 53 | name := n; 54 | k ty 55 | | DeclPtr d -> 56 | go (fun x -> TPtr (k x)) d 57 | | DeclArray (d, sz) -> 58 | go (fun x -> TArray (k x, sz)) d 59 | | DeclFun (d, dvs) -> 60 | go (fun x -> TFun (k x, List.map get_ty dvs)) d in 61 | let ty = go id decl in 62 | typedef_env := List.filter (((<>) !name) << fst) !typedef_env; 63 | enum_env := List.filter (((<>) !name) << fst) !enum_env; 64 | Decl (ln, ty, !name, exp) 65 | 66 | let make_decls ln ty decls = 67 | if decls = [] then begin 68 | let rec go target = function 69 | | (name, (id, depth)) :: _ when id = target -> 70 | (depth = List.length !scope_stack, name) 71 | | _ :: l -> 72 | go target l 73 | | [] -> 74 | assert false in 75 | match ty with 76 | | TStruct s_id -> 77 | let (flag, name) = go s_id !struct_table in 78 | if not flag then ignore (add_struct_decl (Some name) []) else () 79 | | TUnion u_id -> 80 | let (flag, name) = go u_id !union_table in 81 | if not flag then ignore (add_union_decl (Some name) []) else () 82 | | _ -> 83 | () 84 | end; 85 | List.map (make_decl ln ty) decls 86 | 87 | let rec get_params = function 88 | | DeclFun (_, dvs) -> 89 | let go = function 90 | | Decl(ln, TArray (ty, _), nm, e) -> 91 | Decl(ln, TPtr ty, nm, e) 92 | | x -> x in 93 | List.map go dvs 94 | | DeclPtr d -> get_params d 95 | | _ -> raise (ParserError "get_params") 96 | 97 | let make_type ty decl = 98 | match make_decl NoLink ty (decl, None) with 99 | | Decl (_, ty, "", None) -> 100 | ty 101 | | _ -> 102 | raise (ParserError "make_type") 103 | 104 | let lookup_structty name = 105 | try 106 | TStruct (fst (List.assoc name !struct_table)) 107 | with Not_found -> 108 | add_struct_decl (Some name) [] 109 | 110 | let lookup_unionty name = 111 | try 112 | TUnion (fst (List.assoc name !union_table)) 113 | with Not_found -> 114 | add_union_decl (Some name) [] 115 | 116 | let insert_struct_decl name decl = 117 | try 118 | let (id, depth) = List.assoc name !struct_table in 119 | if depth = List.length !scope_stack then begin 120 | struct_env := list_set !struct_env id (List.map get_namety decl); 121 | TStruct id 122 | end else 123 | add_struct_decl (Some name) decl 124 | with Not_found -> 125 | add_struct_decl (Some name) decl 126 | 127 | let insert_union_decl name decl = 128 | try 129 | let (id, depth) = List.assoc name !union_table in 130 | if depth = List.length !scope_stack then begin 131 | union_env := list_set !union_env id (List.map get_namety decl); 132 | TUnion id 133 | end else 134 | add_union_decl (Some name) decl 135 | with Not_found -> 136 | add_union_decl (Some name) decl 137 | 138 | let make_structty decl = function 139 | | Some name -> 140 | insert_struct_decl name decl 141 | | None -> 142 | add_struct_decl None decl 143 | 144 | let make_unionty decl = function 145 | | Some name -> 146 | insert_union_decl name decl 147 | | None -> 148 | add_union_decl None decl 149 | 150 | let make_enumty enums = 151 | let go num = function 152 | | (enum, Some cnst) -> 153 | enum_def enum cnst; 154 | cnst+1 155 | | (enum, None) -> 156 | enum_def enum num; 157 | num+1 in 158 | ignore (List.fold_left go 0 enums) 159 | 160 | let scope_enter () = 161 | push scope_stack (!struct_table, !union_table, !typedef_env, !enum_env) 162 | 163 | let scope_leave () = 164 | let (s, u, t, e) = peek scope_stack in 165 | struct_table := s; 166 | union_table := u; 167 | typedef_env := t; 168 | enum_env := e; 169 | pop scope_stack 170 | 171 | let const_check e = 172 | let rec go = function 173 | | EConst (VInt i) -> 174 | Some i 175 | | EArith(op, e1, e2) -> 176 | opMap2 (arith2fun TInt op) (go e1) (go e2) 177 | | EUnary(op, e1) -> 178 | if op = PostInc || op = PostDec then None else 179 | opMap (unary2fun op) (go e1) 180 | | _ -> None in 181 | match go e with 182 | | Some x -> x 183 | | None -> failwith "const_check" 184 | 185 | let to_unsigned = function 186 | | (TInt, true) -> TUInt 187 | | (TShort, true) -> TUShort 188 | | (TLong, true) -> TULong 189 | | (TChar, true) -> TUChar 190 | | (t, _) -> t 191 | 192 | let create_type (t1, u1) (t2, u2) = 193 | let go = function 194 | | (t1, t2) when not (is_integral t1 && is_integral t2) -> 195 | failwith "create_type" 196 | | (TLong, _) | (_, TLong) -> TLong 197 | | (TShort, _) | (_, TShort) -> TShort 198 | | (TChar, _) | (_, TChar) -> TChar 199 | | _ -> TInt in 200 | (go (t1, t2), u1 || u2) 201 | 202 | %} 203 | 204 | %token INT UINT LINT ULINT 205 | %token FLOAT DOUBLE 206 | %token STR 207 | %token ID 208 | %token TYPEDEF_NAME 209 | %token ENUM_ID 210 | %token TINT TUNSIGNED TSIGNED TFLOAT TDOUBLE TCHAR TSHORT TLONG TVOID 211 | %token STRUCT UNION TYPEDEF ENUM 212 | %token STATIC EXTERN 213 | %token IF ELSE WHILE DO FOR 214 | %token RETURN CONTINUE BREAK GOTO 215 | %token SWITCH CASE DEFAULT 216 | %token LPAREN RPAREN 217 | %token LBRACE RBRACE 218 | %token LBRACKET RBRACKET 219 | %token INC DEC 220 | %token AND OR 221 | %token NOT COND COLON 222 | %token AMP HAT BAR TILDE 223 | %token PLUS MINUS MOD STAR LSHIFT RSHIFT SLASH 224 | %token DOT ARROW 225 | %token EQ NEQ LT LE GT GE 226 | %token SEMICOLON COMMA 227 | %token ASSIGN PLUS_ASSIGN MINUS_ASSIGN 228 | %token STAR_ASSIGN SLASH_ASSIGN MOD_ASSIGN LSHIFT_ASSIGN RSHIFT_ASSIGN 229 | %token AMP_ASSIGN HAT_ASSIGN BAR_ASSIGN 230 | %token SIZEOF 231 | %token DOTS 232 | %token EOF 233 | 234 | /* avoid dangling-else problem */ 235 | %nonassoc RPAREN 236 | %nonassoc ELSE 237 | 238 | %type main 239 | %start main 240 | 241 | %% 242 | 243 | main: 244 | | external_decl_list EOF 245 | { List.concat $1 } 246 | | error 247 | { failwith "parse error" } 248 | 249 | external_decl: 250 | | fun_definition 251 | { [$1] } 252 | | decl 253 | { List.map (fun x -> DefVar x) $1 } 254 | 255 | external_decl_list: 256 | | 257 | { [] } 258 | | external_decl external_decl_list 259 | { $1 :: $2 } 260 | 261 | fun_definition: 262 | | linkage decl_specs declarator compound_stat 263 | { DefFun (make_decl $1 $2 ($3, None), get_params $3, $4) } 264 | 265 | linkage: 266 | | 267 | { NoLink } 268 | | EXTERN 269 | { Extern } 270 | | STATIC 271 | { Static } 272 | 273 | decl_list: 274 | | 275 | { [] } 276 | | decl decl_list 277 | { $1 :: $2 } 278 | 279 | decl: 280 | | linkage decl_specs init_declarator_list SEMICOLON 281 | { make_decls $1 $2 $3 } 282 | | TYPEDEF decl_specs declarator SEMICOLON 283 | { typedef (make_decl NoLink $2 ($3, None)); [] } 284 | 285 | decl_specs: 286 | | decl_specs_sub 287 | { to_unsigned $1 } 288 | | TYPEDEF_NAME 289 | { List.assoc $1 !typedef_env } 290 | 291 | decl_specs_sub: 292 | | type_spec 293 | { $1 } 294 | | type_spec decl_specs_sub 295 | { create_type $1 $2 } 296 | 297 | type_spec: 298 | | TINT 299 | { (TInt, false) } 300 | | TSIGNED 301 | { (TInt, false) } 302 | | TSHORT 303 | { (TShort, false) } 304 | | TLONG 305 | { (TLong, false) } 306 | | TUNSIGNED 307 | { (TInt, true) } 308 | | TCHAR 309 | { (TChar, false) } 310 | | TFLOAT 311 | { (TFloat, false) } 312 | | TDOUBLE 313 | { (TDouble, false) } 314 | | TVOID 315 | { (TVoid, false) } 316 | | struct_spec 317 | { ($1, false) } 318 | | enum_spec 319 | { ($1, false) } 320 | 321 | ident_option: 322 | | 323 | { None } 324 | | ident 325 | { Some $1 } 326 | 327 | struct_spec: 328 | | STRUCT ident_option LBRACE struct_decl_list RBRACE 329 | { make_structty (List.concat $4) $2 } 330 | | STRUCT ident 331 | { lookup_structty $2 } 332 | | UNION ident_option LBRACE struct_decl_list RBRACE 333 | { make_unionty (List.concat $4) $2 } 334 | | UNION ident 335 | { lookup_unionty $2 } 336 | 337 | struct_decl: 338 | | decl 339 | { $1 } 340 | 341 | struct_decl_list: 342 | | struct_decl 343 | { [$1] } 344 | | struct_decl struct_decl_list 345 | { $1 :: $2 } 346 | 347 | enum_spec: 348 | | ENUM ident_option LBRACE enumerator_list RBRACE 349 | { make_enumty $4; TInt } 350 | | ENUM ident 351 | { TInt } 352 | 353 | enumerator: 354 | | ident 355 | { ($1, None) } 356 | | ident ASSIGN const_expr 357 | { ($1, Some $3) } 358 | 359 | enumerator_list: 360 | | enumerator 361 | { [$1] } 362 | | enumerator COMMA enumerator_list 363 | { $1 :: $3 } 364 | 365 | init_declarator: 366 | | declarator 367 | { ($1, None) } 368 | | declarator ASSIGN initializer_ 369 | { ($1, Some $3) } 370 | 371 | init_declarator_list: 372 | | 373 | { [] } 374 | | init_declarator 375 | { [$1] } 376 | | init_declarator COMMA init_declarator_list 377 | { $1 :: $3 } 378 | 379 | declarator: 380 | | direct_declarator 381 | { $1 } 382 | | STAR declarator 383 | { DeclPtr $2 } 384 | 385 | direct_declarator: 386 | | ident 387 | { DeclIdent $1 } 388 | | LPAREN id_declarator RPAREN 389 | { $2 } 390 | | direct_declarator LBRACKET const_expr RBRACKET 391 | { DeclArray($1, $3) } 392 | | direct_declarator LBRACKET RBRACKET 393 | { DeclArray($1, 0) } 394 | | direct_declarator LPAREN param_decl_list RPAREN 395 | { DeclFun ($1, $3)} 396 | | direct_declarator LPAREN RPAREN 397 | { DeclFun ($1, [])} 398 | 399 | id_declarator: 400 | | direct_id_declarator 401 | { $1 } 402 | | STAR declarator 403 | { DeclPtr $2 } 404 | 405 | direct_id_declarator: 406 | | ID 407 | { DeclIdent $1 } 408 | | ENUM_ID 409 | { DeclIdent $1 } 410 | | LPAREN id_declarator RPAREN 411 | { $2 } 412 | | direct_id_declarator LBRACKET const_expr RBRACKET 413 | { DeclArray($1, $3) } 414 | | direct_id_declarator LBRACKET RBRACKET 415 | { DeclArray($1, 0) } 416 | | direct_id_declarator LPAREN param_decl_list RPAREN 417 | { DeclFun ($1, $3)} 418 | | direct_id_declarator LPAREN RPAREN 419 | { DeclFun ($1, [])} 420 | 421 | param_decl_list: 422 | | param_decl 423 | { [$1] } 424 | | param_decl COMMA DOTS 425 | { [$1] } 426 | | param_decl COMMA param_decl_list 427 | { $1 :: $3 } 428 | 429 | param_decl: 430 | | decl_specs declarator 431 | { make_decl NoLink $1 ($2, None) } 432 | | decl_specs abstract_declarator 433 | { make_decl NoLink $1 ($2, None) } 434 | | decl_specs 435 | { make_decl NoLink $1 (DeclIdent "", None) } 436 | 437 | initializer_: /* 'initializer' is an OCaml's keyword! */ 438 | | assign_expr 439 | { IScal $1 } 440 | | LBRACE initializer_list RBRACE 441 | { IVect $2 } 442 | 443 | initializer_list: 444 | | initializer_ 445 | { [$1] } 446 | | initializer_ COMMA initializer_list 447 | { $1 :: $3 } 448 | 449 | type_name: 450 | | decl_specs 451 | { make_type $1 (DeclIdent "") } 452 | | decl_specs abstract_declarator 453 | { make_type $1 $2 } 454 | 455 | abstract_declarator: 456 | | STAR 457 | { DeclPtr (DeclIdent "") } 458 | | STAR abstract_declarator 459 | { DeclPtr $2 } 460 | | direct_abstract_declarator 461 | { $1 } 462 | 463 | direct_abstract_declarator: 464 | | LPAREN abstract_declarator RPAREN 465 | { $2 } 466 | | LBRACKET const_expr RBRACKET 467 | { DeclArray (DeclIdent "", $2) } 468 | | LPAREN param_decl_list RPAREN 469 | { DeclFun (DeclIdent "", $2) } 470 | | direct_abstract_declarator LBRACKET RBRACKET 471 | { DeclArray ($1, 0) } 472 | | direct_abstract_declarator LBRACKET const_expr RBRACKET 473 | { DeclArray ($1, $3) } 474 | | direct_abstract_declarator LPAREN param_decl_list RPAREN 475 | { DeclFun ($1, $3) } 476 | 477 | stat: 478 | | expr_stat 479 | { $1 } 480 | | compound_stat 481 | { $1 } 482 | | selection_stat 483 | { $1 } 484 | | iteration_stat 485 | { $1 } 486 | | jump_stat 487 | { $1 } 488 | | labeled_stat 489 | { $1 } 490 | 491 | stat_list: 492 | | 493 | { [] } 494 | | stat stat_list 495 | { $1 :: $2 } 496 | 497 | expr_stat: 498 | | SEMICOLON 499 | { SNil } 500 | | expr SEMICOLON 501 | { SExpr($1) } 502 | 503 | compound_stat: 504 | | lbrace_with_action decl_list stat_list rbrace_with_action 505 | { SBlock(List.concat $2, $3) } 506 | 507 | lbrace_with_action: 508 | | LBRACE 509 | { scope_enter () } 510 | 511 | rbrace_with_action: 512 | | RBRACE 513 | { scope_leave () } 514 | 515 | selection_stat: 516 | | IF LPAREN expr RPAREN stat 517 | { SIfElse($3, $5, SNil) } 518 | | IF LPAREN expr RPAREN stat ELSE stat 519 | { SIfElse($3, $5, $7) } 520 | | SWITCH LPAREN expr RPAREN stat 521 | { SSwitch($3, $5) } 522 | 523 | iteration_stat: 524 | | WHILE LPAREN expr RPAREN stat 525 | { SWhile($3, $5) } 526 | | DO stat WHILE LPAREN expr RPAREN SEMICOLON 527 | { SDoWhile($2, $5) } 528 | | FOR LPAREN expr_option SEMICOLON expr_option SEMICOLON expr_option RPAREN stat 529 | { SFor($3, $5, $7, $9) } 530 | 531 | jump_stat: 532 | | GOTO ident SEMICOLON 533 | { SGoto $2 } 534 | | BREAK SEMICOLON 535 | { SBreak } 536 | | CONTINUE SEMICOLON 537 | { SContinue } 538 | | RETURN expr_option SEMICOLON 539 | { SReturn $2 } 540 | 541 | labeled_stat: 542 | | ID COLON stat 543 | { SLabel($1, $3) } 544 | | CASE cond_expr COLON 545 | { SCase($2) } 546 | | DEFAULT COLON 547 | { SDefault } 548 | 549 | expr: 550 | | assign_expr 551 | { $1 } 552 | | expr COMMA assign_expr 553 | { EComma($1, $3) } 554 | 555 | expr_option: 556 | | 557 | { None } 558 | | expr 559 | { Some $1 } 560 | 561 | assign_expr: 562 | | cond_expr 563 | { $1 } 564 | | unary_expr ASSIGN assign_expr 565 | { EAssign(None, $1, $3) } 566 | | unary_expr PLUS_ASSIGN assign_expr 567 | { EAssign(Some Add, $1, $3) } 568 | | unary_expr MINUS_ASSIGN assign_expr 569 | { EAssign(Some Sub, $1, $3) } 570 | | unary_expr STAR_ASSIGN assign_expr 571 | { EAssign(Some Mul, $1, $3) } 572 | | unary_expr SLASH_ASSIGN assign_expr 573 | { EAssign(Some Div, $1, $3) } 574 | | unary_expr MOD_ASSIGN assign_expr 575 | { EAssign(Some Mod, $1, $3) } 576 | | unary_expr LSHIFT_ASSIGN assign_expr 577 | { EAssign(Some LShift, $1, $3) } 578 | | unary_expr RSHIFT_ASSIGN assign_expr 579 | { EAssign(Some RShift, $1, $3) } 580 | | unary_expr AMP_ASSIGN assign_expr 581 | { EAssign(Some BitAnd, $1, $3) } 582 | | unary_expr HAT_ASSIGN assign_expr 583 | { EAssign(Some BitXor, $1, $3) } 584 | | unary_expr BAR_ASSIGN assign_expr 585 | { EAssign(Some BitOr, $1, $3) } 586 | 587 | cond_expr: 588 | | logor_expr 589 | { $1 } 590 | | logor_expr COND expr COLON cond_expr 591 | { ECond($1, $3, $5) } 592 | 593 | const_expr: 594 | | cond_expr 595 | { const_check $1 } 596 | 597 | logor_expr: 598 | | logand_expr 599 | { $1 } 600 | | logor_expr OR logand_expr 601 | { ELog (LogOr, $1, $3) } 602 | 603 | logand_expr: 604 | | bitor_expr 605 | { $1 } 606 | | logand_expr AND bitor_expr 607 | { ELog (LogAnd, $1, $3) } 608 | 609 | bitor_expr: 610 | | bitxor_expr 611 | { $1 } 612 | | bitor_expr BAR bitxor_expr 613 | { EArith (BitOr, $1, $3) } 614 | 615 | bitxor_expr: 616 | | bitand_expr 617 | { $1 } 618 | | bitxor_expr HAT bitand_expr 619 | { EArith (BitXor, $1, $3) } 620 | 621 | bitand_expr: 622 | | equal_expr 623 | { $1 } 624 | | bitand_expr AMP equal_expr 625 | { EArith (BitAnd, $1, $3) } 626 | 627 | equal_expr: 628 | | rel_expr 629 | { $1 } 630 | | equal_expr EQ rel_expr 631 | { EEq(Eq, $1, $3) } 632 | | equal_expr NEQ rel_expr 633 | { EEq(Ne, $1, $3) } 634 | 635 | rel_expr: 636 | | shift_expr 637 | { $1 } 638 | | rel_expr LT shift_expr 639 | { ERel(Lt, $1, $3)} 640 | | rel_expr GT shift_expr 641 | { ERel(Gt, $1, $3)} 642 | | rel_expr LE shift_expr 643 | { ERel(Le, $1, $3)} 644 | | rel_expr GE shift_expr 645 | { ERel(Ge, $1, $3)} 646 | 647 | shift_expr: 648 | | additive_expr 649 | { $1 } 650 | | shift_expr LSHIFT additive_expr 651 | { EArith(LShift, $1, $3)} 652 | | shift_expr RSHIFT additive_expr 653 | { EArith(RShift, $1, $3)} 654 | 655 | additive_expr: 656 | | multiplicative_expr 657 | { $1 } 658 | | additive_expr PLUS multiplicative_expr 659 | { EArith(Add, $1, $3)} 660 | | additive_expr MINUS multiplicative_expr 661 | { EArith(Sub, $1, $3)} 662 | 663 | multiplicative_expr: 664 | | cast_expr 665 | { $1 } 666 | | multiplicative_expr STAR cast_expr 667 | { EArith(Mul, $1, $3)} 668 | | multiplicative_expr SLASH cast_expr 669 | { EArith(Div, $1, $3)} 670 | | multiplicative_expr MOD cast_expr 671 | { EArith(Mod, $1, $3)} 672 | 673 | cast_expr: 674 | | unary_expr 675 | { $1 } 676 | | LPAREN type_name RPAREN cast_expr 677 | { ECast($2, $4) } 678 | 679 | unary_expr: 680 | | postfix_expr 681 | { $1 } 682 | | INC unary_expr 683 | { EAssign(Some Add, $2, EConst(VInt(1))) } 684 | | DEC unary_expr 685 | { EAssign(Some Sub, $2, EConst(VInt(1))) } 686 | | NOT cast_expr 687 | { EEq (Eq, $2, EConst (VInt 0)) } 688 | | PLUS cast_expr 689 | { EUnary (Plus, $2) } 690 | | MINUS cast_expr 691 | { EUnary (Minus, $2) } 692 | | STAR cast_expr 693 | { EPtr $2 } 694 | | AMP cast_expr 695 | { EAddr $2 } 696 | | TILDE cast_expr 697 | { EUnary (BitNot, $2) } 698 | | SIZEOF LPAREN type_name RPAREN 699 | { ECast (TUInt, EConst (VInt (sizeof $3))) } 700 | | SIZEOF unary_expr 701 | { ESizeof $2 } 702 | 703 | postfix_expr: 704 | | primary_expr 705 | { $1 } 706 | | postfix_expr LBRACKET expr RBRACKET 707 | { EPtr(EArith(Add, $1, $3)) } 708 | | postfix_expr INC 709 | { EUnary (PostInc, $1) } 710 | | postfix_expr DEC 711 | { EUnary (PostDec, $1) } 712 | | postfix_expr LPAREN arg_expr_list RPAREN 713 | { ECall($1, $3) } 714 | | postfix_expr DOT ident 715 | { EDot($1, $3) } 716 | | postfix_expr ARROW ident 717 | { EDot(EPtr $1, $3) } 718 | 719 | primary_expr: 720 | | INT 721 | { EConst (VInt $1) } 722 | | UINT 723 | { ECast (TUInt, EConst (VInt $1)) } 724 | | LINT 725 | { ECast (TLong, EConst (VInt $1)) } 726 | | ULINT 727 | { ECast (TULong, EConst (VInt $1)) } 728 | | FLOAT 729 | { EConst (VFloat $1) } 730 | | DOUBLE 731 | { ECast (TDouble, EConst (VFloat $1)) } 732 | | string_literal 733 | { EConst (VStr $1) } 734 | | ID 735 | { EVar $1 } 736 | | LPAREN expr RPAREN 737 | { $2 } 738 | | ENUM_ID 739 | { EConst (VInt (get_enum $1)) } 740 | 741 | string_literal: 742 | | STR 743 | { $1 } 744 | | STR string_literal 745 | { $1 @ $2 } 746 | 747 | arg_expr_list: 748 | | 749 | { [] } 750 | | assign_expr 751 | { [$1] } 752 | | assign_expr COMMA arg_expr_list 753 | { $1 :: $3 } 754 | 755 | ident: 756 | | ID 757 | { $1 } 758 | | TYPEDEF_NAME 759 | { $1 } 760 | | ENUM_ID 761 | { $1 } 762 | -------------------------------------------------------------------------------- /src/typing.ml: -------------------------------------------------------------------------------- 1 | open Ctype 2 | open Printf 3 | open Util 4 | open Typed_syntax 5 | 6 | let venv_ref : (string * ctype) list ref = ref [] 7 | let ret_ty_ref : ctype ref = ref TInt 8 | let fun_name_ref : string ref = ref "global" 9 | 10 | let raise_error fmt = 11 | ksprintf (fun s -> 12 | fprintf stderr "TypingError: %s (%s)\n" s !fun_name_ref; 13 | exit 1 14 | ) fmt 15 | 16 | let get_ret_ty = function 17 | | Decl (_, TFun (ty, _), _, _) -> ty 18 | | _ -> raise_error "get return type" 19 | 20 | let resolve_var_type name = 21 | let rec go name = function 22 | | [] -> raise_error "variable not found: %s" name 23 | | (s, ty)::_ when s=name -> ty 24 | | _ :: xs -> go name xs in 25 | go name !venv_ref 26 | 27 | let resolve_member_type ty mem_name = 28 | match ty with 29 | | TStruct s_id -> 30 | let dvs = List.nth !struct_env s_id in 31 | List.assoc mem_name dvs 32 | | TUnion u_id -> 33 | let dvs = List.nth !union_env u_id in 34 | List.assoc mem_name dvs 35 | | _ -> failwith "resolve_member_type" 36 | 37 | let is_null = function 38 | | EConst (_, VInt 0) -> true 39 | | _ -> false 40 | 41 | let arith_conv = function 42 | | t1, t2 when not (is_arith t1 && is_arith t2) -> None 43 | | TDouble, _ | _, TDouble -> Some TDouble 44 | | TFloat, _ | _, TFloat -> Some TFloat 45 | | TULong, _ | _, TULong -> Some TULong 46 | | TLong, TUInt | TUInt, TLong -> Some TULong 47 | | TLong, _ | _, TLong -> Some TLong 48 | | TUInt, _ | _, TUInt -> Some TUInt 49 | | _ -> Some TInt 50 | 51 | let initialize ty init = 52 | let pad pos ty = 53 | let a = align ty in 54 | let x = if pos mod a = 0 then 0 else a - pos mod a in 55 | (rep (TChar, Syntax.EConst (Syntax.VInt 0)) x, pos + x) in 56 | let scalar ty = function 57 | | Syntax.IVect ((Syntax.IVect _)::_) -> 58 | raise_error "too many braces around scalar initializer" 59 | | Syntax.IVect [Syntax.IScal e] -> [(ty, e)] 60 | | Syntax.IVect _ -> 61 | raise_error "invalid scalar initializer" 62 | | Syntax.IScal e -> [(ty, e)] in 63 | let rec compound ty init idx pos = 64 | match ty, init with 65 | | TStruct s_id, Syntax.IVect ilist -> 66 | let s = List.nth !struct_env s_id in 67 | if List.length s = idx then ([], init, pos) 68 | else 69 | let pad_ty = 70 | if List.length s = idx + 1 then ty else 71 | snd (List.nth s (idx + 1)) in 72 | let l, rem, pos = inner (snd (List.nth s idx)) ilist pos in 73 | let padding, pos = pad pos pad_ty in 74 | let r, tail, pos = compound ty rem (idx + 1) pos in 75 | (l @ padding @ r, tail, pos) 76 | | TUnion u_id, Syntax.IVect ilist -> 77 | let u = List.nth !union_env u_id in 78 | let res, tail, pos = inner (snd (List.hd u)) ilist pos in 79 | let padding, pos = pad pos ty in 80 | (res @ padding, tail, pos) 81 | | TArray (inner_ty, sz), Syntax.IVect ilist -> 82 | if sz > 0 && sz = idx then ([], init, pos) 83 | else 84 | let l, rem, pos = inner inner_ty ilist pos in 85 | if sz = 0 && rem = Syntax.IVect [] then (l, rem, pos) 86 | else 87 | let r, tail, pos = compound ty rem (idx + 1) pos in 88 | (l @ r, tail, pos) 89 | | TArray (TChar, sz), Syntax.IScal (Syntax.EConst (Syntax.VStr str)) -> 90 | let str = if sz = 0 then str @ [0] else str in 91 | let f i = Syntax.IScal (Syntax.EConst (Syntax.VInt i)) in 92 | let ilist = Syntax.IVect (List.map f str) in 93 | compound ty ilist 0 pos 94 | | _ -> raise_error "requied initializer list" 95 | and inner inner_ty ilist pos = 96 | let i, is = 97 | if ilist = [] then 98 | Syntax.IScal (Syntax.EConst (Syntax.VInt 0)), [] 99 | else 100 | List.hd ilist, List.tl ilist in 101 | match inner_ty, i with 102 | | TStruct _, Syntax.IVect _ | TArray _, Syntax.IVect _ -> 103 | let res, tail, pos = compound inner_ty i 0 pos in 104 | if tail <> Syntax.IVect [] then 105 | raise_error "initializer eccess elements"; 106 | (res, Syntax.IVect is, pos) 107 | | TArray (TChar, sz), Syntax.IScal (Syntax.EConst (Syntax.VStr str)) -> 108 | let str = if sz = 0 then str @ [0] else str in 109 | let f i = Syntax.IScal (Syntax.EConst (Syntax.VInt i)) in 110 | inner inner_ty (Syntax.IVect (List.map f str) :: is) pos 111 | | TStruct _, _ | TArray _, _ -> 112 | compound inner_ty (Syntax.IVect ilist) 0 pos 113 | | _, _ -> (scalar inner_ty i, Syntax.IVect is, pos + sizeof inner_ty) in 114 | match init with 115 | | None -> ([], 0) 116 | | Some init -> 117 | match ty, init with 118 | | TStruct _, Syntax.IVect _ 119 | | TUnion _, Syntax.IVect _ -> 120 | let res, tail, pos = compound ty init 0 0 in 121 | if tail <> Syntax.IVect [] then 122 | raise_error "initializer eccess elements"; 123 | (res, 1) 124 | | TArray (t, _), _ -> 125 | let res, tail, pos = compound ty init 0 0 in 126 | if tail <> Syntax.IVect [] then 127 | raise_error "initializer eccess elements"; 128 | (res, pos / sizeof t) 129 | | _ -> (scalar ty init, 1) 130 | 131 | let rec deref_cast = function 132 | | ECast (t1, t2, e) when t1 = t2 -> e 133 | | ECast (ty, _, e) as expr -> 134 | begin match deref_cast e with 135 | | EConst (_, VInt i) when is_real ty -> 136 | EConst (ty, VFloat (float i)) 137 | | EConst (_, VFloat f) when is_integral ty -> 138 | EConst (ty, VInt (truncate f)) 139 | | EConst (_, v) -> 140 | EConst (ty, v) 141 | | _ -> 142 | expr 143 | end 144 | | e -> e 145 | 146 | let fold_int_expr f ty e1 e2 expr = 147 | match deref_cast e1, deref_cast e2 with 148 | | EConst (_, VInt i1), EConst (_, VInt i2) -> 149 | EConst (ty, VInt (f i1 i2)) 150 | | _ -> expr 151 | 152 | let fold_float_expr f ty e1 e2 expr = 153 | match deref_cast e1, deref_cast e2 with 154 | | EConst (_, VFloat f1), EConst (_, VFloat f2) -> 155 | EConst (ty, VFloat (f f1 f2)) 156 | | _ -> expr 157 | 158 | let fold_ftoi_expr f e1 e2 expr = 159 | match deref_cast e1, deref_cast e2 with 160 | | EConst (_, VFloat f1), EConst (_, VFloat f2) -> 161 | EConst (TInt, VInt (f f1 f2)) 162 | | _ -> expr 163 | 164 | let fold_expr = function 165 | | EConst _ as e -> e 166 | | EArith (ty, op, e1, e2) as expr -> 167 | fold_int_expr (arith2fun ty op) ty e1 e2 expr 168 | | EFArith (ty, op, e1, e2) as expr -> 169 | fold_float_expr (farith2fun op) ty e1 e2 expr 170 | | EPAdd (ty, e1, e2) as expr -> 171 | let sz = sizeof (deref_pointer ty) in 172 | fold_int_expr (fun x y -> x + sz * y) ty e1 e2 expr 173 | | EPDiff (_, e1, e2) as expr -> 174 | let sz = sizeof (deref_pointer (typeof e1)) in 175 | fold_int_expr (fun x y -> (x - y) / sz) TInt e1 e2 expr 176 | | ERel (_, op, e1, e2) as expr -> 177 | fold_int_expr (rel2fun op) TInt e1 e2 expr 178 | | EURel (_, op, e1, e2) as expr -> 179 | fold_int_expr (urel2fun op) TInt e1 e2 expr 180 | | EFRel (_, op, e1, e2) as expr -> 181 | fold_ftoi_expr (rel2fun op) e1 e2 expr 182 | | EEq (_, op, e1, e2) as expr -> 183 | fold_int_expr (eq2fun op) TInt e1 e2 expr 184 | | EFEq (_, op, e1, e2) as expr -> 185 | fold_ftoi_expr (eq2fun op) e1 e2 expr 186 | | ELog (_, LogAnd, e1, e2) as expr -> 187 | begin match deref_cast e1, deref_cast e2 with 188 | | EConst (_, VInt 0), _ 189 | | EConst (_, VInt _), EConst (_, VInt 0) -> 190 | EConst (TInt, VInt 0) 191 | | EConst (_, VInt _), EConst (_, VInt _) -> 192 | EConst (TInt, VInt 1) 193 | | _ -> expr 194 | end 195 | | ELog (_, LogOr, e1, e2) as expr -> 196 | begin match deref_cast e1, deref_cast e2 with 197 | | EConst (_, VInt x), _ when x <> 0 -> 198 | EConst (TInt, VInt 1) 199 | | EConst (_, VInt 0), EConst (_, VInt x) when x <> 0 -> 200 | EConst (TInt, VInt 1) 201 | | EConst (_, VInt 0), EConst (_, VInt 0) -> 202 | EConst (TInt, VInt 0) 203 | | _ -> expr 204 | end 205 | | EUnary (ty, op, e) as expr -> 206 | if op = PostInc || op = PostDec then expr else 207 | begin match deref_cast e with 208 | | EConst (_, VInt i) -> 209 | EConst (ty, VInt ((unary2fun op) i)) 210 | | _ -> expr 211 | end 212 | | EFUnary (ty, op, e) as expr -> 213 | assert (op = Plus || op = Minus); 214 | begin match deref_cast e with 215 | | EConst (ty, VFloat f) -> 216 | EConst (ty, VFloat (if op = Plus then f else -.f)) 217 | | _ -> expr 218 | end 219 | | ECond (ty, e1, e2, e3) as expr -> 220 | begin match deref_cast e1 with 221 | | EConst (_, VInt 0) -> deref_cast e3 222 | | EConst (_, VInt _) -> deref_cast e2 223 | | _ -> expr 224 | end 225 | | expr -> deref_cast expr 226 | 227 | let rec ex e = 228 | let e = ex' e in 229 | match typeof e with 230 | | TArray (ty, _) -> 231 | EAddr (TPtr ty, e) 232 | | TFun _ as ty -> 233 | EAddr (TPtr ty, e) 234 | | _ -> 235 | fold_expr e 236 | 237 | and ex' = function 238 | | Syntax.EConst v -> 239 | let (ty, v) = match v with 240 | | Syntax.VInt i -> TInt, VInt i 241 | | Syntax.VFloat f -> TFloat, VFloat f 242 | | Syntax.VStr s -> TArray (TChar, List.length s + 1), VStr s in 243 | EConst (ty, v) 244 | | Syntax.EVar name -> 245 | if name = "__asm" then 246 | EVar (TFun (TVoid, [TPtr TChar]), name) 247 | else 248 | EVar (resolve_var_type name, name) 249 | | Syntax.EComma (e1, e2) -> 250 | let e = ex e2 in 251 | EComma(typeof e, ex e1, e) 252 | | Syntax.EArith (op, e1, e2) -> 253 | let ex1 = ex e1 in 254 | let ex2 = ex e2 in 255 | let ty1 = typeof ex1 in 256 | let ty2 = typeof ex2 in 257 | begin match op with 258 | | Add -> 259 | begin match (ty1, ty2) with 260 | | (TPtr ty, i) when is_integral i -> 261 | EPAdd (TPtr ty, ex1, ex2) 262 | | (i, TPtr ty) when is_integral i -> 263 | EPAdd (TPtr ty, ex2, ex1) 264 | | _ -> 265 | begin match arith_conv (ty1, ty2) with 266 | | Some ty when is_real ty -> 267 | EFArith (ty, Add, 268 | ECast(ty, ty1, ex1), 269 | ECast(ty, ty2, ex2)) 270 | | Some ty -> 271 | EArith (ty, Add, ex1, ex2) 272 | | None -> 273 | raise_error "EArith: add" 274 | end 275 | end 276 | | Sub -> 277 | begin match (ty1, ty2) with 278 | | (TPtr ty1, TPtr ty2) when ty1 = ty2 -> 279 | EPDiff(TInt, ex1, ex2) 280 | | (TPtr ty1, i) when is_integral i -> 281 | let m_ex2 = ex (Syntax.EUnary(Minus, e2)) in 282 | assert (is_integral (typeof m_ex2)); 283 | EPAdd (TPtr ty1, ex1, m_ex2) 284 | | _ -> 285 | begin match arith_conv (ty1, ty2) with 286 | | Some ty when is_real ty -> 287 | EFArith (ty, Sub, 288 | ECast(ty, ty1, ex1), 289 | ECast(ty, ty2, ex2)) 290 | | Some ty -> 291 | EArith (ty, Sub, ex1, ex2) 292 | | None -> 293 | raise_error "EArith: sub" 294 | end 295 | end 296 | | LShift | RShift -> 297 | begin match arith_conv (ty1, TInt) with 298 | | Some ty when is_integral ty2 -> 299 | EArith (ty, op, ex1, ex2) 300 | | _ -> 301 | raise_error "EArith: shl/shr" 302 | end 303 | | _ -> 304 | begin match arith_conv (ty1, ty2) with 305 | | Some ty when is_real ty -> 306 | begin match op with 307 | | Mul | Div -> 308 | EFArith (ty, op, 309 | ECast(ty, ty1, ex1), 310 | ECast(ty, ty2, ex2)) 311 | | _ -> 312 | raise_error "EFArith; float" 313 | end 314 | | Some ty -> 315 | EArith (ty, op, ex1, ex2) 316 | | None -> raise_error "EArith" 317 | end 318 | end 319 | | Syntax.ERel (op, e1, e2) -> 320 | let ex1 = ex e1 in 321 | let ex2 = ex e2 in 322 | begin match (typeof ex1, typeof ex2) with 323 | | (TPtr _, TPtr _) -> 324 | EURel (TInt, op, ex1, ex2) 325 | | (ty1, ty2) -> 326 | begin match arith_conv (ty1, ty2) with 327 | | Some ty when is_real ty -> 328 | EFRel (TInt, op, 329 | ECast(ty, ty1, ex1), 330 | ECast(ty, ty2, ex2)) 331 | | Some TUInt 332 | | Some TULong -> 333 | EURel (TInt, op, ex1, ex2) 334 | | Some _ -> 335 | ERel (TInt, op, ex1, ex2) 336 | | None -> 337 | raise_error "relation" 338 | end 339 | end 340 | | Syntax.EEq (op, e1, e2) -> 341 | let ex1 = ex e1 in 342 | let ex2 = ex e2 in 343 | begin match (typeof ex1, typeof ex2) with 344 | | (TPtr _, TPtr _) -> 345 | EEq (TInt, op, ex1, ex2) 346 | | (_, TPtr _) when is_null ex1 -> 347 | EEq (TInt, op, ex1, ex2) 348 | | (TPtr _, _) when is_null ex2 -> 349 | EEq (TInt, op, ex2, ex1) 350 | | (t1, t2) -> 351 | begin match arith_conv (t1, t2) with 352 | | Some ty when is_real ty -> 353 | EFEq (TInt, op, 354 | ECast(ty, t1, ex1), 355 | ECast(ty, t2, ex2)) 356 | | Some _ -> 357 | EEq (TInt, op, ex1, ex2) 358 | | _ -> 359 | raise_error "eq" 360 | end 361 | end 362 | | Syntax.ELog (op, e1, e2) -> 363 | let ex1 = ex e1 in 364 | let ex2 = ex e2 in 365 | let t1 = typeof ex1 in 366 | let t2 = typeof ex2 in 367 | if is_scalar t1 || is_scalar t2 then 368 | ELog (TInt, op, ex1, ex2) 369 | else 370 | raise_error "logical" 371 | | Syntax.EUnary (op, e1) -> 372 | let ex1 = ex e1 in 373 | begin match op, typeof ex1 with 374 | | (Plus, ty) | (Minus, ty) when is_integral ty -> 375 | EUnary (from_some (arith_conv (ty, TInt)), op, ex1) 376 | | (Plus, ty) | (Minus, ty) when is_real ty -> 377 | EFUnary (ty, op, ex1) 378 | | (BitNot, ty) when is_integral ty -> 379 | EUnary (from_some (arith_conv (ty, TInt)), op, ex1) 380 | | (PostInc, TPtr t) -> 381 | EPPost (TPtr t, Inc, ex1) 382 | | (PostDec, TPtr t) -> 383 | EPPost (TPtr t, Dec, ex1) 384 | | (PostInc, t) | (PostDec, t) when is_integral t -> 385 | EUnary(t, op, ex1) 386 | | _ -> 387 | raise_error "unary" 388 | end 389 | | Syntax.EAssign (op, e1, e2) -> 390 | let ex1 = ex e1 in 391 | let ex2 = ex e2 in 392 | begin match (typeof ex1, typeof ex2) with 393 | | (ty1, ty2) when is_integral ty1 && ty1 = ty2 -> 394 | EAssign (ty1, op, ex1, ex2) 395 | | (ty1, ty2) when is_integral ty1 && is_arith ty2 -> 396 | EAssign (ty1, op, ex1, ECast(ty1, ty2, ex2)) 397 | | (ty1, ty2) when is_real ty1 && is_arith ty2 -> 398 | EFAssign (ty1, op, ex1, ECast(ty1, ty2, ex2)) 399 | | (TPtr ty, i) when is_integral i -> 400 | begin match op with 401 | | None -> 402 | EAssign (TPtr ty, op, ex1, ex2) 403 | | Some Add -> 404 | EAssign (TPtr ty, op, ex1, ex2) 405 | | Some Sub -> 406 | let m_ex2 = ex (Syntax.EUnary(Minus, e2)) in 407 | EAssign (TPtr ty, Some Add, ex1, m_ex2) 408 | | _ -> 409 | raise_error "EAssign: TPtr" 410 | end 411 | | (ty1, ty2) -> 412 | if op = None then 413 | if ty1 = ty2 then 414 | EAssign (ty1, op, ex1, ex2) 415 | else 416 | EAssign (ty1, op, ex1, ECast(ty1, ty2, ex2)) 417 | else 418 | raise_error "EAssign" 419 | end 420 | | Syntax.ECall (Syntax.EVar ("__asm"), 421 | [Syntax.EConst(Syntax.VStr asm)]) -> 422 | EAsm (TVoid, asm) 423 | | Syntax.ECall (e1, elist) -> 424 | let ex1 = ex e1 in 425 | begin match typeof ex1 with 426 | | TPtr (TFun (retty, argtys)) -> 427 | let go a t = 428 | let arg = ex a in 429 | let ty = typeof arg in 430 | if t = TVoid && is_arith ty then 431 | ECast(promote ty, ty, arg) 432 | else if t = TVoid || typeof arg = t then 433 | arg 434 | else 435 | ECast(t, typeof arg, arg) in 436 | let exlen = List.length elist in 437 | let tylen = List.length argtys in 438 | let args = 439 | if exlen = tylen then 440 | List.map2 go elist argtys 441 | else if exlen > tylen then (* for variadic function *) 442 | let argtys = argtys @ (rep TVoid (exlen - tylen)) in 443 | List.map2 go elist argtys 444 | else 445 | List.map ex elist in 446 | if retty = TVoid || sizeof retty <= 4 then 447 | ECall (retty, ex1, args) 448 | else 449 | raise_error "ECall : function that returns struct is not supported" 450 | | _ -> 451 | raise_error "ECall: not a function given" 452 | end 453 | | Syntax.EAddr e -> 454 | let ex1 = ex' e in 455 | EAddr (TPtr (typeof ex1), ex1) 456 | | Syntax.EPtr e -> 457 | let ex1 = ex e in 458 | begin match typeof ex1 with 459 | | TPtr ty -> EPtr (ty, ex1) 460 | | _ -> raise_error "ptr" 461 | end 462 | | Syntax.ECond (e1, e2, e3) -> 463 | let ex1 = ex e1 in 464 | let ex2 = ex e2 in 465 | let ex3 = ex e3 in 466 | let ty1 = typeof ex1 in 467 | let ty2 = typeof ex2 in 468 | let ty3 = typeof ex3 in 469 | let ex1 = 470 | if is_real ty1 then 471 | fold_expr (EFEq (TInt, Ne, ex1, EConst (ty1, VFloat 0.0))) 472 | else ex1 in 473 | if ty2 = ty3 then 474 | ECond (ty2, ex1, ex2, ex3) 475 | else if is_pointer ty2 && (ty3 = TPtr TVoid || is_null ex3) then 476 | ECond (ty2, ex1, ex2, ECast (ty2, ty3, ex3)) 477 | else if is_pointer ty3 && (ty2 = TPtr TVoid || is_null ex2) then 478 | ECond (ty3, ex1, ECast (ty3, ty2, ex2), ex3) 479 | else 480 | begin match arith_conv (ty2, ty3) with 481 | | Some ty -> 482 | ECond (ty, ex1, 483 | ECast (ty, ty2, ex2), 484 | ECast (ty, ty3, ex3)) 485 | | None -> 486 | raise_error "cond" 487 | end 488 | | Syntax.EDot (e1, name) -> 489 | let ex1 = ex e1 in 490 | let ty = resolve_member_type (typeof ex1) name in 491 | EDot(ty, ex1, name) 492 | | Syntax.ECast (ty, e) -> 493 | let e = ex e in 494 | let ty2 = typeof e in 495 | ECast (ty, ty2, e) 496 | | Syntax.ESizeof e -> 497 | let i = sizeof (typeof (ex' e)) in 498 | EConst (TUInt, VInt i) 499 | 500 | let ex_opt = function 501 | | Some e -> 502 | Some (ex e) 503 | | None -> 504 | None 505 | 506 | let dv = function 507 | | Syntax.Decl(ln, ty, name, x) -> 508 | let init, len = initialize ty x in 509 | let ty = 510 | match ty with 511 | | TArray (t, 0) -> 512 | TArray (t, len) 513 | | _ -> ty in 514 | push venv_ref (name, ty); 515 | let f (ty, e) = 516 | let e = ex e in 517 | deref_cast (ECast(ty, typeof e, e)) in 518 | Decl(ln, ty, name, List.map f init) 519 | 520 | let rec st = function 521 | | Syntax.SNil -> SNil 522 | | Syntax.SBlock(x, y) -> 523 | let x1 = List.map dv x in 524 | let y1 = List.map st y in 525 | SBlock(x1, y1) 526 | | Syntax.SWhile (e, stmt) -> 527 | let e1 = ex e in 528 | let s1 = st stmt in 529 | SWhile (e1, s1) 530 | | Syntax.SDoWhile (stmt, e) -> 531 | let s1 = st stmt in 532 | let e1 = ex e in 533 | SDoWhile (s1, e1) 534 | | Syntax.SFor (e1, e2, e3, stmt) -> 535 | let oe1 = ex_opt e1 in 536 | let oe2 = ex_opt e2 in 537 | let oe3 = ex_opt e3 in 538 | let s1 = st stmt in 539 | SFor (oe1, oe2, oe3, s1) 540 | | Syntax.SIfElse (e, s1, s2) -> 541 | let ex1 = ex e in 542 | let ty1 = typeof ex1 in 543 | let ex1 = 544 | if is_real ty1 then 545 | fold_expr (EFEq (TInt, Ne, ex1, EConst (ty1, VFloat 0.0))) 546 | else ex1 in 547 | let st1 = st s1 in 548 | let st2 = st s2 in 549 | SIfElse (ex1, st1, st2) 550 | | Syntax.SReturn e -> 551 | begin match ex_opt e with 552 | | None -> 553 | SReturn (None) 554 | | Some ex1 -> 555 | let ty = typeof ex1 in 556 | if ty = !ret_ty_ref then 557 | SReturn (Some ex1) 558 | else 559 | SReturn (Some (ECast(!ret_ty_ref, ty, ex1))) 560 | end 561 | | Syntax.SContinue -> 562 | SContinue 563 | | Syntax.SBreak -> 564 | SBreak 565 | | Syntax.SLabel (str, stmt) -> 566 | let st1 = st stmt in 567 | SLabel (str, st1) 568 | | Syntax.SGoto str -> 569 | SGoto str 570 | | Syntax.SSwitch (e, stmt) -> 571 | let ex1 = ex e in 572 | let st1 = st stmt in 573 | SSwitch (ex1, st1) 574 | | Syntax.SCase e -> 575 | begin match ex e with 576 | | EConst (_, VInt i) -> SCase i 577 | | _ -> raise_error "case: required constant expression" 578 | end 579 | | Syntax.SDefault -> 580 | SDefault 581 | | Syntax.SExpr e -> 582 | let ex1 = ex e in 583 | SExpr ex1 584 | 585 | let def = function 586 | | Syntax.DefFun (d, dlist, b) -> 587 | let Syntax.Decl( _, _, fname, _) = d in 588 | fun_name_ref := fname; 589 | let d1 = dv d in 590 | ret_ty_ref := get_ret_ty d1; 591 | if !ret_ty_ref != TVoid && sizeof !ret_ty_ref > 4 then 592 | raise_error "def : function that returns struct is not supported"; 593 | let old_venv = !venv_ref in 594 | let a1 = List.map dv dlist in 595 | let b1 = st b in 596 | let ret = DefFun (d1, a1, b1) in 597 | venv_ref := old_venv; 598 | fun_name_ref := ""; 599 | ret 600 | | Syntax.DefVar decl -> 601 | DefVar (dv decl) 602 | 603 | let main defs = 604 | List.map def defs 605 | -------------------------------------------------------------------------------- /lib/libc.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define max(m, n) ((m) > (n) ? (m) : (n)) 14 | #define min(m, n) ((m) < (n) ? (m) : (n)) 15 | 16 | 17 | 18 | /* assert.h */ 19 | 20 | void __assert_fail(const char *expr, const char *file, int line) 21 | { 22 | printf("%s:%d: Assertion `%s' failed.\n", file, line, expr); 23 | abort(); 24 | } 25 | 26 | 27 | 28 | /* ctype.h */ 29 | 30 | int isalnum(int c) { return isalpha(c) || isdigit(c); } 31 | int isalpha(int c) { return islower(c) || isupper(c); } 32 | int isdigit(int c) { return '0' <= c && c <= '9'; } 33 | int islower(int c) { return 'a' <= c && c <= 'z'; } 34 | int isspace(int c) { return c == ' ' || ('\t' <= c && c <= '\r'); } 35 | int isupper(int c) { return 'A' <= c && c <= 'Z'; } 36 | int tolower(int c) { return isupper(c) ? c - 'A' + 'a' : c; } 37 | int toupper(int c) { return islower(c) ? c - 'a' + 'A' : c; } 38 | 39 | 40 | 41 | /* setjmp.h */ 42 | 43 | int setjmp(jmp_buf buf) 44 | { 45 | __asm("\ 46 | mov r1, [rbp + 4] # r1 <- buf \n\ 47 | mov r2, [rbp] # r2 <- caller rbp \n\ 48 | mov [r1], r2 # save caller rbp \n\ 49 | mov [r1 + 4], r28 # save r28 (return address) \n\ 50 | mov [r1 + 8], rbp # save current rbp \n\ 51 | jl r2, 0 # get PC \n\ 52 | add r2, r2, 12 # r2 <- address of 'ret' \n\ 53 | mov [r1 + 12], r2 # save r2 \n\ 54 | mov r1, 0 # return 0 \n\ 55 | ret \n\ 56 | "); 57 | } 58 | 59 | void longjmp(jmp_buf buf, int val) 60 | { 61 | __asm("\ 62 | mov r1, [rbp + 8] # r1 <- val \n\ 63 | cmpeq r2, r1, 0 # if (val == 0) \n\ 64 | add r1, r1, r2 # r1 <- 1 \n\ 65 | mov r2, [rbp + 4] # r2 <- buf \n\ 66 | mov r3, [r2] # r3 <- caller rbp \n\ 67 | mov r28, [r2 + 4] # restore r28 \n\ 68 | mov rbp, [r2 + 8] # restore setjmp rbp \n\ 69 | mov [rbp], r3 # restore setjmp's caller rbp \n\ 70 | mov r2, [r2 + 12] # r2 <- address of 'ret' \n\ 71 | jr r2 # jump \n\ 72 | "); 73 | } 74 | 75 | 76 | 77 | /* stdio.h */ 78 | 79 | static FILE stdin_entity = { getchar, NULL }; 80 | static FILE stdout_entity = { NULL, putchar }; 81 | 82 | FILE *stdin = &stdin_entity; 83 | FILE *stdout = &stdout_entity; 84 | FILE *stderr = &stdout_entity; 85 | 86 | int putchar(int c) 87 | { 88 | __asm("\ 89 | mov r1, [rbp + 4] \n\ 90 | write r1 \n\ 91 | ret \n\ 92 | "); 93 | } 94 | 95 | int getchar(void) 96 | { 97 | __asm("\ 98 | read r1 \n\ 99 | ret \n\ 100 | "); 101 | } 102 | 103 | int putc(int c, FILE *stream) 104 | { 105 | return fputc(c, stream); 106 | } 107 | 108 | int fputc(int c, FILE *stream) 109 | { 110 | if (! stream->write) 111 | return EOF; 112 | return stream->write(c); 113 | } 114 | 115 | int getc(FILE *stream) 116 | { 117 | return fgetc(stream); 118 | } 119 | 120 | int fgetc(FILE *stream) 121 | { 122 | if (! stream->read) 123 | return EOF; 124 | return stream->read(); 125 | } 126 | 127 | int fputs(char *s, FILE *stream) 128 | { 129 | 130 | while(*s != '\0') { 131 | 132 | if (fputc(*s, stream) == EOF) 133 | return EOF; 134 | 135 | ++s; 136 | 137 | } 138 | 139 | return 1; 140 | 141 | } 142 | 143 | 144 | int puts(char *s) 145 | { 146 | int i = 0; 147 | 148 | while(*s != '\0') { 149 | 150 | if (putchar(*s) == EOF) 151 | return EOF; 152 | 153 | ++i; ++s; 154 | 155 | } 156 | 157 | putchar('\n'); 158 | 159 | return i + 1; 160 | } 161 | 162 | 163 | 164 | char *fgets(char *s, int size, FILE *stream) 165 | { 166 | int c; 167 | char *buf; 168 | buf = s; 169 | 170 | if (size == 0) 171 | return NULL; 172 | 173 | while (--size > 0 && (c = fgetc(stream)) != EOF) { 174 | 175 | if ((*buf++ = c) == '\n') 176 | break; 177 | 178 | } 179 | 180 | *buf = '\0'; 181 | 182 | return (c == EOF && buf == s) ? NULL : s; 183 | 184 | } 185 | 186 | char *gets(char *s) 187 | { 188 | int c; 189 | char *buf; 190 | buf = s; 191 | 192 | while ((c = getc(stdin)) != EOF && c != '\n') { 193 | 194 | *buf++ = c; 195 | 196 | } 197 | 198 | *buf = '\0'; 199 | 200 | return (c == EOF && buf == s) ? NULL : s; 201 | 202 | } 203 | 204 | #define LEFT (1 << 0) 205 | #define ZEROPAD (1 << 1) 206 | #define SIGN (1 << 2) 207 | #define PLUS (1 << 3) 208 | #define SPACE (1 << 4) 209 | #define OCTPRE (1 << 5) 210 | #define HEXPRE (1 << 6) 211 | #define CAP (1 << 7) 212 | #define DOT (1 << 8) 213 | #define TRUNC (1 << 9) 214 | 215 | static int prints(FILE *fp, const char *str, int w, int prec, int flag) 216 | { 217 | int i, len; 218 | 219 | if (! str) 220 | str = "(null)"; 221 | 222 | len = strlen(str);; 223 | if (prec >= 0 && len > prec) 224 | len = prec; 225 | 226 | if (! (flag & LEFT)) 227 | for (i = 0; i < w - len; ++i) 228 | fp->write(' '); 229 | 230 | for (i = 0; i < len; ++i) 231 | fp->write(str[i]); 232 | 233 | if (flag & LEFT) 234 | for (i = 0; i < w - len; ++i) 235 | fp->write(' '); 236 | 237 | return max(len, w); 238 | } 239 | 240 | static int printi(FILE *fp, int x, int base, int w, int prec, int flag) 241 | { 242 | char buf[12], pbuf[2]; 243 | int i, n, len = 0, plen = 0; 244 | unsigned u = x; 245 | 246 | if (prec >= 0) 247 | flag &= ~ZEROPAD; 248 | 249 | if (flag & SIGN) { 250 | if (x < 0) { 251 | u = -x; 252 | pbuf[plen++] = '-'; 253 | } else if (flag & (PLUS | SPACE)) { 254 | pbuf[plen++] = flag & PLUS ? '+' : ' '; 255 | } 256 | } 257 | if (x && flag & HEXPRE) { 258 | pbuf[plen++] = '0'; 259 | pbuf[plen++] = flag & CAP ? 'X' : 'x'; 260 | } 261 | 262 | while (u > 0) { 263 | int t = u % base; 264 | buf[len++] = (t < 10) ? (t + '0') : (t - 10 + (flag & CAP ? 'A' : 'a')); 265 | u /= base; 266 | } 267 | if (x == 0 || flag & OCTPRE) 268 | buf[len++] = '0'; 269 | 270 | n = max(len, prec) + plen; 271 | 272 | if (! (flag & (LEFT | ZEROPAD))) 273 | for (i = 0; i < w - n; ++i) 274 | fp->write(' '); 275 | 276 | for (i = 0; i < plen; ++i) 277 | fp->write(pbuf[i]); 278 | 279 | if (flag & ZEROPAD) 280 | for (i = 0; i < w - n; ++i) 281 | fp->write('0'); 282 | 283 | for (i = 0; i < prec - len; ++i) 284 | fp->write('0'); 285 | 286 | for (i = len - 1; i >= 0; --i) 287 | fp->write(buf[i]); 288 | 289 | if (flag & LEFT) 290 | for (i = 0; i < w - n; ++i) 291 | fp->write(' '); 292 | 293 | return max(w, n); 294 | } 295 | 296 | static float normalize(float f, int *e) 297 | { 298 | static float table_p[] = { 1e1, 1e2, 1e4, 1e8, 1e16, 1e32 }; 299 | static float table_m[] = { 1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32 }; 300 | static float table_m1[] = { 1e0, 1e-1, 1e-3, 1e-7, 1e-15, 1e-31 }; 301 | 302 | int i; 303 | 304 | *e = 0; 305 | for (i = 5; i >= 0; --i) { 306 | if (f >= table_p[i]) { 307 | *e += 1 << i; 308 | f *= table_m[i]; 309 | } 310 | if (f < table_m1[i]) { 311 | *e -= 1 << i; 312 | f *= table_p[i]; 313 | } 314 | } 315 | 316 | return f; 317 | } 318 | 319 | static int printef(FILE *fp, float f, int w, int prec, int flag) 320 | { 321 | char buf[10], pbuf[1]; 322 | int i, n, expo = 0, len = 0, plen = 0, sp = 0; 323 | union { float f; unsigned i; } u; 324 | 325 | u.f = f; 326 | 327 | if (prec < 0) 328 | prec = 6; 329 | 330 | if (u.i >> 31) { 331 | f = -f; 332 | pbuf[plen++] = '-'; 333 | } else if (flag & (PLUS | SPACE)) { 334 | pbuf[plen++] = flag & PLUS ? '+' : ' '; 335 | } 336 | 337 | if ((u.i >> 23 & 255) == 255) { 338 | int ofs = flag & CAP ? 'A' - 'a' : 0; 339 | sp = 1; 340 | flag &= ~ZEROPAD; 341 | if ((u.i & 0x7fffff) == 0) { 342 | buf[len++] = 'i' + ofs; 343 | buf[len++] = 'n' + ofs; 344 | buf[len++] = 'f' + ofs; 345 | } else { 346 | buf[len++] = 'n' + ofs; 347 | buf[len++] = 'a' + ofs; 348 | buf[len++] = 'n' + ofs; 349 | } 350 | } else if (f == 0.0) { 351 | buf[len++] = '0'; 352 | buf[len++] = '.'; 353 | /* prec >= 9 is treated as prec = 8 */ 354 | for (i = 0; i < min(prec, 8); ++i) 355 | buf[len++] = '0'; 356 | } else { 357 | int x = 0; 358 | f = normalize(f, &expo); 359 | 360 | len = min(prec, 8) + 2; 361 | for (i = 0; i < len - 1; ++i) { 362 | int d = f; 363 | x = x * 10 + d; 364 | f = (f - d) * 10.0; 365 | } 366 | if (f >= 5.0) ++x; 367 | 368 | buf[1] = '.'; 369 | for (i = len - 1; i >= 2; --i) { 370 | buf[i] = x % 10 + '0'; 371 | x /= 10; 372 | } 373 | if (x == 10) { 374 | ++expo; 375 | buf[0] = '1'; 376 | } else { 377 | buf[0] = x + '0'; 378 | } 379 | } 380 | 381 | if (flag & TRUNC) 382 | while (buf[len - 1] == '0') 383 | --len; 384 | if (buf[len - 1] == '.' && ~flag & DOT) 385 | --len; 386 | 387 | n = len + plen + (sp || flag & TRUNC ? 0 : max(prec - 8, 0)) + (sp ? 0 : 4); 388 | 389 | if (! (flag & (LEFT | ZEROPAD))) 390 | for (i = 0; i < w - n; ++i) 391 | fp->write(' '); 392 | 393 | for (i = 0; i < plen; ++i) 394 | fp->write(pbuf[i]); 395 | 396 | if (flag & ZEROPAD) 397 | for (i = 0; i < w - n; ++i) 398 | fp->write('0'); 399 | 400 | for (i = 0; i < len; ++i) 401 | fp->write(buf[i]); 402 | 403 | if (! (sp || flag & TRUNC)) 404 | for (i = 0; i < prec - 8; ++i) 405 | fp->write('0'); 406 | 407 | if (! sp) { 408 | fp->write(flag & CAP ? 'E' : 'e'); 409 | fp->write(expo < 0 ? '-' : '+'); 410 | if (expo < 0) expo = -expo; 411 | fp->write(expo / 10 + '0'); 412 | fp->write(expo % 10 + '0'); 413 | } 414 | 415 | if (flag & LEFT) 416 | for (i = 0; i < w - n; ++i) 417 | fp->write(' '); 418 | 419 | return max(w, n); 420 | } 421 | 422 | static int printff(FILE *fp, float f, int w, int prec, int flag) 423 | { 424 | static float round_table[] = { 425 | 5e-1, 5e-2, 5e-3, 5e-4, 5e-5, 5e-6, 5e-7, 5e-8, 5e-9, 5e-10 426 | }; 427 | 428 | char buf[49], pbuf[1]; 429 | int i, n, len = 0, plen = 0, sp = 0; 430 | union { float f; unsigned i; } u; 431 | 432 | u.f = f; 433 | 434 | if (prec < 0) 435 | prec = 6; 436 | 437 | if (u.i >> 31) { 438 | f = -f; 439 | pbuf[plen++] = '-'; 440 | } else if (flag & (PLUS | SPACE)) { 441 | pbuf[plen++] = flag & PLUS ? '+' : ' '; 442 | } 443 | 444 | if ((u.i >> 23 & 255) == 255) { 445 | int ofs = flag & CAP ? 'A' - 'a' : 0; 446 | sp = 1; 447 | flag &= ~ZEROPAD; 448 | if ((u.i & 0x7fffff) == 0) { 449 | buf[len++] = 'i' + ofs; 450 | buf[len++] = 'n' + ofs; 451 | buf[len++] = 'f' + ofs; 452 | } else { 453 | buf[len++] = 'n' + ofs; 454 | buf[len++] = 'a' + ofs; 455 | buf[len++] = 'n' + ofs; 456 | } 457 | } else { 458 | int expo; 459 | float g; 460 | 461 | /* prec >= 10 is treated as prec = 9 */ 462 | f += round_table[min(prec, 9)]; 463 | 464 | g = normalize(f, &expo); 465 | if (expo < 0) 466 | expo = 0; 467 | else 468 | f = g; 469 | 470 | for (; expo >= 0; --expo) { 471 | int d = f; 472 | buf[len++] = d + '0'; 473 | f = (f - d) * 10.0; 474 | } 475 | 476 | buf[len++] = '.'; 477 | for (i = 0; i < min(prec, 9); ++i) { 478 | int d = f; 479 | buf[len++] = d + '0'; 480 | f = (f - d) * 10.0; 481 | } 482 | } 483 | 484 | if (flag & TRUNC) 485 | while (buf[len - 1] == '0') 486 | --len; 487 | if (buf[len - 1] == '.' && ~flag & DOT) 488 | --len; 489 | 490 | n = len + plen + (sp || flag & TRUNC ? 0 : max(prec - 9, 0)); 491 | 492 | if (! (flag & (LEFT | ZEROPAD))) 493 | for (i = 0; i < w - n; ++i) 494 | fp->write(' '); 495 | 496 | for (i = 0; i < plen; ++i) 497 | fp->write(pbuf[i]); 498 | 499 | if (flag & ZEROPAD) 500 | for (i = 0; i < w - n; ++i) 501 | fp->write('0'); 502 | 503 | for (i = 0; i < len; ++i) 504 | fp->write(buf[i]); 505 | 506 | if (! (sp || flag & TRUNC)) 507 | for (i = 0; i < prec - 9; ++i) 508 | fp->write('0'); 509 | 510 | if (flag & LEFT) 511 | for (i = 0; i < w - n; ++i) 512 | fp->write(' '); 513 | 514 | return max(w, n); 515 | } 516 | 517 | static int printgf(FILE *fp, float f, int w, int prec, int flag) 518 | { 519 | int expo; 520 | 521 | if (prec < 0) 522 | prec = 6; 523 | if (prec == 0) 524 | prec = 1; 525 | 526 | normalize(f, &expo); 527 | 528 | if (-4 <= expo && expo < prec) { 529 | return printff(fp, f, w, prec - expo - 1, flag); 530 | } else { 531 | return printef(fp, f, w, prec - 1, flag); 532 | } 533 | } 534 | 535 | static char *write_string_dst; 536 | static int write_string(int c) 537 | { 538 | *write_string_dst = c; 539 | ++write_string_dst; 540 | return c; 541 | } 542 | 543 | int printf(const char *fmt, ...) 544 | { 545 | va_list ap; 546 | va_start(ap, fmt); 547 | return vfprintf(stdout, fmt, ap); 548 | } 549 | 550 | int fprintf(FILE *fp, const char *fmt, ...) 551 | { 552 | va_list ap; 553 | va_start(ap, fmt); 554 | return vfprintf(fp, fmt, ap); 555 | } 556 | 557 | int sprintf(char *s, const char *fmt, ...) 558 | { 559 | va_list ap; 560 | va_start(ap, fmt); 561 | return vsprintf(s, fmt, ap); 562 | } 563 | 564 | int vprintf(const char *fmt, va_list ap) 565 | { 566 | return vfprintf(stdout, fmt, ap); 567 | } 568 | 569 | int vfprintf(FILE *fp, const char *fmt, va_list ap) 570 | { 571 | int ret = 0; 572 | 573 | if (! fp->write) 574 | return -1; 575 | 576 | for (; *fmt; ++fmt) { 577 | if (*fmt == '%') { 578 | int flag = 0; 579 | int alt = 0; 580 | int w = 0; 581 | int prec = -1; 582 | const char *bak = fmt++; 583 | if (*fmt == '%') { 584 | ++ret; 585 | fp->write('%'); 586 | continue; 587 | } 588 | while (strchr("-+ #0", *fmt)) { 589 | switch (*(fmt++)) { 590 | case '-': flag |= LEFT; break; 591 | case '+': flag |= PLUS; break; 592 | case ' ': flag |= SPACE; break; 593 | case '#': alt = -1; break; 594 | case '0': flag |= ZEROPAD; break; 595 | } 596 | } 597 | if (flag & LEFT) 598 | flag &= ~ZEROPAD; 599 | if (flag & PLUS) 600 | flag &= ~SPACE; 601 | if (*fmt == '*') { 602 | ++fmt; 603 | w = va_arg(ap, int); 604 | } else while (isdigit(*fmt)) { 605 | w = w * 10 + *(fmt++) - '0'; 606 | } 607 | if (*fmt == '.') { 608 | ++fmt; 609 | prec = 0; 610 | if (*fmt == '*') { 611 | ++fmt; 612 | prec = va_arg(ap, int); 613 | } else while (isdigit(*fmt)) { 614 | prec = prec * 10 + *(fmt++) - '0'; 615 | } 616 | } 617 | while (strchr("hlL", *fmt)) 618 | ++fmt; 619 | switch (*fmt) { 620 | case 'c': 621 | ++ret; 622 | fp->write(va_arg(ap, int)); 623 | break; 624 | case 's': 625 | ret += prints(fp, va_arg(ap, char*), w, prec, flag); 626 | break; 627 | case 'd': 628 | case 'i': 629 | ret += printi(fp, va_arg(ap, int), 10, w, prec, flag | SIGN); 630 | break; 631 | case 'o': 632 | ret += printi(fp, va_arg(ap, int), 8, w, prec, flag | (alt & OCTPRE)); 633 | break; 634 | case 'x': 635 | ret += printi(fp, va_arg(ap, int), 16, w, prec, flag | (alt & HEXPRE)); 636 | break; 637 | case 'X': 638 | ret += printi(fp, va_arg(ap, int), 16, w, prec, flag | (alt & HEXPRE) | CAP); 639 | break; 640 | case 'u': 641 | ret += printi(fp, va_arg(ap, int), 10, w, prec, flag); 642 | break; 643 | case 'p': 644 | ret += printi(fp, va_arg(ap, int), 16, w, prec, flag | HEXPRE); 645 | break; 646 | case 'e': 647 | ret += printef(fp, va_arg(ap, double), w, prec, flag | (alt & DOT)); 648 | break; 649 | case 'E': 650 | ret += printef(fp, va_arg(ap, double), w, prec, flag | (alt & DOT) | CAP); 651 | break; 652 | case 'f': 653 | ret += printff(fp, va_arg(ap, double), w, prec, flag | (alt & DOT)); 654 | break; 655 | case 'F': 656 | ret += printff(fp, va_arg(ap, double), w, prec, flag | (alt & DOT) | CAP); 657 | break; 658 | case 'g': 659 | ret += printgf(fp, va_arg(ap, double), w, prec, flag | (~alt & TRUNC)); 660 | break; 661 | case 'G': 662 | ret += printgf(fp, va_arg(ap, double), w, prec, flag | (~alt & TRUNC) | CAP); 663 | break; 664 | case 'n': 665 | *va_arg(ap, int*) = ret; 666 | break; 667 | default: 668 | ret += fmt - bak; 669 | for (; bak < fmt; ++bak){ 670 | fp->write(*bak); 671 | } 672 | --fmt; 673 | break; 674 | } 675 | } else { 676 | ++ret; 677 | fp->write(*fmt); 678 | } 679 | } 680 | 681 | return ret; 682 | } 683 | 684 | int vsprintf(char *s, const char *fmt, va_list ap) 685 | { 686 | int ret; 687 | FILE stream = { NULL, write_string }; 688 | write_string_dst = s; 689 | ret = vfprintf(&stream, fmt, ap); 690 | *write_string_dst = '\0'; 691 | return ret; 692 | } 693 | 694 | 695 | 696 | /* stdlib.h */ 697 | 698 | void abort(void) 699 | { 700 | printf("abort!\n"); 701 | __asm(" halt\n"); 702 | } 703 | 704 | int abs(int n) 705 | { 706 | __asm("\ 707 | mov r1, [rbp + 4] \n\ 708 | sar r2, r1, 31 \n\ 709 | xor r1, r1, r2 \n\ 710 | sub r1, r1, r2 \n\ 711 | ret \n\ 712 | "); 713 | } 714 | 715 | 716 | long strtol(const char *str, char **end, int base) 717 | { 718 | long l = 0; 719 | 720 | if (base > 36) { 721 | if (end) 722 | *end = (char *)str; 723 | return 0; 724 | } 725 | 726 | if (base == 0) { 727 | if (*str == '0') { 728 | ++str; 729 | if (*str == 'x' || *str == 'X') { 730 | ++str; 731 | base = 16; 732 | } else { 733 | base = 8; 734 | } 735 | } else { 736 | base = 10; 737 | } 738 | } 739 | 740 | while (1) { 741 | char c = *str; 742 | long n = base; 743 | 744 | if (isdigit(c)) n = c - '0'; 745 | if (islower(c)) n = c - 'a' + 10; 746 | if (isupper(c)) n = c - 'A' + 10; 747 | 748 | if (base <= n) 749 | break; 750 | 751 | ++str; 752 | l = l * base + n; 753 | } 754 | 755 | if (end) 756 | *end = (char *)str; 757 | return l; 758 | } 759 | 760 | 761 | static unsigned rbuf[32], ridx = -1; 762 | 763 | int rand(void) 764 | { 765 | if (ridx >= 32) srand(1); 766 | if (ridx == 31) { 767 | ridx = 0; 768 | return (rbuf[31] = rbuf[0] + rbuf[28]) >> 1; 769 | } else { 770 | int tmp = rbuf[ridx + 1] + rbuf[ridx + (ridx < 3 ? 29 : -3)]; 771 | return (rbuf[ridx++] = tmp) >> 1; 772 | } 773 | } 774 | 775 | void srand(unsigned seed) 776 | { 777 | int i; 778 | unsigned tmp, lo, hi; 779 | const unsigned mod = 0x7fffffff; 780 | ridx = 2; 781 | rbuf[0] = seed ? seed : 1; 782 | for (i = 1; i < 31; ++i) { 783 | /* rbuf[i] = (16807ll * (int)rbuf[i - 1] % mod + mod) % mod; */ 784 | tmp = rbuf[i - 1]; 785 | if ((int)tmp < 0) tmp = -tmp; 786 | lo = 16807 * (tmp & 0xffff); 787 | hi = 16807 * (tmp >> 16); 788 | tmp = (lo + ((hi & 0x7fff) << 16) + (hi >> 15)); 789 | if (tmp >= mod) tmp -= mod; 790 | rbuf[i] = (int)rbuf[i - 1] < 0 && tmp ? mod - tmp : tmp; 791 | } 792 | rbuf[31] = rbuf[0]; rbuf[0] = rbuf[1]; rbuf[1] = rbuf[2]; 793 | for (i = 34; i < 344; ++i) rand(); 794 | } 795 | 796 | 797 | #define NALLOC 1024 798 | 799 | struct header { 800 | struct header *next; 801 | size_t size; 802 | }; 803 | 804 | typedef struct header Header; 805 | 806 | static Header base; 807 | static Header *freep; 808 | 809 | static Header *morecore(size_t); 810 | 811 | void *malloc(size_t nbytes) 812 | { 813 | Header *p, *prevp; 814 | size_t nunits; 815 | 816 | nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1; 817 | if (! (prevp = freep)) { /* no free list yet */ 818 | base.next = freep = prevp = &base; 819 | base.size = 0; 820 | } 821 | for (p = prevp->next; ; prevp = p, p = p->next) { 822 | if (p->size >= nunits) { /* big enough */ 823 | if (p->size == nunits) { /* exactly */ 824 | prevp->next = p->next; 825 | } else { /* allocate tail end */ 826 | p->size -= nunits; 827 | p += p->size; 828 | p->size = nunits; 829 | } 830 | freep = prevp; 831 | return (void *)(p + 1); 832 | } 833 | if (p == freep) 834 | if (! (p = morecore(nunits))) 835 | return NULL; 836 | } 837 | } 838 | 839 | void free(void *ap) 840 | { 841 | Header *bp, *p; 842 | 843 | if (! ap) 844 | return; 845 | 846 | bp = (Header *)ap - 1; 847 | for (p = freep; !(p < bp && bp < p->next); p = p->next) 848 | if (p->next <= p && (p < bp || bp < p->next)) 849 | break; 850 | 851 | if (bp + bp->size == p->next) { 852 | bp->size += p->next->size; 853 | bp->next = p->next->next; 854 | } else { 855 | bp->next = p->next; 856 | } 857 | 858 | if (p + p->size == bp) { 859 | p->size += bp->size; 860 | p->next = bp->next; 861 | } else { 862 | p->next = bp; 863 | } 864 | 865 | freep = p; 866 | } 867 | 868 | static size_t malloc_size(void *ap) 869 | { 870 | Header *p; 871 | 872 | p = (Header *)ap - 1; 873 | return (p->size - 1) * sizeof(Header); 874 | } 875 | 876 | void *realloc(void *ptr, size_t size) 877 | { 878 | void *new; 879 | 880 | if (! ptr) 881 | return malloc(size); 882 | 883 | if (size <= malloc_size(ptr)) 884 | return ptr; 885 | 886 | new = malloc(size); 887 | if (! new) 888 | return NULL; 889 | 890 | memcpy(new, ptr, malloc_size(ptr)); 891 | free(ptr); 892 | 893 | return new; 894 | } 895 | 896 | static void *sbrk(size_t s) { 897 | extern char __UCC_HEAP_START; 898 | static char *ptr = NULL; 899 | 900 | if (! ptr) 901 | ptr = &__UCC_HEAP_START; 902 | 903 | if (ptr + s >= (char *)0x400000) 904 | return NULL; 905 | 906 | ptr += s; 907 | return ptr - s; 908 | } 909 | 910 | static Header *morecore(size_t nunits) 911 | { 912 | Header *p; 913 | 914 | nunits = (nunits + NALLOC - 1) / NALLOC * NALLOC; 915 | p = (Header *)sbrk(nunits * sizeof(Header)); 916 | if (! p) 917 | return NULL; 918 | p->size = nunits; 919 | free(p + 1); 920 | return freep; 921 | } 922 | 923 | 924 | void *calloc(size_t n, size_t size) 925 | { 926 | char *ptr = malloc(n * size); 927 | 928 | if (! ptr) 929 | return NULL; 930 | 931 | memset(ptr, 0, n * size); 932 | 933 | return (void *) ptr; 934 | } 935 | 936 | 937 | /* string.h */ 938 | 939 | size_t strlen(const char *str) 940 | { 941 | size_t len = 0; 942 | 943 | while (*str++) { 944 | ++len; 945 | } 946 | return len; 947 | } 948 | 949 | int strcmp(const char *l, const char *r) 950 | { 951 | while (*l) { 952 | if (*l++ != *r++) { 953 | return l[-1] < r[-1] ? -1 : 1; 954 | } 955 | } 956 | return *r ? -1 : 0; 957 | } 958 | 959 | int strncmp(const char *l, const char *r, size_t n) 960 | { 961 | while (*l && 0 < n) { 962 | if (*l++ != *r++) { 963 | return l[-1] < r[-1] ? -1 : 1; 964 | } 965 | --n; 966 | } 967 | return 0; 968 | } 969 | 970 | char *strchr(const char *str, int c) 971 | { 972 | do { 973 | if (*str == c) { 974 | return (char *)str; 975 | } 976 | } while (*str++); 977 | return NULL; 978 | } 979 | 980 | char *strcpy(char *dst, const char *src) 981 | { 982 | char *d = dst; 983 | 984 | while (*d++ = *src++); 985 | return dst; 986 | } 987 | 988 | char *strncpy(char *dst, const char *src, size_t n) 989 | { 990 | char *d = dst; 991 | 992 | while (n-- > 0 && (*d++ = *src++)); 993 | return dst; 994 | } 995 | 996 | 997 | void *memset(void *dst, int c, size_t n) 998 | { 999 | char *d = dst; 1000 | 1001 | while (n-- > 0) { 1002 | *d++ = c; 1003 | } 1004 | return dst; 1005 | } 1006 | 1007 | void *memcpy(void *dst, const void *src, size_t n) 1008 | { 1009 | const char *s = src; 1010 | char *d = dst; 1011 | 1012 | while (n-- > 0) { 1013 | *d++ = *s++; 1014 | } 1015 | return dst; 1016 | } 1017 | --------------------------------------------------------------------------------