start bridge gen tool
[ia32rtools.git] / tools / mkbridge.c
CommitLineData
57e4efe9 1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "my_assert.h"
6#include "my_str.h"
7
8static int find_protostr(char *dst, size_t dlen, FILE *fhdr,
9 const char *sym, int *pline)
10{
11 int line = 0;
12 char *p;
13
14 while (fgets(dst, dlen, fhdr))
15 {
16 line++;
17 if (strstr(dst, sym) != NULL)
18 break;
19 }
20 *pline = line;
21
22 if (feof(fhdr))
23 return -1;
24
25 p = dst + strlen(dst);
26 for (p--; p > dst && my_isblank(*p); --p)
27 *p = 0;
28
29 return 0;
30}
31
32static int get_regparm(char *dst, size_t dlen, char *p)
33{
34 int i, o;
35
36 if (*p != '<')
37 return 0;
38
39 for (o = 0, i = 1; o < dlen; i++) {
40 if (p[i] == 0)
41 return 0;
42 if (p[i] == '>')
43 break;
44 dst[o++] = p[i];
45 }
46 dst[o] = 0;
47 return i + 1;
48}
49
50static const char *known_types[] = {
51 "unsigned int",
52 "signed int",
53 "int",
54 "void",
55 "DWORD",
56 "HMODULE",
57 "HANDLE",
58 "HWND",
59};
60
61static int check_type(const char *name)
62{
63 int i, l;
64
65 for (i = 0; i < sizeof(known_types) / sizeof(known_types[0]); i++) {
66 l = strlen(known_types[i]);
67 if (strncmp(known_types[i], name, l) == 0)
68 return l;
69 }
70
71 return 0;
72}
73
74int main(int argc, char *argv[])
75{
76 FILE *fout, *fsyms, *fhdr;
77 const char *hdrfn;
78 char protostr[256];
79 char line[256];
80 char sym[256];
81 char buf[256];
82 char regparm[16];
83 char *p;
84 int first_regparm = 0;
85 int have_regparm;
86 int pline = 0;
87 int xarg;
88 int ret;
89
90 if (argc != 4) {
91 // -c - patch callsites
92 printf("usage:\n%s <bridge.s> <symf> <hdrf>\n",
93 argv[0]);
94 return 1;
95 }
96
97 hdrfn = argv[3];
98 fhdr = fopen(hdrfn, "r");
99 my_assert_not(fhdr, NULL);
100
101 fsyms = fopen(argv[2], "r");
102 my_assert_not(fsyms, NULL);
103
104 fout = fopen(argv[1], "w");
105 my_assert_not(fout, NULL);
106
107 fprintf(fout, ".text\n\n");
108
109 while (fgets(line, sizeof(line), fsyms))
110 {
111 next_word(sym, sizeof(sym), line);
112 if (sym[0] == 0 || sym[0] == ';' || sym[0] == '#')
113 continue;
114
115 ret = find_protostr(protostr, sizeof(protostr), fhdr,
116 sym, &pline);
117 if (ret != 0) {
118 printf("%s: sym '%s' is missing\n",
119 hdrfn, sym);
120 return 1;
121 }
122
123 p = protostr;
124 if (p[0] == '/' && p[1] == '/') {
125 printf("warning: decl for sym '%s' is commented out\n", sym);
126 p = sskip(p + 2);
127 }
128
129 ret = check_type(p);
130 if (ret <= 0) {
131 printf("%s:%d:%ld: unhandled return in '%s'\n",
132 hdrfn, pline, (p - protostr) + 1, protostr);
133 return 1;
134 }
135 p += ret;
136 p = sskip(p);
137
138 // ignore calling convention specifier, for now
139 p = next_word(buf, sizeof(buf), p);
140 p = sskip(p);
141 if (buf[0] == 0) {
142 printf("%s:%d:%ld: cconv missing\n",
143 hdrfn, pline, (p - protostr) + 1);
144 return 1;
145 }
146
147 p = next_idt(buf, sizeof(buf), p);
148 p = sskip(p);
149 if (buf[0] == 0) {
150 printf("%s:%d:%ld: func name missing\n",
151 hdrfn, pline, (p - protostr) + 1);
152 return 1;
153 }
154
155 ret = get_regparm(regparm, sizeof(regparm), p);
156 if (ret > 0) {
157 if (strcmp(regparm, "eax") && strcmp(regparm, "ax")) {
158 printf("%s:%d:%ld: bad regparm: %s\n",
159 hdrfn, pline, (p - protostr) + 1, regparm);
160 return 1;
161 }
162 p += ret;
163 p = sskip(p);
164 }
165
166 if (*p != '(') {
167 printf("%s:%d:%ld: '(' expected, got '%c'\n",
168 hdrfn, pline, (p - protostr) + 1, *p);
169 return 1;
170 }
171 p++;
172
173 fprintf(fout, ".global _asm_%s\n", sym);
174 fprintf(fout, "_asm_%s:\n", sym);
175
176 xarg = 1;
177 while (1) {
178 p = sskip(p);
179 if (*p == ')')
180 break;
181 if (*p == ',')
182 p = sskip(p + 1);
183
184 ret = check_type(p);
185 if (ret <= 0) {
186 printf("%s:%d:%ld: unhandled type for arg%d\n",
187 hdrfn, pline, (p - protostr) + 1, xarg);
188 return 1;
189 }
190 p += ret;
191 p = sskip(p);
192
193 p = next_idt(buf, sizeof(buf), p);
194 p = sskip(p);
195 if (buf[0] == 0) {
196 printf("%s:%d:%ld: idt missing for arg%d\n",
197 hdrfn, pline, (p - protostr) + 1, xarg);
198 return 1;
199 }
200
201 have_regparm = 0;
202 ret = get_regparm(regparm, sizeof(regparm), p);
203 if (ret > 0) {
204 p += ret;
205 p = sskip(p);
206
207 have_regparm = 1;
208 fprintf(fout, "\t movl %d(%%esp), %%%s\n",
209 xarg * 4, regparm);
210 }
211 if (xarg == 1)
212 first_regparm = have_regparm;
213 else if (have_regparm != first_regparm) {
214 printf("%s:%d:%ld: mixed regparm is unhandled\n",
215 hdrfn, pline, (p - protostr) + 1);
216 return 1;
217 }
218 }
219
220 fprintf(fout, "\t jmp %s\n\n", sym);
221 }
222
223 fclose(fout);
224 return 0;
225}