start bridge gen tool
authornotaz <notasas@gmail.com>
Sun, 24 Nov 2013 01:15:06 +0000 (03:15 +0200)
committernotaz <notasas@gmail.com>
Sun, 24 Nov 2013 01:29:31 +0000 (03:29 +0200)
but some registers should probably be saved..

run_mkpubinc.sh
tools/Makefile
tools/asmproc.c
tools/mkbridge.c [new file with mode: 0644]
tools/my_str.h [new file with mode: 0644]

index 3cbcac8..889e0db 100755 (executable)
@@ -23,6 +23,7 @@ echo "; funcs called from C" >> $3
 
 cat $2 | \
 while read a; do
-  echo "_$a equ $a" >> $3
-  echo "PUBLIC _$a" >> $3
+#  echo "_$a equ $a" >> $3
+#  echo "PUBLIC _$a" >> $3
+  echo "PUBLIC $a" >> $3
 done
index 7c03266..2f21042 100644 (file)
@@ -1,6 +1,8 @@
 CFLAGS += -Wall -ggdb
 
-all: asmproc cmpmrg_text
+T = asmproc cmpmrg_text mkbridge
+
+all: $(T)
 
 clean:
-       $(RM) asmproc cmpmrg_text
+       $(RM) $(T)
index 4b40090..02d06a3 100644 (file)
@@ -3,38 +3,7 @@
 #include <string.h>
 
 #include "my_assert.h"
