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, "owner") == 0)
472 if (SpecType != SPEC_WIN16)
473 fatal_error( "Owner only supported for Win16 spec files\n" );
474 strcpy( owner_name, GetToken() );
476 else if (strcmp(token, "@") == 0)
478 if (SpecType != SPEC_WIN32)
479 fatal_error( "'@' ordinals not supported for Win16\n" );
482 else if (IsNumberString(token))
484 ParseOrdinal( atoi(token) );
487 fatal_error( "Expected name, id, length or ordinal\n" );
492 if (SpecMode == SPEC_MODE_DLL)
493 sprintf( DLLFileName, "%s.dll", DLLName );
495 sprintf( DLLFileName, "%s.exe", DLLName );
498 if (SpecType == SPEC_INVALID) fatal_error( "Missing 'type' declaration\n" );
499 if (SpecType == SPEC_WIN16 && !owner_name[0])
500 fatal_error( "'owner' not specified for Win16 dll\n" );
502 current_line = 0; /* no longer parsing the input file */