]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - ld/deffilep.y
2009-12-17 Rafael Avila de Espindola <espindola@google.com>
[thirdparty/binutils-gdb.git] / ld / deffilep.y
CommitLineData
252b5132
RH
1%{ /* deffilep.y - parser for .def files */
2
aa820537
AM
3/* Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
4 2007, 2009 Free Software Foundation, Inc.
252b5132 5
a35bc64f 6 This file is part of GNU Binutils.
252b5132 7
a35bc64f
NC
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
f96b4a7b 10 the Free Software Foundation; either version 3 of the License, or
a35bc64f 11 (at your option) any later version.
252b5132 12
a35bc64f
NC
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
252b5132 17
a35bc64f
NC
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
f96b4a7b
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132 22
3db64b00 23#include "sysdep.h"
252b5132 24#include "libiberty.h"
3882b010 25#include "safe-ctype.h"
252b5132 26#include "bfd.h"
252b5132
RH
27#include "ld.h"
28#include "ldmisc.h"
29#include "deffile.h"
30
31#define TRACE 0
32
33#define ROUND_UP(a, b) (((a)+((b)-1))&~((b)-1))
34
35/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
36 as well as gratuitiously global symbol names, so we can have multiple
37 yacc generated parsers in ld. Note that these are only the variables
38 produced by yacc. If other parser generators (bison, byacc, etc) produce
39 additional global names that conflict at link time, then those parser
a35bc64f 40 generators need to be fixed instead of adding those names to this list. */
252b5132
RH
41
42#define yymaxdepth def_maxdepth
43#define yyparse def_parse
44#define yylex def_lex
45#define yyerror def_error
46#define yylval def_lval
47#define yychar def_char
48#define yydebug def_debug
49#define yypact def_pact
50#define yyr1 def_r1
51#define yyr2 def_r2
52#define yydef def_def
53#define yychk def_chk
54#define yypgo def_pgo
55#define yyact def_act
56#define yyexca def_exca
57#define yyerrflag def_errflag
58#define yynerrs def_nerrs
59#define yyps def_ps
60#define yypv def_pv
61#define yys def_s
62#define yy_yys def_yys
63#define yystate def_state
64#define yytmp def_tmp
65#define yyv def_v
66#define yy_yyv def_yyv
67#define yyval def_val
68#define yylloc def_lloc
a35bc64f
NC
69#define yyreds def_reds /* With YYDEBUG defined. */
70#define yytoks def_toks /* With YYDEBUG defined. */
252b5132
RH
71#define yylhs def_yylhs
72#define yylen def_yylen
73#define yydefred def_yydefred
74#define yydgoto def_yydgoto
75#define yysindex def_yysindex
76#define yyrindex def_yyrindex
77#define yygindex def_yygindex
78#define yytable def_yytable
79#define yycheck def_yycheck
80
1579bae1 81static void def_description (const char *);
7fcab871 82static void def_exports (const char *, const char *, int, int, const char *);
1579bae1
AM
83static void def_heapsize (int, int);
84static void def_import (const char *, const char *, const char *, const char *,
7fcab871 85 int, const char *);
a880c748 86static void def_image_name (const char *, int, int);
1579bae1
AM
87static void def_section (const char *, int);
88static void def_section_alt (const char *, const char *);
89static void def_stacksize (int, int);
90static void def_version (int, int);
91static void def_directive (char *);
c1711530 92static void def_aligncomm (char *str, int align);
1579bae1
AM
93static int def_parse (void);
94static int def_error (const char *);
95static int def_lex (void);
252b5132
RH
96
97static int lex_forced_token = 0;
98static const char *lex_parse_string = 0;
99static const char *lex_parse_string_end = 0;
100
101%}
102
103%union {
104 char *id;
105 int number;
05056a8d 106 char *digits;
252b5132
RH
107};
108
8e58566f 109%token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL
655f76a2 110%token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
c1711530 111%token PRIVATEU PRIVATEL ALIGNCOMM
7fcab871 112%token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE EQUAL
252b5132 113%token <id> ID
05056a8d
DK
114%token <digits> DIGITS
115%type <number> NUMBER
116%type <digits> opt_digits
252b5132
RH
117%type <number> opt_base opt_ordinal
118%type <number> attr attr_list opt_number exp_opt_list exp_opt
05056a8d 119%type <id> opt_name opt_equal_name dot_name anylang_id opt_id
7fcab871 120%type <id> opt_equalequal_name
252b5132
RH
121
122%%
123
124start: start command
125 | command
126 ;
127
128command:
a880c748
DS
129 NAME opt_name opt_base { def_image_name ($2, $3, 0); }
130 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); }
252b5132 131 | DESCRIPTION ID { def_description ($2);}
8e58566f 132 | STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);}
252b5132
RH
133 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
134 | CODE attr_list { def_section ("CODE", $2);}
7c9e78f8 135 | DATAU attr_list { def_section ("DATA", $2);}
252b5132
RH
136 | SECTIONS seclist
137 | EXPORTS explist
138 | IMPORTS implist
139 | VERSIONK NUMBER { def_version ($2, 0);}
140 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
141 | DIRECTIVE ID { def_directive ($2);}
05056a8d 142 | ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);}
252b5132
RH
143 ;
144
145
146explist:
147 /* EMPTY */
148 | expline
149 | explist expline
150 ;
151
152expline:
7c9e78f8
DD
153 /* The opt_comma is necessary to support both the usual
154 DEF file syntax as well as .drectve syntax which
155 mandates <expsym>,<expoptlist>. */
7fcab871
KT
156 dot_name opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name
157 { def_exports ($1, $2, $3, $5, $7); }
252b5132
RH
158 ;
159exp_opt_list:
7c9e78f8
DD
160 /* The opt_comma is necessary to support both the usual
161 DEF file syntax as well as .drectve syntax which
162 allows for comma separated opt list. */
163 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; }
252b5132
RH
164 | { $$ = 0; }
165 ;
166exp_opt:
7c9e78f8
DD
167 NONAMEU { $$ = 1; }
168 | NONAMEL { $$ = 1; }
169 | CONSTANTU { $$ = 2; }
170 | CONSTANTL { $$ = 2; }
171 | DATAU { $$ = 4; }
172 | DATAL { $$ = 4; }
173 | PRIVATEU { $$ = 8; }
174 | PRIVATEL { $$ = 8; }
252b5132
RH
175 ;
176implist:
177 implist impline
178 | impline
179 ;
180
181impline:
7fcab871
KT
182 ID '=' ID '.' ID '.' ID opt_equalequal_name
183 { def_import ($1, $3, $5, $7, -1, $8); }
184 | ID '=' ID '.' ID '.' NUMBER opt_equalequal_name
185 { def_import ($1, $3, $5, 0, $7, $8); }
186 | ID '=' ID '.' ID opt_equalequal_name
187 { def_import ($1, $3, 0, $5, -1, $6); }
188 | ID '=' ID '.' NUMBER opt_equalequal_name
189 { def_import ($1, $3, 0, 0, $5, $6); }
190 | ID '.' ID '.' ID opt_equalequal_name
191 { def_import( 0, $1, $3, $5, -1, $6); }
192 | ID '.' ID opt_equalequal_name
193 { def_import ( 0, $1, 0, $3, -1, $4); }
252b5132
RH
194;
195
196seclist:
197 seclist secline
198 | secline
199 ;
200
201secline:
202 ID attr_list { def_section ($1, $2);}
203 | ID ID { def_section_alt ($1, $2);}
204 ;
205
206attr_list:
207 attr_list opt_comma attr { $$ = $1 | $3; }
208 | attr { $$ = $1; }
209 ;
210
211opt_comma:
212 ','
213 |
214 ;
215opt_number: ',' NUMBER { $$=$2;}
216 | { $$=-1;}
217 ;
218
219attr:
220 READ { $$ = 1;}
221 | WRITE { $$ = 2;}
222 | EXECUTE { $$=4;}
223 | SHARED { $$=8;}
224 ;
225
226opt_name: ID { $$ = $1; }
5aaace27
NC
227 | ID '.' ID
228 {
1579bae1 229 char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
5aaace27
NC
230 sprintf (name, "%s.%s", $1, $3);
231 $$ = name;
232 }
233 | { $$ = ""; }
252b5132
RH
234 ;
235
7fcab871
KT
236opt_equalequal_name: EQUAL ID { $$ = $2; }
237 | { $$ = 0; }
238 ;
239
252b5132
RH
240opt_ordinal:
241 '@' NUMBER { $$ = $2;}
242 | { $$ = -1;}
243 ;
244
245opt_equal_name:
053c44e1 246 '=' dot_name { $$ = $2; }
252b5132
RH
247 | { $$ = 0; }
248 ;
249
250opt_base: BASE '=' NUMBER { $$ = $3;}
4064c856 251 | { $$ = -1;}
252b5132
RH
252 ;
253
053c44e1
DS
254dot_name: ID { $$ = $1; }
255 | dot_name '.' ID
256 {
1579bae1 257 char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
053c44e1
DS
258 sprintf (name, "%s.%s", $1, $3);
259 $$ = name;
260 }
261 ;
05056a8d
DK
262
263anylang_id: ID { $$ = $1; }
264 | anylang_id '.' opt_digits opt_id
265 {
266 char *id = xmalloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
267 sprintf (id, "%s.%s%s", $1, $3, $4);
268 $$ = id;
269 }
270 ;
271
272opt_digits: DIGITS { $$ = $1; }
273 | { $$ = ""; }
274 ;
275
276opt_id: ID { $$ = $1; }
277 | { $$ = ""; }
278 ;
279
280NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); }
252b5132
RH
281
282%%
283
284/*****************************************************************************
285 API
286 *****************************************************************************/
287
288static FILE *the_file;
289static const char *def_filename;
290static int linenumber;
291static def_file *def;
292static int saw_newline;
293
294struct directive
295 {
296 struct directive *next;
297 char *name;
298 int len;
299 };
300
301static struct directive *directives = 0;
302
303def_file *
1579bae1 304def_file_empty (void)
252b5132 305{
1579bae1 306 def_file *rv = xmalloc (sizeof (def_file));
252b5132
RH
307 memset (rv, 0, sizeof (def_file));
308 rv->is_dll = -1;
1579bae1 309 rv->base_address = (bfd_vma) -1;
252b5132
RH
310 rv->stack_reserve = rv->stack_commit = -1;
311 rv->heap_reserve = rv->heap_commit = -1;
312 rv->version_major = rv->version_minor = -1;
313 return rv;
314}
315
316def_file *
1579bae1 317def_file_parse (const char *filename, def_file *add_to)
252b5132
RH
318{
319 struct directive *d;
320
321 the_file = fopen (filename, "r");
322 def_filename = filename;
323 linenumber = 1;
324 if (!the_file)
325 {
326 perror (filename);
327 return 0;
328 }
329 if (add_to)
330 {
331 def = add_to;
332 }
333 else
334 {
335 def = def_file_empty ();
336 }
337
338 saw_newline = 1;
339 if (def_parse ())
340 {
341 def_file_free (def);
342 fclose (the_file);
343 return 0;
344 }
345
346 fclose (the_file);
347
348 for (d = directives; d; d = d->next)
349 {
350#if TRACE
351 printf ("Adding directive %08x `%s'\n", d->name, d->name);
352#endif
353 def_file_add_directive (def, d->name, d->len);
354 }
355
356 return def;
357}
358
359void
91d6fa6a 360def_file_free (def_file *fdef)
252b5132
RH
361{
362 int i;
a35bc64f 363
91d6fa6a 364 if (!fdef)
252b5132 365 return;
91d6fa6a
NC
366 if (fdef->name)
367 free (fdef->name);
368 if (fdef->description)
369 free (fdef->description);
252b5132 370
91d6fa6a 371 if (fdef->section_defs)
252b5132 372 {
91d6fa6a 373 for (i = 0; i < fdef->num_section_defs; i++)
252b5132 374 {
91d6fa6a
NC
375 if (fdef->section_defs[i].name)
376 free (fdef->section_defs[i].name);
377 if (fdef->section_defs[i].class)
378 free (fdef->section_defs[i].class);
252b5132 379 }
91d6fa6a 380 free (fdef->section_defs);
252b5132
RH
381 }
382
91d6fa6a 383 if (fdef->exports)
252b5132
RH
384 {
385 for (i = 0; i < def->num_exports; i++)
386 {
91d6fa6a
NC
387 if (fdef->exports[i].internal_name
388 && fdef->exports[i].internal_name != fdef->exports[i].name)
389 free (fdef->exports[i].internal_name);
390 if (fdef->exports[i].name)
391 free (fdef->exports[i].name);
392 if (fdef->exports[i].its_name)
393 free (fdef->exports[i].its_name);
252b5132 394 }
91d6fa6a 395 free (fdef->exports);
252b5132
RH
396 }
397
91d6fa6a 398 if (fdef->imports)
252b5132 399 {
91d6fa6a 400 for (i = 0; i < fdef->num_imports; i++)
252b5132 401 {
91d6fa6a
NC
402 if (fdef->imports[i].internal_name
403 && fdef->imports[i].internal_name != fdef->imports[i].name)
404 free (fdef->imports[i].internal_name);
405 if (fdef->imports[i].name)
406 free (fdef->imports[i].name);
407 if (fdef->imports[i].its_name)
408 free (fdef->imports[i].its_name);
252b5132 409 }
91d6fa6a 410 free (fdef->imports);
252b5132
RH
411 }
412
91d6fa6a 413 while (fdef->modules)
252b5132 414 {
91d6fa6a
NC
415 def_file_module *m = fdef->modules;
416
417 fdef->modules = fdef->modules->next;
252b5132
RH
418 free (m);
419 }
420
91d6fa6a 421 while (fdef->aligncomms)
c1711530 422 {
91d6fa6a
NC
423 def_file_aligncomm *c = fdef->aligncomms;
424
425 fdef->aligncomms = fdef->aligncomms->next;
c1711530
DK
426 free (c->symbol_name);
427 free (c);
428 }
429
91d6fa6a 430 free (fdef);
252b5132
RH
431}
432
433#ifdef DEF_FILE_PRINT
434void
91d6fa6a 435def_file_print (FILE *file, def_file *fdef)
252b5132
RH
436{
437 int i;
a35bc64f 438
91d6fa6a
NC
439 fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
440 if (fdef->name)
441 fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)");
442 if (fdef->is_dll != -1)
443 fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no");
444 if (fdef->base_address != (bfd_vma) -1)
445 fprintf (file, " base address: 0x%08x\n", fdef->base_address);
446 if (fdef->description)
447 fprintf (file, " description: `%s'\n", fdef->description);
448 if (fdef->stack_reserve != -1)
449 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve);
450 if (fdef->stack_commit != -1)
451 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit);
452 if (fdef->heap_reserve != -1)
453 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve);
454 if (fdef->heap_commit != -1)
455 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit);
456
457 if (fdef->num_section_defs > 0)
252b5132
RH
458 {
459 fprintf (file, " section defs:\n");
a35bc64f 460
91d6fa6a 461 for (i = 0; i < fdef->num_section_defs; i++)
252b5132
RH
462 {
463 fprintf (file, " name: `%s', class: `%s', flags:",
91d6fa6a
NC
464 fdef->section_defs[i].name, fdef->section_defs[i].class);
465 if (fdef->section_defs[i].flag_read)
252b5132 466 fprintf (file, " R");
91d6fa6a 467 if (fdef->section_defs[i].flag_write)
252b5132 468 fprintf (file, " W");
91d6fa6a 469 if (fdef->section_defs[i].flag_execute)
252b5132 470 fprintf (file, " X");
91d6fa6a 471 if (fdef->section_defs[i].flag_shared)
252b5132
RH
472 fprintf (file, " S");
473 fprintf (file, "\n");
474 }
475 }
476
91d6fa6a 477 if (fdef->num_exports > 0)
252b5132
RH
478 {
479 fprintf (file, " exports:\n");
a35bc64f 480
91d6fa6a 481 for (i = 0; i < fdef->num_exports; i++)
252b5132
RH
482 {
483 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
91d6fa6a
NC
484 fdef->exports[i].name, fdef->exports[i].internal_name,
485 fdef->exports[i].ordinal);
486 if (fdef->exports[i].flag_private)
252b5132 487 fprintf (file, " P");
91d6fa6a 488 if (fdef->exports[i].flag_constant)
252b5132 489 fprintf (file, " C");
91d6fa6a 490 if (fdef->exports[i].flag_noname)
252b5132 491 fprintf (file, " N");
91d6fa6a 492 if (fdef->exports[i].flag_data)
252b5132
RH
493 fprintf (file, " D");
494 fprintf (file, "\n");
495 }
496 }
497
91d6fa6a 498 if (fdef->num_imports > 0)
252b5132
RH
499 {
500 fprintf (file, " imports:\n");
a35bc64f 501
91d6fa6a 502 for (i = 0; i < fdef->num_imports; i++)
252b5132
RH
503 {
504 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
91d6fa6a
NC
505 fdef->imports[i].internal_name,
506 fdef->imports[i].module,
507 fdef->imports[i].name,
508 fdef->imports[i].ordinal);
252b5132
RH
509 }
510 }
a35bc64f 511
91d6fa6a
NC
512 if (fdef->version_major != -1)
513 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor);
a35bc64f 514
252b5132
RH
515 fprintf (file, "<<<< def_file at 0x%08x\n", def);
516}
517#endif
518
519def_file_export *
91d6fa6a 520def_file_add_export (def_file *fdef,
1579bae1
AM
521 const char *external_name,
522 const char *internal_name,
7fcab871
KT
523 int ordinal,
524 const char *its_name)
252b5132
RH
525{
526 def_file_export *e;
91d6fa6a 527 int max_exports = ROUND_UP(fdef->num_exports, 32);
a35bc64f 528
91d6fa6a 529 if (fdef->num_exports >= max_exports)
252b5132 530 {
91d6fa6a
NC
531 max_exports = ROUND_UP(fdef->num_exports + 1, 32);
532 if (fdef->exports)
533 fdef->exports = xrealloc (fdef->exports,
1579bae1 534 max_exports * sizeof (def_file_export));
252b5132 535 else
91d6fa6a 536 fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
252b5132 537 }
91d6fa6a 538 e = fdef->exports + fdef->num_exports;
252b5132
RH
539 memset (e, 0, sizeof (def_file_export));
540 if (internal_name && !external_name)
541 external_name = internal_name;
542 if (external_name && !internal_name)
543 internal_name = external_name;
544 e->name = xstrdup (external_name);
545 e->internal_name = xstrdup (internal_name);
7fcab871 546 e->its_name = (its_name ? xstrdup (its_name) : NULL);
252b5132 547 e->ordinal = ordinal;
91d6fa6a 548 fdef->num_exports++;
252b5132
RH
549 return e;
550}
551
a35bc64f 552def_file_module *
91d6fa6a 553def_get_module (def_file *fdef, const char *name)
a35bc64f
NC
554{
555 def_file_module *s;
556
91d6fa6a 557 for (s = fdef->modules; s; s = s->next)
a35bc64f
NC
558 if (strcmp (s->name, name) == 0)
559 return s;
560
1579bae1 561 return NULL;
a35bc64f
NC
562}
563
252b5132 564static def_file_module *
91d6fa6a 565def_stash_module (def_file *fdef, const char *name)
252b5132
RH
566{
567 def_file_module *s;
a35bc64f 568
91d6fa6a 569 if ((s = def_get_module (fdef, name)) != NULL)
252b5132 570 return s;
1579bae1 571 s = xmalloc (sizeof (def_file_module) + strlen (name));
252b5132 572 s->next = def->modules;
91d6fa6a 573 fdef->modules = s;
252b5132
RH
574 s->user_data = 0;
575 strcpy (s->name, name);
576 return s;
577}
578
579def_file_import *
91d6fa6a 580def_file_add_import (def_file *fdef,
1579bae1
AM
581 const char *name,
582 const char *module,
583 int ordinal,
7fcab871
KT
584 const char *internal_name,
585 const char *its_name)
252b5132
RH
586{
587 def_file_import *i;
91d6fa6a 588 int max_imports = ROUND_UP (fdef->num_imports, 16);
a35bc64f 589
91d6fa6a 590 if (fdef->num_imports >= max_imports)
252b5132 591 {
91d6fa6a 592 max_imports = ROUND_UP (fdef->num_imports+1, 16);
a35bc64f 593
91d6fa6a
NC
594 if (fdef->imports)
595 fdef->imports = xrealloc (fdef->imports,
1579bae1 596 max_imports * sizeof (def_file_import));
252b5132 597 else
91d6fa6a 598 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
252b5132 599 }
91d6fa6a 600 i = fdef->imports + fdef->num_imports;
252b5132
RH
601 memset (i, 0, sizeof (def_file_import));
602 if (name)
603 i->name = xstrdup (name);
604 if (module)
db09f25b 605 i->module = def_stash_module (def, module);
252b5132
RH
606 i->ordinal = ordinal;
607 if (internal_name)
608 i->internal_name = xstrdup (internal_name);
609 else
610 i->internal_name = i->name;
7fcab871 611 i->its_name = (its_name ? xstrdup (its_name) : NULL);
91d6fa6a 612 fdef->num_imports++;
a35bc64f 613
252b5132
RH
614 return i;
615}
616
617struct
618{
619 char *param;
620 int token;
621}
622diropts[] =
623{
624 { "-heap", HEAPSIZE },
8e58566f 625 { "-stack", STACKSIZE_K },
252b5132
RH
626 { "-attr", SECTIONS },
627 { "-export", EXPORTS },
c1711530 628 { "-aligncomm", ALIGNCOMM },
252b5132
RH
629 { 0, 0 }
630};
631
632void
1579bae1 633def_file_add_directive (def_file *my_def, const char *param, int len)
252b5132
RH
634{
635 def_file *save_def = def;
636 const char *pend = param + len;
dc17f155 637 char * tend = (char *) param;
252b5132
RH
638 int i;
639
640 def = my_def;
641
642 while (param < pend)
643 {
1579bae1
AM
644 while (param < pend
645 && (ISSPACE (*param) || *param == '\n' || *param == 0))
252b5132 646 param++;
a35bc64f 647
dc17f155
NC
648 if (param == pend)
649 break;
650
651 /* Scan forward until we encounter any of:
652 - the end of the buffer
653 - the start of a new option
654 - a newline seperating options
655 - a NUL seperating options. */
656 for (tend = (char *) (param + 1);
1579bae1
AM
657 (tend < pend
658 && !(ISSPACE (tend[-1]) && *tend == '-')
659 && *tend != '\n' && *tend != 0);
a35bc64f
NC
660 tend++)
661 ;
252b5132
RH
662
663 for (i = 0; diropts[i].param; i++)
664 {
91d6fa6a 665 len = strlen (diropts[i].param);
a35bc64f 666
252b5132
RH
667 if (tend - param >= len
668 && strncmp (param, diropts[i].param, len) == 0
669 && (param[len] == ':' || param[len] == ' '))
670 {
671 lex_parse_string_end = tend;
672 lex_parse_string = param + len + 1;
673 lex_forced_token = diropts[i].token;
674 saw_newline = 0;
dc17f155
NC
675 if (def_parse ())
676 continue;
252b5132
RH
677 break;
678 }
679 }
680
681 if (!diropts[i].param)
dc17f155
NC
682 {
683 char saved;
684
685 saved = * tend;
686 * tend = 0;
687 /* xgettext:c-format */
688 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
689 * tend = saved;
690 }
a35bc64f 691
252b5132
RH
692 lex_parse_string = 0;
693 param = tend;
694 }
695
696 def = save_def;
697}
698
a35bc64f 699/* Parser Callbacks. */
252b5132
RH
700
701static void
a880c748 702def_image_name (const char *name, int base, int is_dll)
252b5132 703{
a2877985
DS
704 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
705 to do here. We retain the output filename specified on command line. */
706 if (*name)
707 {
708 const char* image_name = lbasename (name);
91d6fa6a 709
a2877985
DS
710 if (image_name != name)
711 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
712 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
713 name);
714 if (def->name)
715 free (def->name);
716 /* Append the default suffix, if none specified. */
717 if (strchr (image_name, '.') == 0)
718 {
719 const char * suffix = is_dll ? ".dll" : ".exe";
720
721 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
722 sprintf (def->name, "%s%s", image_name, suffix);
723 }
724 else
725 def->name = xstrdup (image_name);
726 }
727
728 /* Honor a BASE address statement, even if LIBRARY string is empty. */
252b5132 729 def->base_address = base;
a880c748 730 def->is_dll = is_dll;
252b5132
RH
731}
732
733static void
1579bae1 734def_description (const char *text)
252b5132
RH
735{
736 int len = def->description ? strlen (def->description) : 0;
a35bc64f 737
252b5132
RH
738 len += strlen (text) + 1;
739 if (def->description)
740 {
1579bae1 741 def->description = xrealloc (def->description, len);
252b5132
RH
742 strcat (def->description, text);
743 }
744 else
745 {
1579bae1 746 def->description = xmalloc (len);
252b5132
RH
747 strcpy (def->description, text);
748 }
749}
750
751static void
1579bae1 752def_stacksize (int reserve, int commit)
252b5132
RH
753{
754 def->stack_reserve = reserve;
755 def->stack_commit = commit;
756}
757
758static void
1579bae1 759def_heapsize (int reserve, int commit)
252b5132
RH
760{
761 def->heap_reserve = reserve;
762 def->heap_commit = commit;
763}
764
765static void
1579bae1 766def_section (const char *name, int attr)
252b5132
RH
767{
768 def_file_section *s;
1579bae1 769 int max_sections = ROUND_UP (def->num_section_defs, 4);
a35bc64f 770
252b5132
RH
771 if (def->num_section_defs >= max_sections)
772 {
1579bae1 773 max_sections = ROUND_UP (def->num_section_defs+1, 4);
a35bc64f 774
252b5132 775 if (def->section_defs)
1579bae1
AM
776 def->section_defs = xrealloc (def->section_defs,
777 max_sections * sizeof (def_file_import));
252b5132 778 else
1579bae1 779 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
252b5132
RH
780 }
781 s = def->section_defs + def->num_section_defs;
782 memset (s, 0, sizeof (def_file_section));
783 s->name = xstrdup (name);
784 if (attr & 1)
785 s->flag_read = 1;
786 if (attr & 2)
787 s->flag_write = 1;
788 if (attr & 4)
789 s->flag_execute = 1;
790 if (attr & 8)
791 s->flag_shared = 1;
792
793 def->num_section_defs++;
794}
795
796static void
1579bae1 797def_section_alt (const char *name, const char *attr)
252b5132
RH
798{
799 int aval = 0;
a35bc64f 800
252b5132
RH
801 for (; *attr; attr++)
802 {
803 switch (*attr)
804 {
805 case 'R':
806 case 'r':
807 aval |= 1;
808 break;
809 case 'W':
810 case 'w':
811 aval |= 2;
812 break;
813 case 'X':
814 case 'x':
815 aval |= 4;
816 break;
817 case 'S':
818 case 's':
819 aval |= 8;
820 break;
821 }
822 }
823 def_section (name, aval);
824}
825
826static void
1579bae1
AM
827def_exports (const char *external_name,
828 const char *internal_name,
829 int ordinal,
7fcab871
KT
830 int flags,
831 const char *its_name)
252b5132
RH
832{
833 def_file_export *dfe;
834
835 if (!internal_name && external_name)
836 internal_name = external_name;
837#if TRACE
838 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
839#endif
840
7fcab871
KT
841 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
842 its_name);
252b5132
RH
843 if (flags & 1)
844 dfe->flag_noname = 1;
845 if (flags & 2)
846 dfe->flag_constant = 1;
847 if (flags & 4)
848 dfe->flag_data = 1;
849 if (flags & 8)
850 dfe->flag_private = 1;
851}
852
853static void
1579bae1
AM
854def_import (const char *internal_name,
855 const char *module,
856 const char *dllext,
857 const char *name,
7fcab871
KT
858 int ordinal,
859 const char *its_name)
252b5132
RH
860{
861 char *buf = 0;
053c44e1
DS
862 const char *ext = dllext ? dllext : "dll";
863
1579bae1 864 buf = xmalloc (strlen (module) + strlen (ext) + 2);
053c44e1
DS
865 sprintf (buf, "%s.%s", module, ext);
866 module = buf;
252b5132 867
7fcab871 868 def_file_add_import (def, name, module, ordinal, internal_name, its_name);
252b5132
RH
869 if (buf)
870 free (buf);
871}
872
873static void
1579bae1 874def_version (int major, int minor)
252b5132
RH
875{
876 def->version_major = major;
877 def->version_minor = minor;
878}
879
880static void
1579bae1 881def_directive (char *str)
252b5132 882{
1579bae1 883 struct directive *d = xmalloc (sizeof (struct directive));
a35bc64f 884
252b5132
RH
885 d->next = directives;
886 directives = d;
887 d->name = xstrdup (str);
888 d->len = strlen (str);
889}
890
c1711530
DK
891static void
892def_aligncomm (char *str, int align)
893{
894 def_file_aligncomm *c = xmalloc (sizeof (def_file_aligncomm));
895
896 c->symbol_name = xstrdup (str);
897 c->alignment = (unsigned int) align;
898
899 c->next = def->aligncomms;
900 def->aligncomms = c;
901}
902
252b5132 903static int
1579bae1 904def_error (const char *err)
252b5132 905{
1579bae1
AM
906 einfo ("%P: %s:%d: %s\n",
907 def_filename ? def_filename : "<unknown-file>", linenumber, err);
252b5132
RH
908 return 0;
909}
910
911
a35bc64f 912/* Lexical Scanner. */
252b5132
RH
913
914#undef TRACE
915#define TRACE 0
916
a35bc64f 917/* Never freed, but always reused as needed, so no real leak. */
252b5132
RH
918static char *buffer = 0;
919static int buflen = 0;
920static int bufptr = 0;
921
922static void
1579bae1 923put_buf (char c)
252b5132
RH
924{
925 if (bufptr == buflen)
926 {
a35bc64f 927 buflen += 50; /* overly reasonable, eh? */
252b5132 928 if (buffer)
1579bae1 929 buffer = xrealloc (buffer, buflen + 1);
252b5132 930 else
1579bae1 931 buffer = xmalloc (buflen + 1);
252b5132
RH
932 }
933 buffer[bufptr++] = c;
a35bc64f 934 buffer[bufptr] = 0; /* not optimal, but very convenient. */
252b5132
RH
935}
936
937static struct
938{
939 char *name;
940 int token;
941}
942tokens[] =
943{
944 { "BASE", BASE },
945 { "CODE", CODE },
7c9e78f8
DD
946 { "CONSTANT", CONSTANTU },
947 { "constant", CONSTANTL },
948 { "DATA", DATAU },
949 { "data", DATAL },
252b5132
RH
950 { "DESCRIPTION", DESCRIPTION },
951 { "DIRECTIVE", DIRECTIVE },
952 { "EXECUTE", EXECUTE },
953 { "EXPORTS", EXPORTS },
954 { "HEAPSIZE", HEAPSIZE },
955 { "IMPORTS", IMPORTS },
956 { "LIBRARY", LIBRARY },
957 { "NAME", NAME },
7c9e78f8
DD
958 { "NONAME", NONAMEU },
959 { "noname", NONAMEL },
960 { "PRIVATE", PRIVATEU },
961 { "private", PRIVATEL },
252b5132
RH
962 { "READ", READ },
963 { "SECTIONS", SECTIONS },
964 { "SEGMENTS", SECTIONS },
965 { "SHARED", SHARED },
8e58566f 966 { "STACKSIZE", STACKSIZE_K },
252b5132
RH
967 { "VERSION", VERSIONK },
968 { "WRITE", WRITE },
969 { 0, 0 }
970};
971
972static int
1579bae1 973def_getc (void)
252b5132
RH
974{
975 int rv;
a35bc64f 976
252b5132
RH
977 if (lex_parse_string)
978 {
979 if (lex_parse_string >= lex_parse_string_end)
980 rv = EOF;
981 else
982 rv = *lex_parse_string++;
983 }
984 else
985 {
986 rv = fgetc (the_file);
987 }
988 if (rv == '\n')
989 saw_newline = 1;
990 return rv;
991}
992
993static int
1579bae1 994def_ungetc (int c)
252b5132
RH
995{
996 if (lex_parse_string)
997 {
998 lex_parse_string--;
999 return c;
1000 }
1001 else
1002 return ungetc (c, the_file);
1003}
1004
1005static int
1579bae1 1006def_lex (void)
252b5132
RH
1007{
1008 int c, i, q;
1009
1010 if (lex_forced_token)
1011 {
1012 i = lex_forced_token;
1013 lex_forced_token = 0;
1014#if TRACE
1015 printf ("lex: forcing token %d\n", i);
1016#endif
1017 return i;
1018 }
1019
1020 c = def_getc ();
1021
a35bc64f 1022 /* Trim leading whitespace. */
252b5132
RH
1023 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1024 c = def_getc ();
1025
1026 if (c == EOF)
1027 {
1028#if TRACE
1029 printf ("lex: EOF\n");
1030#endif
1031 return 0;
1032 }
1033
1034 if (saw_newline && c == ';')
1035 {
1036 do
1037 {
1038 c = def_getc ();
1039 }
1040 while (c != EOF && c != '\n');
1041 if (c == '\n')
1042 return def_lex ();
1043 return 0;
1044 }
a35bc64f
NC
1045
1046 /* Must be something else. */
252b5132
RH
1047 saw_newline = 0;
1048
3882b010 1049 if (ISDIGIT (c))
252b5132
RH
1050 {
1051 bufptr = 0;
3882b010 1052 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
252b5132
RH
1053 {
1054 put_buf (c);
1055 c = def_getc ();
1056 }
1057 if (c != EOF)
1058 def_ungetc (c);
05056a8d 1059 yylval.digits = xstrdup (buffer);
252b5132 1060#if TRACE
05056a8d 1061 printf ("lex: `%s' returns DIGITS\n", buffer);
252b5132 1062#endif
05056a8d 1063 return DIGITS;
252b5132
RH
1064 }
1065
c9e38879 1066 if (ISALPHA (c) || strchr ("$:-_?@", c))
252b5132
RH
1067 {
1068 bufptr = 0;
c9e38879
NC
1069 q = c;
1070 put_buf (c);
1071 c = def_getc ();
1072
1073 if (q == '@')
1074 {
1075 if (ISBLANK (c) ) /* '@' followed by whitespace. */
1076 return (q);
1077 else if (ISDIGIT (c)) /* '@' followed by digit. */
1078 {
1079 def_ungetc (c);
1080 return (q);
1081 }
1082#if TRACE
1083 printf ("lex: @ returns itself\n");
1084#endif
1085 }
1086
424908eb 1087 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
252b5132
RH
1088 {
1089 put_buf (c);
1090 c = def_getc ();
1091 }
1092 if (c != EOF)
1093 def_ungetc (c);
c9e38879
NC
1094 if (ISALPHA (q)) /* Check for tokens. */
1095 {
1096 for (i = 0; tokens[i].name; i++)
1097 if (strcmp (tokens[i].name, buffer) == 0)
1098 {
252b5132 1099#if TRACE
c9e38879 1100 printf ("lex: `%s' is a string token\n", buffer);
252b5132 1101#endif
c9e38879
NC
1102 return tokens[i].token;
1103 }
1104 }
252b5132
RH
1105#if TRACE
1106 printf ("lex: `%s' returns ID\n", buffer);
1107#endif
1108 yylval.id = xstrdup (buffer);
1109 return ID;
1110 }
1111
1112 if (c == '\'' || c == '"')
1113 {
1114 q = c;
1115 c = def_getc ();
1116 bufptr = 0;
a35bc64f 1117
252b5132
RH
1118 while (c != EOF && c != q)
1119 {
1120 put_buf (c);
1121 c = def_getc ();
1122 }
1123 yylval.id = xstrdup (buffer);
1124#if TRACE
1125 printf ("lex: `%s' returns ID\n", buffer);
1126#endif
1127 return ID;
1128 }
1129
7fcab871
KT
1130 if ( c == '=')
1131 {
1132 c = def_getc ();
1133 if (c == '=')
1134 {
1135#if TRACE
1136 printf ("lex: `==' returns EQUAL\n");
1137#endif
1138 return EQUAL;
1139 }
1140 def_ungetc (c);
1141#if TRACE
1142 printf ("lex: `=' returns itself\n");
1143#endif
1144 return '=';
1145 }
1146 if (c == '.' || c == ',')
252b5132
RH
1147 {
1148#if TRACE
1149 printf ("lex: `%c' returns itself\n", c);
1150#endif
1151 return c;
1152 }
1153
1154 if (c == '\n')
1155 {
1156 linenumber++;
1157 saw_newline = 1;
1158 }
1159
1160 /*printf ("lex: 0x%02x ignored\n", c); */
1161 return def_lex ();
1162}