blob: 78b5d80f0d4593ba86e682060aff19d282282928 [file] [log] [blame]
Alexandre Julliarde482eeb2000-06-23 20:15:35 +00001/*
2 * Spec file parser
3 *
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Martin von Loewis
Alexandre Julliard492ac292004-02-17 20:36:16 +00006 * Copyright 1995, 1996, 1997, 2004 Alexandre Julliard
Alexandre Julliarde482eeb2000-06-23 20:15:35 +00007 * Copyright 1997 Eric Youngdale
8 * Copyright 1999 Ulrich Weigand
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00009 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
Jonathan Ernst360a3f92006-05-18 14:49:52 +020022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000023 */
24
Francois Gougete5ddd262001-10-14 16:18:52 +000025#include "config.h"
Alexandre Julliard894b1882002-04-25 21:40:56 +000026#include "wine/port.h"
Francois Gougete5ddd262001-10-14 16:18:52 +000027
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000028#include <assert.h>
29#include <ctype.h>
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000030#include <stdarg.h>
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000031#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000034
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000035#include "windef.h"
Alexandre Julliard0a8114c2000-11-12 03:45:55 +000036#include "winbase.h"
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000037#include "build.h"
38
39int current_line = 0;
40
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000041static char ParseBuffer[512];
Alexandre Julliard49886962001-02-15 21:27:06 +000042static char TokenBuffer[512];
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000043static char *ParseNext = ParseBuffer;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000044static FILE *input_file;
45
Alexandre Julliard492ac292004-02-17 20:36:16 +000046static const char *separator_chars;
47static const char *comment_chars;
48
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000049static const char * const TypeNames[TYPE_NBTYPES] =
50{
Alexandre Julliard39b31952000-11-26 04:31:48 +000051 "variable", /* TYPE_VARIABLE */
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000052 "pascal", /* TYPE_PASCAL */
53 "equate", /* TYPE_ABS */
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000054 "stub", /* TYPE_STUB */
55 "stdcall", /* TYPE_STDCALL */
56 "cdecl", /* TYPE_CDECL */
57 "varargs", /* TYPE_VARARGS */
Alexandre Julliardf489a272003-03-17 04:56:10 +000058 "extern" /* TYPE_EXTERN */
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000059};
60
Alexandre Julliard39b31952000-11-26 04:31:48 +000061static const char * const FlagNames[] =
62{
Alexandre Julliard39b31952000-11-26 04:31:48 +000063 "norelay", /* FLAG_NORELAY */
Alexandre Julliard15a75252002-07-28 17:54:31 +000064 "noname", /* FLAG_NONAME */
Alexandre Julliard617839d2003-08-27 02:20:44 +000065 "ret16", /* FLAG_RET16 */
Alexandre Julliard39b31952000-11-26 04:31:48 +000066 "ret64", /* FLAG_RET64 */
67 "i386", /* FLAG_I386 */
Alexandre Julliard7662ea12001-12-14 23:14:22 +000068 "register", /* FLAG_REGISTER */
Alexandre Julliard152b98f2003-07-28 19:19:48 +000069 "private", /* FLAG_PRIVATE */
Alexandre Julliard39b31952000-11-26 04:31:48 +000070 NULL
71};
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000072
Alexandre Julliard49886962001-02-15 21:27:06 +000073static int IsNumberString(const char *s)
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000074{
75 while (*s) if (!isdigit(*s++)) return 0;
76 return 1;
77}
78
Alexandre Julliard39b31952000-11-26 04:31:48 +000079inline static int is_token_separator( char ch )
80{
Alexandre Julliard492ac292004-02-17 20:36:16 +000081 return strchr( separator_chars, ch ) != NULL;
82}
83
84inline static int is_token_comment( char ch )
85{
86 return strchr( comment_chars, ch ) != NULL;
Alexandre Julliard39b31952000-11-26 04:31:48 +000087}
88
Alexandre Julliard49edd192003-03-18 05:30:54 +000089/* get the next line from the input file, or return 0 if at eof */
90static int get_next_line(void)
91{
92 ParseNext = ParseBuffer;
93 current_line++;
94 return (fgets(ParseBuffer, sizeof(ParseBuffer), input_file) != NULL);
95}
96
97static const char * GetToken( int allow_eol )
Alexandre Julliarde482eeb2000-06-23 20:15:35 +000098{
Alexandre Julliard49886962001-02-15 21:27:06 +000099 char *p = ParseNext;
100 char *token = TokenBuffer;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000101
Alexandre Julliard49edd192003-03-18 05:30:54 +0000102 for (;;)
103 {
104 /* remove initial white space */
105 p = ParseNext;
106 while (isspace(*p)) p++;
Alexandre Julliard49886962001-02-15 21:27:06 +0000107
Alexandre Julliard49edd192003-03-18 05:30:54 +0000108 if (*p == '\\' && p[1] == '\n') /* line continuation */
109 {
110 if (!get_next_line())
111 {
112 if (!allow_eol) error( "Unexpected end of file\n" );
113 return NULL;
114 }
115 }
116 else break;
117 }
118
Alexandre Julliard492ac292004-02-17 20:36:16 +0000119 if ((*p == '\0') || is_token_comment(*p))
Alexandre Julliard49edd192003-03-18 05:30:54 +0000120 {
121 if (!allow_eol) error( "Declaration not terminated properly\n" );
122 return NULL;
123 }
Alexandre Julliard49886962001-02-15 21:27:06 +0000124
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000125 /*
126 * Find end of token.
127 */
Alexandre Julliard49886962001-02-15 21:27:06 +0000128 if (is_token_separator(*p))
129 {
130 /* a separator is always a complete token */
131 *token++ = *p++;
132 }
133 else while (*p != '\0' && !is_token_separator(*p) && !isspace(*p))
134 {
135 if (*p == '\\') p++;
136 if (*p) *token++ = *p++;
137 }
138 *token = '\0';
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000139 ParseNext = p;
Alexandre Julliard49886962001-02-15 21:27:06 +0000140 return TokenBuffer;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000141}
142
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000143
Alexandre Julliard8611e652004-02-11 06:41:01 +0000144static ORDDEF *add_entry_point( DLLSPEC *spec )
145{
146 if (spec->nb_entry_points == spec->alloc_entry_points)
147 {
148 spec->alloc_entry_points += 128;
149 spec->entry_points = xrealloc( spec->entry_points,
150 spec->alloc_entry_points * sizeof(*spec->entry_points) );
151 }
152 return &spec->entry_points[spec->nb_entry_points++];
153}
154
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000155/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000156 * parse_spec_variable
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000157 *
Alexandre Julliard492ac292004-02-17 20:36:16 +0000158 * Parse a variable definition in a .spec file.
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000159 */
Alexandre Julliard492ac292004-02-17 20:36:16 +0000160static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec )
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000161{
162 char *endptr;
163 int *value_array;
164 int n_values;
165 int value_array_size;
Alexandre Julliard52ec0a32003-03-17 00:02:11 +0000166 const char *token;
Alexandre Julliard49886962001-02-15 21:27:06 +0000167
Alexandre Julliard8611e652004-02-11 06:41:01 +0000168 if (spec->type == SPEC_WIN32)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000169 {
170 error( "'variable' not supported in Win32, use 'extern' instead\n" );
171 return 0;
172 }
Alexandre Julliard52ec0a32003-03-17 00:02:11 +0000173
Alexandre Julliard49edd192003-03-18 05:30:54 +0000174 if (!(token = GetToken(0))) return 0;
175 if (*token != '(')
176 {
177 error( "Expected '(' got '%s'\n", token );
178 return 0;
179 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000180
181 n_values = 0;
182 value_array_size = 25;
183 value_array = xmalloc(sizeof(*value_array) * value_array_size);
Vincent Béron9a624912002-05-31 23:06:46 +0000184
Alexandre Julliard39b31952000-11-26 04:31:48 +0000185 for (;;)
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000186 {
Alexandre Julliard49edd192003-03-18 05:30:54 +0000187 if (!(token = GetToken(0)))
188 {
189 free( value_array );
190 return 0;
191 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000192 if (*token == ')')
193 break;
194
195 value_array[n_values++] = strtol(token, &endptr, 0);
196 if (n_values == value_array_size)
197 {
198 value_array_size += 25;
Vincent Béron9a624912002-05-31 23:06:46 +0000199 value_array = xrealloc(value_array,
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000200 sizeof(*value_array) * value_array_size);
201 }
Vincent Béron9a624912002-05-31 23:06:46 +0000202
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000203 if (endptr == NULL || *endptr != '\0')
Alexandre Julliard49edd192003-03-18 05:30:54 +0000204 {
205 error( "Expected number value, got '%s'\n", token );
206 free( value_array );
207 return 0;
208 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000209 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000210
211 odp->u.var.n_values = n_values;
212 odp->u.var.values = xrealloc(value_array, sizeof(*value_array) * n_values);
Alexandre Julliard49edd192003-03-18 05:30:54 +0000213 return 1;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000214}
215
216
217/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000218 * parse_spec_export
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000219 *
Alexandre Julliard492ac292004-02-17 20:36:16 +0000220 * Parse an exported function definition in a .spec file.
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000221 */
Alexandre Julliard492ac292004-02-17 20:36:16 +0000222static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000223{
Alexandre Julliard49886962001-02-15 21:27:06 +0000224 const char *token;
Joerg Mayerabe635c2000-11-11 00:38:37 +0000225 unsigned int i;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000226
Alexandre Julliard8611e652004-02-11 06:41:01 +0000227 switch(spec->type)
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000228 {
229 case SPEC_WIN16:
Alexandre Julliard39b31952000-11-26 04:31:48 +0000230 if (odp->type == TYPE_STDCALL)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000231 {
232 error( "'stdcall' not supported for Win16\n" );
233 return 0;
234 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000235 break;
236 case SPEC_WIN32:
Alexandre Julliard617839d2003-08-27 02:20:44 +0000237 if (odp->type == TYPE_PASCAL)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000238 {
239 error( "'pascal' not supported for Win32\n" );
240 return 0;
241 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000242 break;
243 default:
244 break;
245 }
246
Alexandre Julliard49edd192003-03-18 05:30:54 +0000247 if (!(token = GetToken(0))) return 0;
248 if (*token != '(')
249 {
250 error( "Expected '(' got '%s'\n", token );
251 return 0;
252 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000253
Alexandre Julliarda8378492000-10-01 01:33:50 +0000254 for (i = 0; i < sizeof(odp->u.func.arg_types); i++)
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000255 {
Alexandre Julliard49edd192003-03-18 05:30:54 +0000256 if (!(token = GetToken(0))) return 0;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000257 if (*token == ')')
258 break;
259
260 if (!strcmp(token, "word"))
261 odp->u.func.arg_types[i] = 'w';
262 else if (!strcmp(token, "s_word"))
263 odp->u.func.arg_types[i] = 's';
264 else if (!strcmp(token, "long") || !strcmp(token, "segptr"))
265 odp->u.func.arg_types[i] = 'l';
266 else if (!strcmp(token, "ptr"))
267 odp->u.func.arg_types[i] = 'p';
268 else if (!strcmp(token, "str"))
269 odp->u.func.arg_types[i] = 't';
270 else if (!strcmp(token, "wstr"))
271 odp->u.func.arg_types[i] = 'W';
272 else if (!strcmp(token, "segstr"))
273 odp->u.func.arg_types[i] = 'T';
274 else if (!strcmp(token, "double"))
275 {
276 odp->u.func.arg_types[i++] = 'l';
Alexandre Julliarda999a992005-09-19 17:04:43 +0000277 if (get_ptr_size() == 4 && i < sizeof(odp->u.func.arg_types))
278 odp->u.func.arg_types[i] = 'l';
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000279 }
Alexandre Julliard49edd192003-03-18 05:30:54 +0000280 else
281 {
282 error( "Unknown argument type '%s'\n", token );
283 return 0;
284 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000285
Alexandre Julliard8611e652004-02-11 06:41:01 +0000286 if (spec->type == SPEC_WIN32)
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000287 {
288 if (strcmp(token, "long") &&
289 strcmp(token, "ptr") &&
290 strcmp(token, "str") &&
291 strcmp(token, "wstr") &&
292 strcmp(token, "double"))
293 {
Alexandre Julliard49edd192003-03-18 05:30:54 +0000294 error( "Type '%s' not supported for Win32\n", token );
295 return 0;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000296 }
297 }
298 }
299 if ((*token != ')') || (i >= sizeof(odp->u.func.arg_types)))
Alexandre Julliard49edd192003-03-18 05:30:54 +0000300 {
301 error( "Too many arguments\n" );
302 return 0;
303 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000304
305 odp->u.func.arg_types[i] = '\0';
Alexandre Julliard39b31952000-11-26 04:31:48 +0000306 if (odp->type == TYPE_VARARGS)
307 odp->flags |= FLAG_NORELAY; /* no relay debug possible for varags entry point */
Alexandre Julliard49edd192003-03-18 05:30:54 +0000308
309 if (!(token = GetToken(1)))
Alexandre Julliard470cbf22002-12-15 01:22:40 +0000310 {
Alexandre Julliard49edd192003-03-18 05:30:54 +0000311 if (!strcmp( odp->name, "@" ))
312 {
313 error( "Missing handler name for anonymous function\n" );
314 return 0;
315 }
316 odp->link_name = xstrdup( odp->name );
Alexandre Julliard470cbf22002-12-15 01:22:40 +0000317 }
Alexandre Julliard49edd192003-03-18 05:30:54 +0000318 else
319 {
320 odp->link_name = xstrdup( token );
321 if (strchr( odp->link_name, '.' ))
322 {
Alexandre Julliard8611e652004-02-11 06:41:01 +0000323 if (spec->type == SPEC_WIN16)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000324 {
325 error( "Forwarded functions not supported for Win16\n" );
326 return 0;
327 }
328 odp->flags |= FLAG_FORWARD;
329 }
330 }
331 return 1;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000332}
333
334
335/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000336 * parse_spec_equate
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000337 *
Alexandre Julliard492ac292004-02-17 20:36:16 +0000338 * Parse an 'equate' definition in a .spec file.
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000339 */
Alexandre Julliard492ac292004-02-17 20:36:16 +0000340static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec )
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000341{
342 char *endptr;
Alexandre Julliard49edd192003-03-18 05:30:54 +0000343 int value;
344 const char *token;
Alexandre Julliard49886962001-02-15 21:27:06 +0000345
Alexandre Julliard8611e652004-02-11 06:41:01 +0000346 if (spec->type == SPEC_WIN32)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000347 {
348 error( "'equate' not supported for Win32\n" );
349 return 0;
350 }
351 if (!(token = GetToken(0))) return 0;
352 value = strtol(token, &endptr, 0);
353 if (endptr == NULL || *endptr != '\0')
354 {
355 error( "Expected number value, got '%s'\n", token );
356 return 0;
357 }
Alexandre Julliard210bd2d2005-09-21 11:10:54 +0000358 if (value < -0x8000 || value > 0xffff)
359 {
360 error( "Value %d for absolute symbol doesn't fit in 16 bits\n", value );
361 value = 0;
362 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000363 odp->u.abs.value = value;
Alexandre Julliard49edd192003-03-18 05:30:54 +0000364 return 1;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000365}
366
367
368/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000369 * parse_spec_stub
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000370 *
Alexandre Julliard492ac292004-02-17 20:36:16 +0000371 * Parse a 'stub' definition in a .spec file
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000372 */
Alexandre Julliard492ac292004-02-17 20:36:16 +0000373static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000374{
375 odp->u.func.arg_types[0] = '\0';
Alexandre Julliard66fed8c2000-12-15 23:04:40 +0000376 odp->link_name = xstrdup("");
Alexandre Julliard3fa56782005-09-14 15:49:45 +0000377 odp->flags |= FLAG_I386; /* don't bother generating stubs for Winelib */
Alexandre Julliard49edd192003-03-18 05:30:54 +0000378 return 1;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000379}
380
381
382/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000383 * parse_spec_extern
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000384 *
Alexandre Julliard492ac292004-02-17 20:36:16 +0000385 * Parse an 'extern' definition in a .spec file.
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000386 */
Alexandre Julliard492ac292004-02-17 20:36:16 +0000387static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000388{
Alexandre Julliard49edd192003-03-18 05:30:54 +0000389 const char *token;
390
Alexandre Julliard8611e652004-02-11 06:41:01 +0000391 if (spec->type == SPEC_WIN16)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000392 {
393 error( "'extern' not supported for Win16, use 'variable' instead\n" );
394 return 0;
395 }
396 if (!(token = GetToken(1)))
397 {
398 if (!strcmp( odp->name, "@" ))
399 {
400 error( "Missing handler name for anonymous extern\n" );
401 return 0;
402 }
403 odp->link_name = xstrdup( odp->name );
404 }
405 else
406 {
407 odp->link_name = xstrdup( token );
408 if (strchr( odp->link_name, '.' )) odp->flags |= FLAG_FORWARD;
409 }
410 return 1;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000411}
412
413
414/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000415 * parse_spec_flags
Alexandre Julliard39b31952000-11-26 04:31:48 +0000416 *
Alexandre Julliard492ac292004-02-17 20:36:16 +0000417 * Parse the optional flags for an entry point in a .spec file.
Alexandre Julliard39b31952000-11-26 04:31:48 +0000418 */
Alexandre Julliard492ac292004-02-17 20:36:16 +0000419static const char *parse_spec_flags( ORDDEF *odp )
Alexandre Julliard39b31952000-11-26 04:31:48 +0000420{
421 unsigned int i;
Alexandre Julliard49886962001-02-15 21:27:06 +0000422 const char *token;
Alexandre Julliard39b31952000-11-26 04:31:48 +0000423
424 do
425 {
Alexandre Julliard49edd192003-03-18 05:30:54 +0000426 if (!(token = GetToken(0))) break;
Alexandre Julliard39b31952000-11-26 04:31:48 +0000427 for (i = 0; FlagNames[i]; i++)
428 if (!strcmp( FlagNames[i], token )) break;
Alexandre Julliard49edd192003-03-18 05:30:54 +0000429 if (!FlagNames[i])
430 {
431 error( "Unknown flag '%s'\n", token );
432 return NULL;
433 }
Alexandre Julliard39b31952000-11-26 04:31:48 +0000434 odp->flags |= 1 << i;
435 token = GetToken(0);
Alexandre Julliard49edd192003-03-18 05:30:54 +0000436 } while (token && *token == '-');
Alexandre Julliard39b31952000-11-26 04:31:48 +0000437
438 return token;
439}
440
Alexandre Julliardc585a502000-09-27 23:40:43 +0000441
442/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000443 * parse_spec_ordinal
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000444 *
Alexandre Julliard492ac292004-02-17 20:36:16 +0000445 * Parse an ordinal definition in a .spec file.
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000446 */
Alexandre Julliard492ac292004-02-17 20:36:16 +0000447static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000448{
Alexandre Julliard49886962001-02-15 21:27:06 +0000449 const char *token;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000450
Alexandre Julliard8611e652004-02-11 06:41:01 +0000451 ORDDEF *odp = add_entry_point( spec );
Alexandre Julliard66fed8c2000-12-15 23:04:40 +0000452 memset( odp, 0, sizeof(*odp) );
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000453
Alexandre Julliard49edd192003-03-18 05:30:54 +0000454 if (!(token = GetToken(0))) goto error;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000455
456 for (odp->type = 0; odp->type < TYPE_NBTYPES; odp->type++)
457 if (TypeNames[odp->type] && !strcmp( token, TypeNames[odp->type] ))
458 break;
459
460 if (odp->type >= TYPE_NBTYPES)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000461 {
Dimitrie O. Paun8b255842003-09-26 04:32:19 +0000462 error( "Expected type after ordinal, found '%s' instead\n", token );
463 goto error;
Alexandre Julliard49edd192003-03-18 05:30:54 +0000464 }
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000465
Alexandre Julliard49edd192003-03-18 05:30:54 +0000466 if (!(token = GetToken(0))) goto error;
Alexandre Julliard492ac292004-02-17 20:36:16 +0000467 if (*token == '-' && !(token = parse_spec_flags( odp ))) goto error;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000468
Alexandre Julliard66fed8c2000-12-15 23:04:40 +0000469 odp->name = xstrdup( token );
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000470 odp->lineno = current_line;
471 odp->ordinal = ordinal;
472
473 switch(odp->type)
474 {
Alexandre Julliard39b31952000-11-26 04:31:48 +0000475 case TYPE_VARIABLE:
Alexandre Julliard492ac292004-02-17 20:36:16 +0000476 if (!parse_spec_variable( odp, spec )) goto error;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000477 break;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000478 case TYPE_PASCAL:
479 case TYPE_STDCALL:
480 case TYPE_VARARGS:
481 case TYPE_CDECL:
Alexandre Julliard492ac292004-02-17 20:36:16 +0000482 if (!parse_spec_export( odp, spec )) goto error;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000483 break;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000484 case TYPE_ABS:
Alexandre Julliard492ac292004-02-17 20:36:16 +0000485 if (!parse_spec_equate( odp, spec )) goto error;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000486 break;
487 case TYPE_STUB:
Alexandre Julliard492ac292004-02-17 20:36:16 +0000488 if (!parse_spec_stub( odp, spec )) goto error;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000489 break;
490 case TYPE_EXTERN:
Alexandre Julliard492ac292004-02-17 20:36:16 +0000491 if (!parse_spec_extern( odp, spec )) goto error;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000492 break;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000493 default:
494 assert( 0 );
495 }
496
Alexandre Julliard803c8d92005-06-27 11:23:24 +0000497 if ((target_cpu != CPU_x86) && (odp->flags & FLAG_I386))
Alexandre Julliard39b31952000-11-26 04:31:48 +0000498 {
499 /* ignore this entry point on non-Intel archs */
Alexandre Julliard8611e652004-02-11 06:41:01 +0000500 spec->nb_entry_points--;
Alexandre Julliard49edd192003-03-18 05:30:54 +0000501 return 1;
Alexandre Julliard39b31952000-11-26 04:31:48 +0000502 }
Alexandre Julliard39b31952000-11-26 04:31:48 +0000503
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000504 if (ordinal != -1)
505 {
Alexandre Julliard49edd192003-03-18 05:30:54 +0000506 if (!ordinal)
507 {
508 error( "Ordinal 0 is not valid\n" );
509 goto error;
510 }
511 if (ordinal >= MAX_ORDINALS)
512 {
513 error( "Ordinal number %d too large\n", ordinal );
514 goto error;
515 }
Alexandre Julliard8611e652004-02-11 06:41:01 +0000516 if (ordinal > spec->limit) spec->limit = ordinal;
517 if (ordinal < spec->base) spec->base = ordinal;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000518 odp->ordinal = ordinal;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000519 }
520
Alexandre Julliardd78ee142004-08-27 19:40:53 +0000521 if (odp->type == TYPE_STDCALL && !(odp->flags & FLAG_PRIVATE))
522 {
523 if (!strcmp( odp->name, "DllRegisterServer" ) ||
524 !strcmp( odp->name, "DllUnregisterServer" ) ||
525 !strcmp( odp->name, "DllGetClassObject" ) ||
Alexandre Julliardd5d89672005-08-09 10:24:05 +0000526 !strcmp( odp->name, "DllGetVersion" ) ||
527 !strcmp( odp->name, "DllInstall" ) ||
Alexandre Julliardd78ee142004-08-27 19:40:53 +0000528 !strcmp( odp->name, "DllCanUnloadNow" ))
529 {
530 warning( "Function %s should be marked private\n", odp->name );
Alexandre Julliardd5d89672005-08-09 10:24:05 +0000531 if (strcmp( odp->name, odp->link_name ))
532 warning( "Function %s should not use a different internal name (%s)\n",
533 odp->name, odp->link_name );
Alexandre Julliardd78ee142004-08-27 19:40:53 +0000534 }
535 }
536
Alexandre Julliard15a75252002-07-28 17:54:31 +0000537 if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME)
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000538 {
539 if (ordinal == -1)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000540 {
541 error( "Nameless function needs an explicit ordinal number\n" );
542 goto error;
543 }
Alexandre Julliard8611e652004-02-11 06:41:01 +0000544 if (spec->type != SPEC_WIN32)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000545 {
546 error( "Nameless functions not supported for Win16\n" );
547 goto error;
548 }
Alexandre Julliard15a75252002-07-28 17:54:31 +0000549 if (!strcmp( odp->name, "@" )) free( odp->name );
550 else odp->export_name = odp->name;
551 odp->name = NULL;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000552 }
Alexandre Julliard49edd192003-03-18 05:30:54 +0000553 return 1;
554
555error:
Alexandre Julliard8611e652004-02-11 06:41:01 +0000556 spec->nb_entry_points--;
Alexandre Julliard49edd192003-03-18 05:30:54 +0000557 free( odp->name );
Alexandre Julliard49edd192003-03-18 05:30:54 +0000558 return 0;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000559}
560
561
Alexandre Julliard7a521902005-09-19 14:44:28 +0000562static int name_compare( const void *ptr1, const void *ptr2 )
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000563{
Alexandre Julliard7a521902005-09-19 14:44:28 +0000564 const ORDDEF *odp1 = *(const ORDDEF * const *)ptr1;
565 const ORDDEF *odp2 = *(const ORDDEF * const *)ptr2;
566 const char *name1 = odp1->name ? odp1->name : odp1->export_name;
567 const char *name2 = odp2->name ? odp2->name : odp2->export_name;
568 return strcmp( name1, name2 );
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000569}
570
571/*******************************************************************
Alexandre Julliard8611e652004-02-11 06:41:01 +0000572 * assign_names
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000573 *
Alexandre Julliard8611e652004-02-11 06:41:01 +0000574 * Build the name array and catch duplicates.
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000575 */
Alexandre Julliard8611e652004-02-11 06:41:01 +0000576static void assign_names( DLLSPEC *spec )
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000577{
Alexandre Julliard7a521902005-09-19 14:44:28 +0000578 int i, j, nb_exp_names = 0;
579 ORDDEF **all_names;
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000580
Alexandre Julliard8611e652004-02-11 06:41:01 +0000581 spec->nb_names = 0;
582 for (i = 0; i < spec->nb_entry_points; i++)
583 if (spec->entry_points[i].name) spec->nb_names++;
Alexandre Julliard7a521902005-09-19 14:44:28 +0000584 else if (spec->entry_points[i].export_name) nb_exp_names++;
Alexandre Julliard8611e652004-02-11 06:41:01 +0000585
Alexandre Julliard7a521902005-09-19 14:44:28 +0000586 if (!spec->nb_names && !nb_exp_names) return;
587
588 /* check for duplicates */
589
590 all_names = xmalloc( (spec->nb_names + nb_exp_names) * sizeof(all_names[0]) );
Alexandre Julliard8611e652004-02-11 06:41:01 +0000591 for (i = j = 0; i < spec->nb_entry_points; i++)
Alexandre Julliard7a521902005-09-19 14:44:28 +0000592 if (spec->entry_points[i].name || spec->entry_points[i].export_name)
593 all_names[j++] = &spec->entry_points[i];
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000594
Alexandre Julliard7a521902005-09-19 14:44:28 +0000595 qsort( all_names, j, sizeof(all_names[0]), name_compare );
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000596
Alexandre Julliard7a521902005-09-19 14:44:28 +0000597 for (i = 0; i < j - 1; i++)
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000598 {
Alexandre Julliard7a521902005-09-19 14:44:28 +0000599 const char *name1 = all_names[i]->name ? all_names[i]->name : all_names[i]->export_name;
600 const char *name2 = all_names[i+1]->name ? all_names[i+1]->name : all_names[i+1]->export_name;
601 if (!strcmp( name1, name2 ))
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000602 {
Alexandre Julliard7a521902005-09-19 14:44:28 +0000603 current_line = max( all_names[i]->lineno, all_names[i+1]->lineno );
Alexandre Julliard49edd192003-03-18 05:30:54 +0000604 error( "'%s' redefined\n%s:%d: First defined here\n",
Alexandre Julliard7a521902005-09-19 14:44:28 +0000605 name1, input_file_name,
606 min( all_names[i]->lineno, all_names[i+1]->lineno ) );
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000607 }
608 }
Alexandre Julliard7a521902005-09-19 14:44:28 +0000609 free( all_names );
610
611 if (spec->nb_names)
612 {
613 spec->names = xmalloc( spec->nb_names * sizeof(spec->names[0]) );
614 for (i = j = 0; i < spec->nb_entry_points; i++)
615 if (spec->entry_points[i].name) spec->names[j++] = &spec->entry_points[i];
616
617 /* sort the list of names */
618 qsort( spec->names, spec->nb_names, sizeof(spec->names[0]), name_compare );
619 }
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000620}
621
Alexandre Julliard8611e652004-02-11 06:41:01 +0000622/*******************************************************************
623 * assign_ordinals
624 *
625 * Build the ordinal array.
626 */
627static void assign_ordinals( DLLSPEC *spec )
628{
629 int i, count, ordinal;
630
631 /* start assigning from base, or from 1 if no ordinal defined yet */
Alexandre Julliardd13b99d2005-08-29 15:15:42 +0000632
633 spec->base = MAX_ORDINALS;
634 spec->limit = 0;
635 for (i = 0; i < spec->nb_entry_points; i++)
636 {
637 ordinal = spec->entry_points[i].ordinal;
638 if (ordinal == -1) continue;
639 if (ordinal > spec->limit) spec->limit = ordinal;
640 if (ordinal < spec->base) spec->base = ordinal;
641 }
Alexandre Julliard8611e652004-02-11 06:41:01 +0000642 if (spec->base == MAX_ORDINALS) spec->base = 1;
643 if (spec->limit < spec->base) spec->limit = spec->base;
644
645 count = max( spec->limit + 1, spec->base + spec->nb_entry_points );
646 spec->ordinals = xmalloc( count * sizeof(spec->ordinals[0]) );
647 memset( spec->ordinals, 0, count * sizeof(spec->ordinals[0]) );
648
649 /* fill in all explicitly specified ordinals */
650 for (i = 0; i < spec->nb_entry_points; i++)
651 {
652 ordinal = spec->entry_points[i].ordinal;
653 if (ordinal == -1) continue;
654 if (spec->ordinals[ordinal])
655 {
656 current_line = max( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno );
657 error( "ordinal %d redefined\n%s:%d: First defined here\n",
658 ordinal, input_file_name,
659 min( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno ) );
660 }
661 else spec->ordinals[ordinal] = &spec->entry_points[i];
662 }
663
664 /* now assign ordinals to the rest */
Alexandre Julliard63e9a422005-06-23 16:46:20 +0000665 for (i = 0, ordinal = spec->base; i < spec->nb_entry_points; i++)
Alexandre Julliard8611e652004-02-11 06:41:01 +0000666 {
Alexandre Julliard63e9a422005-06-23 16:46:20 +0000667 if (spec->entry_points[i].ordinal != -1) continue;
Alexandre Julliard8611e652004-02-11 06:41:01 +0000668 while (spec->ordinals[ordinal]) ordinal++;
669 if (ordinal >= MAX_ORDINALS)
670 {
Alexandre Julliard63e9a422005-06-23 16:46:20 +0000671 current_line = spec->entry_points[i].lineno;
Alexandre Julliard8611e652004-02-11 06:41:01 +0000672 fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
673 }
Alexandre Julliard63e9a422005-06-23 16:46:20 +0000674 spec->entry_points[i].ordinal = ordinal;
675 spec->ordinals[ordinal] = &spec->entry_points[i];
Alexandre Julliard8611e652004-02-11 06:41:01 +0000676 }
677 if (ordinal > spec->limit) spec->limit = ordinal;
678}
679
Alexandre Julliard0a8114c2000-11-12 03:45:55 +0000680
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000681/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000682 * parse_spec_file
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000683 *
Alexandre Julliard492ac292004-02-17 20:36:16 +0000684 * Parse a .spec file.
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000685 */
Alexandre Julliard492ac292004-02-17 20:36:16 +0000686int parse_spec_file( FILE *file, DLLSPEC *spec )
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000687{
Alexandre Julliard49886962001-02-15 21:27:06 +0000688 const char *token;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000689
690 input_file = file;
Alexandre Julliardb0c6e362002-08-27 22:32:01 +0000691 current_line = 0;
Alexandre Julliard77afd6c2002-06-21 19:15:45 +0000692
Alexandre Julliard492ac292004-02-17 20:36:16 +0000693 comment_chars = "#;";
694 separator_chars = "()-";
695
Alexandre Julliard49edd192003-03-18 05:30:54 +0000696 while (get_next_line())
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000697 {
Alexandre Julliard49edd192003-03-18 05:30:54 +0000698 if (!(token = GetToken(1))) continue;
Alexandre Julliard2cd4ed22002-12-07 23:54:12 +0000699 if (strcmp(token, "@") == 0)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000700 {
Alexandre Julliard8611e652004-02-11 06:41:01 +0000701 if (spec->type != SPEC_WIN32)
Alexandre Julliard49edd192003-03-18 05:30:54 +0000702 {
703 error( "'@' ordinals not supported for Win16\n" );
704 continue;
705 }
Alexandre Julliard492ac292004-02-17 20:36:16 +0000706 if (!parse_spec_ordinal( -1, spec )) continue;
Alexandre Julliard49edd192003-03-18 05:30:54 +0000707 }
708 else if (IsNumberString(token))
709 {
Alexandre Julliard492ac292004-02-17 20:36:16 +0000710 if (!parse_spec_ordinal( atoi(token), spec )) continue;
Alexandre Julliard49edd192003-03-18 05:30:54 +0000711 }
712 else
713 {
714 error( "Expected ordinal declaration, got '%s'\n", token );
715 continue;
716 }
717 if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token );
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000718 }
719
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000720 current_line = 0; /* no longer parsing the input file */
Alexandre Julliard8611e652004-02-11 06:41:01 +0000721 assign_names( spec );
722 assign_ordinals( spec );
Alexandre Julliard49edd192003-03-18 05:30:54 +0000723 return !nb_errors;
Alexandre Julliarde482eeb2000-06-23 20:15:35 +0000724}
Alexandre Julliardad533832002-05-14 20:54:58 +0000725
726
727/*******************************************************************
Alexandre Julliard492ac292004-02-17 20:36:16 +0000728 * parse_def_library
729 *
730 * Parse a LIBRARY declaration in a .def file.
731 */
732static int parse_def_library( DLLSPEC *spec )
733{
734 const char *token = GetToken(1);
735
736 if (!token) return 1;
737 if (strcmp( token, "BASE" ))
738 {
739 free( spec->file_name );
740 spec->file_name = xstrdup( token );
741 if (!(token = GetToken(1))) return 1;
742 }
743 if (strcmp( token, "BASE" ))
744 {
745 error( "Expected library name or BASE= declaration, got '%s'\n", token );
746 return 0;
747 }
748 if (!(token = GetToken(0))) return 0;
749 if (strcmp( token, "=" ))
750 {
751 error( "Expected '=' after BASE, got '%s'\n", token );
752 return 0;
753 }
754 if (!(token = GetToken(0))) return 0;
755 /* FIXME: do something with base address */
756
757 return 1;
758}
759
760
761/*******************************************************************
762 * parse_def_stack_heap_size
763 *
764 * Parse a STACKSIZE or HEAPSIZE declaration in a .def file.
765 */
766static int parse_def_stack_heap_size( int is_stack, DLLSPEC *spec )
767{
768 const char *token = GetToken(0);
769 char *end;
770 unsigned long size;
771
772 if (!token) return 0;
773 size = strtoul( token, &end, 0 );
774 if (*end)
775 {
776 error( "Invalid number '%s'\n", token );
777 return 0;
778 }
779 if (is_stack) spec->stack_size = size / 1024;
780 else spec->heap_size = size / 1024;
781 if (!(token = GetToken(1))) return 1;
782 if (strcmp( token, "," ))
783 {
784 error( "Expected ',' after size, got '%s'\n", token );
785 return 0;
786 }
787 if (!(token = GetToken(0))) return 0;
788 /* FIXME: do something with reserve size */
789 return 1;
790}
791
792
793/*******************************************************************
794 * parse_def_export
795 *
796 * Parse an export declaration in a .def file.
797 */
798static int parse_def_export( char *name, DLLSPEC *spec )
799{
800 int i, args;
801 const char *token = GetToken(1);
802
803 ORDDEF *odp = add_entry_point( spec );
804 memset( odp, 0, sizeof(*odp) );
805
806 odp->lineno = current_line;
807 odp->ordinal = -1;
808 odp->name = name;
809 args = remove_stdcall_decoration( odp->name );
810 if (args == -1) odp->type = TYPE_CDECL;
811 else
812 {
813 odp->type = TYPE_STDCALL;
Alexandre Julliard43bd5512005-09-08 11:35:19 +0000814 args /= get_ptr_size();
Alexandre Julliard492ac292004-02-17 20:36:16 +0000815 if (args >= sizeof(odp->u.func.arg_types))
816 {
817 error( "Too many arguments in stdcall function '%s'\n", odp->name );
818 return 0;
819 }
820 for (i = 0; i < args; i++) odp->u.func.arg_types[i] = 'l';
821 }
822
823 /* check for optional internal name */
824
825 if (token && !strcmp( token, "=" ))
826 {
827 if (!(token = GetToken(0))) goto error;
828 odp->link_name = xstrdup( token );
829 remove_stdcall_decoration( odp->link_name );
830 token = GetToken(1);
831 }
Eric Friasf23b3582004-11-21 15:39:51 +0000832 else
833 {
834 odp->link_name = xstrdup( name );
835 }
Alexandre Julliard492ac292004-02-17 20:36:16 +0000836
837 /* check for optional ordinal */
838
839 if (token && token[0] == '@')
840 {
841 int ordinal;
842
843 if (!IsNumberString( token+1 ))
844 {
845 error( "Expected number after '@', got '%s'\n", token+1 );
846 goto error;
847 }
848 ordinal = atoi( token+1 );
849 if (!ordinal)
850 {
851 error( "Ordinal 0 is not valid\n" );
852 goto error;
853 }
854 if (ordinal >= MAX_ORDINALS)
855 {
856 error( "Ordinal number %d too large\n", ordinal );
857 goto error;
858 }
Alexandre Julliard492ac292004-02-17 20:36:16 +0000859 odp->ordinal = ordinal;
860 token = GetToken(1);
861 }
862
863 /* check for other optional keywords */
864
865 if (token && !strcmp( token, "NONAME" ))
866 {
867 if (odp->ordinal == -1)
868 {
869 error( "NONAME requires an ordinal\n" );
870 goto error;
871 }
872 odp->export_name = odp->name;
873 odp->name = NULL;
874 odp->flags |= FLAG_NONAME;
875 token = GetToken(1);
876 }
877 if (token && !strcmp( token, "PRIVATE" ))
878 {
879 odp->flags |= FLAG_PRIVATE;
880 token = GetToken(1);
881 }
882 if (token && !strcmp( token, "DATA" ))
883 {
884 odp->type = TYPE_EXTERN;
885 token = GetToken(1);
886 }
887 if (token)
888 {
889 error( "Garbage text '%s' found at end of export declaration\n", token );
890 goto error;
891 }
892 return 1;
893
894error:
895 spec->nb_entry_points--;
896 free( odp->name );
897 return 0;
898}
899
900
901/*******************************************************************
902 * parse_def_file
903 *
904 * Parse a .def file.
905 */
906int parse_def_file( FILE *file, DLLSPEC *spec )
907{
908 const char *token;
909 int in_exports = 0;
910
911 input_file = file;
912 current_line = 0;
913
914 comment_chars = ";";
915 separator_chars = ",=";
916
917 while (get_next_line())
918 {
919 if (!(token = GetToken(1))) continue;
920
921 if (!strcmp( token, "LIBRARY" ) || !strcmp( token, "NAME" ))
922 {
923 if (!parse_def_library( spec )) continue;
924 goto end_of_line;
925 }
926 else if (!strcmp( token, "STACKSIZE" ))
927 {
928 if (!parse_def_stack_heap_size( 1, spec )) continue;
929 goto end_of_line;
930 }
931 else if (!strcmp( token, "HEAPSIZE" ))
932 {
933 if (!parse_def_stack_heap_size( 0, spec )) continue;
934 goto end_of_line;
935 }
936 else if (!strcmp( token, "EXPORTS" ))
937 {
938 in_exports = 1;
939 if (!(token = GetToken(1))) continue;
940 }
941 else if (!strcmp( token, "IMPORTS" ))
942 {
943 in_exports = 0;
944 if (!(token = GetToken(1))) continue;
945 }
946 else if (!strcmp( token, "SECTIONS" ))
947 {
948 in_exports = 0;
949 if (!(token = GetToken(1))) continue;
950 }
951
952 if (!in_exports) continue; /* ignore this line */
953 if (!parse_def_export( xstrdup(token), spec )) continue;
954
955 end_of_line:
956 if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token );
957 }
958
959 current_line = 0; /* no longer parsing the input file */
960 assign_names( spec );
961 assign_ordinals( spec );
962 return !nb_errors;
963}