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