ChangeLog binutils
[deliverable/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 return 0;
626 if (max == 1)
627 return 1;
628 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
629 return max;
630 else if (!e || max == 2)
631 return max - 1;
632 l = 0; r = max - 1;
633 while (l < r)
634 {
635 p = (l + r) / 2;
636 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
637 if (!e)
638 {
639 *is_ident = 1;
640 return p;
641 }
642 else if (e < 0)
643 r = p - 1;
644 else if (e > 0)
645 l = p + 1;
646 }
647 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
648 ++l;
649 else if (!e)
650 *is_ident = 1;
651 return l;
652 }
653
654 def_file_export *
655 def_file_add_export (def_file *fdef,
656 const char *external_name,
657 const char *internal_name,
658 int ordinal,
659 const char *its_name,
660 int *is_dup)
661 {
662 def_file_export *e;
663 int pos;
664 int max_exports = ROUND_UP(fdef->num_exports, 32);
665
666 if (internal_name && !external_name)
667 external_name = internal_name;
668 if (external_name && !internal_name)
669 internal_name = external_name;
670
671 /* We need to avoid duplicates. */
672 *is_dup = 0;
673 pos = find_export_in_list (fdef->exports, fdef->num_exports,
674 external_name, internal_name,
675 its_name, ordinal, is_dup);
676
677 if (*is_dup != 0)
678 return (fdef->exports + pos);
679
680 if (fdef->num_exports >= max_exports)
681 {
682 max_exports = ROUND_UP(fdef->num_exports + 1, 32);
683 if (fdef->exports)
684 fdef->exports = xrealloc (fdef->exports,
685 max_exports * sizeof (def_file_export));
686 else
687 fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
688 }
689
690 e = fdef->exports + pos;
691 if (pos != fdef->num_exports)
692 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
693 memset (e, 0, sizeof (def_file_export));
694 e->name = xstrdup (external_name);
695 e->internal_name = xstrdup (internal_name);
696 e->its_name = (its_name ? xstrdup (its_name) : NULL);
697 e->ordinal = ordinal;
698 fdef->num_exports++;
699 return e;
700 }
701
702 def_file_module *
703 def_get_module (def_file *fdef, const char *name)
704 {
705 def_file_module *s;
706
707 for (s = fdef->modules; s; s = s->next)
708 if (strcmp (s->name, name) == 0)
709 return s;
710
711 return NULL;
712 }
713
714 static def_file_module *
715 def_stash_module (def_file *fdef, const char *name)
716 {
717 def_file_module *s;
718
719 if ((s = def_get_module (fdef, name)) != NULL)
720 return s;
721 s = xmalloc (sizeof (def_file_module) + strlen (name));
722 s->next = fdef->modules;
723 fdef->modules = s;
724 s->user_data = 0;
725 strcpy (s->name, name);
726 return s;
727 }
728
729 static int
730 cmp_import_elem (const def_file_import *e, const char *ex_name,
731 const char *in_name, const char *module,
732 int ord)
733 {
734 int r;
735
736 if ((r = are_names_equal (ex_name, e->name)) != 0)
737 return r;
738 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
739 return r;
740 if (ord != e->ordinal)
741 return (ord < e->ordinal ? -1 : 1);
742 return are_names_equal (module, (e->module ? e->module->name : NULL));
743 }
744
745 /* Search the position of the identical element, or returns the position
746 of the next higher element. If last valid element is smaller, then MAX
747 is returned. */
748
749 static int
750 find_import_in_list (def_file_import *b, int max,
751 const char *ex_name, const char *in_name,
752 const char *module, int ord, int *is_ident)
753 {
754 int e, l, r, p;
755
756 *is_ident = 0;
757 if (!max)
758 return 0;
759 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
760 return 0;
761 if (max == 1)
762 return 1;
763 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
764 return max;
765 else if (!e || max == 2)
766 return max - 1;
767 l = 0; r = max - 1;
768 while (l < r)
769 {
770 p = (l + r) / 2;
771 e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
772 if (!e)
773 {
774 *is_ident = 1;
775 return p;
776 }
777 else if (e < 0)
778 r = p - 1;
779 else if (e > 0)
780 l = p + 1;
781 }
782 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
783 ++l;
784 else if (!e)
785 *is_ident = 1;
786 return l;
787 }
788
789 def_file_import *
790 def_file_add_import (def_file *fdef,
791 const char *name,
792 const char *module,
793 int ordinal,
794 const char *internal_name,
795 const char *its_name,
796 int *is_dup)
797 {
798 def_file_import *i;
799 int pos;
800 int max_imports = ROUND_UP (fdef->num_imports, 16);
801
802 /* We need to avoid here duplicates. */
803 *is_dup = 0;
804 pos = find_import_in_list (fdef->imports, fdef->num_imports,
805 name,
806 (!internal_name ? name : internal_name),
807 module, ordinal, is_dup);
808 if (*is_dup != 0)
809 return fdef->imports + pos;
810
811 if (fdef->num_imports >= max_imports)
812 {
813 max_imports = ROUND_UP (fdef->num_imports+1, 16);
814
815 if (fdef->imports)
816 fdef->imports = xrealloc (fdef->imports,
817 max_imports * sizeof (def_file_import));
818 else
819 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
820 }
821 i = fdef->imports + pos;
822 if (pos != fdef->num_imports)
823 memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos)));
824 memset (i, 0, sizeof (def_file_import));
825 if (name)
826 i->name = xstrdup (name);
827 if (module)
828 i->module = def_stash_module (fdef, module);
829 i->ordinal = ordinal;
830 if (internal_name)
831 i->internal_name = xstrdup (internal_name);
832 else
833 i->internal_name = i->name;
834 i->its_name = (its_name ? xstrdup (its_name) : NULL);
835 fdef->num_imports++;
836
837 return i;
838 }
839
840 struct
841 {
842 char *param;
843 int token;
844 }
845 diropts[] =
846 {
847 { "-heap", HEAPSIZE },
848 { "-stack", STACKSIZE_K },
849 { "-attr", SECTIONS },
850 { "-export", EXPORTS },
851 { "-aligncomm", ALIGNCOMM },
852 { 0, 0 }
853 };
854
855 void
856 def_file_add_directive (def_file *my_def, const char *param, int len)
857 {
858 def_file *save_def = def;
859 const char *pend = param + len;
860 char * tend = (char *) param;
861 int i;
862
863 def = my_def;
864
865 while (param < pend)
866 {
867 while (param < pend
868 && (ISSPACE (*param) || *param == '\n' || *param == 0))
869 param++;
870
871 if (param == pend)
872 break;
873
874 /* Scan forward until we encounter any of:
875 - the end of the buffer
876 - the start of a new option
877 - a newline seperating options
878 - a NUL seperating options. */
879 for (tend = (char *) (param + 1);
880 (tend < pend
881 && !(ISSPACE (tend[-1]) && *tend == '-')
882 && *tend != '\n' && *tend != 0);
883 tend++)
884 ;
885
886 for (i = 0; diropts[i].param; i++)
887 {
888 len = strlen (diropts[i].param);
889
890 if (tend - param >= len
891 && strncmp (param, diropts[i].param, len) == 0
892 && (param[len] == ':' || param[len] == ' '))
893 {
894 lex_parse_string_end = tend;
895 lex_parse_string = param + len + 1;
896 lex_forced_token = diropts[i].token;
897 saw_newline = 0;
898 if (def_parse ())
899 continue;
900 break;
901 }
902 }
903
904 if (!diropts[i].param)
905 {
906 char saved;
907
908 saved = * tend;
909 * tend = 0;
910 /* xgettext:c-format */
911 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
912 * tend = saved;
913 }
914
915 lex_parse_string = 0;
916 param = tend;
917 }
918
919 def = save_def;
920 def_pool_free ();
921 }
922
923 /* Parser Callbacks. */
924
925 static void
926 def_image_name (const char *name, int base, int is_dll)
927 {
928 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
929 to do here. We retain the output filename specified on command line. */
930 if (*name)
931 {
932 const char* image_name = lbasename (name);
933
934 if (image_name != name)
935 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
936 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
937 name);
938 if (def->name)
939 free (def->name);
940 /* Append the default suffix, if none specified. */
941 if (strchr (image_name, '.') == 0)
942 {
943 const char * suffix = is_dll ? ".dll" : ".exe";
944
945 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
946 sprintf (def->name, "%s%s", image_name, suffix);
947 }
948 else
949 def->name = xstrdup (image_name);
950 }
951
952 /* Honor a BASE address statement, even if LIBRARY string is empty. */
953 def->base_address = base;
954 def->is_dll = is_dll;
955 }
956
957 static void
958 def_description (const char *text)
959 {
960 int len = def->description ? strlen (def->description) : 0;
961
962 len += strlen (text) + 1;
963 if (def->description)
964 {
965 def->description = xrealloc (def->description, len);
966 strcat (def->description, text);
967 }
968 else
969 {
970 def->description = xmalloc (len);
971 strcpy (def->description, text);
972 }
973 }
974
975 static void
976 def_stacksize (int reserve, int commit)
977 {
978 def->stack_reserve = reserve;
979 def->stack_commit = commit;
980 }
981
982 static void
983 def_heapsize (int reserve, int commit)
984 {
985 def->heap_reserve = reserve;
986 def->heap_commit = commit;
987 }
988
989 static void
990 def_section (const char *name, int attr)
991 {
992 def_file_section *s;
993 int max_sections = ROUND_UP (def->num_section_defs, 4);
994
995 if (def->num_section_defs >= max_sections)
996 {
997 max_sections = ROUND_UP (def->num_section_defs+1, 4);
998
999 if (def->section_defs)
1000 def->section_defs = xrealloc (def->section_defs,
1001 max_sections * sizeof (def_file_import));
1002 else
1003 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
1004 }
1005 s = def->section_defs + def->num_section_defs;
1006 memset (s, 0, sizeof (def_file_section));
1007 s->name = xstrdup (name);
1008 if (attr & 1)
1009 s->flag_read = 1;
1010 if (attr & 2)
1011 s->flag_write = 1;
1012 if (attr & 4)
1013 s->flag_execute = 1;
1014 if (attr & 8)
1015 s->flag_shared = 1;
1016
1017 def->num_section_defs++;
1018 }
1019
1020 static void
1021 def_section_alt (const char *name, const char *attr)
1022 {
1023 int aval = 0;
1024
1025 for (; *attr; attr++)
1026 {
1027 switch (*attr)
1028 {
1029 case 'R':
1030 case 'r':
1031 aval |= 1;
1032 break;
1033 case 'W':
1034 case 'w':
1035 aval |= 2;
1036 break;
1037 case 'X':
1038 case 'x':
1039 aval |= 4;
1040 break;
1041 case 'S':
1042 case 's':
1043 aval |= 8;
1044 break;
1045 }
1046 }
1047 def_section (name, aval);
1048 }
1049
1050 static void
1051 def_exports (const char *external_name,
1052 const char *internal_name,
1053 int ordinal,
1054 int flags,
1055 const char *its_name)
1056 {
1057 def_file_export *dfe;
1058 int is_dup = 0;
1059
1060 if (!internal_name && external_name)
1061 internal_name = external_name;
1062 #if TRACE
1063 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1064 #endif
1065
1066 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
1067 its_name, &is_dup);
1068
1069 /* We might check here for flag redefinition and warn. For now we
1070 ignore duplicates silently. */
1071 if (is_dup)
1072 return;
1073
1074 if (flags & 1)
1075 dfe->flag_noname = 1;
1076 if (flags & 2)
1077 dfe->flag_constant = 1;
1078 if (flags & 4)
1079 dfe->flag_data = 1;
1080 if (flags & 8)
1081 dfe->flag_private = 1;
1082 }
1083
1084 static void
1085 def_import (const char *internal_name,
1086 const char *module,
1087 const char *dllext,
1088 const char *name,
1089 int ordinal,
1090 const char *its_name)
1091 {
1092 char *buf = 0;
1093 const char *ext = dllext ? dllext : "dll";
1094 int is_dup = 0;
1095
1096 buf = xmalloc (strlen (module) + strlen (ext) + 2);
1097 sprintf (buf, "%s.%s", module, ext);
1098 module = buf;
1099
1100 def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1101 &is_dup);
1102 free (buf);
1103 }
1104
1105 static void
1106 def_version (int major, int minor)
1107 {
1108 def->version_major = major;
1109 def->version_minor = minor;
1110 }
1111
1112 static void
1113 def_directive (char *str)
1114 {
1115 struct directive *d = xmalloc (sizeof (struct directive));
1116
1117 d->next = directives;
1118 directives = d;
1119 d->name = xstrdup (str);
1120 d->len = strlen (str);
1121 }
1122
1123 static void
1124 def_aligncomm (char *str, int align)
1125 {
1126 def_file_aligncomm *c, *p;
1127
1128 p = NULL;
1129 c = def->aligncomms;
1130 while (c != NULL)
1131 {
1132 int e = strcmp (c->symbol_name, str);
1133 if (!e)
1134 {
1135 /* Not sure if we want to allow here duplicates with
1136 different alignments, but for now we keep them. */
1137 e = (int) c->alignment - align;
1138 if (!e)
1139 return;
1140 }
1141 if (e > 0)
1142 break;
1143 c = (p = c)->next;
1144 }
1145
1146 c = xmalloc (sizeof (def_file_aligncomm));
1147 c->symbol_name = xstrdup (str);
1148 c->alignment = (unsigned int) align;
1149 if (!p)
1150 {
1151 c->next = def->aligncomms;
1152 def->aligncomms = c;
1153 }
1154 else
1155 {
1156 c->next = p->next;
1157 p->next = c;
1158 }
1159 }
1160
1161 static int
1162 def_error (const char *err)
1163 {
1164 einfo ("%P: %s:%d: %s\n",
1165 def_filename ? def_filename : "<unknown-file>", linenumber, err);
1166 return 0;
1167 }
1168
1169
1170 /* Lexical Scanner. */
1171
1172 #undef TRACE
1173 #define TRACE 0
1174
1175 /* Never freed, but always reused as needed, so no real leak. */
1176 static char *buffer = 0;
1177 static int buflen = 0;
1178 static int bufptr = 0;
1179
1180 static void
1181 put_buf (char c)
1182 {
1183 if (bufptr == buflen)
1184 {
1185 buflen += 50; /* overly reasonable, eh? */
1186 if (buffer)
1187 buffer = xrealloc (buffer, buflen + 1);
1188 else
1189 buffer = xmalloc (buflen + 1);
1190 }
1191 buffer[bufptr++] = c;
1192 buffer[bufptr] = 0; /* not optimal, but very convenient. */
1193 }
1194
1195 static struct
1196 {
1197 char *name;
1198 int token;
1199 }
1200 tokens[] =
1201 {
1202 { "BASE", BASE },
1203 { "CODE", CODE },
1204 { "CONSTANT", CONSTANTU },
1205 { "constant", CONSTANTL },
1206 { "DATA", DATAU },
1207 { "data", DATAL },
1208 { "DESCRIPTION", DESCRIPTION },
1209 { "DIRECTIVE", DIRECTIVE },
1210 { "EXECUTE", EXECUTE },
1211 { "EXPORTS", EXPORTS },
1212 { "HEAPSIZE", HEAPSIZE },
1213 { "IMPORTS", IMPORTS },
1214 { "LIBRARY", LIBRARY },
1215 { "NAME", NAME },
1216 { "NONAME", NONAMEU },
1217 { "noname", NONAMEL },
1218 { "PRIVATE", PRIVATEU },
1219 { "private", PRIVATEL },
1220 { "READ", READ },
1221 { "SECTIONS", SECTIONS },
1222 { "SEGMENTS", SECTIONS },
1223 { "SHARED", SHARED },
1224 { "STACKSIZE", STACKSIZE_K },
1225 { "VERSION", VERSIONK },
1226 { "WRITE", WRITE },
1227 { 0, 0 }
1228 };
1229
1230 static int
1231 def_getc (void)
1232 {
1233 int rv;
1234
1235 if (lex_parse_string)
1236 {
1237 if (lex_parse_string >= lex_parse_string_end)
1238 rv = EOF;
1239 else
1240 rv = *lex_parse_string++;
1241 }
1242 else
1243 {
1244 rv = fgetc (the_file);
1245 }
1246 if (rv == '\n')
1247 saw_newline = 1;
1248 return rv;
1249 }
1250
1251 static int
1252 def_ungetc (int c)
1253 {
1254 if (lex_parse_string)
1255 {
1256 lex_parse_string--;
1257 return c;
1258 }
1259 else
1260 return ungetc (c, the_file);
1261 }
1262
1263 static int
1264 def_lex (void)
1265 {
1266 int c, i, q;
1267
1268 if (lex_forced_token)
1269 {
1270 i = lex_forced_token;
1271 lex_forced_token = 0;
1272 #if TRACE
1273 printf ("lex: forcing token %d\n", i);
1274 #endif
1275 return i;
1276 }
1277
1278 c = def_getc ();
1279
1280 /* Trim leading whitespace. */
1281 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1282 c = def_getc ();
1283
1284 if (c == EOF)
1285 {
1286 #if TRACE
1287 printf ("lex: EOF\n");
1288 #endif
1289 return 0;
1290 }
1291
1292 if (saw_newline && c == ';')
1293 {
1294 do
1295 {
1296 c = def_getc ();
1297 }
1298 while (c != EOF && c != '\n');
1299 if (c == '\n')
1300 return def_lex ();
1301 return 0;
1302 }
1303
1304 /* Must be something else. */
1305 saw_newline = 0;
1306
1307 if (ISDIGIT (c))
1308 {
1309 bufptr = 0;
1310 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
1311 {
1312 put_buf (c);
1313 c = def_getc ();
1314 }
1315 if (c != EOF)
1316 def_ungetc (c);
1317 yylval.digits = def_pool_strdup (buffer);
1318 #if TRACE
1319 printf ("lex: `%s' returns DIGITS\n", buffer);
1320 #endif
1321 return DIGITS;
1322 }
1323
1324 if (ISALPHA (c) || strchr ("$:-_?@", c))
1325 {
1326 bufptr = 0;
1327 q = c;
1328 put_buf (c);
1329 c = def_getc ();
1330
1331 if (q == '@')
1332 {
1333 if (ISBLANK (c) ) /* '@' followed by whitespace. */
1334 return (q);
1335 else if (ISDIGIT (c)) /* '@' followed by digit. */
1336 {
1337 def_ungetc (c);
1338 return (q);
1339 }
1340 #if TRACE
1341 printf ("lex: @ returns itself\n");
1342 #endif
1343 }
1344
1345 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
1346 {
1347 put_buf (c);
1348 c = def_getc ();
1349 }
1350 if (c != EOF)
1351 def_ungetc (c);
1352 if (ISALPHA (q)) /* Check for tokens. */
1353 {
1354 for (i = 0; tokens[i].name; i++)
1355 if (strcmp (tokens[i].name, buffer) == 0)
1356 {
1357 #if TRACE
1358 printf ("lex: `%s' is a string token\n", buffer);
1359 #endif
1360 return tokens[i].token;
1361 }
1362 }
1363 #if TRACE
1364 printf ("lex: `%s' returns ID\n", buffer);
1365 #endif
1366 yylval.id = def_pool_strdup (buffer);
1367 return ID;
1368 }
1369
1370 if (c == '\'' || c == '"')
1371 {
1372 q = c;
1373 c = def_getc ();
1374 bufptr = 0;
1375
1376 while (c != EOF && c != q)
1377 {
1378 put_buf (c);
1379 c = def_getc ();
1380 }
1381 yylval.id = def_pool_strdup (buffer);
1382 #if TRACE
1383 printf ("lex: `%s' returns ID\n", buffer);
1384 #endif
1385 return ID;
1386 }
1387
1388 if ( c == '=')
1389 {
1390 c = def_getc ();
1391 if (c == '=')
1392 {
1393 #if TRACE
1394 printf ("lex: `==' returns EQUAL\n");
1395 #endif
1396 return EQUAL;
1397 }
1398 def_ungetc (c);
1399 #if TRACE
1400 printf ("lex: `=' returns itself\n");
1401 #endif
1402 return '=';
1403 }
1404 if (c == '.' || c == ',')
1405 {
1406 #if TRACE
1407 printf ("lex: `%c' returns itself\n", c);
1408 #endif
1409 return c;
1410 }
1411
1412 if (c == '\n')
1413 {
1414 linenumber++;
1415 saw_newline = 1;
1416 }
1417
1418 /*printf ("lex: 0x%02x ignored\n", c); */
1419 return def_lex ();
1420 }
1421
1422 static char *
1423 def_pool_alloc (size_t sz)
1424 {
1425 def_pool_str *e;
1426
1427 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1428 e->next = pool_strs;
1429 pool_strs = e;
1430 return e->data;
1431 }
1432
1433 static char *
1434 def_pool_strdup (const char *str)
1435 {
1436 char *s;
1437 size_t len;
1438 if (!str)
1439 return NULL;
1440 len = strlen (str) + 1;
1441 s = def_pool_alloc (len);
1442 memcpy (s, str, len);
1443 return s;
1444 }
1445
1446 static void
1447 def_pool_free (void)
1448 {
1449 def_pool_str *p;
1450 while ((p = pool_strs) != NULL)
1451 {
1452 pool_strs = p->next;
1453 free (p);
1454 }
1455 }
This page took 0.08218 seconds and 5 git commands to generate.