4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Martin von Loewis
6 * Copyright 1995, 1996, 1997 Alexandre Julliard
7 * Copyright 1997 Eric Youngdale
8 * Copyright 1999 Ulrich Weigand
22 static SPEC_TYPE SpecType
= SPEC_INVALID
;
24 static char ParseBuffer
[512];
25 static char *ParseNext
= ParseBuffer
;
26 static char ParseSaveChar
;
27 static FILE *input_file
;
29 static const char * const TypeNames
[TYPE_NBTYPES
] =
31 "byte", /* TYPE_BYTE */
32 "word", /* TYPE_WORD */
33 "long", /* TYPE_LONG */
34 "pascal16", /* TYPE_PASCAL_16 */
35 "pascal", /* TYPE_PASCAL */
36 "equate", /* TYPE_ABS */
37 "register", /* TYPE_REGISTER */
38 "interrupt", /* TYPE_INTERRUPT */
39 "stub", /* TYPE_STUB */
40 "stdcall", /* TYPE_STDCALL */
41 "cdecl", /* TYPE_CDECL */
42 "varargs", /* TYPE_VARARGS */
43 "extern", /* TYPE_EXTERN */
44 "forward" /* TYPE_FORWARD */
47 /* callback function used for stub functions */
48 #define STUB_CALLBACK \
49 ((SpecType == SPEC_WIN16) ? "RELAY_Unimplemented16": "RELAY_Unimplemented32")
51 static int IsNumberString(char *s
)
53 while (*s
) if (!isdigit(*s
++)) return 0;
57 static char * GetTokenInLine(void)
62 if (ParseNext
!= ParseBuffer
)
64 if (ParseSaveChar
== '\0')
66 *ParseNext
= ParseSaveChar
;
70 * Remove initial white space.
72 for (p
= ParseNext
; isspace(*p
); p
++)
75 if ((*p
== '\0') || (*p
== '#'))
82 if (*token
!= '(' && *token
!= ')')
83 while (*p
!= '\0' && *p
!= '(' && *p
!= ')' && !isspace(*p
))
93 static char * GetToken(void)
97 while ((token
= GetTokenInLine()) == NULL
)
99 ParseNext
= ParseBuffer
;
103 if (fgets(ParseBuffer
, sizeof(ParseBuffer
), input_file
) == NULL
)
105 if (ParseBuffer
[0] != '#')
113 /*******************************************************************
116 * Parse a variable definition.
118 static void ParseVariable( ORDDEF
*odp
)
123 int value_array_size
;
125 char *token
= GetToken();
126 if (*token
!= '(') fatal_error( "Expected '(' got '%s'\n", token
);
129 value_array_size
= 25;
130 value_array
= xmalloc(sizeof(*value_array
) * value_array_size
);
132 while ((token
= GetToken()) != NULL
)
137 value_array
[n_values
++] = strtol(token
, &endptr
, 0);
138 if (n_values
== value_array_size
)
140 value_array_size
+= 25;
141 value_array
= xrealloc(value_array
,
142 sizeof(*value_array
) * value_array_size
);
145 if (endptr
== NULL
|| *endptr
!= '\0')
146 fatal_error( "Expected number value, got '%s'\n", token
);
150 fatal_error( "End of file in variable declaration\n" );
152 odp
->u
.var
.n_values
= n_values
;
153 odp
->u
.var
.values
= xrealloc(value_array
, sizeof(*value_array
) * n_values
);
157 /*******************************************************************
158 * ParseExportFunction
160 * Parse a function definition.
162 static void ParseExportFunction( ORDDEF
*odp
)
170 if (odp
->type
== TYPE_STDCALL
)
171 fatal_error( "'stdcall' not supported for Win16\n" );
172 if (odp
->type
== TYPE_VARARGS
)
173 fatal_error( "'varargs' not supported for Win16\n" );
176 if ((odp
->type
== TYPE_PASCAL
) || (odp
->type
== TYPE_PASCAL_16
))
177 fatal_error( "'pascal' not supported for Win32\n" );
184 if (*token
!= '(') fatal_error( "Expected '(' got '%s'\n", token
);
186 for (i
= 0; i
< sizeof(odp
->u
.func
.arg_types
)-1; i
++)
192 if (!strcmp(token
, "word"))
193 odp
->u
.func
.arg_types
[i
] = 'w';
194 else if (!strcmp(token
, "s_word"))
195 odp
->u
.func
.arg_types
[i
] = 's';
196 else if (!strcmp(token
, "long") || !strcmp(token
, "segptr"))
197 odp
->u
.func
.arg_types
[i
] = 'l';
198 else if (!strcmp(token
, "ptr"))
199 odp
->u
.func
.arg_types
[i
] = 'p';
200 else if (!strcmp(token
, "str"))
201 odp
->u
.func
.arg_types
[i
] = 't';
202 else if (!strcmp(token
, "wstr"))
203 odp
->u
.func
.arg_types
[i
] = 'W';
204 else if (!strcmp(token
, "segstr"))
205 odp
->u
.func
.arg_types
[i
] = 'T';
206 else if (!strcmp(token
, "double"))
208 odp
->u
.func
.arg_types
[i
++] = 'l';
209 odp
->u
.func
.arg_types
[i
] = 'l';
211 else fatal_error( "Unknown variable type '%s'\n", token
);
213 if (SpecType
== SPEC_WIN32
)
215 if (strcmp(token
, "long") &&
216 strcmp(token
, "ptr") &&
217 strcmp(token
, "str") &&
218 strcmp(token
, "wstr") &&
219 strcmp(token
, "double"))
221 fatal_error( "Type '%s' not supported for Win32\n", token
);
225 if ((*token
!= ')') || (i
>= sizeof(odp
->u
.func
.arg_types
)))
226 fatal_error( "Too many arguments\n" );
228 odp
->u
.func
.arg_types
[i
] = '\0';
229 if ((odp
->type
== TYPE_STDCALL
) && !i
)
230 odp
->type
= TYPE_CDECL
; /* stdcall is the same as cdecl for 0 args */
231 strcpy(odp
->u
.func
.link_name
, GetToken());
235 /*******************************************************************
238 * Parse an 'equate' definition.
240 static void ParseEquate( ORDDEF
*odp
)
244 char *token
= GetToken();
245 int value
= strtol(token
, &endptr
, 0);
246 if (endptr
== NULL
|| *endptr
!= '\0')
247 fatal_error( "Expected number value, got '%s'\n", token
);
248 if (SpecType
== SPEC_WIN32
)
249 fatal_error( "'equate' not supported for Win32\n" );
250 odp
->u
.abs
.value
= value
;
254 /*******************************************************************
257 * Parse a 'stub' definition.
259 static void ParseStub( ORDDEF
*odp
)
261 odp
->u
.func
.arg_types
[0] = '\0';
262 strcpy( odp
->u
.func
.link_name
, STUB_CALLBACK
);
266 /*******************************************************************
269 * Parse an 'interrupt' definition.
271 static void ParseInterrupt( ORDDEF
*odp
)
275 if (SpecType
== SPEC_WIN32
)
276 fatal_error( "'interrupt' not supported for Win32\n" );
279 if (*token
!= '(') fatal_error( "Expected '(' got '%s'\n", token
);
282 if (*token
!= ')') fatal_error( "Expected ')' got '%s'\n", token
);
284 odp
->u
.func
.arg_types
[0] = '\0';
285 strcpy( odp
->u
.func
.link_name
, GetToken() );
289 /*******************************************************************
292 * Parse an 'extern' definition.
294 static void ParseExtern( ORDDEF
*odp
)
296 if (SpecType
== SPEC_WIN16
) fatal_error( "'extern' not supported for Win16\n" );
297 strcpy( odp
->u
.ext
.link_name
, GetToken() );
301 /*******************************************************************
304 * Parse a 'forward' definition.
306 static void ParseForward( ORDDEF
*odp
)
308 if (SpecType
== SPEC_WIN16
) fatal_error( "'forward' not supported for Win16\n" );
309 strcpy( odp
->u
.fwd
.link_name
, GetToken() );
313 /*******************************************************************
316 * Parse an ordinal definition.
318 static void ParseOrdinal(int ordinal
)
322 ORDDEF
*odp
= &EntryPoints
[nb_entry_points
++];
324 if (!(token
= GetToken())) fatal_error( "Expected type after ordinal\n" );
326 for (odp
->type
= 0; odp
->type
< TYPE_NBTYPES
; odp
->type
++)
327 if (TypeNames
[odp
->type
] && !strcmp( token
, TypeNames
[odp
->type
] ))
330 if (odp
->type
>= TYPE_NBTYPES
)
331 fatal_error( "Expected type after ordinal, found '%s' instead\n", token
);
333 if (!(token
= GetToken())) fatal_error( "Expected name after type\n" );
335 strcpy( odp
->name
, token
);
336 odp
->lineno
= current_line
;
337 odp
->ordinal
= ordinal
;
344 ParseVariable( odp
);
347 ParseExportFunction( odp
);
349 /* ignore Win32 'register' routines on non-Intel archs */
350 if (SpecType
== SPEC_WIN32
)
362 ParseExportFunction( odp
);
365 ParseInterrupt( odp
);
385 if (ordinal
>= MAX_ORDINALS
) fatal_error( "Ordinal number %d too large\n", ordinal
);
386 if (ordinal
> Limit
) Limit
= ordinal
;
387 if (ordinal
< Base
) Base
= ordinal
;
388 odp
->ordinal
= ordinal
;
389 Ordinals
[ordinal
] = odp
;
392 if (!strcmp( odp
->name
, "@" ))
395 fatal_error( "Nameless function needs an explicit ordinal number\n" );
396 if (SpecType
!= SPEC_WIN32
)
397 fatal_error( "Nameless functions not supported for Win16\n" );
400 else Names
[nb_names
++] = odp
;
404 /*******************************************************************
409 SPEC_TYPE
ParseTopLevel( FILE *file
)
415 while ((token
= GetToken()) != NULL
)
417 if (strcmp(token
, "name") == 0)
419 strcpy(DLLName
, GetToken());
421 else if (strcmp(token
, "file") == 0)
423 strcpy(DLLFileName
, GetToken());
424 strupper(DLLFileName
);
426 else if (strcmp(token
, "type") == 0)
429 if (!strcmp(token
, "win16" )) SpecType
= SPEC_WIN16
;
430 else if (!strcmp(token
, "win32" )) SpecType
= SPEC_WIN32
;
431 else fatal_error( "Type must be 'win16' or 'win32'\n" );
433 else if (strcmp(token
, "mode") == 0)
436 if (!strcmp(token
, "dll" )) SpecMode
= SPEC_MODE_DLL
;
437 else if (!strcmp(token
, "guiexe" )) SpecMode
= SPEC_MODE_GUIEXE
;
438 else if (!strcmp(token
, "cuiexe" )) SpecMode
= SPEC_MODE_CUIEXE
;
439 else fatal_error( "Mode must be 'dll', 'guiexe' or 'cuiexe'\n" );
441 else if (strcmp(token
, "heap") == 0)
444 if (!IsNumberString(token
)) fatal_error( "Expected number after heap\n" );
445 DLLHeapSize
= atoi(token
);
447 else if (strcmp(token
, "init") == 0)
449 strcpy(DLLInitFunc
, GetToken());
450 if (SpecType
== SPEC_WIN16
)
451 fatal_error( "init cannot be used for Win16 spec files\n" );
453 fatal_error( "Expected function name after init\n" );
454 if (!strcmp(DLLInitFunc
, "main"))
455 fatal_error( "The init function cannot be named 'main'\n" );
457 else if (strcmp(token
, "import") == 0)
459 if (nb_imports
>= MAX_IMPORTS
)
460 fatal_error( "Too many imports (limit %d)\n", MAX_IMPORTS
);
461 if (SpecType
!= SPEC_WIN32
)
462 fatal_error( "Imports not supported for Win16\n" );
463 DLLImports
[nb_imports
++] = xstrdup(GetToken());
465 else if (strcmp(token
, "rsrc") == 0)
467 strcpy( rsrc_name
, GetToken() );
468 strcat( rsrc_name
, "_ResourceDescriptor" );
470 else if (strcmp(token
, "@") == 0)
472 if (SpecType
!= SPEC_WIN32
)
473 fatal_error( "'@' ordinals not supported for Win16\n" );
476 else if (IsNumberString(token
))
478 ParseOrdinal( atoi(token
) );
481 fatal_error( "Expected name, id, length or ordinal\n" );
486 if (SpecMode
== SPEC_MODE_DLL
)
487 sprintf( DLLFileName
, "%s.dll", DLLName
);
489 sprintf( DLLFileName
, "%s.exe", DLLName
);
492 if (SpecType
== SPEC_INVALID
) fatal_error( "Missing 'type' declaration\n" );
493 current_line
= 0; /* no longer parsing the input file */