0bb66a0bc062327dfc09428cf3ff5ffe11caa757
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__))
79 char* astrCallingConventions
[] =
92 return ((chr
<= ',' && chr
!= '$') ||
93 (chr
>= ':' && chr
< '?') );
97 CompareToken(const char *token
, const char *comparand
)
101 if (*token
!= *comparand
) return 0;
105 if (!IsSeparator(*token
)) return 0;
110 ScanToken(const char *token
, char chr
)
112 while (!IsSeparator(*token
))
114 if (*token
== chr
) return token
;
125 if (pc
[0] == '\n' && pc
[1] == '\r') return pc
+ 2;
126 else if (pc
[0] == '\n') return pc
+ 1;
133 TokenLength(char *pc
)
137 while (!IsSeparator(*pc
++)) length
++;
146 while (!IsSeparator(*pc
)) pc
++;
148 /* Skip white spaces */
149 while (*pc
== ' ' || *pc
== '\t') pc
++;
151 /* Check for end of line */
152 if (*pc
== '\n' || *pc
== '\r' || *pc
== 0) return 0;
154 /* Check for comment */
155 if (*pc
== '#' || *pc
== ';') return 0;
161 OutputHeader_stub(FILE *file
)
163 fprintf(file
, "/* This file is autogenerated, do not edit. */\n\n"
164 "#include <stubs.h>\n\n");
168 OutputLine_stub(FILE *file
, EXPORT
*pexp
)
172 if (pexp
->nCallingConvention
!= CC_STUB
&&
173 (pexp
->uFlags
& FL_STUB
) == 0) return 0;
175 fprintf(file
, "int ");
176 if ((giArch
== ARCH_X86
) &&
177 pexp
->nCallingConvention
== CC_STDCALL
)
179 fprintf(file
, "__stdcall ");
183 if (pexp
->strName
.buf
[0] == '?')
185 fprintf(file
, "stub_function%d(", pexp
->nNumber
);
189 fprintf(file
, "%.*s(", pexp
->strName
.len
, pexp
->strName
.buf
);
192 for (i
= 0; i
< pexp
->nArgCount
; i
++)
194 if (i
!= 0) fprintf(file
, ", ");
195 switch (pexp
->anArgs
[i
])
197 case ARG_LONG
: fprintf(file
, "long"); break;
198 case ARG_PTR
: fprintf(file
, "void*"); break;
199 case ARG_STR
: fprintf(file
, "char*"); break;
200 case ARG_WSTR
: fprintf(file
, "wchar_t*"); break;
202 case ARG_INT64
: fprintf(file
, "__int64"); break;
203 case ARG_INT128
: fprintf(file
, "__int128"); break;
204 case ARG_FLOAT
: fprintf(file
, "float"); break;
206 fprintf(file
, " a%d", i
);
208 fprintf(file
, ")\n{\n\tDbgPrint(\"WARNING: calling stub %.*s(",
209 pexp
->strName
.len
, pexp
->strName
.buf
);
211 for (i
= 0; i
< pexp
->nArgCount
; i
++)
213 if (i
!= 0) fprintf(file
, ",");
214 switch (pexp
->anArgs
[i
])
216 case ARG_LONG
: fprintf(file
, "0x%%lx"); break;
217 case ARG_PTR
: fprintf(file
, "0x%%p"); break;
218 case ARG_STR
: fprintf(file
, "'%%s'"); break;
219 case ARG_WSTR
: fprintf(file
, "'%%ws'"); break;
220 case ARG_DBL
: fprintf(file
, "%%f"); break;
221 case ARG_INT64
: fprintf(file
, "%%\"PRix64\""); break;
222 case ARG_INT128
: fprintf(file
, "%%\"PRix128\""); break;
223 case ARG_FLOAT
: fprintf(file
, "%%f"); break;
226 fprintf(file
, ")\\n\"");
228 for (i
= 0; i
< pexp
->nArgCount
; i
++)
231 switch (pexp
->anArgs
[i
])
233 case ARG_LONG
: fprintf(file
, "(long)a%d", i
); break;
234 case ARG_PTR
: fprintf(file
, "(void*)a%d", i
); break;
235 case ARG_STR
: fprintf(file
, "(char*)a%d", i
); break;
236 case ARG_WSTR
: fprintf(file
, "(wchar_t*)a%d", i
); break;
237 case ARG_DBL
: fprintf(file
, "(double)a%d", i
); break;
238 case ARG_INT64
: fprintf(file
, "(__int64)a%d", i
); break;
239 case ARG_INT128
: fprintf(file
, "(__int128)a%d", i
); break;
240 case ARG_FLOAT
: fprintf(file
, "(float)a%d", i
); break;
243 fprintf(file
, ");\n");
245 if (pexp
->nCallingConvention
== CC_STUB
)
247 fprintf(file
, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName
);
250 fprintf(file
, "\treturn 0;\n}\n\n");
256 OutputHeader_asmstub(FILE *file
, char *libname
)
258 fprintf(file
, "; File generated automatically, do not edit! \n\n");
260 if (giArch
== ARCH_X86
)
262 fprintf(file
, ".586\n.model flat\n.code\n");
264 else if (giArch
== ARCH_AMD64
)
266 fprintf(file
, ".code\n");
268 else if (giArch
== ARCH_ARM
)
271 " AREA |.text|,ALIGN=2,CODE,READONLY\n\n");
276 Output_symbol(FILE *fileDest
, char* pszSymbolName
)
278 if (giArch
== ARCH_ARM
)
281 " EXPORT %s [FUNC]\n%s\n",
288 "PUBLIC %s\n%s: nop\n",
295 OutputLine_asmstub(FILE *fileDest
, EXPORT
*pexp
)
297 char szNameBuffer
[128];
299 /* Handle autoname */
300 if (pexp
->strName
.len
== 1 && pexp
->strName
.buf
[0] == '@')
302 sprintf(szNameBuffer
, "%sordinal%d\n%sordinal%d: nop\n",
303 gpszUnderscore
, pexp
->nOrdinal
, gpszUnderscore
, pexp
->nOrdinal
);
305 else if (giArch
!= ARCH_X86
)
307 sprintf(szNameBuffer
, "_stub_%.*s",
308 pexp
->strName
.len
, pexp
->strName
.buf
);
310 else if (pexp
->nCallingConvention
== CC_STDCALL
)
312 sprintf(szNameBuffer
, "__stub_%.*s@%d",
313 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
);
315 else if (pexp
->nCallingConvention
== CC_FASTCALL
)
317 sprintf(szNameBuffer
, "@_stub_%.*s@%d",
318 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
);
320 else if (pexp
->nCallingConvention
== CC_CDECL
||
321 pexp
->nCallingConvention
== CC_STUB
)
323 sprintf(szNameBuffer
, "__stub_%.*s",
324 pexp
->strName
.len
, pexp
->strName
.buf
);
326 else if (pexp
->nCallingConvention
== CC_EXTERN
)
328 sprintf(szNameBuffer
, "__stub_%.*s",
329 pexp
->strName
.len
, pexp
->strName
.buf
);
332 Output_symbol(fileDest
, szNameBuffer
);
338 OutputHeader_def(FILE *file
, char *libname
)
341 "; File generated automatically, do not edit!\n\n"
348 PrintName(FILE *fileDest
, EXPORT
*pexp
, PSTRING pstr
, int fDeco
)
350 const char *pcName
= pstr
->buf
;
351 int nNameLength
= pstr
->len
;
352 const char* pcDot
, *pcAt
;
354 /* Check for non-x86 first */
355 if (giArch
!= ARCH_X86
)
357 /* Does the string already have stdcall decoration? */
358 pcAt
= ScanToken(pcName
, '@');
359 if (pcAt
&& (pcAt
< (pcName
+ nNameLength
)) && (pcName
[0] == '_'))
361 /* Skip leading underscore and remove trailing decoration */
363 nNameLength
= pcAt
- pcName
;
366 /* Print the undecorated function name */
367 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
370 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
371 (pexp
->nCallingConvention
== CC_FASTCALL
)))
373 /* Scan for a dll forwarding dot */
374 pcDot
= ScanToken(pcName
, '.');
377 /* First print the dll name, followed by a dot */
378 nNameLength
= pcDot
- pcName
;
379 fprintf(fileDest
, "%.*s.", nNameLength
, pcName
);
381 /* Now the actual function name */
383 nNameLength
= pexp
->strTarget
.len
- nNameLength
- 1;
386 /* Does the string already have decoration? */
387 pcAt
= ScanToken(pcName
, '@');
388 if (pcAt
&& (pcAt
< (pcName
+ nNameLength
)))
390 /* On GCC, we need to remove the leading stdcall underscore */
391 if (!gbMSComp
&& (pexp
->nCallingConvention
== CC_STDCALL
))
397 /* Print the already decorated function name */
398 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
402 /* Print the prefix, but skip it for (GCC && stdcall) */
403 if (gbMSComp
|| (pexp
->nCallingConvention
!= CC_STDCALL
))
405 fprintf(fileDest
, "%c", pexp
->nCallingConvention
== CC_FASTCALL
? '@' : '_');
408 /* Print the name with trailing decoration */
409 fprintf(fileDest
, "%.*s@%d", nNameLength
, pcName
, pexp
->nStackBytes
);
414 /* Print the undecorated function name */
415 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
420 OutputLine_def_MS(FILE *fileDest
, EXPORT
*pexp
)
422 PrintName(fileDest
, pexp
, &pexp
->strName
, 0);
426 /* Redirect to a stub function, to get the right decoration in the lib */
427 fprintf(fileDest
, "=_stub_%.*s", pexp
->strName
.len
, pexp
->strName
.buf
);
429 else if (pexp
->strTarget
.buf
)
431 if (pexp
->strName
.buf
[0] == '?')
433 fprintf(stderr
, "warning: ignoring C++ redirection %.*s -> %.*s\n",
434 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
438 fprintf(fileDest
, "=");
440 /* If the original name was decorated, use decoration in the forwarder as well */
441 if ((giArch
== ARCH_X86
) && ScanToken(pexp
->strName
.buf
, '@') &&
442 !ScanToken(pexp
->strTarget
.buf
, '@') &&
443 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
444 (pexp
->nCallingConvention
== CC_FASTCALL
)) )
446 PrintName(fileDest
, pexp
, &pexp
->strTarget
, 1);
450 /* Write the undecorated redirection name */
451 fprintf(fileDest
, "%.*s", pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
455 else if (((pexp
->uFlags
& FL_STUB
) || (pexp
->nCallingConvention
== CC_STUB
)) &&
456 (pexp
->strName
.buf
[0] == '?'))
458 /* C++ stubs are forwarded to C stubs */
459 fprintf(fileDest
, "=stub_function%d", pexp
->nNumber
);
464 OutputLine_def_GCC(FILE *fileDest
, EXPORT
*pexp
)
466 /* Print the function name, with decoration for export libs */
467 PrintName(fileDest
, pexp
, &pexp
->strName
, gbImportLib
);
468 DbgPrint("Generating def line for '%.*s'\n", pexp
->strName
.len
, pexp
->strName
.buf
);
470 /* Check if this is a forwarded export */
471 if (pexp
->strTarget
.buf
)
473 int fIsExternal
= !!ScanToken(pexp
->strTarget
.buf
, '.');
474 DbgPrint("Got redirect '%.*s'\n", pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
476 /* print the target name, don't decorate if it is external */
477 fprintf(fileDest
, "=");
478 PrintName(fileDest
, pexp
, &pexp
->strTarget
, !fIsExternal
);
480 else if (((pexp
->uFlags
& FL_STUB
) || (pexp
->nCallingConvention
== CC_STUB
)) &&
481 (pexp
->strName
.buf
[0] == '?'))
483 /* C++ stubs are forwarded to C stubs */
484 fprintf(fileDest
, "=stub_function%d", pexp
->nNumber
);
487 /* Special handling for stdcall and fastcall */
488 if ((giArch
== ARCH_X86
) &&
489 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
490 (pexp
->nCallingConvention
== CC_FASTCALL
)))
492 /* Is this the import lib? */
495 /* Is the name in the spec file decorated? */
496 const char* pcDeco
= ScanToken(pexp
->strName
.buf
, '@');
497 if (pcDeco
&& (pcDeco
< pexp
->strName
.buf
+ pexp
->strName
.len
))
499 /* Write the name including the leading @ */
500 fprintf(fileDest
, "==%.*s", pexp
->strName
.len
, pexp
->strName
.buf
);
503 else if (!pexp
->strTarget
.buf
)
505 /* Write a forwarder to the actual decorated symbol */
506 fprintf(fileDest
, "=");
507 PrintName(fileDest
, pexp
, &pexp
->strName
, 1);
513 OutputLine_def(FILE *fileDest
, EXPORT
*pexp
)
515 DbgPrint("OutputLine_def: '%.*s'...\n", pexp
->strName
.len
, pexp
->strName
.buf
);
516 fprintf(fileDest
, " ");
519 OutputLine_def_MS(fileDest
, pexp
);
521 OutputLine_def_GCC(fileDest
, pexp
);
523 if (pexp
->uFlags
& FL_ORDINAL
)
525 fprintf(fileDest
, " @%d", pexp
->nOrdinal
);
528 if (pexp
->uFlags
& FL_NONAME
)
530 fprintf(fileDest
, " NONAME");
533 if (pexp
->uFlags
& FL_PRIVATE
)
535 fprintf(fileDest
, " PRIVATE");
538 if (pexp
->nCallingConvention
== CC_EXTERN
)
540 fprintf(fileDest
, " DATA");
543 fprintf(fileDest
, "\n");
549 ParseFile(char* pcStart
, FILE *fileDest
, PFNOUTLINE OutputLine
)
557 //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);
562 for (pcLine
= pcStart
; *pcLine
; pcLine
= NextLine(pcLine
), nLine
++)
571 //if (!strncmp(pcLine, "22 stdcall @(long) MPR_Alloc",28))
574 //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
575 // nLine, TokenLength(pcLine), pcLine);
577 /* Skip white spaces */
578 while (*pc
== ' ' || *pc
== '\t') pc
++;
580 /* Skip empty lines, stop at EOF */
581 if (*pc
== ';' || *pc
<= '#') continue;
582 if (*pc
== 0) return 0;
584 //fprintf(stderr, "info: line %d, token:'%.*s'\n",
585 // nLine, TokenLength(pc), pc);
587 /* Now we should get either an ordinal or @ */
592 exp
.nOrdinal
= atol(pc
);
593 /* The import lib should contain the ordinal only if -ordinal was specified */
595 exp
.uFlags
|= FL_ORDINAL
;
598 /* Go to next token (type) */
599 if (!(pc
= NextToken(pc
)))
601 fprintf(stderr
, "error: line %d, unexpected end of line\n", nLine
);
605 //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc), pc);
607 /* Now we should get the type */
608 if (CompareToken(pc
, "stdcall"))
610 exp
.nCallingConvention
= CC_STDCALL
;
612 else if (CompareToken(pc
, "cdecl") ||
613 CompareToken(pc
, "varargs"))
615 exp
.nCallingConvention
= CC_CDECL
;
617 else if (CompareToken(pc
, "fastcall"))
619 exp
.nCallingConvention
= CC_FASTCALL
;
621 else if (CompareToken(pc
, "thiscall"))
623 exp
.nCallingConvention
= CC_THISCALL
;
625 else if (CompareToken(pc
, "extern"))
627 exp
.nCallingConvention
= CC_EXTERN
;
629 else if (CompareToken(pc
, "stub"))
631 exp
.nCallingConvention
= CC_STUB
;
635 fprintf(stderr
, "error: line %d, expected callconv, got '%.*s' %d\n",
636 nLine
, TokenLength(pc
), pc
, *pc
);
640 //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention);
642 /* Go to next token (options or name) */
643 if (!(pc
= NextToken(pc
)))
645 fprintf(stderr
, "fail2\n");
653 if (CompareToken(pc
, "-arch"))
655 /* Default to not included */
659 /* Look if we are included */
660 while (*pc
== '=' || *pc
== ',')
663 if (CompareToken(pc
, pszArchString
) ||
664 CompareToken(pc
, pszArchString2
))
669 /* Skip to next arch or end */
670 while (*pc
> ',') pc
++;
673 else if (CompareToken(pc
, "-i386"))
675 if (giArch
!= ARCH_X86
) included
= 0;
677 else if (CompareToken(pc
, "-private"))
679 exp
.uFlags
|= FL_PRIVATE
;
681 else if (CompareToken(pc
, "-noname"))
683 exp
.uFlags
|= FL_ORDINAL
| FL_NONAME
;
685 else if (CompareToken(pc
, "-ordinal"))
687 exp
.uFlags
|= FL_ORDINAL
;
688 /* GCC doesn't automatically import by ordinal if an ordinal
689 * is found in the def file. Force it. */
690 if (gbImportLib
&& !gbMSComp
)
691 exp
.uFlags
|= FL_NONAME
;
693 else if (CompareToken(pc
, "-stub"))
695 exp
.uFlags
|= FL_STUB
;
697 else if (CompareToken(pc
, "-norelay") ||
698 CompareToken(pc
, "-register") ||
699 CompareToken(pc
, "-ret64"))
701 /* silently ignore these */
705 fprintf(stderr
, "info: ignored option: '%.*s'\n",
706 TokenLength(pc
), pc
);
709 /* Go to next token */
713 //fprintf(stderr, "info: Name:'%.10s'\n", pc);
715 /* If arch didn't match ours, skip this entry */
716 if (!included
) continue;
719 exp
.strName
.buf
= pc
;
720 exp
.strName
.len
= TokenLength(pc
);
721 DbgPrint("Got name: '%.*s'\n", exp
.strName
.len
, exp
.strName
.buf
);
723 /* Check for autoname */
724 if ((exp
.strName
.len
== 1) && (exp
.strName
.buf
[0] == '@'))
726 sprintf(namebuffer
, "ordinal%d", exp
.nOrdinal
);
727 exp
.strName
.len
= strlen(namebuffer
);
728 exp
.strName
.buf
= namebuffer
;
729 exp
.uFlags
|= FL_ORDINAL
| FL_NONAME
;
732 /* Handle parameters */
734 if (exp
.nCallingConvention
!= CC_EXTERN
&&
735 exp
.nCallingConvention
!= CC_STUB
)
737 /* Go to next token */
738 if (!(pc
= NextToken(pc
)))
740 fprintf(stderr
, "fail4\n");
747 fprintf(stderr
, "error: line %d, expected '('\n", nLine
);
751 /* Skip whitespaces */
752 while (*pc
== ' ' || *pc
== '\t') pc
++;
757 if (CompareToken(pc
, "long"))
759 exp
.nStackBytes
+= 4;
760 exp
.anArgs
[exp
.nArgCount
] = ARG_LONG
;
762 else if (CompareToken(pc
, "double"))
764 exp
.nStackBytes
+= 8;
765 exp
.anArgs
[exp
.nArgCount
] = ARG_DBL
;
767 else if (CompareToken(pc
, "ptr") ||
768 CompareToken(pc
, "str") ||
769 CompareToken(pc
, "wstr"))
771 exp
.nStackBytes
+= 4; // sizeof(void*) on x86
772 exp
.anArgs
[exp
.nArgCount
] = ARG_PTR
; // FIXME: handle strings
774 else if (CompareToken(pc
, "int64"))
776 exp
.nStackBytes
+= 8;
777 exp
.anArgs
[exp
.nArgCount
] = ARG_INT64
;
779 else if (CompareToken(pc
, "int128"))
781 exp
.nStackBytes
+= 16;
782 exp
.anArgs
[exp
.nArgCount
] = ARG_INT128
;
784 else if (CompareToken(pc
, "float"))
786 exp
.nStackBytes
+= 4;
787 exp
.anArgs
[exp
.nArgCount
] = ARG_FLOAT
;
790 fprintf(stderr
, "error: line %d, expected type, got: %.10s\n", nLine
, pc
);
794 /* Go to next parameter */
795 if (!(pc
= NextToken(pc
)))
797 fprintf(stderr
, "fail5\n");
805 fprintf(stderr
, "error: line %d, expected ')'\n", nLine
);
810 /* Handle special stub cases */
811 if (exp
.nCallingConvention
== CC_STUB
)
813 /* Check for c++ mangled name */
816 //printf("Found c++ mangled name...\n");
821 /* Check for stdcall name */
822 const char *p
= ScanToken(pc
, '@');
823 if (p
&& (p
- pc
< exp
.strName
.len
))
827 /* Truncate the name to before the @ */
828 exp
.strName
.len
= (int)(p
- pc
);
829 if (exp
.strName
.len
< 1)
831 fprintf(stderr
, "error, @ in line %d\n", nLine
);
834 exp
.nStackBytes
= atoi(p
+ 1);
835 exp
.nArgCount
= exp
.nStackBytes
/ 4;
836 exp
.nCallingConvention
= CC_STDCALL
;
837 exp
.uFlags
|= FL_STUB
;
838 for (i
= 0; i
< exp
.nArgCount
; i
++)
839 exp
.anArgs
[i
] = ARG_LONG
;
844 /* Get optional redirection */
848 exp
.strTarget
.buf
= pc
;
849 exp
.strTarget
.len
= TokenLength(pc
);
851 /* Check syntax (end of line) */
854 fprintf(stderr
, "error: line %d, additional tokens after ')'\n", nLine
);
860 exp
.strTarget
.buf
= 0;
861 exp
.strTarget
.len
= 0;
864 /* Check for no-name without ordinal */
865 if ((exp
.uFlags
& FL_ORDINAL
) && (exp
.nOrdinal
== -1))
867 fprintf(stderr
, "error: line %d, ordinal export without ordinal!\n", nLine
);
871 OutputLine(fileDest
, &exp
);
881 printf("syntax: spec2pdef [<options> ...] <spec file>\n"
882 "Possible options:\n"
883 " -h --help prints this screen\n"
884 " -l=<file> generates an asm lib stub\n"
885 " -d=<file> generates a def file\n"
886 " -s=<file> generates a stub file\n"
887 " --ms msvc compatibility\n"
888 " -n=<name> name of the dll\n"
889 " --implib generate a def file for an import library\n"
890 " -a=<arch> Set architecture to <arch>. (i386, x86_64, arm)\n");
893 int main(int argc
, char *argv
[])
896 char *pszSource
, *pszDefFileName
= 0, *pszStubFileName
= 0, *pszLibStubName
= 0;
908 for (i
= 1; i
< argc
&& *argv
[i
] == '-'; i
++)
910 if ((strcasecmp(argv
[i
], "--help") == 0) ||
911 (strcasecmp(argv
[i
], "-h") == 0))
916 else if (argv
[i
][1] == 'd' && argv
[i
][2] == '=')
918 pszDefFileName
= argv
[i
] + 3;
920 else if (argv
[i
][1] == 'l' && argv
[i
][2] == '=')
922 pszLibStubName
= argv
[i
] + 3;
924 else if (argv
[i
][1] == 's' && argv
[i
][2] == '=')
926 pszStubFileName
= argv
[i
] + 3;
928 else if (argv
[i
][1] == 'n' && argv
[i
][2] == '=')
930 pszDllName
= argv
[i
] + 3;
932 else if ((strcasecmp(argv
[i
], "--implib") == 0))
936 else if ((strcasecmp(argv
[i
], "--ms") == 0))
940 else if (argv
[i
][1] == 'a' && argv
[i
][2] == '=')
942 pszArchString
= argv
[i
] + 3;
946 fprintf(stderr
, "Unrecognized option: %s\n", argv
[i
]);
951 if (strcasecmp(pszArchString
, "i386") == 0)
954 gpszUnderscore
= "_";
956 else if (strcasecmp(pszArchString
, "x86_64") == 0) giArch
= ARCH_AMD64
;
957 else if (strcasecmp(pszArchString
, "ia64") == 0) giArch
= ARCH_IA64
;
958 else if (strcasecmp(pszArchString
, "arm") == 0) giArch
= ARCH_ARM
;
959 else if (strcasecmp(pszArchString
, "ppc") == 0) giArch
= ARCH_PPC
;
961 if ((giArch
== ARCH_AMD64
) || (giArch
== ARCH_IA64
))
963 pszArchString2
= "win64";
966 pszArchString2
= "win32";
968 /* Set a default dll name */
974 p1
= strrchr(argv
[i
], '\\');
975 if (!p1
) p1
= strrchr(argv
[i
], '/');
976 p2
= p1
= p1
? p1
+ 1 : argv
[i
];
979 while (*p2
!= '.' && *p2
!= 0) p2
++;
981 if (len
>= sizeof(achDllName
) - 5)
983 fprintf(stderr
, "name too long: %s\n", p1
);
987 strncpy(achDllName
, p1
, len
);
988 strncpy(achDllName
+ len
, ".dll", sizeof(achDllName
) - len
);
989 pszDllName
= achDllName
;
992 /* Open input file argv[1] */
993 file
= fopen(argv
[i
], "r");
996 fprintf(stderr
, "error: could not open file %s ", argv
[i
]);
1001 fseek(file
, 0, SEEK_END
);
1002 nFileSize
= ftell(file
);
1005 /* Allocate memory buffer */
1006 pszSource
= malloc(nFileSize
+ 1);
1013 /* Load input file into memory */
1014 nFileSize
= fread(pszSource
, 1, nFileSize
, file
);
1017 /* Zero terminate the source */
1018 pszSource
[nFileSize
] = '\0';
1022 /* Open output file */
1023 file
= fopen(pszDefFileName
, "w");
1026 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1030 OutputHeader_def(file
, pszDllName
);
1031 result
= ParseFile(pszSource
, file
, OutputLine_def
);
1035 if (pszStubFileName
)
1037 /* Open output file */
1038 file
= fopen(pszStubFileName
, "w");
1041 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1045 OutputHeader_stub(file
);
1046 result
= ParseFile(pszSource
, file
, OutputLine_stub
);
1052 /* Open output file */
1053 file
= fopen(pszLibStubName
, "w");
1056 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1060 OutputHeader_asmstub(file
, pszDllName
);
1061 result
= ParseFile(pszSource
, file
, OutputLine_asmstub
);
1062 fprintf(file
, "\n END\n");