ce8ac0be83f53830153485942d7fcaa9b22a2e97
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__))
78 char* astrCallingConventions
[] =
91 return ((chr
<= ',' && chr
!= '$') ||
92 (chr
>= ':' && chr
< '?') );
96 CompareToken(const char *token
, const char *comparand
)
100 if (*token
!= *comparand
) return 0;
104 if (!IsSeparator(*token
)) return 0;
109 ScanToken(const char *token
, char chr
)
111 while (!IsSeparator(*token
))
113 if (*token
== chr
) return token
;
124 if (pc
[0] == '\n' && pc
[1] == '\r') return pc
+ 2;
125 else if (pc
[0] == '\n') return pc
+ 1;
132 TokenLength(char *pc
)
136 while (!IsSeparator(*pc
++)) length
++;
145 while (!IsSeparator(*pc
)) pc
++;
147 /* Skip white spaces */
148 while (*pc
== ' ' || *pc
== '\t') pc
++;
150 /* Check for end of line */
151 if (*pc
== '\n' || *pc
== '\r' || *pc
== 0) return 0;
153 /* Check for comment */
154 if (*pc
== '#' || *pc
== ';') return 0;
160 OutputHeader_stub(FILE *file
)
162 fprintf(file
, "/* This file is autogenerated, do not edit. */\n\n"
163 "#include <stubs.h>\n\n");
167 OutputLine_stub(FILE *file
, EXPORT
*pexp
)
171 if (pexp
->nCallingConvention
!= CC_STUB
&&
172 (pexp
->uFlags
& FL_STUB
) == 0) return 0;
174 fprintf(file
, "int ");
175 if ((giArch
== ARCH_X86
) &&
176 pexp
->nCallingConvention
== CC_STDCALL
)
178 fprintf(file
, "__stdcall ");
182 if (pexp
->strName
.buf
[0] == '?')
184 fprintf(file
, "stub_function%d(", pexp
->nNumber
);
188 fprintf(file
, "%.*s(", pexp
->strName
.len
, pexp
->strName
.buf
);
191 for (i
= 0; i
< pexp
->nArgCount
; i
++)
193 if (i
!= 0) fprintf(file
, ", ");
194 switch (pexp
->anArgs
[i
])
196 case ARG_LONG
: fprintf(file
, "long"); break;
197 case ARG_PTR
: fprintf(file
, "void*"); break;
198 case ARG_STR
: fprintf(file
, "char*"); break;
199 case ARG_WSTR
: fprintf(file
, "wchar_t*"); break;
201 case ARG_INT64
: fprintf(file
, "__int64"); break;
202 case ARG_INT128
: fprintf(file
, "__int128"); break;
203 case ARG_FLOAT
: fprintf(file
, "float"); break;
205 fprintf(file
, " a%d", i
);
207 fprintf(file
, ")\n{\n\tDbgPrint(\"WARNING: calling stub %.*s(",
208 pexp
->strName
.len
, pexp
->strName
.buf
);
210 for (i
= 0; i
< pexp
->nArgCount
; i
++)
212 if (i
!= 0) fprintf(file
, ",");
213 switch (pexp
->anArgs
[i
])
215 case ARG_LONG
: fprintf(file
, "0x%%lx"); break;
216 case ARG_PTR
: fprintf(file
, "0x%%p"); break;
217 case ARG_STR
: fprintf(file
, "'%%s'"); break;
218 case ARG_WSTR
: fprintf(file
, "'%%ws'"); break;
219 case ARG_DBL
: fprintf(file
, "%%f"); break;
220 case ARG_INT64
: fprintf(file
, "%%\"PRix64\""); break;
221 case ARG_INT128
: fprintf(file
, "%%\"PRix128\""); break;
222 case ARG_FLOAT
: fprintf(file
, "%%f"); break;
225 fprintf(file
, ")\\n\"");
227 for (i
= 0; i
< pexp
->nArgCount
; i
++)
230 switch (pexp
->anArgs
[i
])
232 case ARG_LONG
: fprintf(file
, "(long)a%d", i
); break;
233 case ARG_PTR
: fprintf(file
, "(void*)a%d", i
); break;
234 case ARG_STR
: fprintf(file
, "(char*)a%d", i
); break;
235 case ARG_WSTR
: fprintf(file
, "(wchar_t*)a%d", i
); break;
236 case ARG_DBL
: fprintf(file
, "(double)a%d", i
); break;
237 case ARG_INT64
: fprintf(file
, "(__int64)a%d", i
); break;
238 case ARG_INT128
: fprintf(file
, "(__int128)a%d", i
); break;
239 case ARG_FLOAT
: fprintf(file
, "(float)a%d", i
); break;
242 fprintf(file
, ");\n");
244 if (pexp
->nCallingConvention
== CC_STUB
)
246 fprintf(file
, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName
);
249 fprintf(file
, "\treturn 0;\n}\n\n");
255 OutputHeader_asmstub(FILE *file
, char *libname
)
257 fprintf(file
, "; File generated automatically, do not edit! \n\n");
259 if (giArch
== ARCH_X86
)
260 fprintf(file
, ".586\n.model flat\n");
262 fprintf(file
, ".code\n");
266 OutputLine_asmstub(FILE *fileDest
, EXPORT
*pexp
)
268 /* Handle autoname */
269 if (pexp
->strName
.len
== 1 && pexp
->strName
.buf
[0] == '@')
271 fprintf(fileDest
, "PUBLIC %sordinal%d\n%sordinal%d: nop\n",
272 gpszUnderscore
, pexp
->nOrdinal
, gpszUnderscore
, pexp
->nOrdinal
);
274 else if (giArch
!= ARCH_X86
)
276 fprintf(fileDest
, "PUBLIC _stub_%.*s\n_stub_%.*s: nop\n",
277 pexp
->strName
.len
, pexp
->strName
.buf
,
278 pexp
->strName
.len
, pexp
->strName
.buf
);
280 else if (pexp
->nCallingConvention
== CC_STDCALL
)
282 fprintf(fileDest
, "PUBLIC __stub_%.*s@%d\n__stub_%.*s@%d: nop\n",
283 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
,
284 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
);
286 else if (pexp
->nCallingConvention
== CC_FASTCALL
)
288 fprintf(fileDest
, "PUBLIC @_stub_%.*s@%d\n@_stub_%.*s@%d: nop\n",
289 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
,
290 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->nStackBytes
);
292 else if (pexp
->nCallingConvention
== CC_CDECL
||
293 pexp
->nCallingConvention
== CC_STUB
)
295 fprintf(fileDest
, "PUBLIC __stub_%.*s\n__stub_%.*s: nop\n",
296 pexp
->strName
.len
, pexp
->strName
.buf
,
297 pexp
->strName
.len
, pexp
->strName
.buf
);
299 else if (pexp
->nCallingConvention
== CC_EXTERN
)
301 fprintf(fileDest
, "PUBLIC __stub_%.*s\n__stub_%.*s:\n",
302 pexp
->strName
.len
, pexp
->strName
.buf
,
303 pexp
->strName
.len
, pexp
->strName
.buf
);
310 OutputHeader_def(FILE *file
, char *libname
)
313 "; File generated automatically, do not edit!\n\n"
320 PrintName(FILE *fileDest
, EXPORT
*pexp
, PSTRING pstr
, int fDeco
)
322 const char *pcName
= pstr
->buf
;
323 int nNameLength
= pstr
->len
;
324 const char* pcDot
, *pcAt
;
326 if ((giArch
== ARCH_X86
) && fDeco
&&
327 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
328 (pexp
->nCallingConvention
== CC_FASTCALL
)))
330 /* Scan for a dll forwarding dot */
331 pcDot
= ScanToken(pcName
, '.');
334 /* First print the dll name, followed by a dot */
335 nNameLength
= pcDot
- pcName
;
336 fprintf(fileDest
, "%.*s.", nNameLength
, pcName
);
338 /* Now the actual function name */
340 nNameLength
= pexp
->strTarget
.len
- nNameLength
- 1;
343 /* Does the string already have decoration? */
344 pcAt
= ScanToken(pcName
, '@');
345 if (pcAt
&& (pcAt
< (pcName
+ nNameLength
)))
347 /* On GCC, we need to remove the leading stdcall underscore */
348 if (!gbMSComp
&& (pexp
->nCallingConvention
== CC_STDCALL
))
354 /* Print the already decorated function name */
355 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
359 /* Print the prefix, but skip it for (GCC && stdcall) */
360 if (gbMSComp
|| (pexp
->nCallingConvention
!= CC_STDCALL
))
362 fprintf(fileDest
, "%c", pexp
->nCallingConvention
== CC_FASTCALL
? '@' : '_');
365 /* Print the name with trailing decoration */
366 fprintf(fileDest
, "%.*s@%d", nNameLength
, pcName
, pexp
->nStackBytes
);
371 /* Print the undecorated function name */
372 fprintf(fileDest
, "%.*s", nNameLength
, pcName
);
377 OutputLine_def_MS(FILE *fileDest
, EXPORT
*pexp
)
379 PrintName(fileDest
, pexp
, &pexp
->strName
, 0);
383 /* Redirect to a stub function, to get the right decoration in the lib */
384 fprintf(fileDest
, "=_stub_%.*s", pexp
->strName
.len
, pexp
->strName
.buf
);
386 else if (pexp
->strTarget
.buf
)
388 if (pexp
->strName
.buf
[0] == '?')
390 fprintf(stderr
, "warning: ignoring C++ redirection %.*s -> %.*s\n",
391 pexp
->strName
.len
, pexp
->strName
.buf
, pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
395 fprintf(fileDest
, "=");
397 /* If the original name was decorated, use decoration in the forwarder as well */
398 if ((giArch
== ARCH_X86
) && ScanToken(pexp
->strName
.buf
, '@') &&
399 !ScanToken(pexp
->strTarget
.buf
, '@') &&
400 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
401 (pexp
->nCallingConvention
== CC_FASTCALL
)) )
403 PrintName(fileDest
, pexp
, &pexp
->strTarget
, 1);
407 /* Write the undecorated redirection name */
408 fprintf(fileDest
, "%.*s", pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
412 else if (((pexp
->uFlags
& FL_STUB
) || (pexp
->nCallingConvention
== CC_STUB
)) &&
413 (pexp
->strName
.buf
[0] == '?'))
415 /* C++ stubs are forwarded to C stubs */
416 fprintf(fileDest
, "=stub_function%d", pexp
->nNumber
);
421 OutputLine_def_GCC(FILE *fileDest
, EXPORT
*pexp
)
423 /* Print the function name, with decoration for export libs */
424 PrintName(fileDest
, pexp
, &pexp
->strName
, gbImportLib
);
425 DbgPrint("Generating def line for '%.*s'\n", pexp
->strName
.len
, pexp
->strName
.buf
);
427 /* Check if this is a forwarded export */
428 if (pexp
->strTarget
.buf
)
430 int fIsExternal
= !!ScanToken(pexp
->strTarget
.buf
, '.');
431 DbgPrint("Got redirect '%.*s'\n", pexp
->strTarget
.len
, pexp
->strTarget
.buf
);
433 /* print the target name, don't decorate if it is external */
434 fprintf(fileDest
, "=");
435 PrintName(fileDest
, pexp
, &pexp
->strTarget
, !fIsExternal
);
437 else if (((pexp
->uFlags
& FL_STUB
) || (pexp
->nCallingConvention
== CC_STUB
)) &&
438 (pexp
->strName
.buf
[0] == '?'))
440 /* C++ stubs are forwarded to C stubs */
441 fprintf(fileDest
, "=stub_function%d", pexp
->nNumber
);
444 /* Special handling for stdcall and fastcall */
445 if ((giArch
== ARCH_X86
) &&
446 ((pexp
->nCallingConvention
== CC_STDCALL
) ||
447 (pexp
->nCallingConvention
== CC_FASTCALL
)))
449 /* Is this the import lib? */
452 /* Is the name in the spec file decorated? */
453 const char* pcDeco
= ScanToken(pexp
->strName
.buf
, '@');
454 if (pcDeco
&& (pcDeco
< pexp
->strName
.buf
+ pexp
->strName
.len
))
456 /* Write the name including the leading @ */
457 fprintf(fileDest
, "==%.*s", pexp
->strName
.len
, pexp
->strName
.buf
);
460 else if (!pexp
->strTarget
.buf
)
462 /* Write a forwarder to the actual decorated symbol */
463 fprintf(fileDest
, "=");
464 PrintName(fileDest
, pexp
, &pexp
->strName
, 1);
470 OutputLine_def(FILE *fileDest
, EXPORT
*pexp
)
472 fprintf(fileDest
, " ");
475 OutputLine_def_MS(fileDest
, pexp
);
477 OutputLine_def_GCC(fileDest
, pexp
);
479 if (pexp
->nOrdinal
!= -1)
481 fprintf(fileDest
, " @%d", pexp
->nOrdinal
);
484 if (pexp
->uFlags
& FL_NONAME
)
486 fprintf(fileDest
, " NONAME");
489 if (pexp
->uFlags
& FL_PRIVATE
)
491 fprintf(fileDest
, " PRIVATE");
494 if (pexp
->nCallingConvention
== CC_EXTERN
)
496 fprintf(fileDest
, " DATA");
499 fprintf(fileDest
, "\n");
505 ParseFile(char* pcStart
, FILE *fileDest
, PFNOUTLINE OutputLine
)
513 //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);
518 for (pcLine
= pcStart
; *pcLine
; pcLine
= NextLine(pcLine
), nLine
++)
527 //if (!strncmp(pcLine, "22 stdcall @(long) MPR_Alloc",28))
530 //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
531 // nLine, TokenLength(pcLine), pcLine);
533 /* Skip white spaces */
534 while (*pc
== ' ' || *pc
== '\t') pc
++;
536 /* Skip empty lines, stop at EOF */
537 if (*pc
== ';' || *pc
<= '#') continue;
538 if (*pc
== 0) return 0;
540 //fprintf(stderr, "info: line %d, token:'%.*s'\n",
541 // nLine, TokenLength(pc), pc);
543 /* Now we should get either an ordinal or @ */
544 if (*pc
== '@') exp
.nOrdinal
= -1;
545 else exp
.nOrdinal
= atol(pc
);
547 /* Go to next token (type) */
548 if (!(pc
= NextToken(pc
)))
550 fprintf(stderr
, "error: line %d, unexpected end of line\n", nLine
);
554 //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc), pc);
556 /* Now we should get the type */
557 if (CompareToken(pc
, "stdcall"))
559 exp
.nCallingConvention
= CC_STDCALL
;
561 else if (CompareToken(pc
, "cdecl") ||
562 CompareToken(pc
, "varargs"))
564 exp
.nCallingConvention
= CC_CDECL
;
566 else if (CompareToken(pc
, "fastcall"))
568 exp
.nCallingConvention
= CC_FASTCALL
;
570 else if (CompareToken(pc
, "thiscall"))
572 exp
.nCallingConvention
= CC_THISCALL
;
574 else if (CompareToken(pc
, "extern"))
576 exp
.nCallingConvention
= CC_EXTERN
;
578 else if (CompareToken(pc
, "stub"))
580 exp
.nCallingConvention
= CC_STUB
;
584 fprintf(stderr
, "error: line %d, expected callconv, got '%.*s' %d\n",
585 nLine
, TokenLength(pc
), pc
, *pc
);
589 //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention);
591 /* Go to next token (options or name) */
592 if (!(pc
= NextToken(pc
)))
594 fprintf(stderr
, "fail2\n");
602 if (CompareToken(pc
, "-arch"))
604 /* Default to not included */
608 /* Look if we are included */
609 while (*pc
== '=' || *pc
== ',')
612 if (CompareToken(pc
, pszArchString
) ||
613 CompareToken(pc
, pszArchString2
))
618 /* Skip to next arch or end */
619 while (*pc
> ',') pc
++;
622 else if (CompareToken(pc
, "-i386"))
624 if (giArch
!= ARCH_X86
) included
= 0;
626 else if (CompareToken(pc
, "-private"))
628 exp
.uFlags
|= FL_PRIVATE
;
630 else if (CompareToken(pc
, "-noname") ||
631 CompareToken(pc
, "-ordinal"))
633 exp
.uFlags
|= FL_NONAME
;
635 else if (CompareToken(pc
, "-stub"))
637 exp
.uFlags
|= FL_STUB
;
639 else if (CompareToken(pc
, "-norelay") ||
640 CompareToken(pc
, "-register") ||
641 CompareToken(pc
, "-ret64"))
643 /* silently ignore these */
647 fprintf(stderr
, "info: ignored option: '%.*s'\n",
648 TokenLength(pc
), pc
);
651 /* Go to next token */
655 //fprintf(stderr, "info: Name:'%.10s'\n", pc);
657 /* If arch didn't match ours, skip this entry */
658 if (!included
) continue;
661 exp
.strName
.buf
= pc
;
662 exp
.strName
.len
= TokenLength(pc
);
664 /* Check for autoname */
665 if ((exp
.strName
.len
== 1) && (exp
.strName
.buf
[0] == '@'))
667 sprintf(namebuffer
, "ordinal%d", exp
.nOrdinal
);
668 exp
.strName
.len
= strlen(namebuffer
);
669 exp
.strName
.buf
= namebuffer
;
670 exp
.uFlags
|= FL_NONAME
;
673 /* Handle parameters */
675 if (exp
.nCallingConvention
!= CC_EXTERN
&&
676 exp
.nCallingConvention
!= CC_STUB
)
678 //fprintf(stderr, "info: options:'%.10s'\n", pc);
679 /* Go to next token */
680 if (!(pc
= NextToken(pc
)))
682 fprintf(stderr
, "fail4\n");
689 fprintf(stderr
, "error: line %d, expected '('\n", nLine
);
693 /* Skip whitespaces */
694 while (*pc
== ' ' || *pc
== '\t') pc
++;
699 if (CompareToken(pc
, "long"))
701 exp
.nStackBytes
+= 4;
702 exp
.anArgs
[exp
.nArgCount
] = ARG_LONG
;
704 else if (CompareToken(pc
, "double"))
706 exp
.nStackBytes
+= 8;
707 exp
.anArgs
[exp
.nArgCount
] = ARG_DBL
;
709 else if (CompareToken(pc
, "ptr") ||
710 CompareToken(pc
, "str") ||
711 CompareToken(pc
, "wstr"))
713 exp
.nStackBytes
+= 4; // sizeof(void*) on x86
714 exp
.anArgs
[exp
.nArgCount
] = ARG_PTR
; // FIXME: handle strings
716 else if (CompareToken(pc
, "int64"))
718 exp
.nStackBytes
+= 8;
719 exp
.anArgs
[exp
.nArgCount
] = ARG_INT64
;
721 else if (CompareToken(pc
, "int128"))
723 exp
.nStackBytes
+= 16;
724 exp
.anArgs
[exp
.nArgCount
] = ARG_INT128
;
726 else if (CompareToken(pc
, "float"))
728 exp
.nStackBytes
+= 4;
729 exp
.anArgs
[exp
.nArgCount
] = ARG_FLOAT
;
732 fprintf(stderr
, "error: line %d, expected type, got: %.10s\n", nLine
, pc
);
736 /* Go to next parameter */
737 if (!(pc
= NextToken(pc
)))
739 fprintf(stderr
, "fail5\n");
747 fprintf(stderr
, "error: line %d, expected ')'\n", nLine
);
752 /* Handle special stub cases */
753 if (exp
.nCallingConvention
== CC_STUB
)
755 /* Check for c++ mangled name */
758 //printf("Found c++ mangled name...\n");
763 /* Check for stdcall name */
764 const char *p
= ScanToken(pc
, '@');
765 if (p
&& (p
- pc
< exp
.strName
.len
))
769 /* Truncate the name to before the @ */
770 exp
.strName
.len
= (int)(p
- pc
);
771 if (exp
.strName
.len
< 1)
773 fprintf(stderr
, "error, @ in line %d\n", nLine
);
776 exp
.nStackBytes
= atoi(p
+ 1);
777 exp
.nArgCount
= exp
.nStackBytes
/ 4;
778 exp
.nCallingConvention
= CC_STDCALL
;
779 exp
.uFlags
|= FL_STUB
;
780 for (i
= 0; i
< exp
.nArgCount
; i
++)
781 exp
.anArgs
[i
] = ARG_LONG
;
786 /* Get optional redirection */
790 exp
.strTarget
.buf
= pc
;
791 exp
.strTarget
.len
= TokenLength(pc
);
793 /* Check syntax (end of line) */
796 fprintf(stderr
, "error: line %d, additional tokens after ')'\n", nLine
);
802 exp
.strTarget
.buf
= 0;
803 exp
.strTarget
.len
= 0;
806 /* Check for no-name without ordinal */
807 if ((exp
.uFlags
& FL_NONAME
) && (exp
.nOrdinal
== -1))
809 fprintf(stderr
, "error: line %d, noname export without ordinal!\n", nLine
);
812 OutputLine(fileDest
, &exp
);
822 printf("syntax: spec2pdef [<options> ...] <spec file>\n"
823 "Possible options:\n"
824 " -h --help prints this screen\n"
825 " -l=<file> generates an asm lib stub\n"
826 " -d=<file> generates a def file\n"
827 " -s=<file> generates a stub file\n"
828 " --ms msvc compatibility\n"
829 " -n=<name> name of the dll\n"
830 " --implib generate a def file for an import library\n"
831 " -a=<arch> Set architecture to <arch>. (i386, x86_64, arm)\n");
834 int main(int argc
, char *argv
[])
837 char *pszSource
, *pszDefFileName
= 0, *pszStubFileName
= 0, *pszLibStubName
= 0;
849 for (i
= 1; i
< argc
&& *argv
[i
] == '-'; i
++)
851 if ((strcasecmp(argv
[i
], "--help") == 0) ||
852 (strcasecmp(argv
[i
], "-h") == 0))
857 else if (argv
[i
][1] == 'd' && argv
[i
][2] == '=')
859 pszDefFileName
= argv
[i
] + 3;
861 else if (argv
[i
][1] == 'l' && argv
[i
][2] == '=')
863 pszLibStubName
= argv
[i
] + 3;
865 else if (argv
[i
][1] == 's' && argv
[i
][2] == '=')
867 pszStubFileName
= argv
[i
] + 3;
869 else if (argv
[i
][1] == 'n' && argv
[i
][2] == '=')
871 pszDllName
= argv
[i
] + 3;
873 else if ((strcasecmp(argv
[i
], "--implib") == 0))
877 else if ((strcasecmp(argv
[i
], "--ms") == 0))
881 else if (argv
[i
][1] == 'a' && argv
[i
][2] == '=')
883 pszArchString
= argv
[i
] + 3;
887 fprintf(stderr
, "Unrecognized option: %s\n", argv
[i
]);
892 if (strcasecmp(pszArchString
, "i386") == 0)
895 gpszUnderscore
= "_";
897 else if (strcasecmp(pszArchString
, "x86_64") == 0) giArch
= ARCH_AMD64
;
898 else if (strcasecmp(pszArchString
, "ia64") == 0) giArch
= ARCH_IA64
;
899 else if (strcasecmp(pszArchString
, "arm") == 0) giArch
= ARCH_ARM
;
900 else if (strcasecmp(pszArchString
, "ppc") == 0) giArch
= ARCH_PPC
;
902 if ((giArch
== ARCH_AMD64
) || (giArch
== ARCH_IA64
))
904 pszArchString2
= "win64";
907 pszArchString2
= "win32";
909 /* Set a default dll name */
915 p1
= strrchr(argv
[i
], '\\');
916 if (!p1
) p1
= strrchr(argv
[i
], '/');
917 p2
= p1
= p1
? p1
+ 1 : argv
[i
];
920 while (*p2
!= '.' && *p2
!= 0) p2
++;
922 if (len
>= sizeof(achDllName
) - 5)
924 fprintf(stderr
, "name too long: %s\n", p1
);
928 strncpy(achDllName
, p1
, len
);
929 strncpy(achDllName
+ len
, ".dll", sizeof(achDllName
) - len
);
930 pszDllName
= achDllName
;
933 /* Open input file argv[1] */
934 file
= fopen(argv
[i
], "r");
937 fprintf(stderr
, "error: could not open file %s ", argv
[i
]);
942 fseek(file
, 0, SEEK_END
);
943 nFileSize
= ftell(file
);
946 /* Allocate memory buffer */
947 pszSource
= malloc(nFileSize
+ 1);
954 /* Load input file into memory */
955 nFileSize
= fread(pszSource
, 1, nFileSize
, file
);
958 /* Zero terminate the source */
959 pszSource
[nFileSize
] = '\0';
963 /* Open output file */
964 file
= fopen(pszDefFileName
, "w");
967 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
971 OutputHeader_def(file
, pszDllName
);
972 result
= ParseFile(pszSource
, file
, OutputLine_def
);
978 /* Open output file */
979 file
= fopen(pszStubFileName
, "w");
982 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
986 OutputHeader_stub(file
);
987 result
= ParseFile(pszSource
, file
, OutputLine_stub
);
993 /* Open output file */
994 file
= fopen(pszLibStubName
, "w");
997 fprintf(stderr
, "error: could not open output file %s ", argv
[i
+ 1]);
1001 OutputHeader_asmstub(file
, pszDllName
);
1002 result
= ParseFile(pszSource
, file
, OutputLine_asmstub
);
1003 fprintf(file
, "\nEND\n");