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