7 #define strcasecmp _stricmp
10 typedef struct _STRING
20 int nCallingConvention
;
38 typedef int (*PFNOUTLINE
)(FILE *, EXPORT
*);
41 int giArch
= ARCH_X86
;
42 char *pszArchString
= "i386";
45 char *gpszUnderscore
= "";
47 #define DbgPrint(...) (!gbDebug || fprintf(stderr, __VA_ARGS__))
80 char* astrCallingConventions
[] =
93 return ((chr
<= ',' && chr
!= '$') ||
94 (chr
>= ':' && chr
< '?') );
98 CompareToken(const char *token
, const char *comparand
)
102 if (*token
!= *comparand
) return 0;
106 if (!IsSeparator(*token
)) return 0;
111 ScanToken(const char *token
, char chr
)
113 while (!IsSeparator(*token
))
115 if (*token
== chr
) return token
;
126 if (pc
[0] == '\n' && pc
[1] == '\r') return pc
+ 2;
127 else if (pc
[0] == '\n') return pc
+ 1;
134 TokenLength(char *pc
)
138 while (!IsSeparator(*pc
++)) length
++;
147 while (!IsSeparator(*pc
)) pc
++;
149 /* Skip white spaces */
150 while (*pc
== ' ' || *pc
== '\t') pc
++;
152 /* Check for end of line */
153 if (*pc
== '\n' || *pc
== '\r' || *pc
== 0) return 0;
155 /* Check for comment */
156 if (*pc
== '#' || *pc
== ';') return 0;
162 OutputHeader_stub(FILE *file
)
164 fprintf(file
, "/* This file is autogenerated, do not edit. */\n\n"
165 "#include <stubs.h>\n\n");
169 OutputLine_stub(FILE *file
, EXPORT
*pexp
)
173 if (pexp
->nCallingConvention
!= CC_STUB
&&
174 (pexp
->uFlags
& FL_STUB
) == 0) return 0;
176 fprintf(file
, "int ");
177 if ((giArch
== ARCH_X86
) &&
178 pexp
->nCallingConvention
== CC_STDCALL
)
180 fprintf(file
, "__stdcall ");
184 if (pexp
->strName
.buf
[0] == '?')
186 fprintf(file
, "stub_function%d(", pexp
->nNumber
);
190 fprintf(file
, "%.*s(", pexp
->strName
.len
, pexp
->strName
.buf
);
193 for (i
= 0; i
< pexp
->nArgCount
; i
++)
195 if (i
!= 0) fprintf(file
, ", ");
196 switch (pexp
->anArgs
[i
])
198 case ARG_LONG
: fprintf(file
, "long"); break;
199 case ARG_PTR
: fprintf(file
, "void*"); break;
200 case ARG_STR
: fprintf(file
, "char*"); break;
201 case ARG_WSTR
: fprintf(file
, "wchar_t*"); break;
203 case ARG_INT64
: fprintf(file
, "__int64"); break;
204 case ARG_INT128
: fprintf(file
, "__int128"); break;
205 case ARG_FLOAT
: fprintf(file
, "float"); break;
207 fprintf(file
, " a%d", i
);
209 fprintf(file
, ")\n{\n\tDbgPrint(\"WARNING: calling stub %.*s(",
210 pexp
->strName
.len
, pexp
->strName
.buf
);
212 for (i
= 0; i
< pexp
->nArgCount
; i
++)
214 if (i
!= 0) fprintf(file
, ",");
215 switch (pexp
->anArgs
[i
])
217 case ARG_LONG
: fprintf(file
, "0x%%lx"); break;
218 case ARG_PTR
: fprintf(file
, "0x%%p"); break;
219 case ARG_STR
: fprintf(file
, "'%%s'"); break;
220 case ARG_WSTR
: fprintf(file
, "'%%ws'"); break;
221 case ARG_DBL
: fprintf(file
, "%%f"); break;
222 case ARG_INT64
: fprintf(file
, "%%\"PRix64\""); break;
223 case ARG_INT128
: fprintf(file
, "%%\"PRix128\""); break;
224 case ARG_FLOAT
: fprintf(file
, "%%f"); break;
227 fprintf(file
, ")\\n\"");
229 for (i
= 0; i
< pexp
->nArgCount
; i
++)
232 switch (pexp
->anArgs
[i
])
234 case ARG_LONG
: fprintf(file
, "(long)a%d", i
); break;
235 case ARG_PTR
: fprintf(file
, "(void*)a%d", i
); break;
236 case ARG_STR
: fprintf(file
, "(char*)a%d", i
); break;
237 case ARG_WSTR
: fprintf(file
, "(wchar_t*)a%d", i
); break;
238 case ARG_DBL
: fprintf(file
, "(double)a%d", i
); break;
239 case ARG_INT64
: fprintf(file
, "(__int64)a%d", i
); break;
240 case ARG_INT128
: fprintf(file
, "(__int128)a%d", i
); break;
241 case ARG_FLOAT
: fprintf(file
, "(float)a%d", i
); break;
244 fprintf(file
, ");\n");
246 if (pexp
->nCallingConvention
== CC_STUB
)
248 fprintf(file
, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName
);
251 fprintf(file
, "\treturn 0;\n}\n\n");
257 OutputHeader_asmstub(FILE *file
, char *libname
)
259 fprintf(file
, "; File generated automatically, do not edit! \n\n");
261 if (giArch
== ARCH_X86
)
262 fprintf(file
, ".586\n.model flat\n");
264 fprintf(file
, ".code\n");
268 OutputLine_asmstub(FILE *fileDest
, EXPORT
*pexp
)
270 /* Handle autoname */
271 if (pexp
->strName
.len
== 1 && pexp
->strName
.buf
[0] == '@')
273 fprintf(fileDest
, "PUBLIC %sordinal%d\n%sordinal%d: nop\n",
274 gpszUnderscore
, pexp
->nOrdinal
, gpszUnderscore
, pexp
->nOrdinal
);
276 else if (giArch
!= ARCH_X86
)
278 fprintf(fileDest
, "PUBLIC _stub_%.*s\n_stub_%.*s: nop\n",
279 pexp
->strName
.len
, pexp
->strName
.buf
,
280 pexp
->strName
.len
, pexp
->strName
.buf
);
282 else if (pexp
->nCallingConvention
== CC_STDCALL
)
284 fprintf(fileDest
, "PUBLIC __stub_%.*s@%d\n__stub_%.*s@%d: nop\n",
285 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
,
286 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
);
288 else if (pexp
->nCallingConvention
== CC_FASTCALL
)
290 fprintf(fileDest
, "PUBLIC @_stub_%.*s@%d\n@_stub_%.*s@%d: nop\n",
291 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
,
292 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
);
294 else if (pexp
->nCallingConvention
== CC_CDECL
||
295 pexp
->nCallingConvention
== CC_STUB
)
297 fprintf(fileDest
, "PUBLIC __stub_%.*s\n__stub_%.*s: nop\n",
298 pexp
->strName
.len
, pexp
->strName
.buf
,
299 pexp
->strName
.len
, pexp
->strName
.buf
);
301 else if (pexp
->nCallingConvention
== CC_EXTERN
)
303 fprintf(fileDest
, "PUBLIC __stub_%.*s\n__stub_%.*s:\n",
304 pexp
->strName
.len
, pexp
->strName
.buf
,
305 pexp
->strName
.len
, pexp
->strName
.buf
);
312 OutputHeader_def(FILE *file
, char *libname
)
315 "; File generated automatically, do not edit!\n\n"
322 PrintName(FILE *fileDest
, EXPORT
*pexp
, PSTRING pstr
, int fDeco
)
324 const char *pcName
= pstr
->buf
;
325 int nNameLength
= pstr
->len
;
326 const char* pcDot
, *pcAt
;
328 if ((giArch
== ARCH_X86
) && fDeco
&&
329 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
330 (pexp
->nCallingConvention
== CC_FASTCALL
)))
332 /* Scan for a dll forwarding dot */
333 pcDot
= ScanToken(pcName
, '.');
336 /* First print the dll name, followed by a dot */
337 nNameLength
= pcDot
- pcName
;
338 fprintf(fileDest
, "%.*s.", nNameLength
, pcName
);
340 /* Now the actual function name */
342 nNameLength
= pexp
->strTarget
.len
- nNameLength
- 1;
345 /* Does the string already have decoration? */
346 pcAt
= ScanToken(pcName
, '@');
347 if (pcAt
&& (pcAt
< (pcName
+ nNameLength
)))
349 /* On GCC, we need to remove the leading stdcall underscore */
350 if (!gbMSComp
&& (pexp
->nCallingConvention
== CC_STDCALL
))
356 /* Print the already decorated function name */
357 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
361 /* Print the prefix, but skip it for (GCC && stdcall) */
362 if (gbMSComp
|| (pexp
->nCallingConvention
!= CC_STDCALL
))
364 fprintf(fileDest
, "%c", pexp
->nCallingConvention
== CC_FASTCALL
? '@' : '_');
367 /* Print the name with trailing decoration */
368 fprintf(fileDest
, "%.*s@%d", nNameLength
, pcName
, pexp
->nStackBytes
);
373 /* Does the string already have stdcall decoration? */
374 pcAt
= ScanToken(pcName
, '@');
375 if (pcAt
&& (pcAt
< (pcName
+ nNameLength
)) && pcName
[0] == '_')
377 /* Skip leading underscore and remove trailing decoration */
379 nNameLength
= pcAt
- pcName
;
382 /* Print the undecorated function name */
383 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
388 OutputLine_def_MS(FILE *fileDest
, EXPORT
*pexp
)
390 PrintName(fileDest
, pexp
, &pexp
->strName
, 0);
394 /* Redirect to a stub function, to get the right decoration in the lib */
395 fprintf(fileDest
, "=_stub_%.*s", pexp
->strName
.len
, pexp
->strName
.buf
);
397 else if (pexp
->strTarget
.buf
)
399 if (pexp
->strName
.buf
[0] == '?')
401 fprintf(stderr
, "warning: ignoring C++ redirection %.*s -> %.*s\n",
402 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
406 fprintf(fileDest
, "=");
408 /* If the original name was decorated, use decoration in the forwarder as well */
409 if ((giArch
== ARCH_X86
) && ScanToken(pexp
->strName
.buf
, '@') &&
410 !ScanToken(pexp
->strTarget
.buf
, '@') &&
411 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
412 (pexp
->nCallingConvention
== CC_FASTCALL
)) )
414 PrintName(fileDest
, pexp
, &pexp
->strTarget
, 1);
418 /* Write the undecorated redirection name */
419 fprintf(fileDest
, "%.*s", pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
423 else if (((pexp
->uFlags
& FL_STUB
) || (pexp
->nCallingConvention
== CC_STUB
)) &&
424 (pexp
->strName
.buf
[0] == '?'))
426 /* C++ stubs are forwarded to C stubs */
427 fprintf(fileDest
, "=stub_function%d", pexp
->nNumber
);
432 OutputLine_def_GCC(FILE *fileDest
, EXPORT
*pexp
)
434 /* Print the function name, with decoration for export libs */
435 PrintName(fileDest
, pexp
, &pexp
->strName
, gbImportLib
);
436 DbgPrint("Generating def line for '%.*s'\n", pexp
->strName
.len
, pexp
->strName
.buf
);
438 /* Check if this is a forwarded export */
439 if (pexp
->strTarget
.buf
)
441 int fIsExternal
= !!ScanToken(pexp
->strTarget
.buf
, '.');
442 DbgPrint("Got redirect '%.*s'\n", pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
444 /* print the target name, don't decorate if it is external */
445 fprintf(fileDest
, "=");
446 PrintName(fileDest
, pexp
, &pexp
->strTarget
, !fIsExternal
);
448 else if (((pexp
->uFlags
& FL_STUB
) || (pexp
->nCallingConvention
== CC_STUB
)) &&
449 (pexp
->strName
.buf
[0] == '?'))
451 /* C++ stubs are forwarded to C stubs */
452 fprintf(fileDest
, "=stub_function%d", pexp
->nNumber
);
455 /* Special handling for stdcall and fastcall */
456 if ((giArch
== ARCH_X86
) &&
457 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
458 (pexp
->nCallingConvention
== CC_FASTCALL
)))
460 /* Is this the import lib? */
463 /* Is the name in the spec file decorated? */
464 const char* pcDeco
= ScanToken(pexp
->strName
.buf
, '@');
465 if (pcDeco
&& (pcDeco
< pexp
->strName
.buf
+ pexp
->strName
.len
))
467 /* Write the name including the leading @ */
468 fprintf(fileDest
, "==%.*s", pexp
->strName
.len
, pexp
->strName
.buf
);
471 else if (!pexp
->strTarget
.buf
)
473 /* Write a forwarder to the actual decorated symbol */
474 fprintf(fileDest
, "=");
475 PrintName(fileDest
, pexp
, &pexp
->strName
, 1);
481 OutputLine_def(FILE *fileDest
, EXPORT
*pexp
)
483 fprintf(fileDest
, " ");
486 OutputLine_def_MS(fileDest
, pexp
);
488 OutputLine_def_GCC(fileDest
, pexp
);
490 if (pexp
->uFlags
& FL_ORDINAL
)
492 fprintf(fileDest
, " @%d", pexp
->nOrdinal
);
495 if (pexp
->uFlags
& FL_NONAME
)
497 fprintf(fileDest
, " NONAME");
500 if (pexp
->uFlags
& FL_PRIVATE
)
502 fprintf(fileDest
, " PRIVATE");
505 /* Make this a data export, unless this is MSVC and -withalias was given */
506 if ((pexp
->nCallingConvention
== CC_EXTERN
) &&
507 !(gbMSComp
&& (pexp
->uFlags
& FL_DATA_ALIAS
)))
509 fprintf(fileDest
, " DATA");
512 fprintf(fileDest
, "\n");
518 ParseFile(char* pcStart
, FILE *fileDest
, PFNOUTLINE OutputLine
)
526 //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);
531 for (pcLine
= pcStart
; *pcLine
; pcLine
= NextLine(pcLine
), nLine
++)
540 //if (!strncmp(pcLine, "22 stdcall @(long) MPR_Alloc",28))
543 //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
544 // nLine, TokenLength(pcLine), pcLine);
546 /* Skip white spaces */
547 while (*pc
== ' ' || *pc
== '\t') pc
++;
549 /* Skip empty lines, stop at EOF */
550 if (*pc
== ';' || *pc
<= '#') continue;
551 if (*pc
== 0) return 0;
553 //fprintf(stderr, "info: line %d, token:'%.*s'\n",
554 // nLine, TokenLength(pc), pc);
556 /* Now we should get either an ordinal or @ */
561 exp
.nOrdinal
= atol(pc
);
562 exp
.uFlags
|= FL_ORDINAL
;
565 /* Go to next token (type) */
566 if (!(pc
= NextToken(pc
)))
568 fprintf(stderr
, "error: line %d, unexpected end of line\n", nLine
);
572 //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc), pc);
574 /* Now we should get the type */
575 if (CompareToken(pc
, "stdcall"))
577 exp
.nCallingConvention
= CC_STDCALL
;
579 else if (CompareToken(pc
, "cdecl") ||
580 CompareToken(pc
, "varargs"))
582 exp
.nCallingConvention
= CC_CDECL
;
584 else if (CompareToken(pc
, "fastcall"))
586 exp
.nCallingConvention
= CC_FASTCALL
;
588 else if (CompareToken(pc
, "thiscall"))
590 exp
.nCallingConvention
= CC_THISCALL
;
592 else if (CompareToken(pc
, "extern"))
594 exp
.nCallingConvention
= CC_EXTERN
;
596 else if (CompareToken(pc
, "stub"))
598 exp
.nCallingConvention
= CC_STUB
;
602 fprintf(stderr
, "error: line %d, expected callconv, got '%.*s' %d\n",
603 nLine
, TokenLength(pc
), pc
, *pc
);
607 //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention);
609 /* Go to next token (options or name) */
610 if (!(pc
= NextToken(pc
)))
612 fprintf(stderr
, "fail2\n");
620 if (CompareToken(pc
, "-arch"))
622 /* Default to not included */
626 /* Look if we are included */
627 while (*pc
== '=' || *pc
== ',')
630 if (CompareToken(pc
, pszArchString
) ||
631 CompareToken(pc
, pszArchString2
))
636 /* Skip to next arch or end */
637 while (*pc
> ',') pc
++;
640 else if (CompareToken(pc
, "-i386"))
642 if (giArch
!= ARCH_X86
) included
= 0;
644 else if (CompareToken(pc
, "-private"))
646 exp
.uFlags
|= FL_PRIVATE
;
648 else if (CompareToken(pc
, "-noname"))
650 exp
.uFlags
|= FL_ORDINAL
| FL_NONAME
;
652 else if (CompareToken(pc
, "-ordinal"))
654 exp
.uFlags
|= FL_ORDINAL
;
656 else if (CompareToken(pc
, "-stub"))
658 exp
.uFlags
|= FL_STUB
;
660 else if (CompareToken(pc
, "-withalias"))
662 /* This flag is to create a nin _imp_ prefixed alias for a
663 data export, so that the hacked DDK declarations work */
664 if (exp
.nCallingConvention
!= CC_EXTERN
)
665 fprintf(stderr
, "error: line %d -withalias on non-data export\n", nLine
);
667 exp
.uFlags
|= FL_DATA_ALIAS
;
669 else if (CompareToken(pc
, "-norelay") ||
670 CompareToken(pc
, "-register") ||
671 CompareToken(pc
, "-ret64"))
673 /* silently ignore these */
677 fprintf(stderr
, "info: ignored option: '%.*s'\n",
678 TokenLength(pc
), pc
);
681 /* Go to next token */
685 //fprintf(stderr, "info: Name:'%.10s'\n", pc);
687 /* If arch didn't match ours, skip this entry */
688 if (!included
) continue;
691 exp
.strName
.buf
= pc
;
692 exp
.strName
.len
= TokenLength(pc
);
694 /* Check for autoname */
695 if ((exp
.strName
.len
== 1) && (exp
.strName
.buf
[0] == '@'))
697 sprintf(namebuffer
, "ordinal%d", exp
.nOrdinal
);
698 exp
.strName
.len
= strlen(namebuffer
);
699 exp
.strName
.buf
= namebuffer
;
700 exp
.uFlags
|= FL_ORDINAL
| FL_NONAME
;
703 /* Handle parameters */
705 if (exp
.nCallingConvention
!= CC_EXTERN
&&
706 exp
.nCallingConvention
!= CC_STUB
)
708 //fprintf(stderr, "info: options:'%.10s'\n", pc);
709 /* Go to next token */
710 if (!(pc
= NextToken(pc
)))
712 fprintf(stderr
, "fail4\n");
719 fprintf(stderr
, "error: line %d, expected '('\n", nLine
);
723 /* Skip whitespaces */
724 while (*pc
== ' ' || *pc
== '\t') pc
++;
729 if (CompareToken(pc
, "long"))
731 exp
.nStackBytes
+= 4;
732 exp
.anArgs
[exp
.nArgCount
] = ARG_LONG
;
734 else if (CompareToken(pc
, "double"))
736 exp
.nStackBytes
+= 8;
737 exp
.anArgs
[exp
.nArgCount
] = ARG_DBL
;
739 else if (CompareToken(pc
, "ptr") ||
740 CompareToken(pc
, "str") ||
741 CompareToken(pc
, "wstr"))
743 exp
.nStackBytes
+= 4; // sizeof(void*) on x86
744 exp
.anArgs
[exp
.nArgCount
] = ARG_PTR
; // FIXME: handle strings
746 else if (CompareToken(pc
, "int64"))
748 exp
.nStackBytes
+= 8;
749 exp
.anArgs
[exp
.nArgCount
] = ARG_INT64
;
751 else if (CompareToken(pc
, "int128"))
753 exp
.nStackBytes
+= 16;
754 exp
.anArgs
[exp
.nArgCount
] = ARG_INT128
;
756 else if (CompareToken(pc
, "float"))
758 exp
.nStackBytes
+= 4;
759 exp
.anArgs
[exp
.nArgCount
] = ARG_FLOAT
;
762 fprintf(stderr
, "error: line %d, expected type, got: %.10s\n", nLine
, pc
);
766 /* Go to next parameter */
767 if (!(pc
= NextToken(pc
)))
769 fprintf(stderr
, "fail5\n");
777 fprintf(stderr
, "error: line %d, expected ')'\n", nLine
);
782 /* Handle special stub cases */
783 if (exp
.nCallingConvention
== CC_STUB
)
785 /* Check for c++ mangled name */
788 //printf("Found c++ mangled name...\n");
793 /* Check for stdcall name */
794 const char *p
= ScanToken(pc
, '@');
795 if (p
&& (p
- pc
< exp
.strName
.len
))
799 /* Truncate the name to before the @ */
800 exp
.strName
.len
= (int)(p
- pc
);
801 if (exp
.strName
.len
< 1)
803 fprintf(stderr
, "error, @ in line %d\n", nLine
);
806 exp
.nStackBytes
= atoi(p
+ 1);
807 exp
.nArgCount
= exp
.nStackBytes
/ 4;
808 exp
.nCallingConvention
= CC_STDCALL
;
809 exp
.uFlags
|= FL_STUB
;
810 for (i
= 0; i
< exp
.nArgCount
; i
++)
811 exp
.anArgs
[i
] = ARG_LONG
;
816 /* Get optional redirection */
820 exp
.strTarget
.buf
= pc
;
821 exp
.strTarget
.len
= TokenLength(pc
);
823 /* Check syntax (end of line) */
826 fprintf(stderr
, "error: line %d, additional tokens after ')'\n", nLine
);
832 exp
.strTarget
.buf
= 0;
833 exp
.strTarget
.len
= 0;
836 /* Check for no-name without ordinal */
837 if ((exp
.uFlags
& FL_ORDINAL
) && (exp
.nOrdinal
== -1))
839 fprintf(stderr
, "error: line %d, ordinal export without ordinal!\n", nLine
);
843 OutputLine(fileDest
, &exp
);
853 printf("syntax: spec2pdef [<options> ...] <spec file>\n"
854 "Possible options:\n"
855 " -h --help prints this screen\n"
856 " -l=<file> generates an asm lib stub\n"
857 " -d=<file> generates a def file\n"
858 " -s=<file> generates a stub file\n"
859 " --ms msvc compatibility\n"
860 " -n=<name> name of the dll\n"
861 " --implib generate a def file for an import library\n"
862 " -a=<arch> Set architecture to <arch>. (i386, x86_64, arm)\n");
865 int main(int argc
, char *argv
[])
868 char *pszSource
, *pszDefFileName
= 0, *pszStubFileName
= 0, *pszLibStubName
= 0;
880 for (i
= 1; i
< argc
&& *argv
[i
] == '-'; i
++)
882 if ((strcasecmp(argv
[i
], "--help") == 0) ||
883 (strcasecmp(argv
[i
], "-h") == 0))
888 else if (argv
[i
][1] == 'd' && argv
[i
][2] == '=')
890 pszDefFileName
= argv
[i
] + 3;
892 else if (argv
[i
][1] == 'l' && argv
[i
][2] == '=')
894 pszLibStubName
= argv
[i
] + 3;
896 else if (argv
[i
][1] == 's' && argv
[i
][2] == '=')
898 pszStubFileName
= argv
[i
] + 3;
900 else if (argv
[i
][1] == 'n' && argv
[i
][2] == '=')
902 pszDllName
= argv
[i
] + 3;
904 else if ((strcasecmp(argv
[i
], "--implib") == 0))
908 else if ((strcasecmp(argv
[i
], "--ms") == 0))
912 else if (argv
[i
][1] == 'a' && argv
[i
][2] == '=')
914 pszArchString
= argv
[i
] + 3;
918 fprintf(stderr
, "Unrecognized option: %s\n", argv
[i
]);
923 if (strcasecmp(pszArchString
, "i386") == 0)
926 gpszUnderscore
= "_";
928 else if (strcasecmp(pszArchString
, "x86_64") == 0) giArch
= ARCH_AMD64
;
929 else if (strcasecmp(pszArchString
, "ia64") == 0) giArch
= ARCH_IA64
;
930 else if (strcasecmp(pszArchString
, "arm") == 0) giArch
= ARCH_ARM
;
931 else if (strcasecmp(pszArchString
, "ppc") == 0) giArch
= ARCH_PPC
;
933 if ((giArch
== ARCH_AMD64
) || (giArch
== ARCH_IA64
))
935 pszArchString2
= "win64";
938 pszArchString2
= "win32";
940 /* Set a default dll name */
946 p1
= strrchr(argv
[i
], '\\');
947 if (!p1
) p1
= strrchr(argv
[i
], '/');
948 p2
= p1
= p1
? p1
+ 1 : argv
[i
];
951 while (*p2
!= '.' && *p2
!= 0) p2
++;
953 if (len
>= sizeof(achDllName
) - 5)
955 fprintf(stderr
, "name too long: %s\n", p1
);
959 strncpy(achDllName
, p1
, len
);
960 strncpy(achDllName
+ len
, ".dll", sizeof(achDllName
) - len
);
961 pszDllName
= achDllName
;
964 /* Open input file argv[1] */
965 file
= fopen(argv
[i
], "r");
968 fprintf(stderr
, "error: could not open file %s ", argv
[i
]);
973 fseek(file
, 0, SEEK_END
);
974 nFileSize
= ftell(file
);
977 /* Allocate memory buffer */
978 pszSource
= malloc(nFileSize
+ 1);
985 /* Load input file into memory */
986 nFileSize
= fread(pszSource
, 1, nFileSize
, file
);
989 /* Zero terminate the source */
990 pszSource
[nFileSize
] = '\0';
994 /* Open output file */
995 file
= fopen(pszDefFileName
, "w");
998 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1002 OutputHeader_def(file
, pszDllName
);
1003 result
= ParseFile(pszSource
, file
, OutputLine_def
);
1007 if (pszStubFileName
)
1009 /* Open output file */
1010 file
= fopen(pszStubFileName
, "w");
1013 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1017 OutputHeader_stub(file
);
1018 result
= ParseFile(pszSource
, file
, OutputLine_stub
);
1024 /* Open output file */
1025 file
= fopen(pszLibStubName
, "w");
1028 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1032 OutputHeader_asmstub(file
, pszDllName
);
1033 result
= ParseFile(pszSource
, file
, OutputLine_asmstub
);
1034 fprintf(file
, "\nEND\n");