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 /* Check for non-x86 first */
329 if (giArch
!= ARCH_X86
)
331 /* Does the string already have stdcall decoration? */
332 pcAt
= ScanToken(pcName
, '@');
333 if ((pcAt
< (pcName
+ nNameLength
)) && (pcName
[0] == '_'))
335 /* Skip leading underscore and remove trailing decoration */
337 nNameLength
= pcAt
- pcName
;
340 /* Print the undecorated function name */
341 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
344 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
345 (pexp
->nCallingConvention
== CC_FASTCALL
)))
347 /* Scan for a dll forwarding dot */
348 pcDot
= ScanToken(pcName
, '.');
351 /* First print the dll name, followed by a dot */
352 nNameLength
= pcDot
- pcName
;
353 fprintf(fileDest
, "%.*s.", nNameLength
, pcName
);
355 /* Now the actual function name */
357 nNameLength
= pexp
->strTarget
.len
- nNameLength
- 1;
360 /* Does the string already have decoration? */
361 pcAt
= ScanToken(pcName
, '@');
362 if (pcAt
&& (pcAt
< (pcName
+ nNameLength
)))
364 /* On GCC, we need to remove the leading stdcall underscore */
365 if (!gbMSComp
&& (pexp
->nCallingConvention
== CC_STDCALL
))
371 /* Print the already decorated function name */
372 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
376 /* Print the prefix, but skip it for (GCC && stdcall) */
377 if (gbMSComp
|| (pexp
->nCallingConvention
!= CC_STDCALL
))
379 fprintf(fileDest
, "%c", pexp
->nCallingConvention
== CC_FASTCALL
? '@' : '_');
382 /* Print the name with trailing decoration */
383 fprintf(fileDest
, "%.*s@%d", nNameLength
, pcName
, pexp
->nStackBytes
);
388 /* Print the undecorated function name */
389 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
394 OutputLine_def_MS(FILE *fileDest
, EXPORT
*pexp
)
396 PrintName(fileDest
, pexp
, &pexp
->strName
, 0);
400 /* Redirect to a stub function, to get the right decoration in the lib */
401 fprintf(fileDest
, "=_stub_%.*s", pexp
->strName
.len
, pexp
->strName
.buf
);
403 else if (pexp
->strTarget
.buf
)
405 if (pexp
->strName
.buf
[0] == '?')
407 fprintf(stderr
, "warning: ignoring C++ redirection %.*s -> %.*s\n",
408 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
412 fprintf(fileDest
, "=");
414 /* If the original name was decorated, use decoration in the forwarder as well */
415 if ((giArch
== ARCH_X86
) && ScanToken(pexp
->strName
.buf
, '@') &&
416 !ScanToken(pexp
->strTarget
.buf
, '@') &&
417 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
418 (pexp
->nCallingConvention
== CC_FASTCALL
)) )
420 PrintName(fileDest
, pexp
, &pexp
->strTarget
, 1);
424 /* Write the undecorated redirection name */
425 fprintf(fileDest
, "%.*s", pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
429 else if (((pexp
->uFlags
& FL_STUB
) || (pexp
->nCallingConvention
== CC_STUB
)) &&
430 (pexp
->strName
.buf
[0] == '?'))
432 /* C++ stubs are forwarded to C stubs */
433 fprintf(fileDest
, "=stub_function%d", pexp
->nNumber
);
438 OutputLine_def_GCC(FILE *fileDest
, EXPORT
*pexp
)
440 /* Print the function name, with decoration for export libs */
441 PrintName(fileDest
, pexp
, &pexp
->strName
, gbImportLib
);
442 DbgPrint("Generating def line for '%.*s'\n", pexp
->strName
.len
, pexp
->strName
.buf
);
444 /* Check if this is a forwarded export */
445 if (pexp
->strTarget
.buf
)
447 int fIsExternal
= !!ScanToken(pexp
->strTarget
.buf
, '.');
448 DbgPrint("Got redirect '%.*s'\n", pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
450 /* print the target name, don't decorate if it is external */
451 fprintf(fileDest
, "=");
452 PrintName(fileDest
, pexp
, &pexp
->strTarget
, !fIsExternal
);
454 else if (((pexp
->uFlags
& FL_STUB
) || (pexp
->nCallingConvention
== CC_STUB
)) &&
455 (pexp
->strName
.buf
[0] == '?'))
457 /* C++ stubs are forwarded to C stubs */
458 fprintf(fileDest
, "=stub_function%d", pexp
->nNumber
);
461 /* Special handling for stdcall and fastcall */
462 if ((giArch
== ARCH_X86
) &&
463 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
464 (pexp
->nCallingConvention
== CC_FASTCALL
)))
466 /* Is this the import lib? */
469 /* Is the name in the spec file decorated? */
470 const char* pcDeco
= ScanToken(pexp
->strName
.buf
, '@');
471 if (pcDeco
&& (pcDeco
< pexp
->strName
.buf
+ pexp
->strName
.len
))
473 /* Write the name including the leading @ */
474 fprintf(fileDest
, "==%.*s", pexp
->strName
.len
, pexp
->strName
.buf
);
477 else if (!pexp
->strTarget
.buf
)
479 /* Write a forwarder to the actual decorated symbol */
480 fprintf(fileDest
, "=");
481 PrintName(fileDest
, pexp
, &pexp
->strName
, 1);
487 OutputLine_def(FILE *fileDest
, EXPORT
*pexp
)
489 fprintf(fileDest
, " ");
492 OutputLine_def_MS(fileDest
, pexp
);
494 OutputLine_def_GCC(fileDest
, pexp
);
496 if (pexp
->uFlags
& FL_ORDINAL
)
498 fprintf(fileDest
, " @%d", pexp
->nOrdinal
);
501 if (pexp
->uFlags
& FL_NONAME
)
503 fprintf(fileDest
, " NONAME");
506 if (pexp
->uFlags
& FL_PRIVATE
)
508 fprintf(fileDest
, " PRIVATE");
511 /* Make this a data export, unless this is MSVC and -withalias was given */
512 if ((pexp
->nCallingConvention
== CC_EXTERN
) &&
513 !(gbMSComp
&& (pexp
->uFlags
& FL_DATA_ALIAS
)))
515 fprintf(fileDest
, " DATA");
518 fprintf(fileDest
, "\n");
524 ParseFile(char* pcStart
, FILE *fileDest
, PFNOUTLINE OutputLine
)
532 //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);
537 for (pcLine
= pcStart
; *pcLine
; pcLine
= NextLine(pcLine
), nLine
++)
546 //if (!strncmp(pcLine, "22 stdcall @(long) MPR_Alloc",28))
549 //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
550 // nLine, TokenLength(pcLine), pcLine);
552 /* Skip white spaces */
553 while (*pc
== ' ' || *pc
== '\t') pc
++;
555 /* Skip empty lines, stop at EOF */
556 if (*pc
== ';' || *pc
<= '#') continue;
557 if (*pc
== 0) return 0;
559 //fprintf(stderr, "info: line %d, token:'%.*s'\n",
560 // nLine, TokenLength(pc), pc);
562 /* Now we should get either an ordinal or @ */
567 exp
.nOrdinal
= atol(pc
);
568 exp
.uFlags
|= FL_ORDINAL
;
571 /* Go to next token (type) */
572 if (!(pc
= NextToken(pc
)))
574 fprintf(stderr
, "error: line %d, unexpected end of line\n", nLine
);
578 //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc), pc);
580 /* Now we should get the type */
581 if (CompareToken(pc
, "stdcall"))
583 exp
.nCallingConvention
= CC_STDCALL
;
585 else if (CompareToken(pc
, "cdecl") ||
586 CompareToken(pc
, "varargs"))
588 exp
.nCallingConvention
= CC_CDECL
;
590 else if (CompareToken(pc
, "fastcall"))
592 exp
.nCallingConvention
= CC_FASTCALL
;
594 else if (CompareToken(pc
, "thiscall"))
596 exp
.nCallingConvention
= CC_THISCALL
;
598 else if (CompareToken(pc
, "extern"))
600 exp
.nCallingConvention
= CC_EXTERN
;
602 else if (CompareToken(pc
, "stub"))
604 exp
.nCallingConvention
= CC_STUB
;
608 fprintf(stderr
, "error: line %d, expected callconv, got '%.*s' %d\n",
609 nLine
, TokenLength(pc
), pc
, *pc
);
613 //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention);
615 /* Go to next token (options or name) */
616 if (!(pc
= NextToken(pc
)))
618 fprintf(stderr
, "fail2\n");
626 if (CompareToken(pc
, "-arch"))
628 /* Default to not included */
632 /* Look if we are included */
633 while (*pc
== '=' || *pc
== ',')
636 if (CompareToken(pc
, pszArchString
) ||
637 CompareToken(pc
, pszArchString2
))
642 /* Skip to next arch or end */
643 while (*pc
> ',') pc
++;
646 else if (CompareToken(pc
, "-i386"))
648 if (giArch
!= ARCH_X86
) included
= 0;
650 else if (CompareToken(pc
, "-private"))
652 exp
.uFlags
|= FL_PRIVATE
;
654 else if (CompareToken(pc
, "-noname"))
656 exp
.uFlags
|= FL_ORDINAL
| FL_NONAME
;
658 else if (CompareToken(pc
, "-ordinal"))
660 exp
.uFlags
|= FL_ORDINAL
;
662 else if (CompareToken(pc
, "-stub"))
664 exp
.uFlags
|= FL_STUB
;
666 else if (CompareToken(pc
, "-withalias"))
668 /* This flag is to create a nin _imp_ prefixed alias for a
669 data export, so that the hacked DDK declarations work */
670 if (exp
.nCallingConvention
!= CC_EXTERN
)
671 fprintf(stderr
, "error: line %d -withalias on non-data export\n", nLine
);
673 exp
.uFlags
|= FL_DATA_ALIAS
;
675 else if (CompareToken(pc
, "-norelay") ||
676 CompareToken(pc
, "-register") ||
677 CompareToken(pc
, "-ret64"))
679 /* silently ignore these */
683 fprintf(stderr
, "info: ignored option: '%.*s'\n",
684 TokenLength(pc
), pc
);
687 /* Go to next token */
691 //fprintf(stderr, "info: Name:'%.10s'\n", pc);
693 /* If arch didn't match ours, skip this entry */
694 if (!included
) continue;
697 exp
.strName
.buf
= pc
;
698 exp
.strName
.len
= TokenLength(pc
);
700 /* Check for autoname */
701 if ((exp
.strName
.len
== 1) && (exp
.strName
.buf
[0] == '@'))
703 sprintf(namebuffer
, "ordinal%d", exp
.nOrdinal
);
704 exp
.strName
.len
= strlen(namebuffer
);
705 exp
.strName
.buf
= namebuffer
;
706 exp
.uFlags
|= FL_ORDINAL
| FL_NONAME
;
709 /* Handle parameters */
711 if (exp
.nCallingConvention
!= CC_EXTERN
&&
712 exp
.nCallingConvention
!= CC_STUB
)
714 //fprintf(stderr, "info: options:'%.10s'\n", pc);
715 /* Go to next token */
716 if (!(pc
= NextToken(pc
)))
718 fprintf(stderr
, "fail4\n");
725 fprintf(stderr
, "error: line %d, expected '('\n", nLine
);
729 /* Skip whitespaces */
730 while (*pc
== ' ' || *pc
== '\t') pc
++;
735 if (CompareToken(pc
, "long"))
737 exp
.nStackBytes
+= 4;
738 exp
.anArgs
[exp
.nArgCount
] = ARG_LONG
;
740 else if (CompareToken(pc
, "double"))
742 exp
.nStackBytes
+= 8;
743 exp
.anArgs
[exp
.nArgCount
] = ARG_DBL
;
745 else if (CompareToken(pc
, "ptr") ||
746 CompareToken(pc
, "str") ||
747 CompareToken(pc
, "wstr"))
749 exp
.nStackBytes
+= 4; // sizeof(void*) on x86
750 exp
.anArgs
[exp
.nArgCount
] = ARG_PTR
; // FIXME: handle strings
752 else if (CompareToken(pc
, "int64"))
754 exp
.nStackBytes
+= 8;
755 exp
.anArgs
[exp
.nArgCount
] = ARG_INT64
;
757 else if (CompareToken(pc
, "int128"))
759 exp
.nStackBytes
+= 16;
760 exp
.anArgs
[exp
.nArgCount
] = ARG_INT128
;
762 else if (CompareToken(pc
, "float"))
764 exp
.nStackBytes
+= 4;
765 exp
.anArgs
[exp
.nArgCount
] = ARG_FLOAT
;
768 fprintf(stderr
, "error: line %d, expected type, got: %.10s\n", nLine
, pc
);
772 /* Go to next parameter */
773 if (!(pc
= NextToken(pc
)))
775 fprintf(stderr
, "fail5\n");
783 fprintf(stderr
, "error: line %d, expected ')'\n", nLine
);
788 /* Handle special stub cases */
789 if (exp
.nCallingConvention
== CC_STUB
)
791 /* Check for c++ mangled name */
794 //printf("Found c++ mangled name...\n");
799 /* Check for stdcall name */
800 const char *p
= ScanToken(pc
, '@');
801 if (p
&& (p
- pc
< exp
.strName
.len
))
805 /* Truncate the name to before the @ */
806 exp
.strName
.len
= (int)(p
- pc
);
807 if (exp
.strName
.len
< 1)
809 fprintf(stderr
, "error, @ in line %d\n", nLine
);
812 exp
.nStackBytes
= atoi(p
+ 1);
813 exp
.nArgCount
= exp
.nStackBytes
/ 4;
814 exp
.nCallingConvention
= CC_STDCALL
;
815 exp
.uFlags
|= FL_STUB
;
816 for (i
= 0; i
< exp
.nArgCount
; i
++)
817 exp
.anArgs
[i
] = ARG_LONG
;
822 /* Get optional redirection */
826 exp
.strTarget
.buf
= pc
;
827 exp
.strTarget
.len
= TokenLength(pc
);
829 /* Check syntax (end of line) */
832 fprintf(stderr
, "error: line %d, additional tokens after ')'\n", nLine
);
838 exp
.strTarget
.buf
= 0;
839 exp
.strTarget
.len
= 0;
842 /* Check for no-name without ordinal */
843 if ((exp
.uFlags
& FL_ORDINAL
) && (exp
.nOrdinal
== -1))
845 fprintf(stderr
, "error: line %d, ordinal export without ordinal!\n", nLine
);
849 OutputLine(fileDest
, &exp
);
859 printf("syntax: spec2pdef [<options> ...] <spec file>\n"
860 "Possible options:\n"
861 " -h --help prints this screen\n"
862 " -l=<file> generates an asm lib stub\n"
863 " -d=<file> generates a def file\n"
864 " -s=<file> generates a stub file\n"
865 " --ms msvc compatibility\n"
866 " -n=<name> name of the dll\n"
867 " --implib generate a def file for an import library\n"
868 " -a=<arch> Set architecture to <arch>. (i386, x86_64, arm)\n");
871 int main(int argc
, char *argv
[])
874 char *pszSource
, *pszDefFileName
= 0, *pszStubFileName
= 0, *pszLibStubName
= 0;
886 for (i
= 1; i
< argc
&& *argv
[i
] == '-'; i
++)
888 if ((strcasecmp(argv
[i
], "--help") == 0) ||
889 (strcasecmp(argv
[i
], "-h") == 0))
894 else if (argv
[i
][1] == 'd' && argv
[i
][2] == '=')
896 pszDefFileName
= argv
[i
] + 3;
898 else if (argv
[i
][1] == 'l' && argv
[i
][2] == '=')
900 pszLibStubName
= argv
[i
] + 3;
902 else if (argv
[i
][1] == 's' && argv
[i
][2] == '=')
904 pszStubFileName
= argv
[i
] + 3;
906 else if (argv
[i
][1] == 'n' && argv
[i
][2] == '=')
908 pszDllName
= argv
[i
] + 3;
910 else if ((strcasecmp(argv
[i
], "--implib") == 0))
914 else if ((strcasecmp(argv
[i
], "--ms") == 0))
918 else if (argv
[i
][1] == 'a' && argv
[i
][2] == '=')
920 pszArchString
= argv
[i
] + 3;
924 fprintf(stderr
, "Unrecognized option: %s\n", argv
[i
]);
929 if (strcasecmp(pszArchString
, "i386") == 0)
932 gpszUnderscore
= "_";
934 else if (strcasecmp(pszArchString
, "x86_64") == 0) giArch
= ARCH_AMD64
;
935 else if (strcasecmp(pszArchString
, "ia64") == 0) giArch
= ARCH_IA64
;
936 else if (strcasecmp(pszArchString
, "arm") == 0) giArch
= ARCH_ARM
;
937 else if (strcasecmp(pszArchString
, "ppc") == 0) giArch
= ARCH_PPC
;
939 if ((giArch
== ARCH_AMD64
) || (giArch
== ARCH_IA64
))
941 pszArchString2
= "win64";
944 pszArchString2
= "win32";
946 /* Set a default dll name */
952 p1
= strrchr(argv
[i
], '\\');
953 if (!p1
) p1
= strrchr(argv
[i
], '/');
954 p2
= p1
= p1
? p1
+ 1 : argv
[i
];
957 while (*p2
!= '.' && *p2
!= 0) p2
++;
959 if (len
>= sizeof(achDllName
) - 5)
961 fprintf(stderr
, "name too long: %s\n", p1
);
965 strncpy(achDllName
, p1
, len
);
966 strncpy(achDllName
+ len
, ".dll", sizeof(achDllName
) - len
);
967 pszDllName
= achDllName
;
970 /* Open input file argv[1] */
971 file
= fopen(argv
[i
], "r");
974 fprintf(stderr
, "error: could not open file %s ", argv
[i
]);
979 fseek(file
, 0, SEEK_END
);
980 nFileSize
= ftell(file
);
983 /* Allocate memory buffer */
984 pszSource
= malloc(nFileSize
+ 1);
991 /* Load input file into memory */
992 nFileSize
= fread(pszSource
, 1, nFileSize
, file
);
995 /* Zero terminate the source */
996 pszSource
[nFileSize
] = '\0';
1000 /* Open output file */
1001 file
= fopen(pszDefFileName
, "w");
1004 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1008 OutputHeader_def(file
, pszDllName
);
1009 result
= ParseFile(pszSource
, file
, OutputLine_def
);
1013 if (pszStubFileName
)
1015 /* Open output file */
1016 file
= fopen(pszStubFileName
, "w");
1019 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1023 OutputHeader_stub(file
);
1024 result
= ParseFile(pszSource
, file
, OutputLine_stub
);
1030 /* Open output file */
1031 file
= fopen(pszLibStubName
, "w");
1034 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1038 OutputHeader_asmstub(file
, pszDllName
);
1039 result
= ParseFile(pszSource
, file
, OutputLine_asmstub
);
1040 fprintf(file
, "\nEND\n");