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