[SPEC2DEF]
[reactos.git] / reactos / tools / spec2def / spec2def.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <string.h>
5
6 #ifdef _MSC_VER
7 #define strcasecmp _stricmp
8 #endif
9
10 typedef struct
11 {
12 char *pcName;
13 int nNameLength;
14 char *pcRedirection;
15 int nRedirectionLength;
16 int nCallingConvention;
17 int nOrdinal;
18 int nStackBytes;
19 int nArgCount;
20 int anArgs[30];
21 unsigned int uFlags;
22 int nNumber;
23 } EXPORT;
24
25 enum _ARCH
26 {
27 ARCH_X86,
28 ARCH_AMD64,
29 ARCH_IA64,
30 ARCH_ARM,
31 ARCH_PPC
32 };
33
34 typedef int (*PFNOUTLINE)(FILE *, EXPORT *);
35 int gbKillAt = 0;
36 int gbMSComp = 0;
37 int gbImportLib = 0;
38 int no_redirections = 0;
39 int giArch = ARCH_X86;
40 char *pszArchString = "i386";
41 char *pszArchString2;
42 char *pszDllName = 0;
43 char *gpszUnderscore = "";
44
45 enum
46 {
47 FL_PRIVATE = 1,
48 FL_STUB = 2,
49 FL_NONAME = 4,
50 };
51
52 enum
53 {
54 CC_STDCALL,
55 CC_CDECL,
56 CC_FASTCALL,
57 CC_THISCALL,
58 CC_EXTERN,
59 CC_STUB,
60 };
61
62 enum
63 {
64 ARG_LONG,
65 ARG_PTR,
66 ARG_STR,
67 ARG_WSTR,
68 ARG_DBL,
69 ARG_INT64,
70 ARG_INT128,
71 ARG_FLOAT
72 };
73
74 char* astrCallingConventions[] =
75 {
76 "STDCALL",
77 "CDECL",
78 "FASTCALL",
79 "THISCALL",
80 "EXTERN"
81 };
82
83 static
84 int
85 IsSeparator(char chr)
86 {
87 return ((chr <= ',' && chr != '$') ||
88 (chr >= ':' && chr < '?') );
89 }
90
91 int
92 CompareToken(const char *token, const char *comparand)
93 {
94 while (*comparand)
95 {
96 if (*token != *comparand) return 0;
97 token++;
98 comparand++;
99 }
100 if (!IsSeparator(*token)) return 0;
101 return 1;
102 }
103
104 int
105 ScanToken(const char *token, char chr)
106 {
107 while (!IsSeparator(*token))
108 {
109 if (*token++ == chr) return 1;
110 }
111 return 0;
112 }
113
114 char *
115 NextLine(char *pc)
116 {
117 while (*pc != 0)
118 {
119 if (pc[0] == '\n' && pc[1] == '\r') return pc + 2;
120 else if (pc[0] == '\n') return pc + 1;
121 pc++;
122 }
123 return pc;
124 }
125
126 int
127 TokenLength(char *pc)
128 {
129 int length = 0;
130
131 while (!IsSeparator(*pc++)) length++;
132
133 return length;
134 }
135
136 char *
137 NextToken(char *pc)
138 {
139 /* Skip token */
140 while (!IsSeparator(*pc)) pc++;
141
142 /* Skip white spaces */
143 while (*pc == ' ' || *pc == '\t') pc++;
144
145 /* Check for end of line */
146 if (*pc == '\n' || *pc == '\r' || *pc == 0) return 0;
147
148 /* Check for comment */
149 if (*pc == '#' || *pc == ';') return 0;
150
151 return pc;
152 }
153
154 void
155 OutputHeader_stub(FILE *file)
156 {
157 fprintf(file, "/* This file is autogenerated, do not edit. */\n\n"
158 "#include <stubs.h>\n\n");
159 }
160
161 int
162 OutputLine_stub(FILE *file, EXPORT *pexp)
163 {
164 int i;
165
166 if (pexp->nCallingConvention != CC_STUB &&
167 (pexp->uFlags & FL_STUB) == 0) return 0;
168
169 fprintf(file, "int ");
170 if ((giArch == ARCH_X86) &&
171 pexp->nCallingConvention == CC_STDCALL)
172 {
173 fprintf(file, "__stdcall ");
174 }
175
176 /* Check for C++ */
177 if (pexp->pcName[0] == '?')
178 {
179 fprintf(file, "stub_function%d(", pexp->nNumber);
180 }
181 else
182 {
183 fprintf(file, "%.*s(", pexp->nNameLength, pexp->pcName);
184 }
185
186 for (i = 0; i < pexp->nArgCount; i++)
187 {
188 if (i != 0) fprintf(file, ", ");
189 switch (pexp->anArgs[i])
190 {
191 case ARG_LONG: fprintf(file, "long"); break;
192 case ARG_PTR: fprintf(file, "void*"); break;
193 case ARG_STR: fprintf(file, "char*"); break;
194 case ARG_WSTR: fprintf(file, "wchar_t*"); break;
195 case ARG_DBL:
196 case ARG_INT64 : fprintf(file, "__int64"); break;
197 case ARG_INT128 : fprintf(file, "__int128"); break;
198 case ARG_FLOAT: fprintf(file, "float"); break;
199 }
200 fprintf(file, " a%d", i);
201 }
202 fprintf(file, ")\n{\n\tDPRINT1(\"WARNING: calling stub %.*s(",
203 pexp->nNameLength, pexp->pcName);
204
205 for (i = 0; i < pexp->nArgCount; i++)
206 {
207 if (i != 0) fprintf(file, ",");
208 switch (pexp->anArgs[i])
209 {
210 case ARG_LONG: fprintf(file, "0x%%lx"); break;
211 case ARG_PTR: fprintf(file, "0x%%p"); break;
212 case ARG_STR: fprintf(file, "'%%s'"); break;
213 case ARG_WSTR: fprintf(file, "'%%ws'"); break;
214 case ARG_DBL: fprintf(file, "%%f"); break;
215 case ARG_INT64: fprintf(file, "%%\"PRix64\""); break;
216 case ARG_INT128: fprintf(file, "%%\"PRix128\""); break;
217 case ARG_FLOAT: fprintf(file, "%%f"); break;
218 }
219 }
220 fprintf(file, ")\\n\"");
221
222 for (i = 0; i < pexp->nArgCount; i++)
223 {
224 fprintf(file, ", ");
225 switch (pexp->anArgs[i])
226 {
227 case ARG_LONG: fprintf(file, "(long)a%d", i); break;
228 case ARG_PTR: fprintf(file, "(void*)a%d", i); break;
229 case ARG_STR: fprintf(file, "(char*)a%d", i); break;
230 case ARG_WSTR: fprintf(file, "(wchar_t*)a%d", i); break;
231 case ARG_DBL: fprintf(file, "(double)a%d", i); break;
232 case ARG_INT64: fprintf(file, "(__int64)a%d", i); break;
233 case ARG_INT128: fprintf(file, "(__int128)a%d", i); break;
234 case ARG_FLOAT: fprintf(file, "(float)a%d", i); break;
235 }
236 }
237 fprintf(file, ");\n");
238
239 if (pexp->nCallingConvention == CC_STUB)
240 {
241 fprintf(file, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName);
242 }
243
244 fprintf(file, "\treturn 0;\n}\n\n");
245
246 return 1;
247 }
248
249 void
250 OutputHeader_asmstub(FILE *file, char *libname)
251 {
252 fprintf(file, "; File generated automatically, do not edit! \n\n");
253
254 if (giArch == ARCH_X86)
255 fprintf(file, ".586\n.model flat\n");
256
257 fprintf(file, ".code\n");
258 }
259
260 int
261 OutputLine_asmstub(FILE *fileDest, EXPORT *pexp)
262 {
263 /* Handle autoname */
264 if (pexp->nNameLength == 1 && pexp->pcName[0] == '@')
265 {
266 fprintf(fileDest, "PUBLIC %sordinal%d\n%sordinal%d: nop\n",
267 gpszUnderscore, pexp->nOrdinal, gpszUnderscore, pexp->nOrdinal);
268 }
269 else if (giArch != ARCH_X86)
270 {
271 fprintf(fileDest, "PUBLIC _stub_%.*s\n_stub_%.*s: nop\n",
272 pexp->nNameLength, pexp->pcName,
273 pexp->nNameLength, pexp->pcName);
274 }
275 else if (pexp->nCallingConvention == CC_STDCALL)
276 {
277 fprintf(fileDest, "PUBLIC __stub_%.*s@%d\n__stub_%.*s@%d: nop\n",
278 pexp->nNameLength, pexp->pcName, pexp->nStackBytes,
279 pexp->nNameLength, pexp->pcName, pexp->nStackBytes);
280 }
281 else if (pexp->nCallingConvention == CC_FASTCALL)
282 {
283 fprintf(fileDest, "PUBLIC @_stub_%.*s@%d\n@_stub_%.*s@%d: nop\n",
284 pexp->nNameLength, pexp->pcName, pexp->nStackBytes,
285 pexp->nNameLength, pexp->pcName, pexp->nStackBytes);
286 }
287 else if (pexp->nCallingConvention == CC_CDECL ||
288 pexp->nCallingConvention == CC_STUB)
289 {
290 fprintf(fileDest, "PUBLIC __stub_%.*s\n__stub_%.*s: nop\n",
291 pexp->nNameLength, pexp->pcName,
292 pexp->nNameLength, pexp->pcName);
293 }
294 else if (pexp->nCallingConvention == CC_EXTERN)
295 {
296 fprintf(fileDest, "PUBLIC __stub_%.*s\n__stub_%.*s:\n",
297 pexp->nNameLength, pexp->pcName,
298 pexp->nNameLength, pexp->pcName);
299 }
300
301 return 1;
302 }
303
304 void
305 OutputHeader_def(FILE *file, char *libname)
306 {
307 fprintf(file,
308 "; File generated automatically, do not edit!\n\n"
309 "NAME %s\n\n"
310 "EXPORTS\n",
311 libname);
312 }
313
314 void
315 PrintName(FILE *fileDest, EXPORT *pexp, char *pszPrefix, int fRedir, int fDeco)
316 {
317 char *pcName = fRedir ? pexp->pcRedirection : pexp->pcName;
318 int nNameLength = fRedir ? pexp->nRedirectionLength : pexp->nNameLength;
319
320 /* Handle autoname */
321 if (nNameLength == 1 && pcName[0] == '@')
322 {
323 fprintf(fileDest, "ordinal%d", pexp->nOrdinal);
324 }
325 else
326 {
327 if (fDeco && pexp->nCallingConvention == CC_FASTCALL)
328 fprintf(fileDest, "@");
329 fprintf(fileDest, "%s%.*s", pszPrefix, nNameLength, pcName);
330 if ((pexp->nCallingConvention == CC_STDCALL ||
331 pexp->nCallingConvention == CC_FASTCALL) && fDeco)
332 {
333 fprintf(fileDest, "@%d", pexp->nStackBytes);
334 }
335 }
336 }
337
338 int
339 OutputLine_def(FILE *fileDest, EXPORT *pexp)
340 {
341 fprintf(fileDest, " ");
342
343 PrintName(fileDest, pexp, "", 0, (giArch == ARCH_X86) && !gbKillAt);
344
345 if (gbImportLib)
346 {
347 fprintf(fileDest, "=");
348 PrintName(fileDest, pexp, "_stub_", 0, 0);
349 }
350 else if (pexp->pcRedirection)
351 {
352 if (gbMSComp && (pexp->pcName[0] == '?'))
353 {
354 /* ignore c++ redirection, since link doesn't like that! */
355 }
356 else
357 {
358 int fDeco;
359
360 fDeco = ((giArch == ARCH_X86) && !ScanToken(pexp->pcRedirection, '.'));
361 fprintf(fileDest, "=");
362 PrintName(fileDest, pexp, "", 1, fDeco && !gbMSComp);
363 }
364 }
365 else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) &&
366 (pexp->pcName[0] == '?'))
367 {
368 /* C++ stubs are forwarded to C stubs */
369 fprintf(fileDest, "=");
370 fprintf(fileDest, "stub_function%d", pexp->nNumber);
371 }
372 else if ((giArch == ARCH_X86) && gbKillAt && !gbMSComp &&
373 (pexp->nCallingConvention == CC_STDCALL ||
374 pexp->nCallingConvention == CC_FASTCALL))
375 {
376 fprintf(fileDest, "=");
377 PrintName(fileDest, pexp, "", 0, 1);
378 }
379
380 if (pexp->nOrdinal != -1)
381 {
382 fprintf(fileDest, " @%d", pexp->nOrdinal);
383 }
384
385 if (pexp->nCallingConvention == CC_EXTERN)
386 {
387 fprintf(fileDest, " DATA");
388 }
389
390 if (pexp->uFlags & FL_PRIVATE)
391 {
392 fprintf(fileDest, " PRIVATE");
393 }
394
395 if (pexp->uFlags & FL_NONAME)
396 {
397 fprintf(fileDest, " NONAME");
398 }
399
400 fprintf(fileDest, "\n");
401
402 return 1;
403 }
404
405 int
406 ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
407 {
408 char *pc, *pcLine;
409 int nLine;
410 EXPORT exp;
411 int included;
412
413 //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);
414
415 /* Loop all lines */
416 nLine = 1;
417 exp.nNumber = 0;
418 for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++)
419 {
420 pc = pcLine;
421
422 exp.nArgCount = 0;
423 exp.uFlags = 0;
424 exp.nNumber++;
425
426 //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
427 // nLine, TokenLength(pcLine), pcLine);
428
429 /* Skip white spaces */
430 while (*pc == ' ' || *pc == '\t') pc++;
431
432 /* Skip empty lines, stop at EOF */
433 if (*pc == ';' || *pc <= '#') continue;
434 if (*pc == 0) return 0;
435
436 //fprintf(stderr, "info: line %d, token:'%.*s'\n",
437 // nLine, TokenLength(pc), pc);
438
439 /* Now we should get either an ordinal or @ */
440 if (*pc == '@') exp.nOrdinal = -1;
441 else exp.nOrdinal = atol(pc);
442
443 /* Go to next token (type) */
444 if (!(pc = NextToken(pc)))
445 {
446 fprintf(stderr, "error: line %d, unexpected end of line\n", nLine);
447 return -10;
448 }
449
450 //fprintf(stderr, "info: Token:'%.10s'\n", pc);
451
452 /* Now we should get the type */
453 if (CompareToken(pc, "stdcall"))
454 {
455 exp.nCallingConvention = CC_STDCALL;
456 }
457 else if (CompareToken(pc, "cdecl") ||
458 CompareToken(pc, "varargs"))
459 {
460 exp.nCallingConvention = CC_CDECL;
461 }
462 else if (CompareToken(pc, "fastcall"))
463 {
464 exp.nCallingConvention = CC_FASTCALL;
465 }
466 else if (CompareToken(pc, "thiscall"))
467 {
468 exp.nCallingConvention = CC_THISCALL;
469 }
470 else if (CompareToken(pc, "extern"))
471 {
472 exp.nCallingConvention = CC_EXTERN;
473 }
474 else if (CompareToken(pc, "stub"))
475 {
476 exp.nCallingConvention = CC_STUB;
477 }
478 else
479 {
480 fprintf(stderr, "error: line %d, expected type, got '%.*s' %d\n",
481 nLine, TokenLength(pc), pc, *pc);
482 return -11;
483 }
484
485 //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention);
486
487 /* Go to next token (options or name) */
488 if (!(pc = NextToken(pc)))
489 {
490 fprintf(stderr, "fail2\n");
491 return -12;
492 }
493
494 /* Handle options */
495 included = 1;
496 while (*pc == '-')
497 {
498 if (CompareToken(pc, "-arch"))
499 {
500 /* Default to not included */
501 included = 0;
502 pc += 5;
503
504 /* Look if we are included */
505 while (*pc == '=' || *pc == ',')
506 {
507 pc++;
508 if (CompareToken(pc, pszArchString) ||
509 CompareToken(pc, pszArchString2))
510 {
511 included = 1;
512 }
513
514 /* Skip to next arch or end */
515 while (*pc > ',') pc++;
516 }
517 }
518 else if (CompareToken(pc, "-i386"))
519 {
520 if (giArch != ARCH_X86) included = 0;
521 }
522 else if (CompareToken(pc, "-private"))
523 {
524 exp.uFlags |= FL_PRIVATE;
525 }
526 else if (CompareToken(pc, "-noname") ||
527 CompareToken(pc, "-ordinal"))
528 {
529 exp.uFlags |= FL_NONAME;
530 }
531 else if (CompareToken(pc, "-stub"))
532 {
533 exp.uFlags |= FL_STUB;
534 }
535 else if (CompareToken(pc, "-norelay") ||
536 CompareToken(pc, "-register") ||
537 CompareToken(pc, "-ret64"))
538 {
539 /* silently ignore these */
540 }
541 else
542 {
543 fprintf(stderr, "info: ignored option: '%.*s'\n",
544 TokenLength(pc), pc);
545 }
546
547 /* Go to next token */
548 pc = NextToken(pc);
549 }
550
551 //fprintf(stderr, "info: Name:'%.10s'\n", pc);
552
553 /* If arch didn't match ours, skip this entry */
554 if (!included) continue;
555
556 /* Get name */
557 exp.pcName = pc;
558 exp.nNameLength = TokenLength(pc);
559
560 /* Handle parameters */
561 exp.nStackBytes = 0;
562 if (exp.nCallingConvention != CC_EXTERN &&
563 exp.nCallingConvention != CC_STUB)
564 {
565 //fprintf(stderr, "info: options:'%.10s'\n", pc);
566 /* Go to next token */
567 if (!(pc = NextToken(pc)))
568 {
569 fprintf(stderr, "fail4\n");
570 return -13;
571 }
572
573 /* Verify syntax */
574 if (*pc++ != '(')
575 {
576 fprintf(stderr, "error: line %d, expected '('\n", nLine);
577 return -14;
578 }
579
580 /* Skip whitespaces */
581 while (*pc == ' ' || *pc == '\t') pc++;
582
583 exp.nStackBytes = 0;
584 while (*pc >= '0')
585 {
586 if (CompareToken(pc, "long"))
587 {
588 exp.nStackBytes += 4;
589 exp.anArgs[exp.nArgCount] = ARG_LONG;
590 }
591 else if (CompareToken(pc, "double"))
592 {
593 exp.nStackBytes += 8;
594 exp.anArgs[exp.nArgCount] = ARG_DBL;
595 }
596 else if (CompareToken(pc, "ptr") ||
597 CompareToken(pc, "str") ||
598 CompareToken(pc, "wstr"))
599 {
600 exp.nStackBytes += 4; // sizeof(void*) on x86
601 exp.anArgs[exp.nArgCount] = ARG_PTR; // FIXME: handle strings
602 }
603 else if (CompareToken(pc, "int64"))
604 {
605 exp.nStackBytes += 8;
606 exp.anArgs[exp.nArgCount] = ARG_INT64;
607 }
608 else if (CompareToken(pc, "int128"))
609 {
610 exp.nStackBytes += 16;
611 exp.anArgs[exp.nArgCount] = ARG_INT128;
612 }
613 else if (CompareToken(pc, "float"))
614 {
615 exp.nStackBytes += 4;
616 exp.anArgs[exp.nArgCount] = ARG_FLOAT;
617 }
618 else
619 fprintf(stderr, "error: line %d, expected type, got: %.10s\n", nLine, pc);
620
621 exp.nArgCount++;
622
623 /* Go to next parameter */
624 if (!(pc = NextToken(pc)))
625 {
626 fprintf(stderr, "fail5\n");
627 return -15;
628 }
629 }
630
631 /* Check syntax */
632 if (*pc++ != ')')
633 {
634 fprintf(stderr, "error: line %d, expected ')'\n", nLine);
635 return -16;
636 }
637 }
638
639 /* Handle special stub cases */
640 if (exp.nCallingConvention == CC_STUB)
641 {
642 /* Check for c++ mangled name */
643 if (pc[0] == '?')
644 {
645 //printf("Found c++ mangled name...\n");
646 //
647 }
648 else
649 {
650 /* Check for stdcall name */
651 char *p = strchr(pc, '@');
652 if (p && (p - pc < exp.nNameLength))
653 {
654 int i;
655 exp.nNameLength = (int)(p - pc);
656 if (exp.nNameLength < 1)
657 {
658 fprintf(stderr, "error, @ in line %d\n", nLine);
659 return -1;
660 }
661 exp.nStackBytes = atoi(p + 1);
662 exp.nArgCount = exp.nStackBytes / 4;
663 exp.nCallingConvention = CC_STDCALL;
664 exp.uFlags |= FL_STUB;
665 for (i = 0; i < exp.nArgCount; i++)
666 exp.anArgs[i] = ARG_LONG;
667 }
668 }
669 }
670
671 /* Get optional redirection */
672 pc = NextToken(pc);
673 if (pc)
674 {
675 exp.pcRedirection = pc;
676 exp.nRedirectionLength = TokenLength(pc);
677
678 /* Check syntax (end of line) */
679 if (NextToken(pc))
680 {
681 fprintf(stderr, "error: line %d, additional tokens after ')'\n", nLine);
682 return -17;
683 }
684 }
685 else
686 {
687 exp.pcRedirection = 0;
688 exp.nRedirectionLength = 0;
689 }
690
691 OutputLine(fileDest, &exp);
692 }
693
694 return 0;
695 }
696
697
698 void usage(void)
699 {
700 printf("syntax: spec2pdef [<options> ...] <spec file>\n"
701 "Possible options:\n"
702 " -h --help prints this screen\n"
703 " -l=<file> generates an asm lib stub\n"
704 " -d=<file> generates a def file\n"
705 " -s=<file> generates a stub file\n"
706 " --ms msvc compatibility\n"
707 " -n=<name> name of the dll\n"
708 " --kill-at removes @xx decorations from exports\n"
709 " -r removes redirections from def file\n"
710 " -a=<arch> Set architecture to <arch>. (i386, x86_64, arm)\n");
711 }
712
713 int main(int argc, char *argv[])
714 {
715 size_t nFileSize;
716 char *pszSource, *pszDefFileName = 0, *pszStubFileName = 0, *pszLibStubName = 0;
717 char achDllName[40];
718 FILE *file;
719 int result = 0, i;
720
721 if (argc < 2)
722 {
723 usage();
724 return -1;
725 }
726
727 /* Read options */
728 for (i = 1; i < argc && *argv[i] == '-'; i++)
729 {
730 if ((strcasecmp(argv[i], "--help") == 0) ||
731 (strcasecmp(argv[i], "-h") == 0))
732 {
733 usage();
734 return 0;
735 }
736 else if (argv[i][1] == 'd' && argv[i][2] == '=')
737 {
738 pszDefFileName = argv[i] + 3;
739 }
740 else if (argv[i][1] == 'l' && argv[i][2] == '=')
741 {
742 pszLibStubName = argv[i] + 3;
743 }
744 else if (argv[i][1] == 's' && argv[i][2] == '=')
745 {
746 pszStubFileName = argv[i] + 3;
747 }
748 else if (argv[i][1] == 'n' && argv[i][2] == '=')
749 {
750 pszDllName = argv[i] + 3;
751 }
752 else if ((strcasecmp(argv[i], "--implib") == 0))
753 {
754 no_redirections = 1;
755 gbImportLib = 1;
756 }
757 else if ((strcasecmp(argv[i], "--kill-at") == 0))
758 {
759 gbKillAt = 1;
760 }
761 else if ((strcasecmp(argv[i], "--ms") == 0))
762 {
763 gbMSComp = 1;
764 }
765 else if ((strcasecmp(argv[i], "-r") == 0))
766 {
767 no_redirections = 1;
768 }
769 else if (argv[i][1] == 'a' && argv[i][2] == '=')
770 {
771 pszArchString = argv[i] + 3;
772 }
773 else
774 {
775 fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
776 return -1;
777 }
778 }
779
780 if (strcasecmp(pszArchString, "i386") == 0)
781 {
782 giArch = ARCH_X86;
783 gpszUnderscore = "_";
784 }
785 else if (strcasecmp(pszArchString, "x86_64") == 0) giArch = ARCH_AMD64;
786 else if (strcasecmp(pszArchString, "ia64") == 0) giArch = ARCH_IA64;
787 else if (strcasecmp(pszArchString, "arm") == 0) giArch = ARCH_ARM;
788 else if (strcasecmp(pszArchString, "ppc") == 0) giArch = ARCH_PPC;
789
790 if ((giArch == ARCH_AMD64) || (giArch == ARCH_IA64))
791 {
792 pszArchString2 = "win64";
793 }
794 else
795 pszArchString2 = "win32";
796
797 /* Set a default dll name */
798 if (!pszDllName)
799 {
800 char *p1, *p2;
801 size_t len;
802
803 p1 = strrchr(argv[i], '\\');
804 if (!p1) p1 = strrchr(argv[i], '/');
805 p2 = p1 = p1 ? p1 + 1 : argv[i];
806
807 /* walk up to '.' */
808 while (*p2 != '.' && *p2 != 0) p2++;
809 len = p2 - p1;
810 if (len >= sizeof(achDllName) - 5)
811 {
812 fprintf(stderr, "name too long: %s\n", p1);
813 return -2;
814 }
815
816 strncpy(achDllName, p1, len);
817 strncpy(achDllName + len, ".dll", sizeof(achDllName) - len);
818 pszDllName = achDllName;
819 }
820
821 /* Open input file argv[1] */
822 file = fopen(argv[i], "r");
823 if (!file)
824 {
825 fprintf(stderr, "error: could not open file %s ", argv[i]);
826 return -3;
827 }
828
829 /* Get file size */
830 fseek(file, 0, SEEK_END);
831 nFileSize = ftell(file);
832 rewind(file);
833
834 /* Allocate memory buffer */
835 pszSource = malloc(nFileSize + 1);
836 if (!pszSource)
837 {
838 fclose(file);
839 return -4;
840 }
841
842 /* Load input file into memory */
843 nFileSize = fread(pszSource, 1, nFileSize, file);
844 fclose(file);
845
846 /* Zero terminate the source */
847 pszSource[nFileSize] = '\0';
848
849 if (pszDefFileName)
850 {
851 /* Open output file */
852 file = fopen(pszDefFileName, "w");
853 if (!file)
854 {
855 fprintf(stderr, "error: could not open output file %s ", argv[i + 1]);
856 return -5;
857 }
858
859 OutputHeader_def(file, pszDllName);
860 result = ParseFile(pszSource, file, OutputLine_def);
861 fclose(file);
862 }
863
864 if (pszStubFileName)
865 {
866 /* Open output file */
867 file = fopen(pszStubFileName, "w");
868 if (!file)
869 {
870 fprintf(stderr, "error: could not open output file %s ", argv[i + 1]);
871 return -5;
872 }
873
874 OutputHeader_stub(file);
875 result = ParseFile(pszSource, file, OutputLine_stub);
876 fclose(file);
877 }
878
879 if (pszLibStubName)
880 {
881 /* Open output file */
882 file = fopen(pszLibStubName, "w");
883 if (!file)
884 {
885 fprintf(stderr, "error: could not open output file %s ", argv[i + 1]);
886 return -5;
887 }
888
889 OutputHeader_asmstub(file, pszDllName);
890 result = ParseFile(pszSource, file, OutputLine_asmstub);
891 fprintf(file, "\nEND\n");
892 fclose(file);
893 }
894
895
896 return result;
897 }