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