From d30d68d738a68e606533d88c2bf6d14a9f7fb5c1 Mon Sep 17 00:00:00 2001
From: grischka <grischka>
Date: Mon, 16 Dec 2019 22:34:47 +0100
Subject: [PATCH] #pragma comment(option, "file.c")

This allows adding files or libraries from
   #pragma comment(option, ...)

Also, {f}/file.c will be expanded with the directory of
the current source, that is the file that has the #pragma
---
 libtcc.c        | 11 +++++++++++
 tcc.c           | 42 ++++++++++++++++++++++--------------------
 tests/tcctest.c | 12 +++++++++---
 3 files changed, 42 insertions(+), 23 deletions(-)

diff --git a/libtcc.c b/libtcc.c
index 608e515a..da372ace 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -451,6 +451,15 @@ static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *
                 c = p[1], p += 2;
                 if (c == 'B')
                     cstr_cat(&str, s->tcc_lib_path, -1);
+                if (c == 'f' && file) {
+                    /* substitute current file's dir */
+                    const char *f = file->true_filename;
+                    const char *b = tcc_basename(f);
+                    if (b > f)
+                        cstr_cat(&str, f, b - f - 1);
+                    else
+                        cstr_cat(&str, ".", 1);
+                }
             } else {
                 cstr_ccat(&str, c);
             }
@@ -839,6 +848,8 @@ LIBTCCAPI TCCState *tcc_new(void)
 
 #ifdef TCC_TARGET_PE
     tcc_define_symbol(s, "_WIN32", NULL);
+    tcc_define_symbol(s, "__declspec(x)", "__attribute__((x))");
+    tcc_define_symbol(s, "__cdecl", "");
 # ifdef TCC_TARGET_X86_64
     tcc_define_symbol(s, "_WIN64", NULL);
 # endif
diff --git a/tcc.c b/tcc.c
index 63250c69..cbb3581b 100644
--- a/tcc.c
+++ b/tcc.c
@@ -251,7 +251,7 @@ static unsigned getclock_ms(void)
 int main(int argc0, char **argv0)
 {
     TCCState *s, *s1;
-    int ret, opt, n = 0, t = 0;
+    int ret, opt, n = 0, t = 0, done;
     unsigned start_time = 0;
     const char *first_file;
     int argc; char **argv;
@@ -262,11 +262,11 @@ redo:
     s = s1 = tcc_new();
     opt = tcc_parse_args(s, &argc, &argv, 1);
 
-    if ((n | t) == 0) {
+    if (n == 0) {
         if (opt == OPT_HELP)
-            return fputs(help, stdout), 1;
+            return fputs(help, stdout), 0;
         if (opt == OPT_HELP2)
-            return fputs(help2, stdout), 1;
+            return fputs(help2, stdout), 0;
         if (opt == OPT_M32 || opt == OPT_M64)
             tcc_tool_cross(s, argv, opt); /* never returns */
         if (s->verbose)
@@ -287,8 +287,7 @@ redo:
             return 0;
         }
 
-        n = s->nb_files;
-        if (n == 0)
+        if (s->nb_files == 0)
             tcc_error("no input files\n");
 
         if (s->output_type == TCC_OUTPUT_PREPROCESS) {
@@ -300,13 +299,11 @@ redo:
         } else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
             if (s->nb_libraries)
                 tcc_error("cannot specify libraries with -c");
-            if (n > 1 && s->outfile)
+            if (s->nb_files > 1 && s->outfile)
                 tcc_error("cannot specify output file with -c many files");
         } else {
-            if (s->option_pthread) {
+            if (s->option_pthread)
                 tcc_set_options(s, "-lpthread");
-		n = s->nb_files;
-	    }
         }
 
         if (s->do_bench)
@@ -320,12 +317,19 @@ redo:
     s->ppfp = ppfp;
 
     if ((s->output_type == TCC_OUTPUT_MEMORY
-      || s->output_type == TCC_OUTPUT_PREPROCESS) && (s->dflag & 16))
-        s->dflag |= t ? 32 : 0, s->run_test = ++t, n = s->nb_files;
+      || s->output_type == TCC_OUTPUT_PREPROCESS)
+        && (s->dflag & 16)) { /* -dt option */
+        if (t)
+            s->dflag |= 32;
+        s->run_test = ++t;
+        if (n)
+            --n;
+    }
 
     /* compile or add each files or library */
-    for (first_file = NULL, ret = 0;;) {
-        struct filespec *f = s->files[s->nb_files - n];
+    first_file = NULL, ret = 0;
+    do {
+        struct filespec *f = s->files[n];
         s->filetype = f->type;
         if (f->type & AFF_TYPE_LIB) {
             if (tcc_add_library_err(s, f->name) < 0)
@@ -338,10 +342,8 @@ redo:
             if (tcc_add_file(s, f->name) < 0)
                 ret = 1;
         }
-        if (--n == 0 || ret
-            || (s->output_type == TCC_OUTPUT_OBJ && !s->option_r))
-            break;
-    }
+        done = ret || ++n >= s->nb_files;
+    } while (!done && (s->output_type != TCC_OUTPUT_OBJ || s->option_r));
 
     if (s->run_test) {
         t = 0;
@@ -362,10 +364,10 @@ redo:
         }
     }
 
-    if (s->do_bench && (n | t | ret) == 0)
+    if (s->do_bench && done && !(t | ret))
         tcc_print_stats(s, getclock_ms() - start_time);
     tcc_delete(s);
-    if (ret == 0 && n)
+    if (!done)
         goto redo; /* compile more files with -c */
     if (t)
         goto redo; /* run more tests with -dt -run */
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 3333e878..15d849ca 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -1210,7 +1210,13 @@ void struct_test()
 /* simulate char/short return value with undefined upper bits */
 static int __csf(int x) { return x; }
 static void *_csf = __csf;
+#ifdef __TINYC__
 #define csf(t,n) ((t(*)(int))_csf)(n)
+#define csfb csf
+#else /* arm gcc maybe doesn't promote function return values */
+#define csf(t,n) (t) n
+#define csfb(t,n) (t) (n & 255)
+#endif
 
 /* XXX: depend on endianness */
 void char_short_test()
@@ -1252,13 +1258,13 @@ void char_short_test()
     printf("promote char/short assign VA %d %d\n", var3 = var1 + 1, var3 = var4 + 1);
     printf("promote char/short cast VA %d %d\n", (char)(var1 + 1), (char)(var4 + 1));
     var1 = csf(unsigned char,0x89898989);
-    var4 = csf(char,0xabababab);
+    var4 = csf(signed char,0xabababab);
     printf("promote char/short funcret %d "LONG_LONG_FORMAT"\n", var1, var4);
     printf("promote char/short fumcret VA %d %d %d %d\n",
         csf(unsigned short,0xcdcdcdcd),
         csf(short,0xefefefef),
-        csf(_Bool,0x33221100),
-        csf(_Bool,0x33221101));
+        csfb(_Bool,0x33221100),
+        csfb(_Bool,0x33221101));
     var3 = -10;
     var1 = (char)(unsigned char)(var3 + 1);
     var4 = (char)(unsigned char)(var3 + 1);