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