summary refs log blame commit diff stats
path: root/tinyc/tests/libtcc_test.c
blob: a602fb0f496a59778daa5bab4fd9cc8d9d6b923e (plain) (tree)



















































































                                                                              
/*
 * Simple Test program for libtcc
 *
 * libtcc can be useful to use tcc as a "backend" for a code generator.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "libtcc.h"

/* this function is called by the generated code */
int add(int a, int b)
{
    return a + b;
}

char my_program[] =
"int fib(int n)\n"
"{\n"
"    if (n <= 2)\n"
"        return 1;\n"
"    else\n"
"        return fib(n-1) + fib(n-2);\n"
"}\n"
"\n"
"int foo(int n)\n"
"{\n"
"    printf(\"Hello World!\\n\");\n"
"    printf(\"fib(%d) = %d\\n\", n, fib(n));\n"
"    printf(\"add(%d, %d) = %d\\n\", n, 2 * n, add(n, 2 * n));\n"
"    return 0;\n"
"}\n";

int main(int argc, char **argv)
{
    TCCState *s;
    int (*func)(int);
    void *mem;
    int size;

    s = tcc_new();
    if (!s) {
        fprintf(stderr, "Could not create tcc state\n");
        exit(1);
    }

    /* if tcclib.h and libtcc1.a are not installed, where can we find them */
    if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
        tcc_set_lib_path(s, argv[1]+9);

    /* MUST BE CALLED before any compilation */
    tcc_set_output_type(s, TCC_OUTPUT_MEMORY);

    if (tcc_compile_string(s, my_program) == -1)
        return 1;

    /* as a test, we add a symbol that the compiled program can use.
       You may also open a dll with tcc_add_dll() and use symbols from that */
    tcc_add_symbol(s, "add", add);

    /* get needed size of the code */
    size = tcc_relocate(s, NULL);
    if (size == -1)
        return 1;

    /* allocate memory and copy the code into it */
    mem = malloc(size);
    tcc_relocate(s, mem);

    /* get entry symbol */
    func = tcc_get_symbol(s, "foo");
    if (!func)
        return 1;

    /* delete the state */
    tcc_delete(s);

    /* run the code */
    func(32);

    free(mem);
    return 0;
}
mp;id=4f3510d05a144addc9612a046a1f2fa31a8a8c41'>4f3510d0 ^
502d2ea5 ^
104854ca ^
8fb0e672 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

                                            
              
                          

 
                                                                     
             
                  
                                      

                                         

 
                                                               
             
                  
                                 

 
                                                                                           

                  
                        
                                     
                                               

                                             




                                                




                                   
                                                                  

                  
                                



                                                   




                                                


                         
                                                                                                          
             
                  
                                     
                                                   




                                                 

 
                                                              
             
                  
                                     
                                               
                         
                                     
 
# new type to help incrementally scan arrays
container stream:_elem [
  index:number
  data:address:array:_elem
]

def new-stream s:address:array:_elem -> result:address:stream:_elem [
  local-scope
  load-ingredients
  result <- new {(stream _elem): type}
  *result <- put *result, index:offset, 0
  *result <- put *result, data:offset, s
]

def rewind in:address:stream:_elem -> in:address:stream:_elem [
  local-scope
  load-ingredients
  *in <- put *in, index:offset, 0
]

def read in:address:stream:_elem -> result:_elem, empty?:boolean, in:address:stream:_elem [
  local-scope
  load-ingredients
  empty? <- copy 0/false
  idx:number <- get *in, index:offset
  s:address:array:_elem <- get *in, data:offset
  len:number <- length *s
  at-end?:boolean <- greater-or-equal idx len
  {
    break-unless at-end?
    empty-result:address:_elem <- new _elem:type
    return *empty-result, 1/true
  }
  result <- index *s, idx
  idx <- add idx, 1
  *in <- put *in, index:offset, idx
]

def peek in:address:stream:_elem -> result:_elem, empty?:boolean [
  local-scope
  load-ingredients
  empty?:boolean <- copy 0/false
  idx:number <- get *in, index:offset
  s:address:array:character <- get *in, data:offset
  len:number <- length *s
  at-end?:boolean <- greater-or-equal idx len
  {
    break-unless at-end?
    empty-result:address:_elem <- new _elem:type
    return *empty-result, 1/true
  }
  result <- index *s, idx
]

def read-line in:address:stream:character -> result:address:array:character, in:address:stream:character [
  local-scope
  load-ingredients
  idx:number <- get *in, index:offset
  s:address:array:character <- get *in, data:offset
  next-idx:number <- find-next s, 10/newline, idx
  result <- copy-range s, idx, next-idx
  idx <- add next-idx, 1  # skip newline
  # write back
  *in <- put *in, index:offset, idx
]

def end-of-stream? in:address:stream:_elem -> result:boolean [
  local-scope
  load-ingredients
  idx:number <- get *in, index:offset
  s:address:array:_elem <- get *in, data:offset
  len:number <- length *s
  result <- greater-or-equal idx, len
]