2011-04-18 Tristan Gingold <gingold@adacore.com>
[deliverable/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; }
770c040b
KT
227 | '.' ID
228 {
229 char *name = xmalloc (strlen ($2) + 2);
230 sprintf (name, ".%s", $2);
231 $$ = name;
232 }
5aaace27
NC
233 | ID '.' ID
234 {
1579bae1 235 char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
5aaace27
NC
236 sprintf (name, "%s.%s", $1, $3);
237 $$ = name;
238 }
239 | { $$ = ""; }
252b5132
RH
240 ;
241
7fcab871
KT
242opt_equalequal_name: EQUAL ID { $$ = $2; }
243 | { $$ = 0; }
244 ;
245
252b5132
RH
246opt_ordinal:
247 '@' NUMBER { $$ = $2;}
248 | { $$ = -1;}
249 ;
250
251opt_equal_name:
053c44e1 252 '=' dot_name { $$ = $2; }
252b5132
RH
253 | { $$ = 0; }
254 ;
255
256opt_base: BASE '=' NUMBER { $$ = $3;}
4064c856 257 | { $$ = -1;}
252b5132
RH
258 ;
259
053c44e1 260dot_name: ID { $$ = $1; }
770c040b
KT
261 | '.' ID
262 {
263 char *name = xmalloc (strlen ($2) + 2);
264 sprintf (name, ".%s", $2);
265 $$ = name;
266 }
053c44e1
DS
267 | dot_name '.' ID
268 {
1579bae1 269 char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
053c44e1
DS
270 sprintf (name, "%s.%s", $1, $3);
271 $$ = name;
272 }
273 ;
05056a8d
DK
274
275anylang_id: ID { $$ = $1; }
770c040b
KT
276 | '.' ID
277 {
278 char *id = xmalloc (strlen ($2) + 2);
279 sprintf (id, ".%s", $2);
280 $$ = id;
281 }
05056a8d
DK
282 | anylang_id '.' opt_digits opt_id
283 {
284 char *id = xmalloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
285 sprintf (id, "%s.%s%s", $1, $3, $4);
286 $$ = id;
287 }
288 ;
289
290opt_digits: DIGITS { $$ = $1; }
291 | { $$ = ""; }
292 ;
293
294opt_id: ID { $$ = $1; }
295 | { $$ = ""; }
296 ;
297
298NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); }
252b5132
RH
299
300%%
301
302/*****************************************************************************
303 API
304 *****************************************************************************/
305
306static FILE *the_file;
307static const char *def_filename;
308static int linenumber;
309static def_file *def;
310static int saw_newline;
311
312struct directive
313 {
314 struct directive *next;
315 char *name;
316 int len;
317 };
318
319static struct directive *directives = 0;
320
321def_file *
1579bae1 322def_file_empty (void)
252b5132 323{
1579bae1 324 def_file *rv = xmalloc (sizeof (def_file));
252b5132
RH
325 memset (rv, 0, sizeof (def_file));
326 rv->is_dll = -1;
1579bae1 327 rv->base_address = (bfd_vma) -1;
252b5132
RH
328 rv->stack_reserve = rv->stack_commit = -1;
329 rv->heap_reserve = rv->heap_commit = -1;
330 rv->version_major = rv->version_minor = -1;
331 return rv;
332}
333
334def_file *
1579bae1 335def_file_parse (const char *filename, def_file *add_to)
252b5132
RH
336{
337 struct directive *d;
338
339 the_file = fopen (filename, "r");
340 def_filename = filename;
341 linenumber = 1;
342 if (!the_file)
343 {
344 perror (filename);
345 return 0;
346 }
347 if (add_to)
348 {
349 def = add_to;
350 }
351 else
352 {
353 def = def_file_empty ();
354 }
355
356 saw_newline = 1;
357 if (def_parse ())
358 {
359 def_file_free (def);
360 fclose (the_file);
361 return 0;
362 }
363
364 fclose (the_file);
365
366 for (d = directives; d; d = d->next)
367 {
368#if TRACE
369 printf ("Adding directive %08x `%s'\n", d->name, d->name);
370#endif
371 def_file_add_directive (def, d->name, d->len);
372 }
373
374 return def;
375}
376
377void
91d6fa6a 378def_file_free (def_file *fdef)
252b5132
RH
379{
380 int i;
a35bc64f 381
91d6fa6a 382 if (!fdef)
252b5132 383 return;
91d6fa6a
NC
384 if (fdef->name)
385 free (fdef->name);
386 if (fdef->description)
387 free (fdef->description);
252b5132 388
91d6fa6a 389 if (fdef->section_defs)
252b5132 390 {
91d6fa6a 391 for (i = 0; i < fdef->num_section_defs; i++)
252b5132 392 {
91d6fa6a
NC
393 if (fdef->section_defs[i].name)
394 free (fdef->section_defs[i].name);
395 if (fdef->section_defs[i].class)
396 free (fdef->section_defs[i].class);
252b5132 397 }
91d6fa6a 398 free (fdef->section_defs);
252b5132
RH
399 }
400
91d6fa6a 401 if (fdef->exports)
252b5132 402 {
b41d91a7 403 for (i = 0; i < fdef->num_exports; i++)
252b5132 404 {
91d6fa6a
NC
405 if (fdef->exports[i].internal_name
406 && fdef->exports[i].internal_name != fdef->exports[i].name)
407 free (fdef->exports[i].internal_name);
408 if (fdef->exports[i].name)
409 free (fdef->exports[i].name);
410 if (fdef->exports[i].its_name)
411 free (fdef->exports[i].its_name);
252b5132 412 }
91d6fa6a 413 free (fdef->exports);
252b5132
RH
414 }
415
91d6fa6a 416 if (fdef->imports)
252b5132 417 {
91d6fa6a 418 for (i = 0; i < fdef->num_imports; i++)
252b5132 419 {
91d6fa6a
NC
420 if (fdef->imports[i].internal_name
421 && fdef->imports[i].internal_name != fdef->imports[i].name)
422 free (fdef->imports[i].internal_name);
423 if (fdef->imports[i].name)
424 free (fdef->imports[i].name);
425 if (fdef->imports[i].its_name)
426 free (fdef->imports[i].its_name);
252b5132 427 }
91d6fa6a 428 free (fdef->imports);
252b5132
RH
429 }
430
91d6fa6a 431 while (fdef->modules)
252b5132 432 {
91d6fa6a
NC
433 def_file_module *m = fdef->modules;
434
435 fdef->modules = fdef->modules->next;
252b5132
RH
436 free (m);
437 }
438
91d6fa6a 439 while (fdef->aligncomms)
c1711530 440 {
91d6fa6a
NC
441 def_file_aligncomm *c = fdef->aligncomms;
442
443 fdef->aligncomms = fdef->aligncomms->next;
c1711530
DK
444 free (c->symbol_name);
445 free (c);
446 }
447
91d6fa6a 448 free (fdef);
252b5132
RH
449}
450
451#ifdef DEF_FILE_PRINT
452void
91d6fa6a 453def_file_print (FILE *file, def_file *fdef)
252b5132
RH
454{
455 int i;
a35bc64f 456
91d6fa6a
NC
457 fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
458 if (fdef->name)
459 fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)");
460 if (fdef->is_dll != -1)
461 fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no");
462 if (fdef->base_address != (bfd_vma) -1)
463 fprintf (file, " base address: 0x%08x\n", fdef->base_address);
464 if (fdef->description)
465 fprintf (file, " description: `%s'\n", fdef->description);
466 if (fdef->stack_reserve != -1)
467 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve);
468 if (fdef->stack_commit != -1)
469 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit);
470 if (fdef->heap_reserve != -1)
471 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve);
472 if (fdef->heap_commit != -1)
473 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit);
474
475 if (fdef->num_section_defs > 0)
252b5132
RH
476 {
477 fprintf (file, " section defs:\n");
a35bc64f 478
91d6fa6a 479 for (i = 0; i < fdef->num_section_defs; i++)
252b5132
RH
480 {
481 fprintf (file, " name: `%s', class: `%s', flags:",
91d6fa6a
NC
482 fdef->section_defs[i].name, fdef->section_defs[i].class);
483 if (fdef->section_defs[i].flag_read)
252b5132 484 fprintf (file, " R");
91d6fa6a 485 if (fdef->section_defs[i].flag_write)
252b5132 486 fprintf (file, " W");
91d6fa6a 487 if (fdef->section_defs[i].flag_execute)
252b5132 488 fprintf (file, " X");
91d6fa6a 489 if (fdef->section_defs[i].flag_shared)
252b5132
RH
490 fprintf (file, " S");
491 fprintf (file, "\n");
492 }
493 }
494
91d6fa6a 495 if (fdef->num_exports > 0)
252b5132
RH
496 {
497 fprintf (file, " exports:\n");
a35bc64f 498
91d6fa6a 499 for (i = 0; i < fdef->num_exports; i++)
252b5132
RH
500 {
501 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
91d6fa6a
NC
502 fdef->exports[i].name, fdef->exports[i].internal_name,
503 fdef->exports[i].ordinal);
504 if (fdef->exports[i].flag_private)
252b5132 505 fprintf (file, " P");
91d6fa6a 506 if (fdef->exports[i].flag_constant)
252b5132 507 fprintf (file, " C");
91d6fa6a 508 if (fdef->exports[i].flag_noname)
252b5132 509 fprintf (file, " N");
91d6fa6a 510 if (fdef->exports[i].flag_data)
252b5132
RH
511 fprintf (file, " D");
512 fprintf (file, "\n");
513 }
514 }
515
91d6fa6a 516 if (fdef->num_imports > 0)
252b5132
RH
517 {
518 fprintf (file, " imports:\n");
a35bc64f 519
91d6fa6a 520 for (i = 0; i < fdef->num_imports; i++)
252b5132
RH
521 {
522 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
91d6fa6a
NC
523 fdef->imports[i].internal_name,
524 fdef->imports[i].module,
525 fdef->imports[i].name,
526 fdef->imports[i].ordinal);
252b5132
RH
527 }
528 }
a35bc64f 529
91d6fa6a
NC
530 if (fdef->version_major != -1)
531 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor);
a35bc64f 532
b41d91a7 533 fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
252b5132
RH
534}
535#endif
536
db17156e
KT
537/* Helper routine to check for identity of string pointers,
538 which might be NULL. */
539
540static int
541are_names_equal (const char *s1, const char *s2)
542{
543 if (!s1 && !s2)
544 return 0;
545 if (!s1 || !s2)
546 return (!s1 ? -1 : 1);
547 return strcmp (s1, s2);
548}
549
550static int
551cmp_export_elem (const def_file_export *e, const char *ex_name,
552 const char *in_name, const char *its_name,
553 int ord)
554{
555 int r;
556
557 if ((r = are_names_equal (ex_name, e->name)) != 0)
558 return r;
559 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
560 return r;
561 if ((r = are_names_equal (its_name, e->its_name)) != 0)
562 return r;
563 return (ord - e->ordinal);
564}
565
566/* Search the position of the identical element, or returns the position
567 of the next higher element. If last valid element is smaller, then MAX
568 is returned. */
569
570static int
571find_export_in_list (def_file_export *b, int max,
572 const char *ex_name, const char *in_name,
573 const char *its_name, int ord, int *is_ident)
574{
575 int e, l, r, p;
576
577 *is_ident = 0;
578 if (!max)
579 return 0;
580 if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
581 return 0;
582 if (max == 1)
583 return 1;
584 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
585 return max;
586 else if (!e || max == 2)
587 return max - 1;
588 l = 0; r = max - 1;
589 while (l < r)
590 {
591 p = (l + r) / 2;
592 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
593 if (!e)
594 {
595 *is_ident = 1;
596 return p;
597 }
598 else if (e < 0)
599 r = p - 1;
600 else if (e > 0)
601 l = p + 1;
602 }
603 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
604 ++l;
605 else if (!e)
606 *is_ident = 1;
607 return l;
608}
609
252b5132 610def_file_export *
91d6fa6a 611def_file_add_export (def_file *fdef,
1579bae1
AM
612 const char *external_name,
613 const char *internal_name,
7fcab871 614 int ordinal,
db17156e
KT
615 const char *its_name,
616 int *is_dup)
252b5132
RH
617{
618 def_file_export *e;
db17156e 619 int pos;
91d6fa6a 620 int max_exports = ROUND_UP(fdef->num_exports, 32);
a35bc64f 621
db17156e
KT
622 if (internal_name && !external_name)
623 external_name = internal_name;
624 if (external_name && !internal_name)
625 internal_name = external_name;
626
627 /* We need to avoid duplicates. */
628 *is_dup = 0;
629 pos = find_export_in_list (fdef->exports, fdef->num_exports,
630 external_name, internal_name,
631 its_name, ordinal, is_dup);
632
633 if (*is_dup != 0)
634 return (fdef->exports + pos);
635
91d6fa6a 636 if (fdef->num_exports >= max_exports)
252b5132 637 {
91d6fa6a
NC
638 max_exports = ROUND_UP(fdef->num_exports + 1, 32);
639 if (fdef->exports)
640 fdef->exports = xrealloc (fdef->exports,
1579bae1 641 max_exports * sizeof (def_file_export));
252b5132 642 else
91d6fa6a 643 fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
252b5132 644 }
db17156e
KT
645
646 e = fdef->exports + pos;
647 if (pos != fdef->num_exports)
648 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
252b5132 649 memset (e, 0, sizeof (def_file_export));
252b5132
RH
650 e->name = xstrdup (external_name);
651 e->internal_name = xstrdup (internal_name);
7fcab871 652 e->its_name = (its_name ? xstrdup (its_name) : NULL);
252b5132 653 e->ordinal = ordinal;
91d6fa6a 654 fdef->num_exports++;
252b5132
RH
655 return e;
656}
657
a35bc64f 658def_file_module *
91d6fa6a 659def_get_module (def_file *fdef, const char *name)
a35bc64f
NC
660{
661 def_file_module *s;
662
91d6fa6a 663 for (s = fdef->modules; s; s = s->next)
a35bc64f
NC
664 if (strcmp (s->name, name) == 0)
665 return s;
666
1579bae1 667 return NULL;
a35bc64f
NC
668}
669
252b5132 670static def_file_module *
91d6fa6a 671def_stash_module (def_file *fdef, const char *name)
252b5132
RH
672{
673 def_file_module *s;
a35bc64f 674
91d6fa6a 675 if ((s = def_get_module (fdef, name)) != NULL)
252b5132 676 return s;
1579bae1 677 s = xmalloc (sizeof (def_file_module) + strlen (name));
b41d91a7 678 s->next = fdef->modules;
91d6fa6a 679 fdef->modules = s;
252b5132
RH
680 s->user_data = 0;
681 strcpy (s->name, name);
682 return s;
683}
684
db17156e
KT
685static int
686cmp_import_elem (const def_file_import *e, const char *ex_name,
687 const char *in_name, const char *module,
688 int ord)
689{
690 int r;
691
692 if ((r = are_names_equal (ex_name, e->name)) != 0)
693 return r;
694 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
695 return r;
696 if (ord != e->ordinal)
697 return (ord < e->ordinal ? -1 : 1);
698 return are_names_equal (module, (e->module ? e->module->name : NULL));
699}
700
701/* Search the position of the identical element, or returns the position
702 of the next higher element. If last valid element is smaller, then MAX
703 is returned. */
704
705static int
706find_import_in_list (def_file_import *b, int max,
707 const char *ex_name, const char *in_name,
708 const char *module, int ord, int *is_ident)
709{
710 int e, l, r, p;
711
712 *is_ident = 0;
713 if (!max)
714 return 0;
715 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
716 return 0;
717 if (max == 1)
718 return 1;
719 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
720 return max;
721 else if (!e || max == 2)
722 return max - 1;
723 l = 0; r = max - 1;
724 while (l < r)
725 {
726 p = (l + r) / 2;
727 e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
728 if (!e)
729 {
730 *is_ident = 1;
731 return p;
732 }
733 else if (e < 0)
734 r = p - 1;
735 else if (e > 0)
736 l = p + 1;
737 }
738 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
739 ++l;
740 else if (!e)
741 *is_ident = 1;
742 return l;
743}
744
252b5132 745def_file_import *
91d6fa6a 746def_file_add_import (def_file *fdef,
1579bae1
AM
747 const char *name,
748 const char *module,
749 int ordinal,
7fcab871 750 const char *internal_name,
db17156e
KT
751 const char *its_name,
752 int *is_dup)
252b5132
RH
753{
754 def_file_import *i;
db17156e 755 int pos;
91d6fa6a 756 int max_imports = ROUND_UP (fdef->num_imports, 16);
a35bc64f 757
db17156e
KT
758 /* We need to avoid here duplicates. */
759 *is_dup = 0;
760 pos = find_import_in_list (fdef->imports, fdef->num_imports,
761 name,
762 (!internal_name ? name : internal_name),
763 module, ordinal, is_dup);
764 if (*is_dup != 0)
765 return fdef->imports + pos;
766
91d6fa6a 767 if (fdef->num_imports >= max_imports)
252b5132 768 {
91d6fa6a 769 max_imports = ROUND_UP (fdef->num_imports+1, 16);
a35bc64f 770
91d6fa6a
NC
771 if (fdef->imports)
772 fdef->imports = xrealloc (fdef->imports,
1579bae1 773 max_imports * sizeof (def_file_import));
252b5132 774 else
91d6fa6a 775 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
252b5132 776 }
db17156e
KT
777 i = fdef->imports + pos;
778 if (pos != fdef->num_imports)
779 memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos)));
252b5132
RH
780 memset (i, 0, sizeof (def_file_import));
781 if (name)
782 i->name = xstrdup (name);
783 if (module)
b41d91a7 784 i->module = def_stash_module (fdef, module);
252b5132
RH
785 i->ordinal = ordinal;
786 if (internal_name)
787 i->internal_name = xstrdup (internal_name);
788 else
789 i->internal_name = i->name;
7fcab871 790 i->its_name = (its_name ? xstrdup (its_name) : NULL);
91d6fa6a 791 fdef->num_imports++;
a35bc64f 792
252b5132
RH
793 return i;
794}
795
796struct
797{
798 char *param;
799 int token;
800}
801diropts[] =
802{
803 { "-heap", HEAPSIZE },
8e58566f 804 { "-stack", STACKSIZE_K },
252b5132
RH
805 { "-attr", SECTIONS },
806 { "-export", EXPORTS },
c1711530 807 { "-aligncomm", ALIGNCOMM },
252b5132
RH
808 { 0, 0 }
809};
810
811void
1579bae1 812def_file_add_directive (def_file *my_def, const char *param, int len)
252b5132
RH
813{
814 def_file *save_def = def;
815 const char *pend = param + len;
dc17f155 816 char * tend = (char *) param;
252b5132
RH
817 int i;
818
819 def = my_def;
820
821 while (param < pend)
822 {
1579bae1
AM
823 while (param < pend
824 && (ISSPACE (*param) || *param == '\n' || *param == 0))
252b5132 825 param++;
a35bc64f 826
dc17f155
NC
827 if (param == pend)
828 break;
829
830 /* Scan forward until we encounter any of:
831 - the end of the buffer
832 - the start of a new option
833 - a newline seperating options
834 - a NUL seperating options. */
835 for (tend = (char *) (param + 1);
1579bae1
AM
836 (tend < pend
837 && !(ISSPACE (tend[-1]) && *tend == '-')
838 && *tend != '\n' && *tend != 0);
a35bc64f
NC
839 tend++)
840 ;
252b5132
RH
841
842 for (i = 0; diropts[i].param; i++)
843 {
91d6fa6a 844 len = strlen (diropts[i].param);
a35bc64f 845
252b5132
RH
846 if (tend - param >= len
847 && strncmp (param, diropts[i].param, len) == 0
848 && (param[len] == ':' || param[len] == ' '))
849 {
850 lex_parse_string_end = tend;
851 lex_parse_string = param + len + 1;
852 lex_forced_token = diropts[i].token;
853 saw_newline = 0;
dc17f155
NC
854 if (def_parse ())
855 continue;
252b5132
RH
856 break;
857 }
858 }
859
860 if (!diropts[i].param)
dc17f155
NC
861 {
862 char saved;
863
864 saved = * tend;
865 * tend = 0;
866 /* xgettext:c-format */
867 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
868 * tend = saved;
869 }
a35bc64f 870
252b5132
RH
871 lex_parse_string = 0;
872 param = tend;
873 }
874
875 def = save_def;
876}
877
a35bc64f 878/* Parser Callbacks. */
252b5132
RH
879
880static void
a880c748 881def_image_name (const char *name, int base, int is_dll)
252b5132 882{
a2877985
DS
883 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
884 to do here. We retain the output filename specified on command line. */
885 if (*name)
886 {
887 const char* image_name = lbasename (name);
91d6fa6a 888
a2877985
DS
889 if (image_name != name)
890 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
891 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
892 name);
893 if (def->name)
894 free (def->name);
895 /* Append the default suffix, if none specified. */
896 if (strchr (image_name, '.') == 0)
897 {
898 const char * suffix = is_dll ? ".dll" : ".exe";
899
900 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
901 sprintf (def->name, "%s%s", image_name, suffix);
902 }
903 else
904 def->name = xstrdup (image_name);
905 }
906
907 /* Honor a BASE address statement, even if LIBRARY string is empty. */
252b5132 908 def->base_address = base;
a880c748 909 def->is_dll = is_dll;
252b5132
RH
910}
911
912static void
1579bae1 913def_description (const char *text)
252b5132
RH
914{
915 int len = def->description ? strlen (def->description) : 0;
a35bc64f 916
252b5132
RH
917 len += strlen (text) + 1;
918 if (def->description)
919 {
1579bae1 920 def->description = xrealloc (def->description, len);
252b5132
RH
921 strcat (def->description, text);
922 }
923 else
924 {
1579bae1 925 def->description = xmalloc (len);
252b5132
RH
926 strcpy (def->description, text);
927 }
928}
929
930static void
1579bae1 931def_stacksize (int reserve, int commit)
252b5132
RH
932{
933 def->stack_reserve = reserve;
934 def->stack_commit = commit;
935}
936
937static void
1579bae1 938def_heapsize (int reserve, int commit)
252b5132
RH
939{
940 def->heap_reserve = reserve;
941 def->heap_commit = commit;
942}
943
944static void
1579bae1 945def_section (const char *name, int attr)
252b5132
RH
946{
947 def_file_section *s;
1579bae1 948 int max_sections = ROUND_UP (def->num_section_defs, 4);
a35bc64f 949
252b5132
RH
950 if (def->num_section_defs >= max_sections)
951 {
1579bae1 952 max_sections = ROUND_UP (def->num_section_defs+1, 4);
a35bc64f 953
252b5132 954 if (def->section_defs)
1579bae1
AM
955 def->section_defs = xrealloc (def->section_defs,
956 max_sections * sizeof (def_file_import));
252b5132 957 else
1579bae1 958 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
252b5132
RH
959 }
960 s = def->section_defs + def->num_section_defs;
961 memset (s, 0, sizeof (def_file_section));
962 s->name = xstrdup (name);
963 if (attr & 1)
964 s->flag_read = 1;
965 if (attr & 2)
966 s->flag_write = 1;
967 if (attr & 4)
968 s->flag_execute = 1;
969 if (attr & 8)
970 s->flag_shared = 1;
971
972 def->num_section_defs++;
973}
974
975static void
1579bae1 976def_section_alt (const char *name, const char *attr)
252b5132
RH
977{
978 int aval = 0;
a35bc64f 979
252b5132
RH
980 for (; *attr; attr++)
981 {
982 switch (*attr)
983 {
984 case 'R':
985 case 'r':
986 aval |= 1;
987 break;
988 case 'W':
989 case 'w':
990 aval |= 2;
991 break;
992 case 'X':
993 case 'x':
994 aval |= 4;
995 break;
996 case 'S':
997 case 's':
998 aval |= 8;
999 break;
1000 }
1001 }
1002 def_section (name, aval);
1003}
1004
1005static void
1579bae1
AM
1006def_exports (const char *external_name,
1007 const char *internal_name,
1008 int ordinal,
7fcab871
KT
1009 int flags,
1010 const char *its_name)
252b5132
RH
1011{
1012 def_file_export *dfe;
db17156e 1013 int is_dup = 0;
252b5132
RH
1014
1015 if (!internal_name && external_name)
1016 internal_name = external_name;
1017#if TRACE
1018 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1019#endif
1020
7fcab871 1021 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
db17156e
KT
1022 its_name, &is_dup);
1023
1024 /* We might check here for flag redefinition and warn. For now we
1025 ignore duplicates silently. */
1026 if (is_dup)
1027 return;
1028
252b5132
RH
1029 if (flags & 1)
1030 dfe->flag_noname = 1;
1031 if (flags & 2)
1032 dfe->flag_constant = 1;
1033 if (flags & 4)
1034 dfe->flag_data = 1;
1035 if (flags & 8)
1036 dfe->flag_private = 1;
1037}
1038
1039static void
1579bae1
AM
1040def_import (const char *internal_name,
1041 const char *module,
1042 const char *dllext,
1043 const char *name,
7fcab871
KT
1044 int ordinal,
1045 const char *its_name)
252b5132
RH
1046{
1047 char *buf = 0;
db17156e
KT
1048 const char *ext = dllext ? dllext : "dll";
1049 int is_dup = 0;
053c44e1 1050
1579bae1 1051 buf = xmalloc (strlen (module) + strlen (ext) + 2);
053c44e1
DS
1052 sprintf (buf, "%s.%s", module, ext);
1053 module = buf;
252b5132 1054
db17156e
KT
1055 def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1056 &is_dup);
1057 free (buf);
252b5132
RH
1058}
1059
1060static void
1579bae1 1061def_version (int major, int minor)
252b5132
RH
1062{
1063 def->version_major = major;
1064 def->version_minor = minor;
1065}
1066
1067static void
1579bae1 1068def_directive (char *str)
252b5132 1069{
1579bae1 1070 struct directive *d = xmalloc (sizeof (struct directive));
a35bc64f 1071
252b5132
RH
1072 d->next = directives;
1073 directives = d;
1074 d->name = xstrdup (str);
1075 d->len = strlen (str);
1076}
1077
c1711530
DK
1078static void
1079def_aligncomm (char *str, int align)
1080{
1081 def_file_aligncomm *c = xmalloc (sizeof (def_file_aligncomm));
1082
1083 c->symbol_name = xstrdup (str);
1084 c->alignment = (unsigned int) align;
1085
1086 c->next = def->aligncomms;
1087 def->aligncomms = c;
1088}
1089
252b5132 1090static int
1579bae1 1091def_error (const char *err)
252b5132 1092{
1579bae1
AM
1093 einfo ("%P: %s:%d: %s\n",
1094 def_filename ? def_filename : "<unknown-file>", linenumber, err);
252b5132
RH
1095 return 0;
1096}
1097
1098
a35bc64f 1099/* Lexical Scanner. */
252b5132
RH
1100
1101#undef TRACE
1102#define TRACE 0
1103
a35bc64f 1104/* Never freed, but always reused as needed, so no real leak. */
252b5132
RH
1105static char *buffer = 0;
1106static int buflen = 0;
1107static int bufptr = 0;
1108
1109static void
1579bae1 1110put_buf (char c)
252b5132
RH
1111{
1112 if (bufptr == buflen)
1113 {
a35bc64f 1114 buflen += 50; /* overly reasonable, eh? */
252b5132 1115 if (buffer)
1579bae1 1116 buffer = xrealloc (buffer, buflen + 1);
252b5132 1117 else
1579bae1 1118 buffer = xmalloc (buflen + 1);
252b5132
RH
1119 }
1120 buffer[bufptr++] = c;
a35bc64f 1121 buffer[bufptr] = 0; /* not optimal, but very convenient. */
252b5132
RH
1122}
1123
1124static struct
1125{
1126 char *name;
1127 int token;
1128}
1129tokens[] =
1130{
1131 { "BASE", BASE },
1132 { "CODE", CODE },
7c9e78f8
DD
1133 { "CONSTANT", CONSTANTU },
1134 { "constant", CONSTANTL },
1135 { "DATA", DATAU },
1136 { "data", DATAL },
252b5132
RH
1137 { "DESCRIPTION", DESCRIPTION },
1138 { "DIRECTIVE", DIRECTIVE },
1139 { "EXECUTE", EXECUTE },
1140 { "EXPORTS", EXPORTS },
1141 { "HEAPSIZE", HEAPSIZE },
1142 { "IMPORTS", IMPORTS },
1143 { "LIBRARY", LIBRARY },
1144 { "NAME", NAME },
7c9e78f8
DD
1145 { "NONAME", NONAMEU },
1146 { "noname", NONAMEL },
1147 { "PRIVATE", PRIVATEU },
1148 { "private", PRIVATEL },
252b5132
RH
1149 { "READ", READ },
1150 { "SECTIONS", SECTIONS },
1151 { "SEGMENTS", SECTIONS },
1152 { "SHARED", SHARED },
8e58566f 1153 { "STACKSIZE", STACKSIZE_K },
252b5132
RH
1154 { "VERSION", VERSIONK },
1155 { "WRITE", WRITE },
1156 { 0, 0 }
1157};
1158
1159static int
1579bae1 1160def_getc (void)
252b5132
RH
1161{
1162 int rv;
a35bc64f 1163
252b5132
RH
1164 if (lex_parse_string)
1165 {
1166 if (lex_parse_string >= lex_parse_string_end)
1167 rv = EOF;
1168 else
1169 rv = *lex_parse_string++;
1170 }
1171 else
1172 {
1173 rv = fgetc (the_file);
1174 }
1175 if (rv == '\n')
1176 saw_newline = 1;
1177 return rv;
1178}
1179
1180static int
1579bae1 1181def_ungetc (int c)
252b5132
RH
1182{
1183 if (lex_parse_string)
1184 {
1185 lex_parse_string--;
1186 return c;
1187 }
1188 else
1189 return ungetc (c, the_file);
1190}
1191
1192static int
1579bae1 1193def_lex (void)
252b5132
RH
1194{
1195 int c, i, q;
1196
1197 if (lex_forced_token)
1198 {
1199 i = lex_forced_token;
1200 lex_forced_token = 0;
1201#if TRACE
1202 printf ("lex: forcing token %d\n", i);
1203#endif
1204 return i;
1205 }
1206
1207 c = def_getc ();
1208
a35bc64f 1209 /* Trim leading whitespace. */
252b5132
RH
1210 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1211 c = def_getc ();
1212
1213 if (c == EOF)
1214 {
1215#if TRACE
1216 printf ("lex: EOF\n");
1217#endif
1218 return 0;
1219 }
1220
1221 if (saw_newline && c == ';')
1222 {
1223 do
1224 {
1225 c = def_getc ();
1226 }
1227 while (c != EOF && c != '\n');
1228 if (c == '\n')
1229 return def_lex ();
1230 return 0;
1231 }
a35bc64f
NC
1232
1233 /* Must be something else. */
252b5132
RH
1234 saw_newline = 0;
1235
3882b010 1236 if (ISDIGIT (c))
252b5132
RH
1237 {
1238 bufptr = 0;
3882b010 1239 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
252b5132
RH
1240 {
1241 put_buf (c);
1242 c = def_getc ();
1243 }
1244 if (c != EOF)
1245 def_ungetc (c);
05056a8d 1246 yylval.digits = xstrdup (buffer);
252b5132 1247#if TRACE
05056a8d 1248 printf ("lex: `%s' returns DIGITS\n", buffer);
252b5132 1249#endif
05056a8d 1250 return DIGITS;
252b5132
RH
1251 }
1252
c9e38879 1253 if (ISALPHA (c) || strchr ("$:-_?@", c))
252b5132
RH
1254 {
1255 bufptr = 0;
c9e38879
NC
1256 q = c;
1257 put_buf (c);
1258 c = def_getc ();
1259
1260 if (q == '@')
1261 {
1262 if (ISBLANK (c) ) /* '@' followed by whitespace. */
1263 return (q);
1264 else if (ISDIGIT (c)) /* '@' followed by digit. */
1265 {
1266 def_ungetc (c);
1267 return (q);
1268 }
1269#if TRACE
1270 printf ("lex: @ returns itself\n");
1271#endif
1272 }
1273
424908eb 1274 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
252b5132
RH
1275 {
1276 put_buf (c);
1277 c = def_getc ();
1278 }
1279 if (c != EOF)
1280 def_ungetc (c);
c9e38879
NC
1281 if (ISALPHA (q)) /* Check for tokens. */
1282 {
1283 for (i = 0; tokens[i].name; i++)
1284 if (strcmp (tokens[i].name, buffer) == 0)
1285 {
252b5132 1286#if TRACE
c9e38879 1287 printf ("lex: `%s' is a string token\n", buffer);
252b5132 1288#endif
c9e38879
NC
1289 return tokens[i].token;
1290 }
1291 }
252b5132
RH
1292#if TRACE
1293 printf ("lex: `%s' returns ID\n", buffer);
1294#endif
1295 yylval.id = xstrdup (buffer);
1296 return ID;
1297 }
1298
1299 if (c == '\'' || c == '"')
1300 {
1301 q = c;
1302 c = def_getc ();
1303 bufptr = 0;
a35bc64f 1304
252b5132
RH
1305 while (c != EOF && c != q)
1306 {
1307 put_buf (c);
1308 c = def_getc ();
1309 }
1310 yylval.id = xstrdup (buffer);
1311#if TRACE
1312 printf ("lex: `%s' returns ID\n", buffer);
1313#endif
1314 return ID;
1315 }
1316
7fcab871
KT
1317 if ( c == '=')
1318 {
1319 c = def_getc ();
1320 if (c == '=')
1321 {
1322#if TRACE
1323 printf ("lex: `==' returns EQUAL\n");
1324#endif
1325 return EQUAL;
1326 }
1327 def_ungetc (c);
1328#if TRACE
1329 printf ("lex: `=' returns itself\n");
1330#endif
1331 return '=';
1332 }
1333 if (c == '.' || c == ',')
252b5132
RH
1334 {
1335#if TRACE
1336 printf ("lex: `%c' returns itself\n", c);
1337#endif
1338 return c;
1339 }
1340
1341 if (c == '\n')
1342 {
1343 linenumber++;
1344 saw_newline = 1;
1345 }
1346
1347 /*printf ("lex: 0x%02x ignored\n", c); */
1348 return def_lex ();
1349}
This page took 0.551739 seconds and 4 git commands to generate.