-
-static int my_isblank(char c)
-{
-       return c == '\t' || c == ' ' || c == '\r' || c == '\n';
-}
-
-static char *sskip(char *s)
-{
-       while (my_isblank(*s))
-               s++;
-
-       return s;
-}
-
-static char *next_word(char *w, size_t wsize, char *s)
-{
-       size_t i;
-
-       s = sskip(s);
-
-       for (i = 0; i < wsize - 1; i++) {
-               if (*s == 0 || my_isblank(s[i]))
-                       break;
-               w[i] = s[i];
-       }
-       w[i] = 0;
-
-       if (*s != 0 && !my_isblank(s[i]))
-               printf("warning: '%s' truncated\n", w);
-
-       return s + i;
-}
+#include "my_str.h"
 
 struct sl_item {
        char *name;
diff --git a/tools/mkbridge.c b/tools/mkbridge.c
new file mode 100644 (file)
index 0000000..e3b0068
--- /dev/null
@@ -0,0 +1,225 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "my_assert.h"
+#include "my_str.h"
+
+static int find_protostr(char *dst, size_t dlen, FILE *fhdr,
+       const char *sym, int *pline)
+{
+       int line = 0;
+       char *p;
+
+       while (fgets(dst, dlen, fhdr))
+       {
+               line++;
+               if (strstr(dst, sym) != NULL)
+                       break;
+       }
+       *pline = line;
+
+       if (feof(fhdr))
+               return -1;
+
+       p = dst + strlen(dst);
+       for (p--; p > dst && my_isblank(*p); --p)
+               *p = 0;
+
+       return 0;
+}
+
+static int get_regparm(char *dst, size_t dlen, char *p)
+{
+       int i, o;
+
+       if (*p != '<')
+               return 0;
+
+       for (o = 0, i = 1; o < dlen; i++) {
+               if (p[i] == 0)
+                       return 0;
+               if (p[i] == '>')
+                       break;
+               dst[o++] = p[i];
+       }
+       dst[o] = 0;
+       return i + 1;
+}
+
+static const char *known_types[] = {
+       "unsigned int",
+       "signed int",
+       "int",
+       "void",
+       "DWORD",
+       "HMODULE",
+       "HANDLE",
+       "HWND",
+};
+
+static int check_type(const char *name)
+{
+       int i, l;
+
+       for (i = 0; i < sizeof(known_types) / sizeof(known_types[0]); i++) {
+               l = strlen(known_types[i]);
+               if (strncmp(known_types[i], name, l) == 0)
+                       return l;
+       }
+
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       FILE *fout, *fsyms, *fhdr;
+       const char *hdrfn;
+       char protostr[256];
+       char line[256];
+       char sym[256];
+       char buf[256];
+       char regparm[16];
+       char *p;
+       int first_regparm = 0;
+       int have_regparm;
+       int pline = 0;
+       int xarg;
+       int ret;
+
+       if (argc != 4) {
+               // -c - patch callsites
+               printf("usage:\n%s <bridge.s> <symf> <hdrf>\n",
+                       argv[0]);
+               return 1;
+       }
+
+       hdrfn = argv[3];
+       fhdr = fopen(hdrfn, "r");
+       my_assert_not(fhdr, NULL);
+
+       fsyms = fopen(argv[2], "r");
+       my_assert_not(fsyms, NULL);
+
+       fout = fopen(argv[1], "w");
+       my_assert_not(fout, NULL);
+
+       fprintf(fout, ".text\n\n");
+
+       while (fgets(line, sizeof(line), fsyms))
+       {
+               next_word(sym, sizeof(sym), line);
+               if (sym[0] == 0 || sym[0] == ';' || sym[0] == '#')
+                       continue;
+
+               ret = find_protostr(protostr, sizeof(protostr), fhdr,
+                       sym, &pline);
+               if (ret != 0) {
+                       printf("%s: sym '%s' is missing\n",
+                               hdrfn, sym);
+                       return 1;
+               }
+
+               p = protostr;
+               if (p[0] == '/' && p[1] == '/') {
+                       printf("warning: decl for sym '%s' is commented out\n", sym);
+                       p = sskip(p + 2);
+               }
+
+               ret = check_type(p);
+               if (ret <= 0) {
+                       printf("%s:%d:%ld: unhandled return in '%s'\n",
+                               hdrfn, pline, (p - protostr) + 1, protostr);
+                       return 1;
+               }
+               p += ret;
+               p = sskip(p);
+
+               // ignore calling convention specifier, for now
+               p = next_word(buf, sizeof(buf), p);
+               p = sskip(p);
+               if (buf[0] == 0) {
+                       printf("%s:%d:%ld: cconv missing\n",
+                               hdrfn, pline, (p - protostr) + 1);
+                       return 1;
+               }
+
+               p = next_idt(buf, sizeof(buf), p);
+               p = sskip(p);
+               if (buf[0] == 0) {
+                       printf("%s:%d:%ld: func name missing\n",
+                               hdrfn, pline, (p - protostr) + 1);
+                       return 1;
+               }
+
+               ret = get_regparm(regparm, sizeof(regparm), p);
+               if (ret > 0) {
+                       if (strcmp(regparm, "eax") && strcmp(regparm, "ax")) {
+                               printf("%s:%d:%ld: bad regparm: %s\n",
+                                       hdrfn, pline, (p - protostr) + 1, regparm);
+                               return 1;
+                       }
+                       p += ret;
+                       p = sskip(p);
+               }
+
+               if (*p != '(') {
+                       printf("%s:%d:%ld: '(' expected, got '%c'\n",
+                               hdrfn, pline, (p - protostr) + 1, *p);
+                       return 1;
+               }
+               p++;
+
+               fprintf(fout, ".global _asm_%s\n", sym);
+               fprintf(fout, "_asm_%s:\n", sym);
+
+               xarg = 1;
+               while (1) {
+                       p = sskip(p);
+                       if (*p == ')')
+                               break;
+                       if (*p == ',')
+                               p = sskip(p + 1);
+
+                       ret = check_type(p);
+                       if (ret <= 0) {
+                               printf("%s:%d:%ld: unhandled type for arg%d\n",
+                                       hdrfn, pline, (p - protostr) + 1, xarg);
+                               return 1;
+                       }
+                       p += ret;
+                       p = sskip(p);
+
+                       p = next_idt(buf, sizeof(buf), p);
+                       p = sskip(p);
+                       if (buf[0] == 0) {
+                               printf("%s:%d:%ld: idt missing for arg%d\n",
+                                       hdrfn, pline, (p - protostr) + 1, xarg);
+                               return 1;
+                       }
+
+                       have_regparm = 0;
+                       ret = get_regparm(regparm, sizeof(regparm), p);
+                       if (ret > 0) {
+                               p += ret;
+                               p = sskip(p);
+
+                               have_regparm = 1;
+                               fprintf(fout, "\t movl %d(%%esp), %%%s\n",
+                                       xarg * 4, regparm);
+                       }
+                       if (xarg == 1)
+                               first_regparm = have_regparm;
+                       else if (have_regparm != first_regparm) {
+                               printf("%s:%d:%ld: mixed regparm is unhandled\n",
+                                       hdrfn, pline, (p - protostr) + 1);
+                               return 1;
+                       }
+               }
+
+               fprintf(fout, "\t jmp %s\n\n", sym);
+       }
+
+       fclose(fout);
+       return 0;
+}
diff --git a/tools/my_str.h b/tools/my_str.h
new file mode 100644 (file)
index 0000000..44caa7c
--- /dev/null
@@ -0,0 +1,56 @@
+static int my_isblank(char c)
+{
+       return c == '\t' || c == ' ' || c == '\r' || c == '\n';
+}
+
+static int my_issep(char c)
+{
+       return c == '(' || c == ')' || c == '[' || c == ']'
+           || c == '<' || c == '>' || c == ',';
+}
+
+static char *sskip(char *s)
+{
+       while (my_isblank(*s))
+               s++;
+
+       return s;
+}
+
+static char *next_word(char *w, size_t wsize, char *s)
+{
+       size_t i;
+
+       s = sskip(s);
+
+       for (i = 0; i < wsize - 1; i++) {
+               if (*s == 0 || my_isblank(s[i]))
+                       break;
+               w[i] = s[i];
+       }
+       w[i] = 0;
+
+       if (*s != 0 && !my_isblank(s[i]))
+               printf("warning: '%s' truncated\n", w);
+
+       return s + i;
+}
+
+static inline char *next_idt(char *w, size_t wsize, char *s)
+{
+       size_t i;
+
+       s = sskip(s);
+
+       for (i = 0; i < wsize - 1; i++) {
+               if (*s == 0 || my_isblank(s[i]) || my_issep(s[i]))
+                       break;
+               w[i] = s[i];
+       }
+       w[i] = 0;
+
+       if (*s != 0 && !my_isblank(s[i]) && !my_issep(s[i]))
+               printf("warning: '%s' truncated\n", w);
+
+       return s + i;
+}