tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] [PATCH] Add new libtcc C API function tcc_compile_string2


From: Yichun Zhang (agentzh)
Subject: [Tinycc-devel] [PATCH] Add new libtcc C API function tcc_compile_string2().
Date: Thu, 6 Dec 2018 03:27:06 -0800

When using the existing tcc_compile_string() API function, it is
wasteful to always call strlen() on the input C source string when the
length is already known by the caller (which is often the case). Also,
it would be much nicer to have more meaningful chunk name (or pseudo
file name) provided by the caller in the compiler error messages
than the hard-coded "<string>" chunk name.

The existing tcc_compile_string() API function is now implemented atop
tcc_compile_string2() as a special case.

Also added a test program to cover this new feature.
---
 libtcc.c             | 14 +++++---
 libtcc.h             |  5 +++
 tests/Makefile       |  8 +++--
 tests/libtcc_test2.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 120 insertions(+), 6 deletions(-)
 create mode 100644 tests/libtcc_test2.c

diff --git a/libtcc.c b/libtcc.c
index 1e9dd97..0c399cd 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -660,18 +660,24 @@ static int tcc_compile(TCCState *s1)
     return s1->nb_errors != 0 ? -1 : 0;
 }
 
-LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
+LIBTCCAPI int tcc_compile_string2(TCCState *s, const char *str, unsigned len,
+    const char *chunk_name)
 {
-    int len, ret;
+    int ret;
 
-    len = strlen(str);
-    tcc_open_bf(s, "<string>", len);
+    tcc_open_bf(s, chunk_name, len);
     memcpy(file->buffer, str, len);
     ret = tcc_compile(s);
     tcc_close();
     return ret;
 }
 
+
+LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
+{
+    return tcc_compile_string2(s, str, strlen(str), "<string>");
+}
+
 /* define a preprocessor symbol. A value can also be provided with the '=' 
operator */
 LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char 
*value)
 {
diff --git a/libtcc.h b/libtcc.h
index a1b31e3..d7d84fb 100644
--- a/libtcc.h
+++ b/libtcc.h
@@ -53,6 +53,11 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char 
*filename);
 /* compile a string containing a C source. Return -1 if error. */
 LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
 
+/* compile a string containing a C source with pre-calculated length and
+ * a custom chunk name. Return -1 if error. */
+LIBTCCAPI int tcc_compile_string2(TCCState *s, const char *buf, unsigned len,
+    const char *chunk_name);
+
 /*****************************/
 /* linking commands */
 
diff --git a/tests/Makefile b/tests/Makefile
index 5f6777d..0f2d0cc 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -69,13 +69,17 @@ hello-run: ../examples/ex1.c
        @echo ------------ $@ ------------
        $(TCC) -run $< || $(DUMPTCC)
 
-libtest: libtcc_test$(EXESUF)
+libtest: libtcc_test$(EXESUF) libtcc_test2$(EXESUF)
        @echo ------------ $@ ------------
        ./libtcc_test$(EXESUF) $(TCCFLAGS)
+       ./libtcc_test2$(EXESUF) $(TCCFLAGS)
 
 libtcc_test$(EXESUF): libtcc_test.c $(LIBTCC)
        $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
 
+libtcc_test2$(EXESUF): libtcc_test2.c $(LIBTCC)
+       $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+
 %-dir:
        @echo ------------ $@ ------------
        $(MAKE) -k -C $*
@@ -278,7 +282,7 @@ cache: tcc_g
 # clean
 clean:
        rm -f *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.cc *.gcc
-       rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test vla_test tcctest[1234]
+       rm -f *-cc *-gcc *-tcc *.exe hello libtcc_test libtcc_test2 vla_test 
tcctest[1234]
        rm -f asm-c-connect$(EXESUF)
        rm -f ex? tcc_g weaktest.*.txt *.def
        @$(MAKE) -C tests2 $@
diff --git a/tests/libtcc_test2.c b/tests/libtcc_test2.c
new file mode 100644
index 0000000..ad73219
--- /dev/null
+++ b/tests/libtcc_test2.c
@@ -0,0 +1,99 @@
+/*
+ * 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;
+}
+
+/* this strinc is referenced by the generated code */
+const char hello[] = "Hello World!";
+
+char my_program[] =
+"#include <tcclib.h>\n" /* include the "Simple libc header for TCC" */
+"extern int add(int a, int b);\n"
+"#ifdef _WIN32\n" /* dynamically linked data needs 'dllimport' */
+" __attribute__((dllimport))\n"
+"#endif\n"
+"extern const char hello[];\n"
+"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(\"%s\\n\", hello);\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 i;
+    int (*func)(int);
+
+    s = tcc_new();
+    if (!s) {
+        fprintf(stderr, "Could not create tcc state\n");
+        exit(1);
+    }
+
+    tcc_set_options(s, "-g");
+
+    /* if tcclib.h and libtcc1.a are not installed, where can we find them */
+    for (i = 1; i < argc; ++i) {
+        char *a = argv[i];
+        if (a[0] == '-') {
+            if (a[1] == 'B')
+                tcc_set_lib_path(s, a+2);
+            else if (a[1] == 'I')
+                tcc_add_include_path(s, a+2);
+            else if (a[1] == 'L')
+                tcc_add_library_path(s, a+2);
+        }
+    }
+
+    /* MUST BE CALLED before any compilation */
+    tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
+
+    if (tcc_compile_string2(s, my_program, sizeof(my_program) - 1,
+                            "libtcc_test2") == -1)
+        return 1;
+
+    /* as a test, we add symbols 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);
+    tcc_add_symbol(s, "hello", hello);
+
+    /* relocate the code */
+    if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
+        return 1;
+
+    /* get entry symbol */
+    func = tcc_get_symbol(s, "foo");
+    if (!func)
+        return 1;
+
+    /* run the code */
+    func(32);
+
+    /* delete the state */
+    tcc_delete(s);
+
+    return 0;
+}
-- 
2.11.0.295.gd7dffce




reply via email to

[Prev in Thread] Current Thread [Next in Thread]