]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - ld/deffilep.y
x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC
[thirdparty/binutils-gdb.git] / ld / deffilep.y
CommitLineData
252b5132
RH
1%{ /* deffilep.y - parser for .def files */
2
d87bef3a 3/* Copyright (C) 1995-2023 Free Software Foundation, Inc.
252b5132 4
a35bc64f 5 This file is part of GNU Binutils.
252b5132 6
a35bc64f
NC
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
f96b4a7b 9 the Free Software Foundation; either version 3 of the License, or
a35bc64f 10 (at your option) any later version.
252b5132 11
a35bc64f
NC
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
252b5132 16
a35bc64f
NC
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
f96b4a7b
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 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"
0b4453c7 26#include "bfdlink.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
a33a94cf
MS
35#define SYMBOL_LIST_ARRAY_GROW 64
36
252b5132
RH
37/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
38 as well as gratuitiously global symbol names, so we can have multiple
39 yacc generated parsers in ld. Note that these are only the variables
40 produced by yacc. If other parser generators (bison, byacc, etc) produce
41 additional global names that conflict at link time, then those parser
a35bc64f 42 generators need to be fixed instead of adding those names to this list. */
252b5132
RH
43
44#define yymaxdepth def_maxdepth
45#define yyparse def_parse
46#define yylex def_lex
47#define yyerror def_error
48#define yylval def_lval
49#define yychar def_char
50#define yydebug def_debug
e4492aa0
L
51#define yypact def_pact
52#define yyr1 def_r1
53#define yyr2 def_r2
54#define yydef def_def
55#define yychk def_chk
56#define yypgo def_pgo
57#define yyact def_act
252b5132
RH
58#define yyexca def_exca
59#define yyerrflag def_errflag
60#define yynerrs def_nerrs
61#define yyps def_ps
62#define yypv def_pv
63#define yys def_s
64#define yy_yys def_yys
65#define yystate def_state
66#define yytmp def_tmp
67#define yyv def_v
68#define yy_yyv def_yyv
69#define yyval def_val
70#define yylloc def_lloc
a35bc64f
NC
71#define yyreds def_reds /* With YYDEBUG defined. */
72#define yytoks def_toks /* With YYDEBUG defined. */
252b5132
RH
73#define yylhs def_yylhs
74#define yylen def_yylen
75#define yydefred def_yydefred
76#define yydgoto def_yydgoto
77#define yysindex def_yysindex
78#define yyrindex def_yyrindex
79#define yygindex def_yygindex
80#define yytable def_yytable
81#define yycheck def_yycheck
82
bdca0ea1
KT
83typedef struct def_pool_str {
84 struct def_pool_str *next;
85 char data[1];
86} def_pool_str;
87
88static def_pool_str *pool_strs = NULL;
89
90static char *def_pool_alloc (size_t sz);
91static char *def_pool_strdup (const char *str);
92static void def_pool_free (void);
93
1579bae1 94static void def_description (const char *);
7fcab871 95static void def_exports (const char *, const char *, int, int, const char *);
1579bae1
AM
96static void def_heapsize (int, int);
97static void def_import (const char *, const char *, const char *, const char *,
7fcab871 98 int, const char *);
0a4e6638 99static void def_image_name (const char *, bfd_vma, int);
1579bae1
AM
100static void def_section (const char *, int);
101static void def_section_alt (const char *, const char *);
102static void def_stacksize (int, int);
103static void def_version (int, int);
104static void def_directive (char *);
c1711530 105static void def_aligncomm (char *str, int align);
37513c1e 106static void def_exclude_symbols (char *str);
1579bae1 107static int def_parse (void);
314ec7ae 108static void def_error (const char *);
1579bae1 109static int def_lex (void);
252b5132
RH
110
111static int lex_forced_token = 0;
112static const char *lex_parse_string = 0;
113static const char *lex_parse_string_end = 0;
114
115%}
116
117%union {
118 char *id;
aa83d1ec 119 const char *id_const;
252b5132 120 int number;
0a4e6638 121 bfd_vma vma;
05056a8d 122 char *digits;
252b5132
RH
123};
124
8e58566f 125%token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL
655f76a2 126%token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
37513c1e 127%token PRIVATEU PRIVATEL ALIGNCOMM EXCLUDE_SYMBOLS
6abe7848 128%token READ WRITE EXECUTE SHARED_K NONAMEU NONAMEL DIRECTIVE EQUAL
252b5132 129%token <id> ID
05056a8d
DK
130%token <digits> DIGITS
131%type <number> NUMBER
0a4e6638 132%type <vma> VMA opt_base
05056a8d 133%type <digits> opt_digits
0a4e6638 134%type <number> opt_ordinal
252b5132 135%type <number> attr attr_list opt_number exp_opt_list exp_opt
aa83d1ec 136%type <id> opt_name opt_name2 opt_equal_name anylang_id opt_id
37513c1e 137%type <id> opt_equalequal_name symbol_list
aa83d1ec 138%type <id_const> keyword_as_name
252b5132
RH
139
140%%
141
142start: start command
143 | command
144 ;
145
e4492aa0 146command:
a880c748
DS
147 NAME opt_name opt_base { def_image_name ($2, $3, 0); }
148 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); }
252b5132 149 | DESCRIPTION ID { def_description ($2);}
8e58566f 150 | STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);}
252b5132
RH
151 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
152 | CODE attr_list { def_section ("CODE", $2);}
7c9e78f8 153 | DATAU attr_list { def_section ("DATA", $2);}
252b5132 154 | SECTIONS seclist
e4492aa0 155 | EXPORTS explist
252b5132
RH
156 | IMPORTS implist
157 | VERSIONK NUMBER { def_version ($2, 0);}
158 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
159 | DIRECTIVE ID { def_directive ($2);}
05056a8d 160 | ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);}
37513c1e 161 | EXCLUDE_SYMBOLS symbol_list
252b5132
RH
162 ;
163
164
165explist:
166 /* EMPTY */
167 | expline
168 | explist expline
169 ;
170
171expline:
7c9e78f8
DD
172 /* The opt_comma is necessary to support both the usual
173 DEF file syntax as well as .drectve syntax which
174 mandates <expsym>,<expoptlist>. */
aa83d1ec 175 opt_name2 opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name
7fcab871 176 { def_exports ($1, $2, $3, $5, $7); }
252b5132
RH
177 ;
178exp_opt_list:
7c9e78f8
DD
179 /* The opt_comma is necessary to support both the usual
180 DEF file syntax as well as .drectve syntax which
181 allows for comma separated opt list. */
182 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; }
252b5132
RH
183 | { $$ = 0; }
184 ;
185exp_opt:
7c9e78f8
DD
186 NONAMEU { $$ = 1; }
187 | NONAMEL { $$ = 1; }
188 | CONSTANTU { $$ = 2; }
189 | CONSTANTL { $$ = 2; }
190 | DATAU { $$ = 4; }
191 | DATAL { $$ = 4; }
192 | PRIVATEU { $$ = 8; }
193 | PRIVATEL { $$ = 8; }
252b5132 194 ;
e4492aa0 195implist:
252b5132
RH
196 implist impline
197 | impline
198 ;
199
200impline:
6c19b93b
AM
201 ID '=' ID '.' ID '.' ID opt_equalequal_name
202 { def_import ($1, $3, $5, $7, -1, $8); }
7fcab871
KT
203 | ID '=' ID '.' ID '.' NUMBER opt_equalequal_name
204 { def_import ($1, $3, $5, 0, $7, $8); }
205 | ID '=' ID '.' ID opt_equalequal_name
6c19b93b 206 { def_import ($1, $3, 0, $5, -1, $6); }
7fcab871 207 | ID '=' ID '.' NUMBER opt_equalequal_name
6c19b93b 208 { def_import ($1, $3, 0, 0, $5, $6); }
7fcab871 209 | ID '.' ID '.' ID opt_equalequal_name
6c19b93b 210 { def_import( 0, $1, $3, $5, -1, $6); }
7fcab871 211 | ID '.' ID opt_equalequal_name
6c19b93b 212 { def_import ( 0, $1, 0, $3, -1, $4); }
252b5132
RH
213;
214
215seclist:
216 seclist secline
217 | secline
218 ;
219
220secline:
221 ID attr_list { def_section ($1, $2);}
222 | ID ID { def_section_alt ($1, $2);}
223 ;
224
225attr_list:
226 attr_list opt_comma attr { $$ = $1 | $3; }
227 | attr { $$ = $1; }
228 ;
229
230opt_comma:
231 ','
e4492aa0 232 |
252b5132
RH
233 ;
234opt_number: ',' NUMBER { $$=$2;}
235 | { $$=-1;}
236 ;
e4492aa0 237
252b5132
RH
238attr:
239 READ { $$ = 1;}
e4492aa0 240 | WRITE { $$ = 2;}
252b5132 241 | EXECUTE { $$=4;}
6abe7848 242 | SHARED_K { $$=8;}
252b5132
RH
243 ;
244
aa83d1ec
KT
245
246keyword_as_name: BASE { $$ = "BASE"; }
247 | CODE { $$ = "CODE"; }
248 | CONSTANTU { $$ = "CONSTANT"; }
249 | CONSTANTL { $$ = "constant"; }
250 | DATAU { $$ = "DATA"; }
251 | DATAL { $$ = "data"; }
252 | DESCRIPTION { $$ = "DESCRIPTION"; }
253 | DIRECTIVE { $$ = "DIRECTIVE"; }
61f6b650 254 | EXCLUDE_SYMBOLS { $$ = "EXCLUDE_SYMBOLS"; }
aa83d1ec
KT
255 | EXECUTE { $$ = "EXECUTE"; }
256 | EXPORTS { $$ = "EXPORTS"; }
257 | HEAPSIZE { $$ = "HEAPSIZE"; }
258 | IMPORTS { $$ = "IMPORTS"; }
5b3d386e
KT
259/* Disable LIBRARY keyword as valid symbol-name. This is necessary
260 for libtool, which places this command after EXPORTS command.
261 This behavior is illegal by specification, but sadly required by
262 by compatibility reasons.
263 See PR binutils/13710
264 | LIBRARY { $$ = "LIBRARY"; } */
aa83d1ec
KT
265 | NAME { $$ = "NAME"; }
266 | NONAMEU { $$ = "NONAME"; }
267 | NONAMEL { $$ = "noname"; }
268 | PRIVATEU { $$ = "PRIVATE"; }
269 | PRIVATEL { $$ = "private"; }
270 | READ { $$ = "READ"; }
6abe7848 271 | SHARED_K { $$ = "SHARED"; }
aa83d1ec
KT
272 | STACKSIZE_K { $$ = "STACKSIZE"; }
273 | VERSIONK { $$ = "VERSION"; }
274 | WRITE { $$ = "WRITE"; }
275 ;
276
277opt_name2: ID { $$ = $1; }
278 | '.' keyword_as_name
770c040b 279 {
aa83d1ec
KT
280 char *name = xmalloc (strlen ($2) + 2);
281 sprintf (name, ".%s", $2);
282 $$ = name;
283 }
284 | '.' opt_name2
e4492aa0 285 {
bdca0ea1 286 char *name = def_pool_alloc (strlen ($2) + 2);
770c040b
KT
287 sprintf (name, ".%s", $2);
288 $$ = name;
289 }
aa83d1ec 290 | keyword_as_name '.' opt_name2
e4492aa0 291 {
bdca0ea1 292 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
5aaace27
NC
293 sprintf (name, "%s.%s", $1, $3);
294 $$ = name;
295 }
aa83d1ec 296 | ID '.' opt_name2
e4492aa0 297 {
aa83d1ec
KT
298 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1);
299 sprintf (name, "%s.%s", $1, $3);
300 $$ = name;
301 }
302 ;
303
304opt_name: opt_name2 { $$ = $1; }
5aaace27 305 | { $$ = ""; }
252b5132
RH
306 ;
307
7fcab871
KT
308opt_equalequal_name: EQUAL ID { $$ = $2; }
309 | { $$ = 0; }
310 ;
311
e4492aa0 312opt_ordinal:
252b5132
RH
313 '@' NUMBER { $$ = $2;}
314 | { $$ = -1;}
315 ;
316
317opt_equal_name:
6c19b93b
AM
318 '=' opt_name2 { $$ = $2; }
319 | { $$ = 0; }
252b5132
RH
320 ;
321
0a4e6638
KT
322opt_base: BASE '=' VMA { $$ = $3;}
323 | { $$ = (bfd_vma) -1;}
252b5132
RH
324 ;
325
05056a8d 326anylang_id: ID { $$ = $1; }
770c040b
KT
327 | '.' ID
328 {
bdca0ea1 329 char *id = def_pool_alloc (strlen ($2) + 2);
770c040b
KT
330 sprintf (id, ".%s", $2);
331 $$ = id;
332 }
05056a8d
DK
333 | anylang_id '.' opt_digits opt_id
334 {
bdca0ea1 335 char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
05056a8d
DK
336 sprintf (id, "%s.%s%s", $1, $3, $4);
337 $$ = id;
338 }
339 ;
340
37513c1e
MS
341symbol_list:
342 anylang_id { def_exclude_symbols ($1); }
61f6b650 343 | symbol_list anylang_id { def_exclude_symbols ($2); }
37513c1e
MS
344 | symbol_list ',' anylang_id { def_exclude_symbols ($3); }
345 ;
346
05056a8d
DK
347opt_digits: DIGITS { $$ = $1; }
348 | { $$ = ""; }
349 ;
350
351opt_id: ID { $$ = $1; }
352 | { $$ = ""; }
353 ;
354
355NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); }
0a4e6638
KT
356 ;
357VMA: DIGITS { $$ = (bfd_vma) strtoull ($1, 0, 0); }
252b5132
RH
358
359%%
360
361/*****************************************************************************
362 API
363 *****************************************************************************/
364
365static FILE *the_file;
366static const char *def_filename;
367static int linenumber;
368static def_file *def;
369static int saw_newline;
370
371struct directive
372 {
373 struct directive *next;
374 char *name;
375 int len;
376 };
377
378static struct directive *directives = 0;
379
380def_file *
1579bae1 381def_file_empty (void)
252b5132 382{
1579bae1 383 def_file *rv = xmalloc (sizeof (def_file));
252b5132
RH
384 memset (rv, 0, sizeof (def_file));
385 rv->is_dll = -1;
1579bae1 386 rv->base_address = (bfd_vma) -1;
252b5132
RH
387 rv->stack_reserve = rv->stack_commit = -1;
388 rv->heap_reserve = rv->heap_commit = -1;
389 rv->version_major = rv->version_minor = -1;
390 return rv;
391}
392
393def_file *
1579bae1 394def_file_parse (const char *filename, def_file *add_to)
252b5132
RH
395{
396 struct directive *d;
397
398 the_file = fopen (filename, "r");
399 def_filename = filename;
400 linenumber = 1;
401 if (!the_file)
402 {
403 perror (filename);
404 return 0;
405 }
406 if (add_to)
407 {
408 def = add_to;
409 }
410 else
411 {
412 def = def_file_empty ();
413 }
414
415 saw_newline = 1;
416 if (def_parse ())
417 {
418 def_file_free (def);
419 fclose (the_file);
bdca0ea1 420 def_pool_free ();
252b5132
RH
421 return 0;
422 }
423
424 fclose (the_file);
425
bdca0ea1 426 while ((d = directives) != NULL)
252b5132
RH
427 {
428#if TRACE
429 printf ("Adding directive %08x `%s'\n", d->name, d->name);
430#endif
431 def_file_add_directive (def, d->name, d->len);
bdca0ea1
KT
432 directives = d->next;
433 free (d->name);
434 free (d);
252b5132 435 }
bdca0ea1 436 def_pool_free ();
252b5132
RH
437
438 return def;
439}
440
441void
91d6fa6a 442def_file_free (def_file *fdef)
252b5132
RH
443{
444 int i;
a33a94cf 445 unsigned int ui;
a35bc64f 446
91d6fa6a 447 if (!fdef)
252b5132 448 return;
5e2ab612
AM
449 free (fdef->name);
450 free (fdef->description);
252b5132 451
91d6fa6a 452 if (fdef->section_defs)
252b5132 453 {
91d6fa6a 454 for (i = 0; i < fdef->num_section_defs; i++)
252b5132 455 {
5e2ab612
AM
456 free (fdef->section_defs[i].name);
457 free (fdef->section_defs[i].class);
252b5132 458 }
91d6fa6a 459 free (fdef->section_defs);
252b5132
RH
460 }
461
825a844f 462 for (i = 0; i < fdef->num_exports; i++)
252b5132 463 {
825a844f
MS
464 if (fdef->exports[i].internal_name != fdef->exports[i].name)
465 free (fdef->exports[i].internal_name);
466 free (fdef->exports[i].name);
467 free (fdef->exports[i].its_name);
252b5132 468 }
825a844f 469 free (fdef->exports);
252b5132 470
825a844f 471 for (i = 0; i < fdef->num_imports; i++)
252b5132 472 {
825a844f
MS
473 if (fdef->imports[i].internal_name != fdef->imports[i].name)
474 free (fdef->imports[i].internal_name);
475 free (fdef->imports[i].name);
476 free (fdef->imports[i].its_name);
252b5132 477 }
825a844f 478 free (fdef->imports);
252b5132 479
91d6fa6a 480 while (fdef->modules)
252b5132 481 {
91d6fa6a
NC
482 def_file_module *m = fdef->modules;
483
484 fdef->modules = fdef->modules->next;
252b5132
RH
485 free (m);
486 }
487
91d6fa6a 488 while (fdef->aligncomms)
c1711530 489 {
91d6fa6a
NC
490 def_file_aligncomm *c = fdef->aligncomms;
491
492 fdef->aligncomms = fdef->aligncomms->next;
c1711530
DK
493 free (c->symbol_name);
494 free (c);
495 }
496
a33a94cf 497 for (ui = 0; ui < fdef->num_exclude_symbols; ui++)
37513c1e 498 {
a33a94cf 499 free (fdef->exclude_symbols[ui].symbol_name);
37513c1e 500 }
a33a94cf 501 free (fdef->exclude_symbols);
37513c1e 502
91d6fa6a 503 free (fdef);
252b5132
RH
504}
505
506#ifdef DEF_FILE_PRINT
507void
91d6fa6a 508def_file_print (FILE *file, def_file *fdef)
252b5132
RH
509{
510 int i;
a35bc64f 511
91d6fa6a
NC
512 fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
513 if (fdef->name)
514 fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)");
515 if (fdef->is_dll != -1)
516 fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no");
517 if (fdef->base_address != (bfd_vma) -1)
f493c217
AM
518 fprintf (file, " base address: 0x%" PRIx64 "\n",
519 (uint64_t) fdef->base_address);
91d6fa6a
NC
520 if (fdef->description)
521 fprintf (file, " description: `%s'\n", fdef->description);
522 if (fdef->stack_reserve != -1)
523 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve);
524 if (fdef->stack_commit != -1)
525 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit);
526 if (fdef->heap_reserve != -1)
527 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve);
528 if (fdef->heap_commit != -1)
529 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit);
530
531 if (fdef->num_section_defs > 0)
252b5132
RH
532 {
533 fprintf (file, " section defs:\n");
a35bc64f 534
91d6fa6a 535 for (i = 0; i < fdef->num_section_defs; i++)
252b5132
RH
536 {
537 fprintf (file, " name: `%s', class: `%s', flags:",
91d6fa6a
NC
538 fdef->section_defs[i].name, fdef->section_defs[i].class);
539 if (fdef->section_defs[i].flag_read)
252b5132 540 fprintf (file, " R");
91d6fa6a 541 if (fdef->section_defs[i].flag_write)
252b5132 542 fprintf (file, " W");
91d6fa6a 543 if (fdef->section_defs[i].flag_execute)
252b5132 544 fprintf (file, " X");
91d6fa6a 545 if (fdef->section_defs[i].flag_shared)
252b5132
RH
546 fprintf (file, " S");
547 fprintf (file, "\n");
548 }
549 }
550
91d6fa6a 551 if (fdef->num_exports > 0)
252b5132
RH
552 {
553 fprintf (file, " exports:\n");
a35bc64f 554
91d6fa6a 555 for (i = 0; i < fdef->num_exports; i++)
252b5132
RH
556 {
557 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
91d6fa6a
NC
558 fdef->exports[i].name, fdef->exports[i].internal_name,
559 fdef->exports[i].ordinal);
560 if (fdef->exports[i].flag_private)
252b5132 561 fprintf (file, " P");
91d6fa6a 562 if (fdef->exports[i].flag_constant)
252b5132 563 fprintf (file, " C");
91d6fa6a 564 if (fdef->exports[i].flag_noname)
252b5132 565 fprintf (file, " N");
91d6fa6a 566 if (fdef->exports[i].flag_data)
252b5132
RH
567 fprintf (file, " D");
568 fprintf (file, "\n");
569 }
570 }
571
91d6fa6a 572 if (fdef->num_imports > 0)
252b5132
RH
573 {
574 fprintf (file, " imports:\n");
a35bc64f 575
91d6fa6a 576 for (i = 0; i < fdef->num_imports; i++)
252b5132
RH
577 {
578 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
91d6fa6a
NC
579 fdef->imports[i].internal_name,
580 fdef->imports[i].module,
581 fdef->imports[i].name,
582 fdef->imports[i].ordinal);
252b5132
RH
583 }
584 }
a35bc64f 585
91d6fa6a
NC
586 if (fdef->version_major != -1)
587 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor);
a35bc64f 588
b41d91a7 589 fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
252b5132
RH
590}
591#endif
592
db17156e
KT
593/* Helper routine to check for identity of string pointers,
594 which might be NULL. */
595
596static int
597are_names_equal (const char *s1, const char *s2)
598{
599 if (!s1 && !s2)
600 return 0;
601 if (!s1 || !s2)
602 return (!s1 ? -1 : 1);
603 return strcmp (s1, s2);
604}
605
606static int
607cmp_export_elem (const def_file_export *e, const char *ex_name,
608 const char *in_name, const char *its_name,
609 int ord)
610{
611 int r;
612
613 if ((r = are_names_equal (ex_name, e->name)) != 0)
614 return r;
615 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
616 return r;
617 if ((r = are_names_equal (its_name, e->its_name)) != 0)
618 return r;
619 return (ord - e->ordinal);
620}
621
622/* Search the position of the identical element, or returns the position
623 of the next higher element. If last valid element is smaller, then MAX
825a844f
MS
624 is returned. The max parameter indicates the number of elements in the
625 array. On return, *is_ident indicates whether the returned array index
626 points at an element which is identical to the one searched for. */
db17156e 627
825a844f
MS
628static unsigned int
629find_export_in_list (def_file_export *b, unsigned int max,
db17156e 630 const char *ex_name, const char *in_name,
825a844f 631 const char *its_name, int ord, bool *is_ident)
db17156e 632{
825a844f
MS
633 int e;
634 unsigned int l, r, p;
db17156e 635
825a844f 636 *is_ident = false;
db17156e
KT
637 if (!max)
638 return 0;
639 if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
d0ac6938
KT
640 {
641 if (!e)
825a844f 642 *is_ident = true;
d0ac6938
KT
643 return 0;
644 }
db17156e
KT
645 if (max == 1)
646 return 1;
647 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
648 return max;
649 else if (!e || max == 2)
d0ac6938
KT
650 {
651 if (!e)
825a844f 652 *is_ident = true;
d0ac6938
KT
653 return max - 1;
654 }
db17156e
KT
655 l = 0; r = max - 1;
656 while (l < r)
657 {
658 p = (l + r) / 2;
659 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
660 if (!e)
6c19b93b 661 {
825a844f 662 *is_ident = true;
6c19b93b
AM
663 return p;
664 }
db17156e 665 else if (e < 0)
6c19b93b 666 r = p - 1;
db17156e 667 else if (e > 0)
6c19b93b 668 l = p + 1;
db17156e
KT
669 }
670 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
671 ++l;
672 else if (!e)
825a844f 673 *is_ident = true;
db17156e
KT
674 return l;
675}
676
252b5132 677def_file_export *
91d6fa6a 678def_file_add_export (def_file *fdef,
1579bae1
AM
679 const char *external_name,
680 const char *internal_name,
7fcab871 681 int ordinal,
db17156e 682 const char *its_name,
825a844f 683 bool *is_dup)
252b5132
RH
684{
685 def_file_export *e;
825a844f 686 unsigned int pos;
a35bc64f 687
db17156e
KT
688 if (internal_name && !external_name)
689 external_name = internal_name;
690 if (external_name && !internal_name)
691 internal_name = external_name;
692
693 /* We need to avoid duplicates. */
825a844f 694 *is_dup = false;
db17156e
KT
695 pos = find_export_in_list (fdef->exports, fdef->num_exports,
696 external_name, internal_name,
697 its_name, ordinal, is_dup);
698
825a844f 699 if (*is_dup)
db17156e
KT
700 return (fdef->exports + pos);
701
825a844f 702 if ((unsigned)fdef->num_exports >= fdef->max_exports)
252b5132 703 {
825a844f
MS
704 fdef->max_exports += SYMBOL_LIST_ARRAY_GROW;
705 fdef->exports = xrealloc (fdef->exports,
706 fdef->max_exports * sizeof (def_file_export));
252b5132 707 }
db17156e
KT
708
709 e = fdef->exports + pos;
825a844f
MS
710 /* If we're inserting in the middle of the array, we need to move the
711 following elements forward. */
712 if (pos != (unsigned)fdef->num_exports)
db17156e 713 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
825a844f 714 /* Wipe the element for use as a new entry. */
252b5132 715 memset (e, 0, sizeof (def_file_export));
252b5132
RH
716 e->name = xstrdup (external_name);
717 e->internal_name = xstrdup (internal_name);
7fcab871 718 e->its_name = (its_name ? xstrdup (its_name) : NULL);
252b5132 719 e->ordinal = ordinal;
91d6fa6a 720 fdef->num_exports++;
252b5132
RH
721 return e;
722}
723
a35bc64f 724def_file_module *
91d6fa6a 725def_get_module (def_file *fdef, const char *name)
a35bc64f
NC
726{
727 def_file_module *s;
728
91d6fa6a 729 for (s = fdef->modules; s; s = s->next)
a35bc64f
NC
730 if (strcmp (s->name, name) == 0)
731 return s;
732
1579bae1 733 return NULL;
a35bc64f
NC
734}
735
252b5132 736static def_file_module *
91d6fa6a 737def_stash_module (def_file *fdef, const char *name)
252b5132
RH
738{
739 def_file_module *s;
a35bc64f 740
91d6fa6a 741 if ((s = def_get_module (fdef, name)) != NULL)
252b5132 742 return s;
1579bae1 743 s = xmalloc (sizeof (def_file_module) + strlen (name));
b41d91a7 744 s->next = fdef->modules;
91d6fa6a 745 fdef->modules = s;
252b5132
RH
746 s->user_data = 0;
747 strcpy (s->name, name);
748 return s;
749}
750
db17156e
KT
751static int
752cmp_import_elem (const def_file_import *e, const char *ex_name,
753 const char *in_name, const char *module,
754 int ord)
755{
756 int r;
757
6e230cc2
KT
758 if ((r = are_names_equal (module, (e->module ? e->module->name : NULL))))
759 return r;
db17156e
KT
760 if ((r = are_names_equal (ex_name, e->name)) != 0)
761 return r;
762 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
763 return r;
764 if (ord != e->ordinal)
765 return (ord < e->ordinal ? -1 : 1);
6e230cc2 766 return 0;
db17156e
KT
767}
768
769/* Search the position of the identical element, or returns the position
770 of the next higher element. If last valid element is smaller, then MAX
825a844f
MS
771 is returned. The max parameter indicates the number of elements in the
772 array. On return, *is_ident indicates whether the returned array index
773 points at an element which is identical to the one searched for. */
db17156e 774
825a844f
MS
775static unsigned int
776find_import_in_list (def_file_import *b, unsigned int max,
db17156e 777 const char *ex_name, const char *in_name,
825a844f 778 const char *module, int ord, bool *is_ident)
db17156e 779{
825a844f
MS
780 int e;
781 unsigned int l, r, p;
db17156e 782
825a844f 783 *is_ident = false;
db17156e
KT
784 if (!max)
785 return 0;
786 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
d0ac6938
KT
787 {
788 if (!e)
825a844f 789 *is_ident = true;
d0ac6938
KT
790 return 0;
791 }
db17156e
KT
792 if (max == 1)
793 return 1;
794 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
795 return max;
796 else if (!e || max == 2)
d0ac6938
KT
797 {
798 if (!e)
825a844f 799 *is_ident = true;
d0ac6938
KT
800 return max - 1;
801 }
db17156e
KT
802 l = 0; r = max - 1;
803 while (l < r)
804 {
805 p = (l + r) / 2;
806 e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
807 if (!e)
6c19b93b 808 {
825a844f 809 *is_ident = true;
6c19b93b
AM
810 return p;
811 }
db17156e 812 else if (e < 0)
6c19b93b 813 r = p - 1;
db17156e 814 else if (e > 0)
6c19b93b 815 l = p + 1;
db17156e
KT
816 }
817 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
818 ++l;
819 else if (!e)
825a844f 820 *is_ident = true;
db17156e
KT
821 return l;
822}
823
9d8e8f44
EB
824static void
825fill_in_import (def_file_import *i,
826 const char *name,
827 def_file_module *module,
828 int ordinal,
829 const char *internal_name,
830 const char *its_name)
831{
832 memset (i, 0, sizeof (def_file_import));
833 if (name)
834 i->name = xstrdup (name);
835 i->module = module;
836 i->ordinal = ordinal;
837 if (internal_name)
838 i->internal_name = xstrdup (internal_name);
839 else
840 i->internal_name = i->name;
841 i->its_name = (its_name ? xstrdup (its_name) : NULL);
842}
843
252b5132 844def_file_import *
91d6fa6a 845def_file_add_import (def_file *fdef,
1579bae1
AM
846 const char *name,
847 const char *module,
848 int ordinal,
7fcab871 849 const char *internal_name,
db17156e 850 const char *its_name,
825a844f 851 bool *is_dup)
252b5132
RH
852{
853 def_file_import *i;
825a844f 854 unsigned int pos;
a35bc64f 855
db17156e 856 /* We need to avoid here duplicates. */
825a844f 857 *is_dup = false;
db17156e
KT
858 pos = find_import_in_list (fdef->imports, fdef->num_imports,
859 name,
860 (!internal_name ? name : internal_name),
861 module, ordinal, is_dup);
825a844f 862 if (*is_dup)
db17156e
KT
863 return fdef->imports + pos;
864
825a844f 865 if ((unsigned)fdef->num_imports >= fdef->max_imports)
252b5132 866 {
825a844f
MS
867 fdef->max_imports += SYMBOL_LIST_ARRAY_GROW;
868 fdef->imports = xrealloc (fdef->imports,
869 fdef->max_imports * sizeof (def_file_import));
252b5132 870 }
db17156e 871 i = fdef->imports + pos;
825a844f
MS
872 /* If we're inserting in the middle of the array, we need to move the
873 following elements forward. */
874 if (pos != (unsigned)fdef->num_imports)
9d8e8f44
EB
875 memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
876
877 fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
878 internal_name, its_name);
879 fdef->num_imports++;
880
881 return i;
882}
883
884int
885def_file_add_import_from (def_file *fdef,
886 int num_imports,
887 const char *name,
888 const char *module,
889 int ordinal,
890 const char *internal_name,
891 const char *its_name ATTRIBUTE_UNUSED)
892{
893 def_file_import *i;
825a844f
MS
894 bool is_dup;
895 unsigned int pos;
9d8e8f44
EB
896
897 /* We need to avoid here duplicates. */
825a844f 898 is_dup = false;
9d8e8f44
EB
899 pos = find_import_in_list (fdef->imports, fdef->num_imports,
900 name, internal_name ? internal_name : name,
901 module, ordinal, &is_dup);
825a844f 902 if (is_dup)
9d8e8f44 903 return -1;
825a844f 904 if (fdef->imports && pos != (unsigned)fdef->num_imports)
9d8e8f44
EB
905 {
906 i = fdef->imports + pos;
907 if (i->module && strcmp (i->module->name, module) == 0)
908 return -1;
909 }
910
825a844f 911 if ((unsigned)fdef->num_imports + num_imports - 1 >= fdef->max_imports)
9d8e8f44 912 {
825a844f
MS
913 fdef->max_imports = fdef->num_imports + num_imports +
914 SYMBOL_LIST_ARRAY_GROW;
9d8e8f44 915
825a844f
MS
916 fdef->imports = xrealloc (fdef->imports,
917 fdef->max_imports * sizeof (def_file_import));
9d8e8f44
EB
918 }
919 i = fdef->imports + pos;
825a844f
MS
920 /* If we're inserting in the middle of the array, we need to move the
921 following elements forward. */
922 if (pos != (unsigned)fdef->num_imports)
9d8e8f44
EB
923 memmove (i + num_imports, i,
924 sizeof (def_file_import) * (fdef->num_imports - pos));
925
926 return pos;
927}
928
929def_file_import *
930def_file_add_import_at (def_file *fdef,
931 int pos,
932 const char *name,
933 const char *module,
934 int ordinal,
935 const char *internal_name,
936 const char *its_name)
937{
938 def_file_import *i = fdef->imports + pos;
939
940 fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
941 internal_name, its_name);
91d6fa6a 942 fdef->num_imports++;
a35bc64f 943
252b5132
RH
944 return i;
945}
946
a33a94cf
MS
947/* Search the position of the identical element, or returns the position
948 of the next higher element. If last valid element is smaller, then MAX
949 is returned. The max parameter indicates the number of elements in the
950 array. On return, *is_ident indicates whether the returned array index
951 points at an element which is identical to the one searched for. */
952
953static unsigned int
954find_exclude_in_list (def_file_exclude_symbol *b, unsigned int max,
955 const char *name, bool *is_ident)
956{
957 int e;
958 unsigned int l, r, p;
959
960 *is_ident = false;
961 if (!max)
962 return 0;
963 if ((e = strcmp (b[0].symbol_name, name)) <= 0)
964 {
965 if (!e)
966 *is_ident = true;
967 return 0;
968 }
969 if (max == 1)
970 return 1;
971 if ((e = strcmp (b[max - 1].symbol_name, name)) > 0)
972 return max;
973 else if (!e || max == 2)
974 {
975 if (!e)
976 *is_ident = true;
977 return max - 1;
978 }
979 l = 0; r = max - 1;
980 while (l < r)
981 {
982 p = (l + r) / 2;
983 e = strcmp (b[p].symbol_name, name);
984 if (!e)
985 {
986 *is_ident = true;
987 return p;
988 }
989 else if (e < 0)
990 r = p - 1;
991 else if (e > 0)
992 l = p + 1;
993 }
994 if ((e = strcmp (b[l].symbol_name, name)) > 0)
995 ++l;
996 else if (!e)
997 *is_ident = true;
998 return l;
999}
1000
1001static def_file_exclude_symbol *
1002def_file_add_exclude_symbol (def_file *fdef, const char *name)
1003{
1004 def_file_exclude_symbol *e;
1005 unsigned pos;
1006 bool is_dup = false;
1007
1008 pos = find_exclude_in_list (fdef->exclude_symbols, fdef->num_exclude_symbols,
1009 name, &is_dup);
1010
1011 /* We need to avoid duplicates. */
1012 if (is_dup)
1013 return (fdef->exclude_symbols + pos);
1014
1015 if (fdef->num_exclude_symbols >= fdef->max_exclude_symbols)
1016 {
1017 fdef->max_exclude_symbols += SYMBOL_LIST_ARRAY_GROW;
1018 fdef->exclude_symbols = xrealloc (fdef->exclude_symbols,
1019 fdef->max_exclude_symbols * sizeof (def_file_exclude_symbol));
1020 }
1021
1022 e = fdef->exclude_symbols + pos;
1023 /* If we're inserting in the middle of the array, we need to move the
1024 following elements forward. */
1025 if (pos != fdef->num_exclude_symbols)
1026 memmove (&e[1], e, (sizeof (def_file_exclude_symbol) * (fdef->num_exclude_symbols - pos)));
1027 /* Wipe the element for use as a new entry. */
1028 memset (e, 0, sizeof (def_file_exclude_symbol));
1029 e->symbol_name = xstrdup (name);
1030 fdef->num_exclude_symbols++;
1031 return e;
1032}
1033
252b5132
RH
1034struct
1035{
1036 char *param;
1037 int token;
1038}
1039diropts[] =
1040{
1041 { "-heap", HEAPSIZE },
8e58566f 1042 { "-stack", STACKSIZE_K },
252b5132
RH
1043 { "-attr", SECTIONS },
1044 { "-export", EXPORTS },
c1711530 1045 { "-aligncomm", ALIGNCOMM },
37513c1e 1046 { "-exclude-symbols", EXCLUDE_SYMBOLS },
252b5132
RH
1047 { 0, 0 }
1048};
1049
1050void
1579bae1 1051def_file_add_directive (def_file *my_def, const char *param, int len)
252b5132
RH
1052{
1053 def_file *save_def = def;
1054 const char *pend = param + len;
dc17f155 1055 char * tend = (char *) param;
252b5132
RH
1056 int i;
1057
1058 def = my_def;
1059
1060 while (param < pend)
1061 {
1579bae1
AM
1062 while (param < pend
1063 && (ISSPACE (*param) || *param == '\n' || *param == 0))
252b5132 1064 param++;
a35bc64f 1065
dc17f155
NC
1066 if (param == pend)
1067 break;
1068
1069 /* Scan forward until we encounter any of:
6c19b93b 1070 - the end of the buffer
dc17f155 1071 - the start of a new option
cb55e96b 1072 - a newline separating options
6c19b93b 1073 - a NUL separating options. */
dc17f155 1074 for (tend = (char *) (param + 1);
1579bae1
AM
1075 (tend < pend
1076 && !(ISSPACE (tend[-1]) && *tend == '-')
1077 && *tend != '\n' && *tend != 0);
a35bc64f
NC
1078 tend++)
1079 ;
252b5132
RH
1080
1081 for (i = 0; diropts[i].param; i++)
1082 {
91d6fa6a 1083 len = strlen (diropts[i].param);
a35bc64f 1084
252b5132
RH
1085 if (tend - param >= len
1086 && strncmp (param, diropts[i].param, len) == 0
1087 && (param[len] == ':' || param[len] == ' '))
1088 {
1089 lex_parse_string_end = tend;
1090 lex_parse_string = param + len + 1;
1091 lex_forced_token = diropts[i].token;
1092 saw_newline = 0;
dc17f155
NC
1093 if (def_parse ())
1094 continue;
252b5132
RH
1095 break;
1096 }
1097 }
1098
1099 if (!diropts[i].param)
dc17f155 1100 {
3d4a522e
NC
1101 if (tend < pend)
1102 {
1103 char saved;
dc17f155 1104
3d4a522e
NC
1105 saved = * tend;
1106 * tend = 0;
1107 /* xgettext:c-format */
1108 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
1109 * tend = saved;
1110 }
1111 else
1112 {
1113 einfo (_("Warning: corrupt .drectve at end of def file\n"));
1114 }
dc17f155 1115 }
a35bc64f 1116
252b5132
RH
1117 lex_parse_string = 0;
1118 param = tend;
1119 }
1120
1121 def = save_def;
bdca0ea1 1122 def_pool_free ();
252b5132
RH
1123}
1124
a35bc64f 1125/* Parser Callbacks. */
252b5132
RH
1126
1127static void
0a4e6638 1128def_image_name (const char *name, bfd_vma base, int is_dll)
252b5132 1129{
a2877985
DS
1130 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
1131 to do here. We retain the output filename specified on command line. */
1132 if (*name)
1133 {
1134 const char* image_name = lbasename (name);
91d6fa6a 1135
a2877985 1136 if (image_name != name)
02d44d76 1137 einfo (_("%s:%d: Warning: path components stripped from %s, '%s'\n"),
a2877985
DS
1138 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
1139 name);
5e2ab612 1140 free (def->name);
e4492aa0 1141 /* Append the default suffix, if none specified. */
a2877985
DS
1142 if (strchr (image_name, '.') == 0)
1143 {
1144 const char * suffix = is_dll ? ".dll" : ".exe";
1145
1146 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
1147 sprintf (def->name, "%s%s", image_name, suffix);
6c19b93b 1148 }
a2877985
DS
1149 else
1150 def->name = xstrdup (image_name);
1151 }
1152
1153 /* Honor a BASE address statement, even if LIBRARY string is empty. */
252b5132 1154 def->base_address = base;
a880c748 1155 def->is_dll = is_dll;
252b5132
RH
1156}
1157
1158static void
1579bae1 1159def_description (const char *text)
252b5132
RH
1160{
1161 int len = def->description ? strlen (def->description) : 0;
a35bc64f 1162
252b5132
RH
1163 len += strlen (text) + 1;
1164 if (def->description)
1165 {
1579bae1 1166 def->description = xrealloc (def->description, len);
252b5132
RH
1167 strcat (def->description, text);
1168 }
1169 else
1170 {
1579bae1 1171 def->description = xmalloc (len);
252b5132
RH
1172 strcpy (def->description, text);
1173 }
1174}
1175
1176static void
1579bae1 1177def_stacksize (int reserve, int commit)
252b5132
RH
1178{
1179 def->stack_reserve = reserve;
1180 def->stack_commit = commit;
1181}
1182
1183static void
1579bae1 1184def_heapsize (int reserve, int commit)
252b5132
RH
1185{
1186 def->heap_reserve = reserve;
1187 def->heap_commit = commit;
1188}
1189
1190static void
1579bae1 1191def_section (const char *name, int attr)
252b5132
RH
1192{
1193 def_file_section *s;
1579bae1 1194 int max_sections = ROUND_UP (def->num_section_defs, 4);
a35bc64f 1195
252b5132
RH
1196 if (def->num_section_defs >= max_sections)
1197 {
1579bae1 1198 max_sections = ROUND_UP (def->num_section_defs+1, 4);
a35bc64f 1199
252b5132 1200 if (def->section_defs)
1579bae1
AM
1201 def->section_defs = xrealloc (def->section_defs,
1202 max_sections * sizeof (def_file_import));
252b5132 1203 else
1579bae1 1204 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
252b5132
RH
1205 }
1206 s = def->section_defs + def->num_section_defs;
1207 memset (s, 0, sizeof (def_file_section));
1208 s->name = xstrdup (name);
1209 if (attr & 1)
1210 s->flag_read = 1;
1211 if (attr & 2)
1212 s->flag_write = 1;
1213 if (attr & 4)
1214 s->flag_execute = 1;
1215 if (attr & 8)
1216 s->flag_shared = 1;
1217
1218 def->num_section_defs++;
1219}
1220
1221static void
1579bae1 1222def_section_alt (const char *name, const char *attr)
252b5132
RH
1223{
1224 int aval = 0;
a35bc64f 1225
252b5132
RH
1226 for (; *attr; attr++)
1227 {
1228 switch (*attr)
1229 {
1230 case 'R':
1231 case 'r':
1232 aval |= 1;
1233 break;
1234 case 'W':
1235 case 'w':
1236 aval |= 2;
1237 break;
1238 case 'X':
1239 case 'x':
1240 aval |= 4;
1241 break;
1242 case 'S':
1243 case 's':
1244 aval |= 8;
1245 break;
1246 }
1247 }
1248 def_section (name, aval);
1249}
1250
1251static void
1579bae1
AM
1252def_exports (const char *external_name,
1253 const char *internal_name,
1254 int ordinal,
7fcab871
KT
1255 int flags,
1256 const char *its_name)
252b5132
RH
1257{
1258 def_file_export *dfe;
825a844f 1259 bool is_dup = false;
252b5132
RH
1260
1261 if (!internal_name && external_name)
1262 internal_name = external_name;
1263#if TRACE
1264 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1265#endif
1266
7fcab871 1267 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
db17156e
KT
1268 its_name, &is_dup);
1269
1270 /* We might check here for flag redefinition and warn. For now we
1271 ignore duplicates silently. */
1272 if (is_dup)
1273 return;
1274
252b5132
RH
1275 if (flags & 1)
1276 dfe->flag_noname = 1;
1277 if (flags & 2)
1278 dfe->flag_constant = 1;
1279 if (flags & 4)
1280 dfe->flag_data = 1;
1281 if (flags & 8)
1282 dfe->flag_private = 1;
1283}
1284
1285static void
1579bae1
AM
1286def_import (const char *internal_name,
1287 const char *module,
1288 const char *dllext,
1289 const char *name,
7fcab871
KT
1290 int ordinal,
1291 const char *its_name)
252b5132
RH
1292{
1293 char *buf = 0;
db17156e 1294 const char *ext = dllext ? dllext : "dll";
825a844f 1295 bool is_dup = false;
e4492aa0 1296
1579bae1 1297 buf = xmalloc (strlen (module) + strlen (ext) + 2);
053c44e1
DS
1298 sprintf (buf, "%s.%s", module, ext);
1299 module = buf;
252b5132 1300
db17156e
KT
1301 def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1302 &is_dup);
1303 free (buf);
252b5132
RH
1304}
1305
1306static void
1579bae1 1307def_version (int major, int minor)
252b5132
RH
1308{
1309 def->version_major = major;
1310 def->version_minor = minor;
1311}
1312
1313static void
1579bae1 1314def_directive (char *str)
252b5132 1315{
1579bae1 1316 struct directive *d = xmalloc (sizeof (struct directive));
a35bc64f 1317
252b5132
RH
1318 d->next = directives;
1319 directives = d;
1320 d->name = xstrdup (str);
1321 d->len = strlen (str);
1322}
1323
c1711530
DK
1324static void
1325def_aligncomm (char *str, int align)
1326{
dc204beb 1327 def_file_aligncomm *c, *p;
e4492aa0 1328
dc204beb
KT
1329 p = NULL;
1330 c = def->aligncomms;
1331 while (c != NULL)
1332 {
1333 int e = strcmp (c->symbol_name, str);
1334 if (!e)
1335 {
1336 /* Not sure if we want to allow here duplicates with
1337 different alignments, but for now we keep them. */
1338 e = (int) c->alignment - align;
1339 if (!e)
1340 return;
1341 }
1342 if (e > 0)
6c19b93b 1343 break;
dc204beb
KT
1344 c = (p = c)->next;
1345 }
c1711530 1346
dc204beb 1347 c = xmalloc (sizeof (def_file_aligncomm));
c1711530
DK
1348 c->symbol_name = xstrdup (str);
1349 c->alignment = (unsigned int) align;
dc204beb
KT
1350 if (!p)
1351 {
1352 c->next = def->aligncomms;
1353 def->aligncomms = c;
1354 }
37513c1e
MS
1355 else
1356 {
1357 c->next = p->next;
1358 p->next = c;
1359 }
1360}
1361
1362static void
1363def_exclude_symbols (char *str)
1364{
a33a94cf 1365 def_file_add_exclude_symbol (def, str);
c1711530
DK
1366}
1367
314ec7ae 1368static void
1579bae1 1369def_error (const char *err)
252b5132 1370{
1579bae1
AM
1371 einfo ("%P: %s:%d: %s\n",
1372 def_filename ? def_filename : "<unknown-file>", linenumber, err);
252b5132
RH
1373}
1374
1375
a35bc64f 1376/* Lexical Scanner. */
252b5132
RH
1377
1378#undef TRACE
1379#define TRACE 0
1380
a35bc64f 1381/* Never freed, but always reused as needed, so no real leak. */
252b5132
RH
1382static char *buffer = 0;
1383static int buflen = 0;
1384static int bufptr = 0;
1385
1386static void
1579bae1 1387put_buf (char c)
252b5132
RH
1388{
1389 if (bufptr == buflen)
1390 {
a35bc64f 1391 buflen += 50; /* overly reasonable, eh? */
252b5132 1392 if (buffer)
1579bae1 1393 buffer = xrealloc (buffer, buflen + 1);
252b5132 1394 else
1579bae1 1395 buffer = xmalloc (buflen + 1);
252b5132
RH
1396 }
1397 buffer[bufptr++] = c;
a35bc64f 1398 buffer[bufptr] = 0; /* not optimal, but very convenient. */
252b5132
RH
1399}
1400
1401static struct
1402{
1403 char *name;
1404 int token;
1405}
1406tokens[] =
1407{
1408 { "BASE", BASE },
1409 { "CODE", CODE },
7c9e78f8
DD
1410 { "CONSTANT", CONSTANTU },
1411 { "constant", CONSTANTL },
1412 { "DATA", DATAU },
1413 { "data", DATAL },
252b5132
RH
1414 { "DESCRIPTION", DESCRIPTION },
1415 { "DIRECTIVE", DIRECTIVE },
61f6b650 1416 { "EXCLUDE_SYMBOLS", EXCLUDE_SYMBOLS },
252b5132
RH
1417 { "EXECUTE", EXECUTE },
1418 { "EXPORTS", EXPORTS },
1419 { "HEAPSIZE", HEAPSIZE },
1420 { "IMPORTS", IMPORTS },
1421 { "LIBRARY", LIBRARY },
1422 { "NAME", NAME },
7c9e78f8
DD
1423 { "NONAME", NONAMEU },
1424 { "noname", NONAMEL },
1425 { "PRIVATE", PRIVATEU },
1426 { "private", PRIVATEL },
252b5132
RH
1427 { "READ", READ },
1428 { "SECTIONS", SECTIONS },
1429 { "SEGMENTS", SECTIONS },
6abe7848 1430 { "SHARED", SHARED_K },
8e58566f 1431 { "STACKSIZE", STACKSIZE_K },
252b5132
RH
1432 { "VERSION", VERSIONK },
1433 { "WRITE", WRITE },
1434 { 0, 0 }
1435};
1436
1437static int
1579bae1 1438def_getc (void)
252b5132
RH
1439{
1440 int rv;
a35bc64f 1441
252b5132
RH
1442 if (lex_parse_string)
1443 {
1444 if (lex_parse_string >= lex_parse_string_end)
1445 rv = EOF;
1446 else
1447 rv = *lex_parse_string++;
1448 }
1449 else
1450 {
1451 rv = fgetc (the_file);
1452 }
1453 if (rv == '\n')
1454 saw_newline = 1;
1455 return rv;
1456}
1457
1458static int
1579bae1 1459def_ungetc (int c)
252b5132
RH
1460{
1461 if (lex_parse_string)
1462 {
1463 lex_parse_string--;
1464 return c;
1465 }
1466 else
1467 return ungetc (c, the_file);
1468}
1469
1470static int
1579bae1 1471def_lex (void)
252b5132
RH
1472{
1473 int c, i, q;
1474
1475 if (lex_forced_token)
1476 {
1477 i = lex_forced_token;
1478 lex_forced_token = 0;
1479#if TRACE
1480 printf ("lex: forcing token %d\n", i);
1481#endif
1482 return i;
1483 }
1484
1485 c = def_getc ();
1486
a35bc64f 1487 /* Trim leading whitespace. */
252b5132
RH
1488 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1489 c = def_getc ();
1490
1491 if (c == EOF)
1492 {
1493#if TRACE
1494 printf ("lex: EOF\n");
1495#endif
1496 return 0;
1497 }
1498
1499 if (saw_newline && c == ';')
1500 {
1501 do
1502 {
1503 c = def_getc ();
1504 }
1505 while (c != EOF && c != '\n');
1506 if (c == '\n')
1507 return def_lex ();
1508 return 0;
1509 }
a35bc64f
NC
1510
1511 /* Must be something else. */
252b5132
RH
1512 saw_newline = 0;
1513
3882b010 1514 if (ISDIGIT (c))
252b5132
RH
1515 {
1516 bufptr = 0;
3882b010 1517 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
252b5132
RH
1518 {
1519 put_buf (c);
1520 c = def_getc ();
1521 }
1522 if (c != EOF)
1523 def_ungetc (c);
bdca0ea1 1524 yylval.digits = def_pool_strdup (buffer);
252b5132 1525#if TRACE
05056a8d 1526 printf ("lex: `%s' returns DIGITS\n", buffer);
252b5132 1527#endif
05056a8d 1528 return DIGITS;
252b5132
RH
1529 }
1530
c9e38879 1531 if (ISALPHA (c) || strchr ("$:-_?@", c))
252b5132
RH
1532 {
1533 bufptr = 0;
c9e38879
NC
1534 q = c;
1535 put_buf (c);
1536 c = def_getc ();
1537
1538 if (q == '@')
1539 {
6c19b93b 1540 if (ISBLANK (c) ) /* '@' followed by whitespace. */
c9e38879 1541 return (q);
6c19b93b
AM
1542 else if (ISDIGIT (c)) /* '@' followed by digit. */
1543 {
c9e38879 1544 def_ungetc (c);
6c19b93b 1545 return (q);
c9e38879
NC
1546 }
1547#if TRACE
1548 printf ("lex: @ returns itself\n");
1549#endif
1550 }
1551
424908eb 1552 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
252b5132
RH
1553 {
1554 put_buf (c);
1555 c = def_getc ();
1556 }
1557 if (c != EOF)
1558 def_ungetc (c);
c9e38879
NC
1559 if (ISALPHA (q)) /* Check for tokens. */
1560 {
6c19b93b 1561 for (i = 0; tokens[i].name; i++)
c9e38879
NC
1562 if (strcmp (tokens[i].name, buffer) == 0)
1563 {
252b5132 1564#if TRACE
c9e38879 1565 printf ("lex: `%s' is a string token\n", buffer);
252b5132 1566#endif
c9e38879
NC
1567 return tokens[i].token;
1568 }
1569 }
252b5132
RH
1570#if TRACE
1571 printf ("lex: `%s' returns ID\n", buffer);
1572#endif
bdca0ea1 1573 yylval.id = def_pool_strdup (buffer);
252b5132
RH
1574 return ID;
1575 }
1576
1577 if (c == '\'' || c == '"')
1578 {
1579 q = c;
1580 c = def_getc ();
1581 bufptr = 0;
a35bc64f 1582
252b5132
RH
1583 while (c != EOF && c != q)
1584 {
1585 put_buf (c);
1586 c = def_getc ();
1587 }
bdca0ea1 1588 yylval.id = def_pool_strdup (buffer);
252b5132
RH
1589#if TRACE
1590 printf ("lex: `%s' returns ID\n", buffer);
1591#endif
1592 return ID;
1593 }
1594
7fcab871
KT
1595 if ( c == '=')
1596 {
1597 c = def_getc ();
1598 if (c == '=')
6c19b93b 1599 {
7fcab871 1600#if TRACE
6c19b93b 1601 printf ("lex: `==' returns EQUAL\n");
7fcab871 1602#endif
6c19b93b
AM
1603 return EQUAL;
1604 }
7fcab871
KT
1605 def_ungetc (c);
1606#if TRACE
1607 printf ("lex: `=' returns itself\n");
1608#endif
1609 return '=';
1610 }
1611 if (c == '.' || c == ',')
252b5132
RH
1612 {
1613#if TRACE
1614 printf ("lex: `%c' returns itself\n", c);
1615#endif
1616 return c;
1617 }
1618
1619 if (c == '\n')
1620 {
1621 linenumber++;
1622 saw_newline = 1;
1623 }
1624
1625 /*printf ("lex: 0x%02x ignored\n", c); */
1626 return def_lex ();
1627}
bdca0ea1
KT
1628
1629static char *
1630def_pool_alloc (size_t sz)
1631{
1632 def_pool_str *e;
1633
1634 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1635 e->next = pool_strs;
1636 pool_strs = e;
1637 return e->data;
1638}
1639
1640static char *
1641def_pool_strdup (const char *str)
1642{
1643 char *s;
1644 size_t len;
1645 if (!str)
1646 return NULL;
1647 len = strlen (str) + 1;
1648 s = def_pool_alloc (len);
1649 memcpy (s, str, len);
1650 return s;
1651}
1652
1653static void
1654def_pool_free (void)
1655{
1656 def_pool_str *p;
1657 while ((p = pool_strs) != NULL)
1658 {
1659 pool_strs = p->next;
1660 free (p);
1661 }
1662}