1c2c66affSColin Finck #include <stdio.h>
2c2c66affSColin Finck #include <stdlib.h>
3c2c66affSColin Finck #include <ctype.h>
4c2c66affSColin Finck #include <string.h>
5c95b5e6fSTimo Kreuzer #include <stdarg.h>
6c2c66affSColin Finck
7c2c66affSColin Finck #ifdef _MSC_VER
8d564c7c8SMark Jansen #define strcasecmp(_String1, _String2) _stricmp(_String1, _String2)
9d564c7c8SMark Jansen #define strncasecmp(_String1, _String2, _MaxCount) _strnicmp(_String1, _String2, _MaxCount)
10c2c66affSColin Finck #endif
11c2c66affSColin Finck
12c2c66affSColin Finck #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
13c2c66affSColin Finck
14c2c66affSColin Finck typedef struct _STRING
15c2c66affSColin Finck {
16c2c66affSColin Finck const char *buf;
17c2c66affSColin Finck int len;
18c2c66affSColin Finck } STRING, *PSTRING;
19c2c66affSColin Finck
20c2c66affSColin Finck typedef struct
21c2c66affSColin Finck {
22c2c66affSColin Finck STRING strName;
23c2c66affSColin Finck STRING strTarget;
24c2c66affSColin Finck int nCallingConvention;
25c2c66affSColin Finck int nOrdinal;
26c2c66affSColin Finck int nStackBytes;
27c2c66affSColin Finck int nArgCount;
28c2c66affSColin Finck int anArgs[30];
29c2c66affSColin Finck unsigned int uFlags;
30c2c66affSColin Finck int nNumber;
31e8ab2736STimo Kreuzer unsigned nStartVersion;
32e8ab2736STimo Kreuzer unsigned nEndVersion;
33e8ab2736STimo Kreuzer int bVersionIncluded;
34c2c66affSColin Finck } EXPORT;
35c2c66affSColin Finck
36e8ab2736STimo Kreuzer #if 0 // Debug helper function
37e8ab2736STimo Kreuzer void
38e8ab2736STimo Kreuzer PrintExport(EXPORT *pexp)
39e8ab2736STimo Kreuzer {
40e8ab2736STimo Kreuzer fprintf(stderr, "strName='%.*s'\n", pexp->strName.len, pexp->strName.buf);
41e8ab2736STimo Kreuzer fprintf(stderr, "strName='%.*s'\n", pexp->strTarget.len, pexp->strTarget.buf);
42e8ab2736STimo Kreuzer fprintf(stderr, "nCallingConvention=%u\n", pexp->nCallingConvention);
43e8ab2736STimo Kreuzer fprintf(stderr, "nOrdinal=%u\n", pexp->nOrdinal);
44e8ab2736STimo Kreuzer fprintf(stderr, "nStackBytes=%u\n", pexp->nStackBytes);
45e8ab2736STimo Kreuzer fprintf(stderr, "nArgCount=%u\n", pexp->nArgCount);
46e8ab2736STimo Kreuzer fprintf(stderr, "uFlags=0x%x\n", pexp->uFlags);
47e8ab2736STimo Kreuzer fprintf(stderr, "nNumber=%u\n", pexp->nNumber);
48e8ab2736STimo Kreuzer fprintf(stderr, "nStartVersion=%u\n", pexp->nStartVersion);
49e8ab2736STimo Kreuzer fprintf(stderr, "nEndVersion=%u\n", pexp->nEndVersion);
50e8ab2736STimo Kreuzer fprintf(stderr, "bVersionIncluded=%u\n", pexp->bVersionIncluded);
51e8ab2736STimo Kreuzer }
52e8ab2736STimo Kreuzer #endif
53e8ab2736STimo Kreuzer
54c2c66affSColin Finck enum _ARCH
55c2c66affSColin Finck {
56c2c66affSColin Finck ARCH_X86,
57c2c66affSColin Finck ARCH_AMD64,
58c2c66affSColin Finck ARCH_IA64,
59c2c66affSColin Finck ARCH_ARM,
60be223b9dSJustin Miller ARCH_ARM64,
61c2c66affSColin Finck ARCH_PPC
62c2c66affSColin Finck };
63c2c66affSColin Finck
64c2c66affSColin Finck typedef int (*PFNOUTLINE)(FILE *, EXPORT *);
65c2c66affSColin Finck int gbMSComp = 0;
66c2c66affSColin Finck int gbImportLib = 0;
67c2c66affSColin Finck int gbNotPrivateNoWarn = 0;
68c2c66affSColin Finck int gbTracing = 0;
69c2c66affSColin Finck int giArch = ARCH_X86;
70c2c66affSColin Finck char *pszArchString = "i386";
71c2c66affSColin Finck char *pszArchString2;
72c2c66affSColin Finck char *pszSourceFileName = NULL;
73c2c66affSColin Finck char *pszDllName = NULL;
74c2c66affSColin Finck char *gpszUnderscore = "";
75c2c66affSColin Finck int gbDebug;
7601df9a41STimo Kreuzer unsigned guOsVersion = 0x502;
77c2c66affSColin Finck #define DbgPrint(...) (!gbDebug || fprintf(stderr, __VA_ARGS__))
78c2c66affSColin Finck
79c2c66affSColin Finck enum
80c2c66affSColin Finck {
81c2c66affSColin Finck FL_PRIVATE = 1,
82c2c66affSColin Finck FL_STUB = 2,
83c2c66affSColin Finck FL_NONAME = 4,
84c2c66affSColin Finck FL_ORDINAL = 8,
85c2c66affSColin Finck FL_NORELAY = 16,
86c2c66affSColin Finck FL_RET64 = 32,
87c2c66affSColin Finck FL_REGISTER = 64,
8860f4493aSTimo Kreuzer FL_IMPSYM = 128,
89c2c66affSColin Finck };
90c2c66affSColin Finck
91c2c66affSColin Finck enum
92c2c66affSColin Finck {
93c2c66affSColin Finck CC_STDCALL,
94c2c66affSColin Finck CC_CDECL,
95c2c66affSColin Finck CC_FASTCALL,
96c2c66affSColin Finck CC_THISCALL,
97c2c66affSColin Finck CC_EXTERN,
98c2c66affSColin Finck CC_STUB,
99c2c66affSColin Finck };
100c2c66affSColin Finck
101c2c66affSColin Finck enum
102c2c66affSColin Finck {
103c2c66affSColin Finck ARG_LONG,
104c2c66affSColin Finck ARG_PTR,
105c2c66affSColin Finck ARG_STR,
106c2c66affSColin Finck ARG_WSTR,
107c2c66affSColin Finck ARG_DBL,
108c2c66affSColin Finck ARG_INT64,
109c2c66affSColin Finck ARG_INT128,
110c2c66affSColin Finck ARG_FLOAT
111c2c66affSColin Finck };
112c2c66affSColin Finck
113c2c66affSColin Finck const char* astrCallingConventions[] =
114c2c66affSColin Finck {
115c2c66affSColin Finck "STDCALL",
116c2c66affSColin Finck "CDECL",
117c2c66affSColin Finck "FASTCALL",
118c2c66affSColin Finck "THISCALL",
119c2c66affSColin Finck "EXTERN"
120c2c66affSColin Finck };
121c2c66affSColin Finck
1222becb000SHermès Bélusca-Maïto /*
1232becb000SHermès Bélusca-Maïto * List of OLE exports that should be PRIVATE and not be assigned an ordinal.
1242becb000SHermès Bélusca-Maïto * In case these conditions are not met when linking with MS LINK.EXE, warnings
1252becb000SHermès Bélusca-Maïto * LNK4104 and LNK4222 respectively are emitted.
1262becb000SHermès Bélusca-Maïto */
1272becb000SHermès Bélusca-Maïto static const char* astrOlePrivateExports[] =
128c2c66affSColin Finck {
129c2c66affSColin Finck "DllCanUnloadNow",
130c2c66affSColin Finck "DllGetClassObject",
131c2c66affSColin Finck "DllGetClassFactoryFromClassString",
132c2c66affSColin Finck "DllGetDocumentation",
133c2c66affSColin Finck "DllInitialize",
134c2c66affSColin Finck "DllInstall",
135c2c66affSColin Finck "DllRegisterServer",
136c2c66affSColin Finck "DllRegisterServerEx",
137c2c66affSColin Finck "DllRegisterServerExW",
138c2c66affSColin Finck "DllUnload",
139c2c66affSColin Finck "DllUnregisterServer",
140c2c66affSColin Finck "RasCustomDeleteEntryNotify",
141c2c66affSColin Finck "RasCustomDial",
142c2c66affSColin Finck "RasCustomDialDlg",
143c2c66affSColin Finck "RasCustomEntryDlg",
144c2c66affSColin Finck };
145c2c66affSColin Finck
146c2c66affSColin Finck static
147c2c66affSColin Finck int
IsSeparator(char chr)148c2c66affSColin Finck IsSeparator(char chr)
149c2c66affSColin Finck {
150c2c66affSColin Finck return ((chr <= ',' && chr != '$' && chr != '#') ||
151c2c66affSColin Finck (chr >= ':' && chr < '?') );
152c2c66affSColin Finck }
153c2c66affSColin Finck
154c2c66affSColin Finck int
CompareToken(const char * token,const char * comparand)155c2c66affSColin Finck CompareToken(const char *token, const char *comparand)
156c2c66affSColin Finck {
157c2c66affSColin Finck while (*comparand)
158c2c66affSColin Finck {
159c2c66affSColin Finck if (*token != *comparand) return 0;
160c2c66affSColin Finck token++;
161c2c66affSColin Finck comparand++;
162c2c66affSColin Finck }
16301df9a41STimo Kreuzer if (IsSeparator(comparand[-1])) return 1;
164c2c66affSColin Finck if (!IsSeparator(*token)) return 0;
165c2c66affSColin Finck return 1;
166c2c66affSColin Finck }
167c2c66affSColin Finck
168c2c66affSColin Finck const char *
ScanToken(const char * token,char chr)169c2c66affSColin Finck ScanToken(const char *token, char chr)
170c2c66affSColin Finck {
171c2c66affSColin Finck while (!IsSeparator(*token))
172c2c66affSColin Finck {
173c2c66affSColin Finck if (*token == chr) return token;
174c2c66affSColin Finck token++;
175c2c66affSColin Finck }
176c2c66affSColin Finck return 0;
177c2c66affSColin Finck }
178c2c66affSColin Finck
17980c0b083STimo Kreuzer const char *
NextLine(const char * pc)18080c0b083STimo Kreuzer NextLine(const char *pc)
181c2c66affSColin Finck {
182c2c66affSColin Finck while (*pc != 0)
183c2c66affSColin Finck {
184c2c66affSColin Finck if (pc[0] == '\n' && pc[1] == '\r') return pc + 2;
185c2c66affSColin Finck else if (pc[0] == '\n') return pc + 1;
186c2c66affSColin Finck pc++;
187c2c66affSColin Finck }
188c2c66affSColin Finck return pc;
189c2c66affSColin Finck }
190c2c66affSColin Finck
191c2c66affSColin Finck int
TokenLength(const char * pc)19280c0b083STimo Kreuzer TokenLength(const char *pc)
193c2c66affSColin Finck {
194c2c66affSColin Finck int length = 0;
195c2c66affSColin Finck
196c2c66affSColin Finck while (!IsSeparator(*pc++)) length++;
197c2c66affSColin Finck
198c2c66affSColin Finck return length;
199c2c66affSColin Finck }
200c2c66affSColin Finck
20180c0b083STimo Kreuzer const char *
NextToken(const char * pc)20280c0b083STimo Kreuzer NextToken(const char *pc)
203c2c66affSColin Finck {
204c2c66affSColin Finck /* Skip token */
205c2c66affSColin Finck while (!IsSeparator(*pc)) pc++;
206c2c66affSColin Finck
207c2c66affSColin Finck /* Skip white spaces */
208c2c66affSColin Finck while (*pc == ' ' || *pc == '\t') pc++;
209c2c66affSColin Finck
210c2c66affSColin Finck /* Check for end of line */
211c2c66affSColin Finck if (*pc == '\n' || *pc == '\r' || *pc == 0) return 0;
212c2c66affSColin Finck
213c2c66affSColin Finck /* Check for comment */
214c2c66affSColin Finck if (*pc == '#' || *pc == ';') return 0;
215c2c66affSColin Finck
216c2c66affSColin Finck return pc;
217c2c66affSColin Finck }
218c2c66affSColin Finck
219c2c66affSColin Finck void
OutputHeader_stub(FILE * file)220c2c66affSColin Finck OutputHeader_stub(FILE *file)
221c2c66affSColin Finck {
222c2c66affSColin Finck fprintf(file, "/* This file is autogenerated, do not edit. */\n\n"
223c2c66affSColin Finck "#include <stubs.h>\n");
224c2c66affSColin Finck
225c2c66affSColin Finck if (gbTracing)
226c2c66affSColin Finck {
227c2c66affSColin Finck fprintf(file, "#include <wine/debug.h>\n");
228c2c66affSColin Finck fprintf(file, "#include <inttypes.h>\n");
229c2c66affSColin Finck fprintf(file, "WINE_DECLARE_DEBUG_CHANNEL(relay);\n");
230c2c66affSColin Finck }
231c2c66affSColin Finck
232c2c66affSColin Finck fprintf(file, "\n");
233c2c66affSColin Finck }
234c2c66affSColin Finck
235c2c66affSColin Finck int
OutputLine_stub(FILE * file,EXPORT * pexp)236c2c66affSColin Finck OutputLine_stub(FILE *file, EXPORT *pexp)
237c2c66affSColin Finck {
238c2c66affSColin Finck int i;
239c2c66affSColin Finck int bRelay = 0;
240c2c66affSColin Finck int bInPrototype = 0;
241c2c66affSColin Finck
2425387a7ccSJérôme Gardou /* Workaround for forwarded externs. See here for an explanation:
2435387a7ccSJérôme Gardou * https://stackoverflow.com/questions/4060143/forwarding-data-in-a-dll */
2445387a7ccSJérôme Gardou if (gbMSComp &&
2455387a7ccSJérôme Gardou (pexp->nCallingConvention == CC_EXTERN) &&
2465387a7ccSJérôme Gardou (pexp->strTarget.buf != NULL) &&
2475387a7ccSJérôme Gardou (!!ScanToken(pexp->strTarget.buf, '.')))
2485387a7ccSJérôme Gardou {
2495387a7ccSJérôme Gardou fprintf(file, "#pragma comment(linker,\"/export:%s%.*s=%.*s,DATA\")\n\n",
2505387a7ccSJérôme Gardou gpszUnderscore, pexp->strName.len, pexp->strName.buf, pexp->strTarget.len, pexp->strTarget.buf);
2515387a7ccSJérôme Gardou return 0;
2525387a7ccSJérôme Gardou }
2535387a7ccSJérôme Gardou
254c2c66affSColin Finck if (pexp->nCallingConvention != CC_STUB &&
255c2c66affSColin Finck (pexp->uFlags & FL_STUB) == 0)
256c2c66affSColin Finck {
257c2c66affSColin Finck /* Only relay trace stdcall C functions */
258c2c66affSColin Finck if (!gbTracing || (pexp->nCallingConvention != CC_STDCALL)
259c2c66affSColin Finck || (pexp->uFlags & FL_NORELAY)
260c2c66affSColin Finck || (pexp->strName.buf[0] == '?'))
261c2c66affSColin Finck {
262c2c66affSColin Finck return 0;
263c2c66affSColin Finck }
264c2c66affSColin Finck bRelay = 1;
265c2c66affSColin Finck }
266c2c66affSColin Finck
267c2c66affSColin Finck /* Declare the "real" function */
268c2c66affSColin Finck if (bRelay)
269c2c66affSColin Finck {
270c2c66affSColin Finck fprintf(file, "extern ");
271c2c66affSColin Finck bInPrototype = 1;
272c2c66affSColin Finck }
273c2c66affSColin Finck
274c2c66affSColin Finck do
275c2c66affSColin Finck {
276c2c66affSColin Finck if (pexp->uFlags & FL_REGISTER)
277c2c66affSColin Finck {
278c2c66affSColin Finck /* FIXME: Not sure this is right */
279c2c66affSColin Finck fprintf(file, "void ");
280c2c66affSColin Finck }
281c2c66affSColin Finck else if (pexp->uFlags & FL_RET64)
282c2c66affSColin Finck {
283c2c66affSColin Finck fprintf(file, "__int64 ");
284c2c66affSColin Finck }
285c2c66affSColin Finck else
286c2c66affSColin Finck {
287c2c66affSColin Finck fprintf(file, "int ");
288c2c66affSColin Finck }
289c2c66affSColin Finck
290c2c66affSColin Finck if ((giArch == ARCH_X86) &&
291c2c66affSColin Finck pexp->nCallingConvention == CC_STDCALL)
292c2c66affSColin Finck {
293c2c66affSColin Finck fprintf(file, "__stdcall ");
294c2c66affSColin Finck }
295c2c66affSColin Finck
296c2c66affSColin Finck /* Check for C++ */
297c2c66affSColin Finck if (pexp->strName.buf[0] == '?')
298c2c66affSColin Finck {
299c2c66affSColin Finck fprintf(file, "stub_function%d(", pexp->nNumber);
300c2c66affSColin Finck }
301c2c66affSColin Finck else
302c2c66affSColin Finck {
303c2c66affSColin Finck if (!bRelay || bInPrototype)
304c2c66affSColin Finck fprintf(file, "%.*s(", pexp->strName.len, pexp->strName.buf);
305c2c66affSColin Finck else
306c2c66affSColin Finck fprintf(file, "$relaytrace$%.*s(", pexp->strName.len, pexp->strName.buf);
307c2c66affSColin Finck }
308c2c66affSColin Finck
309c2c66affSColin Finck for (i = 0; i < pexp->nArgCount; i++)
310c2c66affSColin Finck {
311c2c66affSColin Finck if (i != 0) fprintf(file, ", ");
312c2c66affSColin Finck switch (pexp->anArgs[i])
313c2c66affSColin Finck {
314c2c66affSColin Finck case ARG_LONG: fprintf(file, "long"); break;
315c2c66affSColin Finck case ARG_PTR: fprintf(file, "void*"); break;
316c2c66affSColin Finck case ARG_STR: fprintf(file, "char*"); break;
317c2c66affSColin Finck case ARG_WSTR: fprintf(file, "wchar_t*"); break;
318c2c66affSColin Finck case ARG_DBL: fprintf(file, "double"); break;
319c2c66affSColin Finck case ARG_INT64: fprintf(file, "__int64"); break;
320bd27b050SHermès Bélusca-Maïto /* __int128 is not supported on x86, so use a custom type */
321bd27b050SHermès Bélusca-Maïto case ARG_INT128: fprintf(file, "MyInt128"); break;
322c2c66affSColin Finck case ARG_FLOAT: fprintf(file, "float"); break;
323c2c66affSColin Finck }
324c2c66affSColin Finck fprintf(file, " a%d", i);
325c2c66affSColin Finck }
326c2c66affSColin Finck
327c2c66affSColin Finck if (bInPrototype)
328c2c66affSColin Finck {
329c2c66affSColin Finck fprintf(file, ");\n\n");
330c2c66affSColin Finck }
331c2c66affSColin Finck } while (bInPrototype--);
332c2c66affSColin Finck
333c2c66affSColin Finck if (!bRelay)
334c2c66affSColin Finck {
335c2c66affSColin Finck fprintf(file, ")\n{\n\tDbgPrint(\"WARNING: calling stub %.*s(",
336c2c66affSColin Finck pexp->strName.len, pexp->strName.buf);
337c2c66affSColin Finck }
338c2c66affSColin Finck else
339c2c66affSColin Finck {
340c2c66affSColin Finck fprintf(file, ")\n{\n");
341c2c66affSColin Finck if (pexp->uFlags & FL_REGISTER)
342c2c66affSColin Finck {
343c2c66affSColin Finck /* No return value */
344c2c66affSColin Finck }
345c2c66affSColin Finck else if (pexp->uFlags & FL_RET64)
346c2c66affSColin Finck {
347c2c66affSColin Finck fprintf(file, "\t__int64 retval;\n");
348c2c66affSColin Finck }
349c2c66affSColin Finck else
350c2c66affSColin Finck {
351c2c66affSColin Finck fprintf(file, "\tint retval;\n");
352c2c66affSColin Finck }
353c2c66affSColin Finck fprintf(file, "\tif (TRACE_ON(relay))\n\t\tDPRINTF(\"%s: %.*s(",
354c2c66affSColin Finck pszDllName, pexp->strName.len, pexp->strName.buf);
355c2c66affSColin Finck }
356c2c66affSColin Finck
357c2c66affSColin Finck for (i = 0; i < pexp->nArgCount; i++)
358c2c66affSColin Finck {
359c2c66affSColin Finck if (i != 0) fprintf(file, ",");
360c2c66affSColin Finck switch (pexp->anArgs[i])
361c2c66affSColin Finck {
362c2c66affSColin Finck case ARG_LONG: fprintf(file, "0x%%lx"); break;
363c2c66affSColin Finck case ARG_PTR: fprintf(file, "0x%%p"); break;
364c2c66affSColin Finck case ARG_STR: fprintf(file, "'%%s'"); break;
365c2c66affSColin Finck case ARG_WSTR: fprintf(file, "'%%ws'"); break;
366c2c66affSColin Finck case ARG_DBL: fprintf(file, "%%f"); break;
367bd27b050SHermès Bélusca-Maïto case ARG_INT64: fprintf(file, "0x%%\"PRIx64\""); break;
368bd27b050SHermès Bélusca-Maïto case ARG_INT128: fprintf(file, "0x%%\"PRIx64\"-0x%%\"PRIx64\""); break;
369c2c66affSColin Finck case ARG_FLOAT: fprintf(file, "%%f"); break;
370c2c66affSColin Finck }
371c2c66affSColin Finck }
372c2c66affSColin Finck fprintf(file, ")\\n\"");
373c2c66affSColin Finck
374c2c66affSColin Finck for (i = 0; i < pexp->nArgCount; i++)
375c2c66affSColin Finck {
376c2c66affSColin Finck fprintf(file, ", ");
377c2c66affSColin Finck switch (pexp->anArgs[i])
378c2c66affSColin Finck {
379bd27b050SHermès Bélusca-Maïto case ARG_LONG: case ARG_PTR: case ARG_STR:
380bd27b050SHermès Bélusca-Maïto case ARG_WSTR: case ARG_DBL: case ARG_INT64:
381bd27b050SHermès Bélusca-Maïto fprintf(file, "a%d", i); break;
382bd27b050SHermès Bélusca-Maïto case ARG_INT128:
383bd27b050SHermès Bélusca-Maïto fprintf(file, "a%d.lower, a%d.upper", i, i); break;
384bd27b050SHermès Bélusca-Maïto case ARG_FLOAT:
385bd27b050SHermès Bélusca-Maïto fprintf(file, "a%d", i); break;
386c2c66affSColin Finck }
387c2c66affSColin Finck }
388c2c66affSColin Finck fprintf(file, ");\n");
389c2c66affSColin Finck
390c2c66affSColin Finck if (pexp->nCallingConvention == CC_STUB)
391c2c66affSColin Finck {
392c2c66affSColin Finck fprintf(file, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName);
393c2c66affSColin Finck }
394c2c66affSColin Finck else if (bRelay)
395c2c66affSColin Finck {
396c2c66affSColin Finck if (pexp->uFlags & FL_REGISTER)
397c2c66affSColin Finck {
398c2c66affSColin Finck fprintf(file,"\t");
399c2c66affSColin Finck }
400c2c66affSColin Finck else
401c2c66affSColin Finck {
402c2c66affSColin Finck fprintf(file, "\tretval = ");
403c2c66affSColin Finck }
404c2c66affSColin Finck fprintf(file, "%.*s(", pexp->strName.len, pexp->strName.buf);
405c2c66affSColin Finck
406c2c66affSColin Finck for (i = 0; i < pexp->nArgCount; i++)
407c2c66affSColin Finck {
408c2c66affSColin Finck if (i != 0) fprintf(file, ", ");
409c2c66affSColin Finck fprintf(file, "a%d", i);
410c2c66affSColin Finck }
411c2c66affSColin Finck fprintf(file, ");\n");
412c2c66affSColin Finck }
413c2c66affSColin Finck
414c2c66affSColin Finck if (!bRelay)
415c2c66affSColin Finck fprintf(file, "\treturn 0;\n}\n\n");
416c2c66affSColin Finck else if ((pexp->uFlags & FL_REGISTER) == 0)
417c2c66affSColin Finck {
418c2c66affSColin Finck if (pexp->uFlags & FL_RET64)
419c2c66affSColin Finck {
420bd27b050SHermès Bélusca-Maïto fprintf(file, "\tif (TRACE_ON(relay))\n\t\tDPRINTF(\"%s: %.*s: retval = 0x%%\"PRIx64\"\\n\", retval);\n",
421c2c66affSColin Finck pszDllName, pexp->strName.len, pexp->strName.buf);
422c2c66affSColin Finck }
423c2c66affSColin Finck else
424c2c66affSColin Finck {
425c2c66affSColin Finck fprintf(file, "\tif (TRACE_ON(relay))\n\t\tDPRINTF(\"%s: %.*s: retval = 0x%%lx\\n\", retval);\n",
426c2c66affSColin Finck pszDllName, pexp->strName.len, pexp->strName.buf);
427c2c66affSColin Finck }
428c2c66affSColin Finck fprintf(file, "\treturn retval;\n}\n\n");
429c2c66affSColin Finck }
430c2c66affSColin Finck
431c2c66affSColin Finck return 1;
432c2c66affSColin Finck }
433c2c66affSColin Finck
434c2c66affSColin Finck void
OutputHeader_asmstub(FILE * file,char * libname)435c2c66affSColin Finck OutputHeader_asmstub(FILE *file, char *libname)
436c2c66affSColin Finck {
437c2c66affSColin Finck fprintf(file, "; File generated automatically, do not edit!\n\n");
438c2c66affSColin Finck
439c2c66affSColin Finck if (giArch == ARCH_X86)
440c2c66affSColin Finck {
441c2c66affSColin Finck fprintf(file, ".586\n.model flat\n.code\n");
442c2c66affSColin Finck }
443c2c66affSColin Finck else if (giArch == ARCH_AMD64)
444c2c66affSColin Finck {
445c2c66affSColin Finck fprintf(file, ".code\n");
446c2c66affSColin Finck }
447be223b9dSJustin Miller else if (giArch == ARCH_ARM || giArch == ARCH_ARM64)
448c2c66affSColin Finck {
449c2c66affSColin Finck fprintf(file, " AREA |.text|,ALIGN=2,CODE,READONLY\n\n");
450c2c66affSColin Finck }
451c2c66affSColin Finck }
452c2c66affSColin Finck
453c2c66affSColin Finck void
Output_stublabel(FILE * fileDest,char * pszSymbolName)454c2c66affSColin Finck Output_stublabel(FILE *fileDest, char* pszSymbolName)
455c2c66affSColin Finck {
456be223b9dSJustin Miller if (giArch == ARCH_ARM || giArch == ARCH_ARM64)
457c2c66affSColin Finck {
458c2c66affSColin Finck fprintf(fileDest,
459c2c66affSColin Finck "\tEXPORT |%s| [FUNC]\n|%s|\n",
460c2c66affSColin Finck pszSymbolName,
461c2c66affSColin Finck pszSymbolName);
462c2c66affSColin Finck }
463c2c66affSColin Finck else
464c2c66affSColin Finck {
465c2c66affSColin Finck fprintf(fileDest,
466c2c66affSColin Finck "PUBLIC %s\n%s: nop\n",
467c2c66affSColin Finck pszSymbolName,
468c2c66affSColin Finck pszSymbolName);
469c2c66affSColin Finck }
470c2c66affSColin Finck }
471c2c66affSColin Finck
472c2c66affSColin Finck int
OutputLine_asmstub(FILE * fileDest,EXPORT * pexp)473c2c66affSColin Finck OutputLine_asmstub(FILE *fileDest, EXPORT *pexp)
474c2c66affSColin Finck {
475c2c66affSColin Finck char szNameBuffer[128];
476c2c66affSColin Finck
477c2c66affSColin Finck /* Handle autoname */
478c2c66affSColin Finck if (pexp->strName.len == 1 && pexp->strName.buf[0] == '@')
479c2c66affSColin Finck {
480824e08c7STimo Kreuzer sprintf(szNameBuffer, "%s_stub_ordinal%d",
481824e08c7STimo Kreuzer gpszUnderscore, pexp->nOrdinal);
482c2c66affSColin Finck }
483c2c66affSColin Finck else if (giArch != ARCH_X86)
484c2c66affSColin Finck {
4859cff6597STimo Kreuzer /* Does the string already have stdcall decoration? */
4869cff6597STimo Kreuzer const char *pcAt = ScanToken(pexp->strName.buf, '@');
4879cff6597STimo Kreuzer if (pcAt && (pcAt < (pexp->strName.buf + pexp->strName.len)) &&
4889cff6597STimo Kreuzer (pexp->strName.buf[0] == '_'))
4899cff6597STimo Kreuzer {
4909cff6597STimo Kreuzer /* Skip leading underscore and remove trailing decoration */
4919cff6597STimo Kreuzer sprintf(szNameBuffer, "_stub_%.*s",
4929cff6597STimo Kreuzer (int)(pcAt - pexp->strName.buf - 1),
4939cff6597STimo Kreuzer pexp->strName.buf + 1);
4949cff6597STimo Kreuzer }
4959cff6597STimo Kreuzer else
4969cff6597STimo Kreuzer {
497c2c66affSColin Finck sprintf(szNameBuffer, "_stub_%.*s",
498c2c66affSColin Finck pexp->strName.len, pexp->strName.buf);
499c2c66affSColin Finck }
5009cff6597STimo Kreuzer }
501c2c66affSColin Finck else if (pexp->nCallingConvention == CC_STDCALL)
502c2c66affSColin Finck {
503c2c66affSColin Finck sprintf(szNameBuffer, "__stub_%.*s@%d",
504c2c66affSColin Finck pexp->strName.len, pexp->strName.buf, pexp->nStackBytes);
505c2c66affSColin Finck }
506c2c66affSColin Finck else if (pexp->nCallingConvention == CC_FASTCALL)
507c2c66affSColin Finck {
508c2c66affSColin Finck sprintf(szNameBuffer, "@_stub_%.*s@%d",
509c2c66affSColin Finck pexp->strName.len, pexp->strName.buf, pexp->nStackBytes);
510c2c66affSColin Finck }
511c2c66affSColin Finck else if ((pexp->nCallingConvention == CC_CDECL) ||
512c2c66affSColin Finck (pexp->nCallingConvention == CC_THISCALL) ||
513c2c66affSColin Finck (pexp->nCallingConvention == CC_EXTERN) ||
514c2c66affSColin Finck (pexp->nCallingConvention == CC_STUB))
515c2c66affSColin Finck {
516c2c66affSColin Finck sprintf(szNameBuffer, "__stub_%.*s",
517c2c66affSColin Finck pexp->strName.len, pexp->strName.buf);
518c2c66affSColin Finck }
519c2c66affSColin Finck else
520c2c66affSColin Finck {
521c2c66affSColin Finck fprintf(stderr, "Invalid calling convention");
522c2c66affSColin Finck return 0;
523c2c66affSColin Finck }
524c2c66affSColin Finck
525c2c66affSColin Finck Output_stublabel(fileDest, szNameBuffer);
526c2c66affSColin Finck
527c2c66affSColin Finck return 1;
528c2c66affSColin Finck }
529c2c66affSColin Finck
530c2c66affSColin Finck void
OutputHeader_def(FILE * file,char * libname)531c2c66affSColin Finck OutputHeader_def(FILE *file, char *libname)
532c2c66affSColin Finck {
533c2c66affSColin Finck fprintf(file,
534c2c66affSColin Finck "; File generated automatically, do not edit!\n\n"
535c2c66affSColin Finck "NAME %s\n\n"
536c2c66affSColin Finck "EXPORTS\n",
537c2c66affSColin Finck libname);
538c2c66affSColin Finck }
539c2c66affSColin Finck
540c2c66affSColin Finck void
PrintName(FILE * fileDest,EXPORT * pexp,PSTRING pstr,int fDeco)541c2c66affSColin Finck PrintName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco)
542c2c66affSColin Finck {
543c2c66affSColin Finck const char *pcName = pstr->buf;
544c2c66affSColin Finck int nNameLength = pstr->len;
545c2c66affSColin Finck const char* pcDot, *pcAt;
546e8ab2736STimo Kreuzer char namebuffer[19];
547824e08c7STimo Kreuzer
548824e08c7STimo Kreuzer if ((nNameLength == 1) && (pcName[0] == '@'))
549824e08c7STimo Kreuzer {
550824e08c7STimo Kreuzer sprintf(namebuffer, "ordinal%d", pexp->nOrdinal);
551824e08c7STimo Kreuzer pcName = namebuffer;
552824e08c7STimo Kreuzer nNameLength = strlen(namebuffer);
553824e08c7STimo Kreuzer }
554c2c66affSColin Finck
555c2c66affSColin Finck /* Check for non-x86 first */
556c2c66affSColin Finck if (giArch != ARCH_X86)
557c2c66affSColin Finck {
558c2c66affSColin Finck /* Does the string already have stdcall decoration? */
559c2c66affSColin Finck pcAt = ScanToken(pcName, '@');
560c2c66affSColin Finck if (pcAt && (pcAt < (pcName + nNameLength)) && (pcName[0] == '_'))
561c2c66affSColin Finck {
562c2c66affSColin Finck /* Skip leading underscore and remove trailing decoration */
563c2c66affSColin Finck pcName++;
564f47f45dbSTimo Kreuzer nNameLength = (int)(pcAt - pcName);
565c2c66affSColin Finck }
566c2c66affSColin Finck
567c2c66affSColin Finck /* Print the undecorated function name */
568c2c66affSColin Finck fprintf(fileDest, "%.*s", nNameLength, pcName);
569c2c66affSColin Finck }
570c2c66affSColin Finck else if (fDeco &&
571c2c66affSColin Finck ((pexp->nCallingConvention == CC_STDCALL) ||
572c2c66affSColin Finck (pexp->nCallingConvention == CC_FASTCALL)))
573c2c66affSColin Finck {
574a8255233SJérôme Gardou /* Beware with C++ exports */
575a8255233SJérôme Gardou int is_cpp = pcName[0] == '?';
576a8255233SJérôme Gardou
577c2c66affSColin Finck /* Scan for a dll forwarding dot */
578c2c66affSColin Finck pcDot = ScanToken(pcName, '.');
579c2c66affSColin Finck if (pcDot)
580c2c66affSColin Finck {
581c2c66affSColin Finck /* First print the dll name, followed by a dot */
582f47f45dbSTimo Kreuzer nNameLength = (int)(pcDot - pcName);
583c2c66affSColin Finck fprintf(fileDest, "%.*s.", nNameLength, pcName);
584c2c66affSColin Finck
585c2c66affSColin Finck /* Now the actual function name */
586c2c66affSColin Finck pcName = pcDot + 1;
587c2c66affSColin Finck nNameLength = pexp->strTarget.len - nNameLength - 1;
588c2c66affSColin Finck }
589c2c66affSColin Finck
590c2c66affSColin Finck /* Does the string already have decoration? */
591c2c66affSColin Finck pcAt = ScanToken(pcName, '@');
592c2c66affSColin Finck if (pcAt && (pcAt < (pcName + nNameLength)))
593c2c66affSColin Finck {
594a8255233SJérôme Gardou /* On GCC, we need to remove the leading stdcall underscore, but not for C++ exports */
595a8255233SJérôme Gardou if (!gbMSComp && !is_cpp && (pexp->nCallingConvention == CC_STDCALL))
596c2c66affSColin Finck {
597c2c66affSColin Finck pcName++;
598c2c66affSColin Finck nNameLength--;
599c2c66affSColin Finck }
600c2c66affSColin Finck
601c2c66affSColin Finck /* Print the already decorated function name */
602c2c66affSColin Finck fprintf(fileDest, "%.*s", nNameLength, pcName);
603c2c66affSColin Finck }
604c2c66affSColin Finck else
605c2c66affSColin Finck {
606c2c66affSColin Finck /* Print the prefix, but skip it for (GCC && stdcall) */
607c2c66affSColin Finck if (gbMSComp || (pexp->nCallingConvention != CC_STDCALL))
608c2c66affSColin Finck {
609c2c66affSColin Finck fprintf(fileDest, "%c", pexp->nCallingConvention == CC_FASTCALL ? '@' : '_');
610c2c66affSColin Finck }
611c2c66affSColin Finck
612c2c66affSColin Finck /* Print the name with trailing decoration */
613c2c66affSColin Finck fprintf(fileDest, "%.*s@%d", nNameLength, pcName, pexp->nStackBytes);
614c2c66affSColin Finck }
615c2c66affSColin Finck }
61660f4493aSTimo Kreuzer else if (fDeco && (pexp->nCallingConvention == CC_CDECL) && gbMSComp)
61760f4493aSTimo Kreuzer {
61860f4493aSTimo Kreuzer /* Print with cdecl decoration */
61960f4493aSTimo Kreuzer fprintf(fileDest, "_%.*s", nNameLength, pcName);
62060f4493aSTimo Kreuzer }
621c2c66affSColin Finck else
622c2c66affSColin Finck {
623c2c66affSColin Finck /* Print the undecorated function name */
624c2c66affSColin Finck fprintf(fileDest, "%.*s", nNameLength, pcName);
625c2c66affSColin Finck }
626c2c66affSColin Finck }
627c2c66affSColin Finck
628c2c66affSColin Finck void
OutputLine_def_MS(FILE * fileDest,EXPORT * pexp)629c2c66affSColin Finck OutputLine_def_MS(FILE *fileDest, EXPORT *pexp)
630c2c66affSColin Finck {
631c2c66affSColin Finck PrintName(fileDest, pexp, &pexp->strName, 0);
632c2c66affSColin Finck
633c2c66affSColin Finck if (gbImportLib)
634c2c66affSColin Finck {
635c2c66affSColin Finck /* Redirect to a stub function, to get the right decoration in the lib */
636824e08c7STimo Kreuzer fprintf(fileDest, "=_stub_");
637824e08c7STimo Kreuzer PrintName(fileDest, pexp, &pexp->strName, 0);
638c2c66affSColin Finck }
639c2c66affSColin Finck else if (pexp->strTarget.buf)
640c2c66affSColin Finck {
641c2c66affSColin Finck if (pexp->strName.buf[0] == '?')
642c2c66affSColin Finck {
643c2c66affSColin Finck //fprintf(stderr, "warning: ignoring C++ redirection %.*s -> %.*s\n",
644c2c66affSColin Finck // pexp->strName.len, pexp->strName.buf, pexp->strTarget.len, pexp->strTarget.buf);
645c2c66affSColin Finck }
646c2c66affSColin Finck else
647c2c66affSColin Finck {
648c2c66affSColin Finck fprintf(fileDest, "=");
649c2c66affSColin Finck
650c2c66affSColin Finck /* If the original name was decorated, use decoration in the forwarder as well */
651c2c66affSColin Finck if ((giArch == ARCH_X86) && ScanToken(pexp->strName.buf, '@') &&
652c2c66affSColin Finck !ScanToken(pexp->strTarget.buf, '@') &&
653c2c66affSColin Finck ((pexp->nCallingConvention == CC_STDCALL) ||
654c2c66affSColin Finck (pexp->nCallingConvention == CC_FASTCALL)) )
655c2c66affSColin Finck {
656c2c66affSColin Finck PrintName(fileDest, pexp, &pexp->strTarget, 1);
657c2c66affSColin Finck }
658c2c66affSColin Finck else
659c2c66affSColin Finck {
660c2c66affSColin Finck /* Write the undecorated redirection name */
661c2c66affSColin Finck fprintf(fileDest, "%.*s", pexp->strTarget.len, pexp->strTarget.buf);
662c2c66affSColin Finck }
663c2c66affSColin Finck }
664c2c66affSColin Finck }
665c2c66affSColin Finck else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) &&
666c2c66affSColin Finck (pexp->strName.buf[0] == '?'))
667c2c66affSColin Finck {
668c2c66affSColin Finck /* C++ stubs are forwarded to C stubs */
669c2c66affSColin Finck fprintf(fileDest, "=stub_function%d", pexp->nNumber);
670c2c66affSColin Finck }
671c2c66affSColin Finck else if (gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) && (pexp->nCallingConvention == CC_STDCALL) &&
672c2c66affSColin Finck (pexp->strName.buf[0] != '?'))
673c2c66affSColin Finck {
674c2c66affSColin Finck /* Redirect it to the relay-tracing trampoline */
675c2c66affSColin Finck fprintf(fileDest, "=$relaytrace$%.*s", pexp->strName.len, pexp->strName.buf);
676c2c66affSColin Finck }
677c2c66affSColin Finck }
678c2c66affSColin Finck
679c2c66affSColin Finck void
OutputLine_def_GCC(FILE * fileDest,EXPORT * pexp)680c2c66affSColin Finck OutputLine_def_GCC(FILE *fileDest, EXPORT *pexp)
681c2c66affSColin Finck {
682c2c66affSColin Finck int bTracing = 0;
683c2c66affSColin Finck /* Print the function name, with decoration for export libs */
684c2c66affSColin Finck PrintName(fileDest, pexp, &pexp->strName, gbImportLib);
685c2c66affSColin Finck DbgPrint("Generating def line for '%.*s'\n", pexp->strName.len, pexp->strName.buf);
686c2c66affSColin Finck
687c2c66affSColin Finck /* Check if this is a forwarded export */
688c2c66affSColin Finck if (pexp->strTarget.buf)
689c2c66affSColin Finck {
690c2c66affSColin Finck int fIsExternal = !!ScanToken(pexp->strTarget.buf, '.');
691c2c66affSColin Finck DbgPrint("Got redirect '%.*s'\n", pexp->strTarget.len, pexp->strTarget.buf);
692c2c66affSColin Finck
693c2c66affSColin Finck /* print the target name, don't decorate if it is external */
69460f4493aSTimo Kreuzer fprintf(fileDest, pexp->uFlags & FL_IMPSYM ? "==" : "=");
695c2c66affSColin Finck PrintName(fileDest, pexp, &pexp->strTarget, !fIsExternal);
696c2c66affSColin Finck }
697c2c66affSColin Finck else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) &&
698c2c66affSColin Finck (pexp->strName.buf[0] == '?'))
699c2c66affSColin Finck {
700c2c66affSColin Finck /* C++ stubs are forwarded to C stubs */
701c2c66affSColin Finck fprintf(fileDest, "=stub_function%d", pexp->nNumber);
702c2c66affSColin Finck }
703c2c66affSColin Finck else if (gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) &&
704c2c66affSColin Finck (pexp->nCallingConvention == CC_STDCALL) &&
705c2c66affSColin Finck (pexp->strName.buf[0] != '?'))
706c2c66affSColin Finck {
707c2c66affSColin Finck /* Redirect it to the relay-tracing trampoline */
708c2c66affSColin Finck char buf[256];
709c2c66affSColin Finck STRING strTarget;
710c2c66affSColin Finck fprintf(fileDest, "=");
711c2c66affSColin Finck sprintf(buf, "$relaytrace$%.*s", pexp->strName.len, pexp->strName.buf);
712c2c66affSColin Finck strTarget.buf = buf;
713c2c66affSColin Finck strTarget.len = pexp->strName.len + 12;
714c2c66affSColin Finck PrintName(fileDest, pexp, &strTarget, 1);
715c2c66affSColin Finck bTracing = 1;
716c2c66affSColin Finck }
717c2c66affSColin Finck
718a8255233SJérôme Gardou /* Special handling for stdcall and fastcall, but not C++ exports*/
719c2c66affSColin Finck if ((giArch == ARCH_X86) &&
720a8255233SJérôme Gardou (pexp->strName.buf[0] != '?') &&
721c2c66affSColin Finck ((pexp->nCallingConvention == CC_STDCALL) ||
722c2c66affSColin Finck (pexp->nCallingConvention == CC_FASTCALL)))
723c2c66affSColin Finck {
724c2c66affSColin Finck /* Is this the import lib? */
725c2c66affSColin Finck if (gbImportLib)
726c2c66affSColin Finck {
727c2c66affSColin Finck /* Is the name in the spec file decorated? */
728c2c66affSColin Finck const char* pcDeco = ScanToken(pexp->strName.buf, '@');
7299cff6597STimo Kreuzer if (pcDeco &&
7309cff6597STimo Kreuzer (pexp->strName.len > 1) &&
7319cff6597STimo Kreuzer (pcDeco < pexp->strName.buf + pexp->strName.len))
732c2c66affSColin Finck {
733c2c66affSColin Finck /* Write the name including the leading @ */
734c2c66affSColin Finck fprintf(fileDest, "==%.*s", pexp->strName.len, pexp->strName.buf);
735c2c66affSColin Finck }
736c2c66affSColin Finck }
737c2c66affSColin Finck else if ((!pexp->strTarget.buf) && !(bTracing))
738c2c66affSColin Finck {
739c2c66affSColin Finck /* Write a forwarder to the actual decorated symbol */
740c2c66affSColin Finck fprintf(fileDest, "=");
741c2c66affSColin Finck PrintName(fileDest, pexp, &pexp->strName, 1);
742c2c66affSColin Finck }
743c2c66affSColin Finck }
744c2c66affSColin Finck }
745c2c66affSColin Finck
746c2c66affSColin Finck int
OutputLine_def(FILE * fileDest,EXPORT * pexp)747c2c66affSColin Finck OutputLine_def(FILE *fileDest, EXPORT *pexp)
748c2c66affSColin Finck {
7490b0bb1a9STimo Kreuzer /* Don't add private exports to the import lib */
7500b0bb1a9STimo Kreuzer if (gbImportLib && (pexp->uFlags & FL_PRIVATE))
7510b0bb1a9STimo Kreuzer {
7520b0bb1a9STimo Kreuzer DbgPrint("OutputLine_def: skipping private export '%.*s'...\n", pexp->strName.len, pexp->strName.buf);
7530b0bb1a9STimo Kreuzer return 1;
7540b0bb1a9STimo Kreuzer }
7550b0bb1a9STimo Kreuzer
75660f4493aSTimo Kreuzer /* Handle import symbols */
75760f4493aSTimo Kreuzer if (pexp->uFlags & FL_IMPSYM)
75860f4493aSTimo Kreuzer {
75960f4493aSTimo Kreuzer /* Skip these, if we are not creating an import lib, or if this is MS */
76060f4493aSTimo Kreuzer if (!gbImportLib || gbMSComp)
76160f4493aSTimo Kreuzer {
76260f4493aSTimo Kreuzer DbgPrint("OutputLine_def: skipping import symbol '%.*s'...\n", pexp->strName.len, pexp->strName.buf);
76360f4493aSTimo Kreuzer return 1;
76460f4493aSTimo Kreuzer }
76560f4493aSTimo Kreuzer }
76660f4493aSTimo Kreuzer
7675387a7ccSJérôme Gardou /* For MS linker, forwarded externs are managed via #pragma comment(linker,"/export:_data=org.data,DATA") */
7685387a7ccSJérôme Gardou if (gbMSComp && !gbImportLib && (pexp->nCallingConvention == CC_EXTERN) &&
7695387a7ccSJérôme Gardou (pexp->strTarget.buf != NULL) && !!ScanToken(pexp->strTarget.buf, '.'))
7705387a7ccSJérôme Gardou {
7715387a7ccSJérôme Gardou DbgPrint("OutputLine_def: skipping forwarded extern export '%.*s' ->'%.*s'...\n",
7725387a7ccSJérôme Gardou pexp->strName.len, pexp->strName.buf, pexp->strTarget.len, pexp->strTarget.buf);
7735387a7ccSJérôme Gardou return 1;
7745387a7ccSJérôme Gardou }
7755387a7ccSJérôme Gardou
776c2c66affSColin Finck DbgPrint("OutputLine_def: '%.*s'...\n", pexp->strName.len, pexp->strName.buf);
777c2c66affSColin Finck fprintf(fileDest, " ");
778c2c66affSColin Finck
779c2c66affSColin Finck if (gbMSComp)
780c2c66affSColin Finck OutputLine_def_MS(fileDest, pexp);
781c2c66affSColin Finck else
782c2c66affSColin Finck OutputLine_def_GCC(fileDest, pexp);
783c2c66affSColin Finck
7847dcfda81STimo Kreuzer /* If it is not an import lib, we force ordinals */
7857dcfda81STimo Kreuzer if ((pexp->uFlags & FL_ORDINAL) || !gbImportLib)
786c2c66affSColin Finck {
787c2c66affSColin Finck fprintf(fileDest, " @%d", pexp->nOrdinal);
788c2c66affSColin Finck }
789c2c66affSColin Finck
790c2c66affSColin Finck if (pexp->uFlags & FL_NONAME)
791c2c66affSColin Finck {
792c2c66affSColin Finck fprintf(fileDest, " NONAME");
793c2c66affSColin Finck }
794c2c66affSColin Finck
795c2c66affSColin Finck /* Either PRIVATE or DATA */
796c2c66affSColin Finck if (pexp->uFlags & FL_PRIVATE)
797c2c66affSColin Finck {
798c2c66affSColin Finck fprintf(fileDest, " PRIVATE");
799c2c66affSColin Finck }
800c2c66affSColin Finck else if (pexp->nCallingConvention == CC_EXTERN)
801c2c66affSColin Finck {
802c2c66affSColin Finck fprintf(fileDest, " DATA");
803c2c66affSColin Finck }
804c2c66affSColin Finck
805c2c66affSColin Finck fprintf(fileDest, "\n");
806c2c66affSColin Finck
807c2c66affSColin Finck return 1;
808c2c66affSColin Finck }
809c2c66affSColin Finck
810c95b5e6fSTimo Kreuzer void
PrintNameOrImpName(FILE * fileDest,EXPORT * pexp,PSTRING pstr,int fDeco,int fImp)81160f4493aSTimo Kreuzer PrintNameOrImpName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco, int fImp)
81260f4493aSTimo Kreuzer {
81360f4493aSTimo Kreuzer if (fImp)
81460f4493aSTimo Kreuzer {
81560f4493aSTimo Kreuzer fprintf(fileDest, "__imp_");
81660f4493aSTimo Kreuzer }
81760f4493aSTimo Kreuzer
81860f4493aSTimo Kreuzer PrintName(fileDest, pexp, pstr, fDeco);
81960f4493aSTimo Kreuzer }
82060f4493aSTimo Kreuzer
82160f4493aSTimo Kreuzer void
OutputAlias(FILE * fileDest,EXPORT * pexp,int fImp)82260f4493aSTimo Kreuzer OutputAlias(FILE *fileDest, EXPORT *pexp, int fImp)
82360f4493aSTimo Kreuzer {
82460f4493aSTimo Kreuzer if ((giArch == ARCH_ARM) || (giArch == ARCH_ARM64))
82560f4493aSTimo Kreuzer {
82660f4493aSTimo Kreuzer fprintf(fileDest, " IMPORT ");
82760f4493aSTimo Kreuzer PrintNameOrImpName(fileDest, pexp, &pexp->strName, 1, fImp);
82860f4493aSTimo Kreuzer fprintf(fileDest, ", WEAK ");
82960f4493aSTimo Kreuzer PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp);
83060f4493aSTimo Kreuzer fprintf(fileDest, "\n");
83160f4493aSTimo Kreuzer }
83260f4493aSTimo Kreuzer else
83360f4493aSTimo Kreuzer {
83460f4493aSTimo Kreuzer fprintf(fileDest, " EXTERN ");
83560f4493aSTimo Kreuzer PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp);
83660f4493aSTimo Kreuzer fprintf(fileDest, ":PROC\n ALIAS <");
83760f4493aSTimo Kreuzer PrintNameOrImpName(fileDest, pexp, &pexp->strName, 1, fImp);
83860f4493aSTimo Kreuzer fprintf(fileDest, "> = <");
83960f4493aSTimo Kreuzer PrintNameOrImpName(fileDest, pexp, &pexp->strTarget, 1, fImp);
84060f4493aSTimo Kreuzer fprintf(fileDest, ">\n");
84160f4493aSTimo Kreuzer }
84260f4493aSTimo Kreuzer }
84360f4493aSTimo Kreuzer
84460f4493aSTimo Kreuzer int
OutputLine_implib_asm(FILE * fileDest,EXPORT * pexp)84560f4493aSTimo Kreuzer OutputLine_implib_asm(FILE *fileDest, EXPORT *pexp)
84660f4493aSTimo Kreuzer {
84760f4493aSTimo Kreuzer if ((pexp->uFlags & FL_IMPSYM) == 0)
84860f4493aSTimo Kreuzer {
84960f4493aSTimo Kreuzer return 1;
85060f4493aSTimo Kreuzer }
85160f4493aSTimo Kreuzer
85260f4493aSTimo Kreuzer OutputAlias(fileDest, pexp, 0);
85360f4493aSTimo Kreuzer OutputAlias(fileDest, pexp, 1);
85460f4493aSTimo Kreuzer
85560f4493aSTimo Kreuzer return 1;
85660f4493aSTimo Kreuzer }
85760f4493aSTimo Kreuzer
85860f4493aSTimo Kreuzer void
Fatalv(const char * filename,unsigned nLine,const char * pcLine,const char * pc,size_t errorlen,const char * format,va_list argptr)859c95b5e6fSTimo Kreuzer Fatalv(
860c95b5e6fSTimo Kreuzer const char* filename,
861c95b5e6fSTimo Kreuzer unsigned nLine,
86280c0b083STimo Kreuzer const char *pcLine,
86380c0b083STimo Kreuzer const char *pc,
864c95b5e6fSTimo Kreuzer size_t errorlen,
865c95b5e6fSTimo Kreuzer const char *format,
866c95b5e6fSTimo Kreuzer va_list argptr)
867c95b5e6fSTimo Kreuzer {
868c95b5e6fSTimo Kreuzer unsigned i, errorpos, len;
869c95b5e6fSTimo Kreuzer const char* pcLineEnd;
870c95b5e6fSTimo Kreuzer
871c95b5e6fSTimo Kreuzer /* Get the length of the line */
872c95b5e6fSTimo Kreuzer pcLineEnd = strpbrk(pcLine, "\r\n");
8736e80f4d0STimo Kreuzer len = (unsigned)(pcLineEnd - pcLine);
874c95b5e6fSTimo Kreuzer
875c95b5e6fSTimo Kreuzer if (pc == NULL)
876c95b5e6fSTimo Kreuzer {
877c95b5e6fSTimo Kreuzer pc = pcLine + len - 1;
878c95b5e6fSTimo Kreuzer errorlen = 1;
879c95b5e6fSTimo Kreuzer }
880c95b5e6fSTimo Kreuzer
881c95b5e6fSTimo Kreuzer errorpos = (unsigned)(pc - pcLine);
882c95b5e6fSTimo Kreuzer
883c95b5e6fSTimo Kreuzer /* Output the error message */
884c95b5e6fSTimo Kreuzer fprintf(stderr, "ERROR: (%s:%u:%u): ", filename, nLine, errorpos);
885c95b5e6fSTimo Kreuzer vfprintf(stderr, format, argptr);
886c95b5e6fSTimo Kreuzer fprintf(stderr, "\n");
887c95b5e6fSTimo Kreuzer
888c95b5e6fSTimo Kreuzer /* Output the line with the error */
889c95b5e6fSTimo Kreuzer fprintf(stderr, "> %.*s\n", len, pcLine);
890c95b5e6fSTimo Kreuzer
891c95b5e6fSTimo Kreuzer if (errorlen == 0)
892c95b5e6fSTimo Kreuzer {
893c95b5e6fSTimo Kreuzer errorlen = TokenLength(pc);
894c95b5e6fSTimo Kreuzer }
895c95b5e6fSTimo Kreuzer
896c95b5e6fSTimo Kreuzer for (i = 0; i < errorpos + 2; i++)
897c95b5e6fSTimo Kreuzer {
898c95b5e6fSTimo Kreuzer fprintf(stderr, " ");
899c95b5e6fSTimo Kreuzer }
900c95b5e6fSTimo Kreuzer for (i = 0; i < errorlen; i++)
901c95b5e6fSTimo Kreuzer {
902c95b5e6fSTimo Kreuzer fprintf(stderr, "~");
903c95b5e6fSTimo Kreuzer }
904c95b5e6fSTimo Kreuzer fprintf(stderr, "\n");
905c95b5e6fSTimo Kreuzer exit(-1);
906c95b5e6fSTimo Kreuzer }
907c95b5e6fSTimo Kreuzer
908c95b5e6fSTimo Kreuzer void
Fatal(const char * filename,unsigned nLine,const char * pcLine,const char * pc,size_t errorlen,const char * format,...)909c95b5e6fSTimo Kreuzer Fatal(
910c95b5e6fSTimo Kreuzer const char* filename,
911c95b5e6fSTimo Kreuzer unsigned nLine,
91280c0b083STimo Kreuzer const char *pcLine,
91380c0b083STimo Kreuzer const char *pc,
914c95b5e6fSTimo Kreuzer size_t errorlen,
915c95b5e6fSTimo Kreuzer const char *format,
916c95b5e6fSTimo Kreuzer ...)
917c95b5e6fSTimo Kreuzer {
918c95b5e6fSTimo Kreuzer va_list argptr;
919c95b5e6fSTimo Kreuzer
920c95b5e6fSTimo Kreuzer va_start(argptr, format);
921c95b5e6fSTimo Kreuzer Fatalv(filename, nLine, pcLine, pc, errorlen, format, argptr);
922c95b5e6fSTimo Kreuzer va_end(argptr);
923c95b5e6fSTimo Kreuzer }
924c95b5e6fSTimo Kreuzer
925e8ab2736STimo Kreuzer EXPORT *
ParseFile(char * pcStart,FILE * fileDest,unsigned * cExports)926e8ab2736STimo Kreuzer ParseFile(char* pcStart, FILE *fileDest, unsigned *cExports)
927c2c66affSColin Finck {
928e8ab2736STimo Kreuzer EXPORT *pexports;
92980c0b083STimo Kreuzer const char *pc, *pcLine;
930e8ab2736STimo Kreuzer int cLines, nLine;
931c2c66affSColin Finck EXPORT exp;
932e8ab2736STimo Kreuzer int included;
933c2c66affSColin Finck unsigned int i;
934c2c66affSColin Finck
935e8ab2736STimo Kreuzer *cExports = 0;
936e8ab2736STimo Kreuzer
937c2c66affSColin Finck //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);
938c2c66affSColin Finck
939e8ab2736STimo Kreuzer /* Count the lines */
940e8ab2736STimo Kreuzer for (cLines = 1, pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), cLines++)
941e8ab2736STimo Kreuzer {
942e8ab2736STimo Kreuzer /* Nothing */
943e8ab2736STimo Kreuzer }
944e8ab2736STimo Kreuzer
945e8ab2736STimo Kreuzer /* Allocate an array of EXPORT structures */
946e8ab2736STimo Kreuzer pexports = malloc(cLines * sizeof(EXPORT));
947e8ab2736STimo Kreuzer if (pexports == NULL)
948e8ab2736STimo Kreuzer {
949e8ab2736STimo Kreuzer fprintf(stderr, "ERROR: %s: failed to allocate EXPORT array of %u elements\n", pszSourceFileName, cLines);
950e8ab2736STimo Kreuzer return NULL;
951e8ab2736STimo Kreuzer }
952e8ab2736STimo Kreuzer
953c2c66affSColin Finck /* Loop all lines */
954c2c66affSColin Finck nLine = 1;
955c2c66affSColin Finck exp.nNumber = 0;
956c2c66affSColin Finck for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++)
957c2c66affSColin Finck {
958c2c66affSColin Finck pc = pcLine;
959c2c66affSColin Finck
960e8ab2736STimo Kreuzer exp.strName.buf = NULL;
961e8ab2736STimo Kreuzer exp.strName.len = 0;
962e8ab2736STimo Kreuzer exp.strTarget.buf = NULL;
963e8ab2736STimo Kreuzer exp.strTarget.len = 0;
964c2c66affSColin Finck exp.nArgCount = 0;
965c2c66affSColin Finck exp.uFlags = 0;
966c2c66affSColin Finck exp.nNumber++;
967e8ab2736STimo Kreuzer exp.nStartVersion = 0;
968e8ab2736STimo Kreuzer exp.nEndVersion = 0xFFFFFFFF;
969e8ab2736STimo Kreuzer exp.bVersionIncluded = 1;
970c2c66affSColin Finck
971c2c66affSColin Finck /* Skip white spaces */
972c2c66affSColin Finck while (*pc == ' ' || *pc == '\t') pc++;
973c2c66affSColin Finck
974e8ab2736STimo Kreuzer /* Check for line break or comment */
975e8ab2736STimo Kreuzer if ((*pc == '\r') || (*pc == '\n') ||
976e8ab2736STimo Kreuzer (*pc == ';') || (*pc == '#'))
977e8ab2736STimo Kreuzer {
978e8ab2736STimo Kreuzer continue;
979e8ab2736STimo Kreuzer }
980e8ab2736STimo Kreuzer
981e8ab2736STimo Kreuzer /* On EOF we are done */
982e8ab2736STimo Kreuzer if (*pc == 0)
983e8ab2736STimo Kreuzer {
984e8ab2736STimo Kreuzer return pexports;
985e8ab2736STimo Kreuzer }
986c2c66affSColin Finck
987c2c66affSColin Finck /* Now we should get either an ordinal or @ */
988c2c66affSColin Finck if (*pc == '@')
989c2c66affSColin Finck {
990c95b5e6fSTimo Kreuzer exp.nOrdinal = -1;
991c95b5e6fSTimo Kreuzer }
992c95b5e6fSTimo Kreuzer else if ((*pc >= '0') && (*pc <= '9'))
993c95b5e6fSTimo Kreuzer {
994c95b5e6fSTimo Kreuzer char* end;
995c95b5e6fSTimo Kreuzer long int number = strtol(pc, &end, 10);
996c95b5e6fSTimo Kreuzer if ((*end != ' ') && (*end != '\t'))
997c95b5e6fSTimo Kreuzer {
998c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, end, 0, "Unexpected character(s) after ordinal");
999c95b5e6fSTimo Kreuzer }
1000c95b5e6fSTimo Kreuzer
1001c95b5e6fSTimo Kreuzer if ((number < 0) || (number > 0xFFFE))
1002c95b5e6fSTimo Kreuzer {
1003c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Invalid value for ordinal");
1004c95b5e6fSTimo Kreuzer }
1005c95b5e6fSTimo Kreuzer
1006c95b5e6fSTimo Kreuzer exp.nOrdinal = number;
1007c95b5e6fSTimo Kreuzer
1008c2c66affSColin Finck /* The import lib should contain the ordinal only if -ordinal was specified */
1009c2c66affSColin Finck if (!gbImportLib)
1010c2c66affSColin Finck exp.uFlags |= FL_ORDINAL;
1011c2c66affSColin Finck }
1012c95b5e6fSTimo Kreuzer else
1013c95b5e6fSTimo Kreuzer {
1014c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Expected '@' or ordinal");
1015c95b5e6fSTimo Kreuzer }
1016c2c66affSColin Finck
1017c2c66affSColin Finck /* Go to next token (type) */
1018c2c66affSColin Finck if (!(pc = NextToken(pc)))
1019c2c66affSColin Finck {
1020c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Unexpected end of line");
1021c2c66affSColin Finck }
1022c2c66affSColin Finck
1023c2c66affSColin Finck //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc), pc);
1024c2c66affSColin Finck
1025c2c66affSColin Finck /* Now we should get the type */
1026c2c66affSColin Finck if (CompareToken(pc, "stdcall"))
1027c2c66affSColin Finck {
1028c2c66affSColin Finck exp.nCallingConvention = CC_STDCALL;
1029c2c66affSColin Finck }
1030c2c66affSColin Finck else if (CompareToken(pc, "cdecl") ||
1031c2c66affSColin Finck CompareToken(pc, "varargs"))
1032c2c66affSColin Finck {
1033c2c66affSColin Finck exp.nCallingConvention = CC_CDECL;
1034c2c66affSColin Finck }
1035c2c66affSColin Finck else if (CompareToken(pc, "fastcall"))
1036c2c66affSColin Finck {
1037c2c66affSColin Finck exp.nCallingConvention = CC_FASTCALL;
1038c2c66affSColin Finck }
1039c2c66affSColin Finck else if (CompareToken(pc, "thiscall"))
1040c2c66affSColin Finck {
1041c2c66affSColin Finck exp.nCallingConvention = CC_THISCALL;
1042c2c66affSColin Finck }
1043c2c66affSColin Finck else if (CompareToken(pc, "extern"))
1044c2c66affSColin Finck {
1045c2c66affSColin Finck exp.nCallingConvention = CC_EXTERN;
1046c2c66affSColin Finck }
1047c2c66affSColin Finck else if (CompareToken(pc, "stub"))
1048c2c66affSColin Finck {
1049c2c66affSColin Finck exp.nCallingConvention = CC_STUB;
1050c2c66affSColin Finck }
1051c2c66affSColin Finck else
1052c2c66affSColin Finck {
1053c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Invalid calling convention");
1054c2c66affSColin Finck }
1055c2c66affSColin Finck
1056c2c66affSColin Finck /* Go to next token (options or name) */
1057c2c66affSColin Finck if (!(pc = NextToken(pc)))
1058c2c66affSColin Finck {
1059c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Unexpected end of line");
1060c2c66affSColin Finck }
1061c2c66affSColin Finck
1062c2c66affSColin Finck /* Handle options */
1063c2c66affSColin Finck included = 1;
1064c2c66affSColin Finck while (*pc == '-')
1065c2c66affSColin Finck {
106601df9a41STimo Kreuzer if (CompareToken(pc, "-arch="))
1067c2c66affSColin Finck {
1068c2c66affSColin Finck /* Default to not included */
1069c2c66affSColin Finck included = 0;
1070c2c66affSColin Finck pc += 5;
1071c2c66affSColin Finck
1072c2c66affSColin Finck /* Look if we are included */
107301df9a41STimo Kreuzer do
1074c2c66affSColin Finck {
1075*7b2bb7ecSTimo Kreuzer int negated = 0, match = 0;
1076*7b2bb7ecSTimo Kreuzer
1077c2c66affSColin Finck pc++;
1078*7b2bb7ecSTimo Kreuzer
1079*7b2bb7ecSTimo Kreuzer /* Check for negated case */
1080*7b2bb7ecSTimo Kreuzer if (*pc == '!')
1081*7b2bb7ecSTimo Kreuzer {
1082*7b2bb7ecSTimo Kreuzer negated = 1;
1083*7b2bb7ecSTimo Kreuzer pc++;
1084*7b2bb7ecSTimo Kreuzer }
1085*7b2bb7ecSTimo Kreuzer
1086c2c66affSColin Finck if (CompareToken(pc, pszArchString) ||
1087c2c66affSColin Finck CompareToken(pc, pszArchString2))
1088c2c66affSColin Finck {
1089*7b2bb7ecSTimo Kreuzer match = 1;
1090*7b2bb7ecSTimo Kreuzer }
1091*7b2bb7ecSTimo Kreuzer
1092*7b2bb7ecSTimo Kreuzer if (match != negated)
1093*7b2bb7ecSTimo Kreuzer {
1094c2c66affSColin Finck included = 1;
1095c2c66affSColin Finck }
1096c2c66affSColin Finck
1097c2c66affSColin Finck /* Skip to next arch or end */
1098c2c66affSColin Finck while (*pc > ',') pc++;
109901df9a41STimo Kreuzer } while (*pc == ',');
1100c2c66affSColin Finck }
1101c2c66affSColin Finck else if (CompareToken(pc, "-i386"))
1102c2c66affSColin Finck {
1103c2c66affSColin Finck if (giArch != ARCH_X86) included = 0;
1104c2c66affSColin Finck }
110501df9a41STimo Kreuzer else if (CompareToken(pc, "-version="))
110601df9a41STimo Kreuzer {
110780c0b083STimo Kreuzer const char *pcVersionStart = pc + 9;
1108c95b5e6fSTimo Kreuzer
110901df9a41STimo Kreuzer /* Default to not included */
1110e8ab2736STimo Kreuzer exp.bVersionIncluded = 0;
111101df9a41STimo Kreuzer pc += 8;
111201df9a41STimo Kreuzer
111301df9a41STimo Kreuzer /* Look if we are included */
111401df9a41STimo Kreuzer do
111501df9a41STimo Kreuzer {
111601df9a41STimo Kreuzer unsigned version, endversion;
111701df9a41STimo Kreuzer
111801df9a41STimo Kreuzer /* Optionally skip leading '0x' */
111901df9a41STimo Kreuzer pc++;
112001df9a41STimo Kreuzer if ((pc[0] == '0') && (pc[1] == 'x')) pc += 2;
112101df9a41STimo Kreuzer
112201df9a41STimo Kreuzer /* Now get the version number */
112380c0b083STimo Kreuzer endversion = version = strtoul(pc, (char**)&pc, 16);
112401df9a41STimo Kreuzer
112501df9a41STimo Kreuzer /* Check if it's a range */
112601df9a41STimo Kreuzer if (pc[0] == '+')
112701df9a41STimo Kreuzer {
112801df9a41STimo Kreuzer endversion = 0xFFF;
112901df9a41STimo Kreuzer pc++;
113001df9a41STimo Kreuzer }
113101df9a41STimo Kreuzer else if (pc[0] == '-')
113201df9a41STimo Kreuzer {
113301df9a41STimo Kreuzer /* Optionally skip leading '0x' */
113401df9a41STimo Kreuzer pc++;
113501df9a41STimo Kreuzer if ((pc[0] == '0') && (pc[1] == 'x')) pc += 2;
113680c0b083STimo Kreuzer endversion = strtoul(pc, (char**)&pc, 16);
113701df9a41STimo Kreuzer }
113801df9a41STimo Kreuzer
113901df9a41STimo Kreuzer /* Check for degenerate range */
114001df9a41STimo Kreuzer if (version > endversion)
114101df9a41STimo Kreuzer {
1142c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName,
1143c95b5e6fSTimo Kreuzer nLine,
1144c95b5e6fSTimo Kreuzer pcLine,
1145c95b5e6fSTimo Kreuzer pcVersionStart,
1146c95b5e6fSTimo Kreuzer pc - pcVersionStart,
1147c95b5e6fSTimo Kreuzer "Invalid version range");
114801df9a41STimo Kreuzer }
114901df9a41STimo Kreuzer
1150e8ab2736STimo Kreuzer exp.nStartVersion = version;
1151e8ab2736STimo Kreuzer exp.nEndVersion = endversion;
1152e8ab2736STimo Kreuzer
115301df9a41STimo Kreuzer /* Now compare the range with our version */
115401df9a41STimo Kreuzer if ((guOsVersion >= version) &&
115501df9a41STimo Kreuzer (guOsVersion <= endversion))
115601df9a41STimo Kreuzer {
1157e8ab2736STimo Kreuzer exp.bVersionIncluded = 1;
115801df9a41STimo Kreuzer }
115901df9a41STimo Kreuzer
116001df9a41STimo Kreuzer /* Skip to next arch or end */
116101df9a41STimo Kreuzer while (*pc > ',') pc++;
116201df9a41STimo Kreuzer
116301df9a41STimo Kreuzer } while (*pc == ',');
116401df9a41STimo Kreuzer }
1165c2c66affSColin Finck else if (CompareToken(pc, "-private"))
1166c2c66affSColin Finck {
1167c2c66affSColin Finck exp.uFlags |= FL_PRIVATE;
1168c2c66affSColin Finck }
1169c2c66affSColin Finck else if (CompareToken(pc, "-noname"))
1170c2c66affSColin Finck {
1171c2c66affSColin Finck exp.uFlags |= FL_ORDINAL | FL_NONAME;
1172c2c66affSColin Finck }
117360f4493aSTimo Kreuzer else if (CompareToken(pc, "-impsym"))
117460f4493aSTimo Kreuzer {
117560f4493aSTimo Kreuzer exp.uFlags |= FL_IMPSYM;
117660f4493aSTimo Kreuzer }
1177c2c66affSColin Finck else if (CompareToken(pc, "-ordinal"))
1178c2c66affSColin Finck {
1179c2c66affSColin Finck exp.uFlags |= FL_ORDINAL;
1180c2c66affSColin Finck /* GCC doesn't automatically import by ordinal if an ordinal
1181c2c66affSColin Finck * is found in the def file. Force it. */
1182c2c66affSColin Finck if (gbImportLib && !gbMSComp)
1183c2c66affSColin Finck exp.uFlags |= FL_NONAME;
1184c2c66affSColin Finck }
1185c2c66affSColin Finck else if (CompareToken(pc, "-stub"))
1186c2c66affSColin Finck {
1187c2c66affSColin Finck exp.uFlags |= FL_STUB;
1188c2c66affSColin Finck }
1189c2c66affSColin Finck else if (CompareToken(pc, "-norelay"))
1190c2c66affSColin Finck {
1191c2c66affSColin Finck exp.uFlags |= FL_NORELAY;
1192c2c66affSColin Finck }
1193c2c66affSColin Finck else if (CompareToken(pc, "-ret64"))
1194c2c66affSColin Finck {
1195c2c66affSColin Finck exp.uFlags |= FL_RET64;
1196c2c66affSColin Finck }
1197c2c66affSColin Finck else if (CompareToken(pc, "-register"))
1198c2c66affSColin Finck {
1199c2c66affSColin Finck exp.uFlags |= FL_REGISTER;
1200c2c66affSColin Finck }
1201c2c66affSColin Finck else
1202c2c66affSColin Finck {
1203c95b5e6fSTimo Kreuzer fprintf(stdout,
1204c95b5e6fSTimo Kreuzer "INFO: %s line %d: Ignored option: '%.*s'\n",
1205c95b5e6fSTimo Kreuzer pszSourceFileName,
1206c95b5e6fSTimo Kreuzer nLine,
1207c95b5e6fSTimo Kreuzer TokenLength(pc),
1208c95b5e6fSTimo Kreuzer pc);
1209c2c66affSColin Finck }
1210c2c66affSColin Finck
1211c2c66affSColin Finck /* Go to next token */
1212c2c66affSColin Finck pc = NextToken(pc);
1213c2c66affSColin Finck }
1214c2c66affSColin Finck
1215c2c66affSColin Finck //fprintf(stderr, "info: Name:'%.10s'\n", pc);
1216c2c66affSColin Finck
1217c2c66affSColin Finck /* If arch didn't match ours, skip this entry */
1218e8ab2736STimo Kreuzer if (!included) continue;
1219c2c66affSColin Finck
1220c2c66affSColin Finck /* Get name */
1221c2c66affSColin Finck exp.strName.buf = pc;
1222c2c66affSColin Finck exp.strName.len = TokenLength(pc);
1223c95b5e6fSTimo Kreuzer //DbgPrint("Got name: '%.*s'\n", exp.strName.len, exp.strName.buf);
1224c2c66affSColin Finck
1225c2c66affSColin Finck /* Check for autoname */
1226c2c66affSColin Finck if ((exp.strName.len == 1) && (exp.strName.buf[0] == '@'))
1227c2c66affSColin Finck {
1228c2c66affSColin Finck exp.uFlags |= FL_ORDINAL | FL_NONAME;
1229c2c66affSColin Finck }
1230c2c66affSColin Finck
1231c2c66affSColin Finck /* Handle parameters */
1232c2c66affSColin Finck exp.nStackBytes = 0;
1233fa56912dSJérôme Gardou pc = NextToken(pc);
1234fa56912dSJérôme Gardou /* Extern can't have parameters, and it's optional to provide ones for stubs. All other exports must have them */
1235fa56912dSJérôme Gardou if (!pc && (exp.nCallingConvention != CC_EXTERN && exp.nCallingConvention != CC_STUB))
1236c2c66affSColin Finck {
1237c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Unexpected end of line");
1238c2c66affSColin Finck }
1239c2c66affSColin Finck
1240fa56912dSJérôme Gardou if (pc && (exp.nCallingConvention != CC_EXTERN))
1241fa56912dSJérôme Gardou {
1242c2c66affSColin Finck /* Verify syntax */
1243c2c66affSColin Finck if (*pc++ != '(')
1244c2c66affSColin Finck {
1245c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc - 1, 0, "Expected '('");
1246c2c66affSColin Finck }
1247c2c66affSColin Finck
1248c2c66affSColin Finck /* Skip whitespaces */
1249c2c66affSColin Finck while (*pc == ' ' || *pc == '\t') pc++;
1250c2c66affSColin Finck
1251c2c66affSColin Finck exp.nStackBytes = 0;
1252c2c66affSColin Finck while (*pc >= '0')
1253c2c66affSColin Finck {
1254c2c66affSColin Finck if (CompareToken(pc, "long"))
1255c2c66affSColin Finck {
1256c2c66affSColin Finck exp.nStackBytes += 4;
1257c2c66affSColin Finck exp.anArgs[exp.nArgCount] = ARG_LONG;
1258c2c66affSColin Finck }
1259c2c66affSColin Finck else if (CompareToken(pc, "double"))
1260c2c66affSColin Finck {
1261c2c66affSColin Finck exp.nStackBytes += 8;
1262c2c66affSColin Finck exp.anArgs[exp.nArgCount] = ARG_DBL;
1263c2c66affSColin Finck }
1264c2c66affSColin Finck else if (CompareToken(pc, "ptr"))
1265c2c66affSColin Finck {
1266c2c66affSColin Finck exp.nStackBytes += 4; // sizeof(void*) on x86
1267c2c66affSColin Finck exp.anArgs[exp.nArgCount] = ARG_PTR;
1268c2c66affSColin Finck }
1269c2c66affSColin Finck else if (CompareToken(pc, "str"))
1270c2c66affSColin Finck {
1271c2c66affSColin Finck exp.nStackBytes += 4; // sizeof(void*) on x86
1272c2c66affSColin Finck exp.anArgs[exp.nArgCount] = ARG_STR;
1273c2c66affSColin Finck }
1274c2c66affSColin Finck else if (CompareToken(pc, "wstr"))
1275c2c66affSColin Finck {
1276c2c66affSColin Finck exp.nStackBytes += 4; // sizeof(void*) on x86
1277c2c66affSColin Finck exp.anArgs[exp.nArgCount] = ARG_WSTR;
1278c2c66affSColin Finck }
1279c2c66affSColin Finck else if (CompareToken(pc, "int64"))
1280c2c66affSColin Finck {
1281c2c66affSColin Finck exp.nStackBytes += 8;
1282c2c66affSColin Finck exp.anArgs[exp.nArgCount] = ARG_INT64;
1283c2c66affSColin Finck }
1284c2c66affSColin Finck else if (CompareToken(pc, "int128"))
1285c2c66affSColin Finck {
1286c2c66affSColin Finck exp.nStackBytes += 16;
1287c2c66affSColin Finck exp.anArgs[exp.nArgCount] = ARG_INT128;
1288c2c66affSColin Finck }
1289c2c66affSColin Finck else if (CompareToken(pc, "float"))
1290c2c66affSColin Finck {
1291c2c66affSColin Finck exp.nStackBytes += 4;
1292c2c66affSColin Finck exp.anArgs[exp.nArgCount] = ARG_FLOAT;
1293c2c66affSColin Finck }
1294c2c66affSColin Finck else
1295c95b5e6fSTimo Kreuzer {
1296c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Unrecognized type");
1297c95b5e6fSTimo Kreuzer }
1298c2c66affSColin Finck
1299c2c66affSColin Finck exp.nArgCount++;
1300c2c66affSColin Finck
1301c2c66affSColin Finck /* Go to next parameter */
1302c2c66affSColin Finck if (!(pc = NextToken(pc)))
1303c2c66affSColin Finck {
1304c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Unexpected end of line");
1305c2c66affSColin Finck }
1306c2c66affSColin Finck }
1307c2c66affSColin Finck
1308c2c66affSColin Finck /* Check syntax */
1309c2c66affSColin Finck if (*pc++ != ')')
1310c2c66affSColin Finck {
1311c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc - 1, 0, "Expected ')'");
1312c2c66affSColin Finck }
1313fa56912dSJérôme Gardou
1314fa56912dSJérôme Gardou /* Go to next token */
1315fa56912dSJérôme Gardou pc = NextToken(pc);
1316c2c66affSColin Finck }
1317c2c66affSColin Finck
1318c2c66affSColin Finck /* Handle special stub cases */
1319c2c66affSColin Finck if (exp.nCallingConvention == CC_STUB)
1320c2c66affSColin Finck {
1321fa56912dSJérôme Gardou /* If we got parameters, assume STDCALL */
1322fa56912dSJérôme Gardou if (exp.nArgCount != 0)
1323fa56912dSJérôme Gardou {
1324fa56912dSJérôme Gardou exp.nCallingConvention = CC_STDCALL;
1325fa56912dSJérôme Gardou exp.uFlags |= FL_STUB;
1326fa56912dSJérôme Gardou }
1327fa56912dSJérôme Gardou
1328c2c66affSColin Finck /* Check for c++ mangled name */
1329fa56912dSJérôme Gardou if (exp.strName.buf[0] == '?')
1330c2c66affSColin Finck {
1331c2c66affSColin Finck //printf("Found c++ mangled name...\n");
1332c2c66affSColin Finck //
1333c2c66affSColin Finck }
1334c2c66affSColin Finck else
1335c2c66affSColin Finck {
1336c2c66affSColin Finck /* Check for stdcall name */
1337fa56912dSJérôme Gardou const char *p = ScanToken(exp.strName.buf, '@');
1338fa56912dSJérôme Gardou if (p && (p - exp.strName.buf < exp.strName.len))
1339c2c66affSColin Finck {
1340c2c66affSColin Finck int i;
1341c2c66affSColin Finck
1342c2c66affSColin Finck /* Truncate the name to before the @ */
1343fa56912dSJérôme Gardou exp.strName.len = (int)(p - exp.strName.buf);
1344c2c66affSColin Finck if (exp.strName.len < 1)
1345c2c66affSColin Finck {
1346c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, p, 1, "Unexpected @");
1347c2c66affSColin Finck }
1348c2c66affSColin Finck exp.nStackBytes = atoi(p + 1);
1349c2c66affSColin Finck exp.nArgCount = exp.nStackBytes / 4;
1350c2c66affSColin Finck exp.nCallingConvention = CC_STDCALL;
1351c2c66affSColin Finck exp.uFlags |= FL_STUB;
1352c2c66affSColin Finck for (i = 0; i < exp.nArgCount; i++)
1353c2c66affSColin Finck exp.anArgs[i] = ARG_LONG;
1354c2c66affSColin Finck }
1355c2c66affSColin Finck }
1356c2c66affSColin Finck }
1357c2c66affSColin Finck
1358fa56912dSJérôme Gardou /* Check optional redirection */
1359c2c66affSColin Finck if (pc)
1360c2c66affSColin Finck {
1361c2c66affSColin Finck exp.strTarget.buf = pc;
1362c2c66affSColin Finck exp.strTarget.len = TokenLength(pc);
1363c2c66affSColin Finck
1364c2c66affSColin Finck /* Check syntax (end of line) */
1365c2c66affSColin Finck if (NextToken(pc))
1366c2c66affSColin Finck {
1367c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, NextToken(pc), 0, "Excess token(s) at end of definition");
1368c2c66affSColin Finck }
1369c2c66affSColin Finck
1370c2c66affSColin Finck /* Don't relay-trace forwarded functions */
1371c2c66affSColin Finck exp.uFlags |= FL_NORELAY;
1372c2c66affSColin Finck }
1373c2c66affSColin Finck else
1374c2c66affSColin Finck {
1375c2c66affSColin Finck exp.strTarget.buf = NULL;
1376c2c66affSColin Finck exp.strTarget.len = 0;
1377c2c66affSColin Finck }
1378c2c66affSColin Finck
1379c2c66affSColin Finck /* Check for no-name without ordinal */
1380c2c66affSColin Finck if ((exp.uFlags & FL_ORDINAL) && (exp.nOrdinal == -1))
1381c2c66affSColin Finck {
1382c95b5e6fSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Ordinal export without ordinal");
1383c2c66affSColin Finck }
1384c2c66affSColin Finck
138560f4493aSTimo Kreuzer /* Check for import symbol without target */
138660f4493aSTimo Kreuzer if ((exp.uFlags & FL_IMPSYM) && (exp.strTarget.buf == NULL))
138760f4493aSTimo Kreuzer {
138860f4493aSTimo Kreuzer Fatal(pszSourceFileName, nLine, pcLine, pc, 1, "Import symbol without target");
138960f4493aSTimo Kreuzer }
139060f4493aSTimo Kreuzer
13912becb000SHermès Bélusca-Maïto /*
13922becb000SHermès Bélusca-Maïto * Check for special handling of OLE exports, only when MSVC
13932becb000SHermès Bélusca-Maïto * is not used, since otherwise this is handled by MS LINK.EXE.
13942becb000SHermès Bélusca-Maïto */
13952becb000SHermès Bélusca-Maïto if (!gbMSComp)
1396c2c66affSColin Finck {
13972becb000SHermès Bélusca-Maïto /* Check whether the current export is not PRIVATE, or has an ordinal */
13982becb000SHermès Bélusca-Maïto int bIsNotPrivate = (!gbNotPrivateNoWarn && /*gbImportLib &&*/ !(exp.uFlags & FL_PRIVATE));
13992becb000SHermès Bélusca-Maïto int bHasOrdinal = (exp.uFlags & FL_ORDINAL);
14002becb000SHermès Bélusca-Maïto
14012becb000SHermès Bélusca-Maïto /* Check whether the current export is an OLE export, in case any of these tests pass */
14022becb000SHermès Bélusca-Maïto if (bIsNotPrivate || bHasOrdinal)
1403c2c66affSColin Finck {
14042becb000SHermès Bélusca-Maïto for (i = 0; i < ARRAYSIZE(astrOlePrivateExports); ++i)
1405c2c66affSColin Finck {
14062becb000SHermès Bélusca-Maïto if (strlen(astrOlePrivateExports[i]) == exp.strName.len &&
14072becb000SHermès Bélusca-Maïto strncmp(exp.strName.buf, astrOlePrivateExports[i], exp.strName.len) == 0)
14082becb000SHermès Bélusca-Maïto {
14092becb000SHermès Bélusca-Maïto /* The current export is an OLE export: display the corresponding warning */
14102becb000SHermès Bélusca-Maïto if (bIsNotPrivate)
14112becb000SHermès Bélusca-Maïto {
1412c95b5e6fSTimo Kreuzer fprintf(stderr, "WARNING: %s line %d: Exported symbol '%.*s' should be PRIVATE\n",
1413c2c66affSColin Finck pszSourceFileName, nLine, exp.strName.len, exp.strName.buf);
1414c2c66affSColin Finck }
14152becb000SHermès Bélusca-Maïto if (bHasOrdinal)
14162becb000SHermès Bélusca-Maïto {
1417c95b5e6fSTimo Kreuzer fprintf(stderr, "WARNING: %s line %d: exported symbol '%.*s' should not be assigned an ordinal\n",
14182becb000SHermès Bélusca-Maïto pszSourceFileName, nLine, exp.strName.len, exp.strName.buf);
14192becb000SHermès Bélusca-Maïto }
14202becb000SHermès Bélusca-Maïto break;
14212becb000SHermès Bélusca-Maïto }
14222becb000SHermès Bélusca-Maïto }
1423c2c66affSColin Finck }
1424c2c66affSColin Finck }
1425c2c66affSColin Finck
1426e8ab2736STimo Kreuzer pexports[*cExports] = exp;
1427e8ab2736STimo Kreuzer (*cExports)++;
1428c2c66affSColin Finck gbDebug = 0;
1429c2c66affSColin Finck }
1430c2c66affSColin Finck
1431e8ab2736STimo Kreuzer return pexports;
1432c2c66affSColin Finck }
1433c2c66affSColin Finck
14346e80f4d0STimo Kreuzer int
ApplyOrdinals(EXPORT * pexports,unsigned cExports)14356e80f4d0STimo Kreuzer ApplyOrdinals(EXPORT* pexports, unsigned cExports)
14366e80f4d0STimo Kreuzer {
14376e80f4d0STimo Kreuzer unsigned short i, j;
14386e80f4d0STimo Kreuzer char* used;
14397dcfda81STimo Kreuzer unsigned short firstOrdinal = 0xFFFF, firstIndex = 0;
14406e80f4d0STimo Kreuzer
14416e80f4d0STimo Kreuzer /* Allocate a table to mark used ordinals */
14426e80f4d0STimo Kreuzer used = malloc(65536);
14436e80f4d0STimo Kreuzer if (used == NULL)
14446e80f4d0STimo Kreuzer {
14456e80f4d0STimo Kreuzer fprintf(stderr, "Failed to allocate memory for ordinal use table\n");
14466e80f4d0STimo Kreuzer return -1;
14476e80f4d0STimo Kreuzer }
14486e80f4d0STimo Kreuzer memset(used, 0, 65536);
14496e80f4d0STimo Kreuzer
14506e80f4d0STimo Kreuzer /* Pass 1: mark the ordinals that are already used */
14516e80f4d0STimo Kreuzer for (i = 0; i < cExports; i++)
14526e80f4d0STimo Kreuzer {
14536e80f4d0STimo Kreuzer if (pexports[i].uFlags & FL_ORDINAL)
14546e80f4d0STimo Kreuzer {
14556e80f4d0STimo Kreuzer if (used[pexports[i].nOrdinal] != 0)
14566e80f4d0STimo Kreuzer {
14576e80f4d0STimo Kreuzer fprintf(stderr, "Found duplicate ordinal: %u\n", pexports[i].nOrdinal);
14586e80f4d0STimo Kreuzer return -1;
14596e80f4d0STimo Kreuzer }
14606e80f4d0STimo Kreuzer used[pexports[i].nOrdinal] = 1;
14617dcfda81STimo Kreuzer if (pexports[i].nOrdinal < firstOrdinal)
14627dcfda81STimo Kreuzer {
14637dcfda81STimo Kreuzer firstOrdinal = pexports[i].nOrdinal;
14647dcfda81STimo Kreuzer firstIndex = i;
14657dcfda81STimo Kreuzer }
14666e80f4d0STimo Kreuzer }
14676e80f4d0STimo Kreuzer }
14686e80f4d0STimo Kreuzer
14697dcfda81STimo Kreuzer /* Check if we found an ordinal and it's larger than it's index */
14707dcfda81STimo Kreuzer if ((firstOrdinal != 0xFFFF) && (firstOrdinal > firstIndex))
14717dcfda81STimo Kreuzer {
14727dcfda81STimo Kreuzer /* We did. Calculate an appropriate starting ordinal. */
14737dcfda81STimo Kreuzer firstOrdinal -= firstIndex;
14747dcfda81STimo Kreuzer }
14757dcfda81STimo Kreuzer else
14767dcfda81STimo Kreuzer {
14777dcfda81STimo Kreuzer /* We didn't, so start with 1 */
14787dcfda81STimo Kreuzer firstOrdinal = 1;
14797dcfda81STimo Kreuzer }
14807dcfda81STimo Kreuzer
14816e80f4d0STimo Kreuzer /* Pass 2: apply available ordinals */
14827dcfda81STimo Kreuzer for (i = 0, j = firstOrdinal; i < cExports; i++)
14836e80f4d0STimo Kreuzer {
1484c1464a40SMark Jansen if ((pexports[i].uFlags & FL_ORDINAL) == 0 && pexports[i].bVersionIncluded)
14856e80f4d0STimo Kreuzer {
14866e80f4d0STimo Kreuzer while (used[j] != 0)
14876e80f4d0STimo Kreuzer j++;
14886e80f4d0STimo Kreuzer
14896e80f4d0STimo Kreuzer pexports[i].nOrdinal = j;
14906e80f4d0STimo Kreuzer used[j] = 1;
14916e80f4d0STimo Kreuzer }
14926e80f4d0STimo Kreuzer }
14936e80f4d0STimo Kreuzer
14946e80f4d0STimo Kreuzer free(used);
14956e80f4d0STimo Kreuzer return 0;
14966e80f4d0STimo Kreuzer }
14976e80f4d0STimo Kreuzer
usage(void)1498c2c66affSColin Finck void usage(void)
1499c2c66affSColin Finck {
1500c2c66affSColin Finck printf("syntax: spec2def [<options> ...] <spec file>\n"
1501c2c66affSColin Finck "Possible options:\n"
1502c2c66affSColin Finck " -h --help print this help screen\n"
1503c2c66affSColin Finck " -l=<file> generate an asm lib stub\n"
1504c2c66affSColin Finck " -d=<file> generate a def file\n"
1505c2c66affSColin Finck " -s=<file> generate a stub file\n"
150660f4493aSTimo Kreuzer " -i=<file> generate an import alias file\n"
1507c2c66affSColin Finck " --ms MSVC compatibility\n"
1508c2c66affSColin Finck " -n=<name> name of the dll\n"
150955e0cab5STimo Kreuzer " --version=<version> Sets the version to create exports for\n"
1510c2c66affSColin Finck " --implib generate a def file for an import library\n"
1511c2c66affSColin Finck " --no-private-warnings suppress warnings about symbols that should be -private\n"
1512be223b9dSJustin Miller " -a=<arch> set architecture to <arch> (i386, x86_64, arm, arm64)\n"
1513c2c66affSColin Finck " --with-tracing generate wine-like \"+relay\" trace trampolines (needs -s)\n");
1514c2c66affSColin Finck }
1515c2c66affSColin Finck
main(int argc,char * argv[])1516c2c66affSColin Finck int main(int argc, char *argv[])
1517c2c66affSColin Finck {
1518c2c66affSColin Finck size_t nFileSize;
1519c2c66affSColin Finck char *pszSource, *pszDefFileName = NULL, *pszStubFileName = NULL, *pszLibStubName = NULL;
152060f4493aSTimo Kreuzer char *pszImpLibAliasFileName = NULL;
1521d564c7c8SMark Jansen const char* pszVersionOption = "--version=0x";
1522c2c66affSColin Finck char achDllName[40];
1523c2c66affSColin Finck FILE *file;
1524e8ab2736STimo Kreuzer unsigned cExports = 0, i;
1525e8ab2736STimo Kreuzer EXPORT *pexports;
1526c2c66affSColin Finck
1527c2c66affSColin Finck if (argc < 2)
1528c2c66affSColin Finck {
1529c2c66affSColin Finck usage();
1530c2c66affSColin Finck return -1;
1531c2c66affSColin Finck }
1532c2c66affSColin Finck
1533c2c66affSColin Finck /* Read options */
1534e8ab2736STimo Kreuzer for (i = 1; i < (unsigned)argc && *argv[i] == '-'; i++)
1535c2c66affSColin Finck {
1536c2c66affSColin Finck if ((strcasecmp(argv[i], "--help") == 0) ||
1537c2c66affSColin Finck (strcasecmp(argv[i], "-h") == 0))
1538c2c66affSColin Finck {
1539c2c66affSColin Finck usage();
1540c2c66affSColin Finck return 0;
1541c2c66affSColin Finck }
1542c2c66affSColin Finck else if (argv[i][1] == 'd' && argv[i][2] == '=')
1543c2c66affSColin Finck {
1544c2c66affSColin Finck pszDefFileName = argv[i] + 3;
1545c2c66affSColin Finck }
1546c2c66affSColin Finck else if (argv[i][1] == 'l' && argv[i][2] == '=')
1547c2c66affSColin Finck {
1548c2c66affSColin Finck pszLibStubName = argv[i] + 3;
1549c2c66affSColin Finck }
1550c2c66affSColin Finck else if (argv[i][1] == 's' && argv[i][2] == '=')
1551c2c66affSColin Finck {
1552c2c66affSColin Finck pszStubFileName = argv[i] + 3;
1553c2c66affSColin Finck }
155460f4493aSTimo Kreuzer else if (argv[i][1] == 'i' && argv[i][2] == '=')
155560f4493aSTimo Kreuzer {
155660f4493aSTimo Kreuzer pszImpLibAliasFileName = argv[i] + 3;
155760f4493aSTimo Kreuzer }
1558c2c66affSColin Finck else if (argv[i][1] == 'n' && argv[i][2] == '=')
1559c2c66affSColin Finck {
1560c2c66affSColin Finck pszDllName = argv[i] + 3;
1561c2c66affSColin Finck }
1562d564c7c8SMark Jansen else if (strncasecmp(argv[i], pszVersionOption, strlen(pszVersionOption)) == 0)
156301df9a41STimo Kreuzer {
1564d564c7c8SMark Jansen guOsVersion = strtoul(argv[i] + strlen(pszVersionOption), NULL, 16);
156501df9a41STimo Kreuzer }
1566c2c66affSColin Finck else if (strcasecmp(argv[i], "--implib") == 0)
1567c2c66affSColin Finck {
1568c2c66affSColin Finck gbImportLib = 1;
1569c2c66affSColin Finck }
1570c2c66affSColin Finck else if (strcasecmp(argv[i], "--ms") == 0)
1571c2c66affSColin Finck {
1572c2c66affSColin Finck gbMSComp = 1;
1573c2c66affSColin Finck }
1574c2c66affSColin Finck else if (strcasecmp(argv[i], "--no-private-warnings") == 0)
1575c2c66affSColin Finck {
1576c2c66affSColin Finck gbNotPrivateNoWarn = 1;
1577c2c66affSColin Finck }
1578c2c66affSColin Finck else if (strcasecmp(argv[i], "--with-tracing") == 0)
1579c2c66affSColin Finck {
1580c2c66affSColin Finck if (!pszStubFileName)
1581c2c66affSColin Finck {
1582c2c66affSColin Finck fprintf(stderr, "Error: cannot use --with-tracing without -s option.\n");
1583c2c66affSColin Finck return -1;
1584c2c66affSColin Finck }
1585c2c66affSColin Finck gbTracing = 1;
1586c2c66affSColin Finck }
1587c2c66affSColin Finck else if (argv[i][1] == 'a' && argv[i][2] == '=')
1588c2c66affSColin Finck {
1589c2c66affSColin Finck pszArchString = argv[i] + 3;
1590c2c66affSColin Finck }
1591c2c66affSColin Finck else
1592c2c66affSColin Finck {
1593c2c66affSColin Finck fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
1594c2c66affSColin Finck return -1;
1595c2c66affSColin Finck }
1596c2c66affSColin Finck }
1597c2c66affSColin Finck
1598c2c66affSColin Finck if (strcasecmp(pszArchString, "i386") == 0)
1599c2c66affSColin Finck {
1600c2c66affSColin Finck giArch = ARCH_X86;
1601c2c66affSColin Finck gpszUnderscore = "_";
1602c2c66affSColin Finck }
1603c2c66affSColin Finck else if (strcasecmp(pszArchString, "x86_64") == 0) giArch = ARCH_AMD64;
1604c2c66affSColin Finck else if (strcasecmp(pszArchString, "ia64") == 0) giArch = ARCH_IA64;
1605c2c66affSColin Finck else if (strcasecmp(pszArchString, "arm") == 0) giArch = ARCH_ARM;
1606be223b9dSJustin Miller else if (strcasecmp(pszArchString, "arm64") == 0) giArch = ARCH_ARM64;
1607c2c66affSColin Finck else if (strcasecmp(pszArchString, "ppc") == 0) giArch = ARCH_PPC;
1608c2c66affSColin Finck
1609c2c66affSColin Finck if ((giArch == ARCH_AMD64) || (giArch == ARCH_IA64))
1610c2c66affSColin Finck {
1611c2c66affSColin Finck pszArchString2 = "win64";
1612c2c66affSColin Finck }
1613c2c66affSColin Finck else
1614c2c66affSColin Finck pszArchString2 = "win32";
1615c2c66affSColin Finck
1616c2c66affSColin Finck /* Set a default dll name */
1617c2c66affSColin Finck if (!pszDllName)
1618c2c66affSColin Finck {
1619c2c66affSColin Finck char *p1, *p2;
1620c2c66affSColin Finck size_t len;
1621c2c66affSColin Finck
1622c2c66affSColin Finck p1 = strrchr(argv[i], '\\');
1623c2c66affSColin Finck if (!p1) p1 = strrchr(argv[i], '/');
1624c2c66affSColin Finck p2 = p1 = p1 ? p1 + 1 : argv[i];
1625c2c66affSColin Finck
1626c2c66affSColin Finck /* walk up to '.' */
1627c2c66affSColin Finck while (*p2 != '.' && *p2 != 0) p2++;
1628c2c66affSColin Finck len = p2 - p1;
1629c2c66affSColin Finck if (len >= sizeof(achDllName) - 5)
1630c2c66affSColin Finck {
1631c2c66affSColin Finck fprintf(stderr, "name too long: %s\n", p1);
1632c2c66affSColin Finck return -2;
1633c2c66affSColin Finck }
1634c2c66affSColin Finck
1635c2c66affSColin Finck strncpy(achDllName, p1, len);
1636c2c66affSColin Finck strncpy(achDllName + len, ".dll", sizeof(achDllName) - len);
1637c2c66affSColin Finck pszDllName = achDllName;
1638c2c66affSColin Finck }
1639c2c66affSColin Finck
1640c2c66affSColin Finck /* Open input file */
1641c2c66affSColin Finck pszSourceFileName = argv[i];
1642c2c66affSColin Finck file = fopen(pszSourceFileName, "r");
1643c2c66affSColin Finck if (!file)
1644c2c66affSColin Finck {
1645c2c66affSColin Finck fprintf(stderr, "error: could not open file %s\n", pszSourceFileName);
1646c2c66affSColin Finck return -3;
1647c2c66affSColin Finck }
1648c2c66affSColin Finck
1649c2c66affSColin Finck /* Get file size */
1650c2c66affSColin Finck fseek(file, 0, SEEK_END);
1651c2c66affSColin Finck nFileSize = ftell(file);
1652c2c66affSColin Finck rewind(file);
1653c2c66affSColin Finck
1654c2c66affSColin Finck /* Allocate memory buffer */
1655c2c66affSColin Finck pszSource = malloc(nFileSize + 1);
1656c2c66affSColin Finck if (!pszSource)
1657c2c66affSColin Finck {
1658c2c66affSColin Finck fclose(file);
1659c2c66affSColin Finck return -4;
1660c2c66affSColin Finck }
1661c2c66affSColin Finck
1662c2c66affSColin Finck /* Load input file into memory */
1663c2c66affSColin Finck nFileSize = fread(pszSource, 1, nFileSize, file);
1664c2c66affSColin Finck fclose(file);
1665c2c66affSColin Finck
1666c2c66affSColin Finck /* Zero terminate the source */
1667c2c66affSColin Finck pszSource[nFileSize] = '\0';
1668c2c66affSColin Finck
1669e8ab2736STimo Kreuzer pexports = ParseFile(pszSource, file, &cExports);
1670e8ab2736STimo Kreuzer if (pexports == NULL)
1671e8ab2736STimo Kreuzer {
16726e80f4d0STimo Kreuzer fprintf(stderr, "error: could not parse file!\n");
1673e8ab2736STimo Kreuzer return -1;
1674e8ab2736STimo Kreuzer }
1675e8ab2736STimo Kreuzer
16766e80f4d0STimo Kreuzer if (ApplyOrdinals(pexports, cExports) < 0)
16776e80f4d0STimo Kreuzer {
16786e80f4d0STimo Kreuzer fprintf(stderr, "error: could not apply ordinals!\n");
16796e80f4d0STimo Kreuzer return -1;
16806e80f4d0STimo Kreuzer }
16816e80f4d0STimo Kreuzer
1682c2c66affSColin Finck if (pszDefFileName)
1683c2c66affSColin Finck {
1684c2c66affSColin Finck /* Open output file */
1685c2c66affSColin Finck file = fopen(pszDefFileName, "w");
1686c2c66affSColin Finck if (!file)
1687c2c66affSColin Finck {
168860f4493aSTimo Kreuzer fprintf(stderr, "error: could not open output file %s\n", pszDefFileName);
1689c2c66affSColin Finck return -5;
1690c2c66affSColin Finck }
1691c2c66affSColin Finck
1692c2c66affSColin Finck OutputHeader_def(file, pszDllName);
1693e8ab2736STimo Kreuzer
1694e8ab2736STimo Kreuzer for (i = 0; i < cExports; i++)
1695e8ab2736STimo Kreuzer {
1696e8ab2736STimo Kreuzer if (pexports[i].bVersionIncluded)
1697e8ab2736STimo Kreuzer OutputLine_def(file, &pexports[i]);
1698e8ab2736STimo Kreuzer }
1699e8ab2736STimo Kreuzer
1700c2c66affSColin Finck fclose(file);
1701c2c66affSColin Finck }
1702c2c66affSColin Finck
1703c2c66affSColin Finck if (pszStubFileName)
1704c2c66affSColin Finck {
1705c2c66affSColin Finck /* Open output file */
1706c2c66affSColin Finck file = fopen(pszStubFileName, "w");
1707c2c66affSColin Finck if (!file)
1708c2c66affSColin Finck {
170960f4493aSTimo Kreuzer fprintf(stderr, "error: could not open output file %s\n", pszStubFileName);
1710c2c66affSColin Finck return -5;
1711c2c66affSColin Finck }
1712c2c66affSColin Finck
1713c2c66affSColin Finck OutputHeader_stub(file);
1714e8ab2736STimo Kreuzer
1715e8ab2736STimo Kreuzer for (i = 0; i < cExports; i++)
1716e8ab2736STimo Kreuzer {
1717e8ab2736STimo Kreuzer if (pexports[i].bVersionIncluded)
1718e8ab2736STimo Kreuzer OutputLine_stub(file, &pexports[i]);
1719e8ab2736STimo Kreuzer }
1720e8ab2736STimo Kreuzer
1721c2c66affSColin Finck fclose(file);
1722c2c66affSColin Finck }
1723c2c66affSColin Finck
1724c2c66affSColin Finck if (pszLibStubName)
1725c2c66affSColin Finck {
1726c2c66affSColin Finck /* Open output file */
1727c2c66affSColin Finck file = fopen(pszLibStubName, "w");
1728c2c66affSColin Finck if (!file)
1729c2c66affSColin Finck {
173060f4493aSTimo Kreuzer fprintf(stderr, "error: could not open output file %s\n", pszLibStubName);
1731c2c66affSColin Finck return -5;
1732c2c66affSColin Finck }
1733c2c66affSColin Finck
1734c2c66affSColin Finck OutputHeader_asmstub(file, pszDllName);
1735e8ab2736STimo Kreuzer
1736e8ab2736STimo Kreuzer for (i = 0; i < cExports; i++)
1737e8ab2736STimo Kreuzer {
1738e8ab2736STimo Kreuzer if (pexports[i].bVersionIncluded)
1739e8ab2736STimo Kreuzer OutputLine_asmstub(file, &pexports[i]);
1740e8ab2736STimo Kreuzer }
1741e8ab2736STimo Kreuzer
1742c2c66affSColin Finck fprintf(file, "\n END\n");
1743c2c66affSColin Finck fclose(file);
1744c2c66affSColin Finck }
1745c2c66affSColin Finck
174660f4493aSTimo Kreuzer if (pszImpLibAliasFileName)
174760f4493aSTimo Kreuzer {
174860f4493aSTimo Kreuzer /* Open output file */
174960f4493aSTimo Kreuzer file = fopen(pszImpLibAliasFileName, "w");
175060f4493aSTimo Kreuzer if (!file)
175160f4493aSTimo Kreuzer {
175260f4493aSTimo Kreuzer fprintf(stderr, "error: could not open output file %s\n", pszImpLibAliasFileName);
175360f4493aSTimo Kreuzer return -5;
175460f4493aSTimo Kreuzer }
175560f4493aSTimo Kreuzer
175660f4493aSTimo Kreuzer OutputHeader_asmstub(file, pszDllName);
175760f4493aSTimo Kreuzer
175860f4493aSTimo Kreuzer for (i = 0; i < cExports; i++)
175960f4493aSTimo Kreuzer {
176060f4493aSTimo Kreuzer if (pexports[i].bVersionIncluded)
176160f4493aSTimo Kreuzer OutputLine_implib_asm(file, &pexports[i]);
176260f4493aSTimo Kreuzer }
176360f4493aSTimo Kreuzer
176460f4493aSTimo Kreuzer fprintf(file, "\n END\n");
176560f4493aSTimo Kreuzer fclose(file);
176660f4493aSTimo Kreuzer }
176760f4493aSTimo Kreuzer
1768e8ab2736STimo Kreuzer free(pexports);
1769e8ab2736STimo Kreuzer
1770e8ab2736STimo Kreuzer return 0;
1771c2c66affSColin Finck }
1772