gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / ld / deffilep.y
CommitLineData
252b5132
RH
1%{ /* deffilep.y - parser for .def files */
2
b3adc24a 3/* Copyright (C) 1995-2020 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
AM
104static int def_parse (void);
105static int def_error (const char *);
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
7fcab871 125%token READ WRITE EXECUTE SHARED 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
RH
237 | EXECUTE { $$=4;}
238 | SHARED { $$=8;}
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"; }
266 | SHARED { $$ = "SHARED"; }
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)
0a4e6638
KT
506 {
507 fprintf (file, " base address: 0x");
508 fprintf_vma (file, fdef->base_address);
509 fprintf (file, "\n");
510 }
91d6fa6a
NC
511 if (fdef->description)
512 fprintf (file, " description: `%s'\n", fdef->description);
513 if (fdef->stack_reserve != -1)
514 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve);
515 if (fdef->stack_commit != -1)
516 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit);
517 if (fdef->heap_reserve != -1)
518 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve);
519 if (fdef->heap_commit != -1)
520 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit);
521
522 if (fdef->num_section_defs > 0)
252b5132
RH
523 {
524 fprintf (file, " section defs:\n");
a35bc64f 525
91d6fa6a 526 for (i = 0; i < fdef->num_section_defs; i++)
252b5132
RH
527 {
528 fprintf (file, " name: `%s', class: `%s', flags:",
91d6fa6a
NC
529 fdef->section_defs[i].name, fdef->section_defs[i].class);
530 if (fdef->section_defs[i].flag_read)
252b5132 531 fprintf (file, " R");
91d6fa6a 532 if (fdef->section_defs[i].flag_write)
252b5132 533 fprintf (file, " W");
91d6fa6a 534 if (fdef->section_defs[i].flag_execute)
252b5132 535 fprintf (file, " X");
91d6fa6a 536 if (fdef->section_defs[i].flag_shared)
252b5132
RH
537 fprintf (file, " S");
538 fprintf (file, "\n");
539 }
540 }
541
91d6fa6a 542 if (fdef->num_exports > 0)
252b5132
RH
543 {
544 fprintf (file, " exports:\n");
a35bc64f 545
91d6fa6a 546 for (i = 0; i < fdef->num_exports; i++)
252b5132
RH
547 {
548 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
91d6fa6a
NC
549 fdef->exports[i].name, fdef->exports[i].internal_name,
550 fdef->exports[i].ordinal);
551 if (fdef->exports[i].flag_private)
252b5132 552 fprintf (file, " P");
91d6fa6a 553 if (fdef->exports[i].flag_constant)
252b5132 554 fprintf (file, " C");
91d6fa6a 555 if (fdef->exports[i].flag_noname)
252b5132 556 fprintf (file, " N");
91d6fa6a 557 if (fdef->exports[i].flag_data)
252b5132
RH
558 fprintf (file, " D");
559 fprintf (file, "\n");
560 }
561 }
562
91d6fa6a 563 if (fdef->num_imports > 0)
252b5132
RH
564 {
565 fprintf (file, " imports:\n");
a35bc64f 566
91d6fa6a 567 for (i = 0; i < fdef->num_imports; i++)
252b5132
RH
568 {
569 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
91d6fa6a
NC
570 fdef->imports[i].internal_name,
571 fdef->imports[i].module,
572 fdef->imports[i].name,
573 fdef->imports[i].ordinal);
252b5132
RH
574 }
575 }
a35bc64f 576
91d6fa6a
NC
577 if (fdef->version_major != -1)
578 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor);
a35bc64f 579
b41d91a7 580 fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
252b5132
RH
581}
582#endif
583
db17156e
KT
584/* Helper routine to check for identity of string pointers,
585 which might be NULL. */
586
587static int
588are_names_equal (const char *s1, const char *s2)
589{
590 if (!s1 && !s2)
591 return 0;
592 if (!s1 || !s2)
593 return (!s1 ? -1 : 1);
594 return strcmp (s1, s2);
595}
596
597static int
598cmp_export_elem (const def_file_export *e, const char *ex_name,
599 const char *in_name, const char *its_name,
600 int ord)
601{
602 int r;
603
604 if ((r = are_names_equal (ex_name, e->name)) != 0)
605 return r;
606 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
607 return r;
608 if ((r = are_names_equal (its_name, e->its_name)) != 0)
609 return r;
610 return (ord - e->ordinal);
611}
612
613/* Search the position of the identical element, or returns the position
614 of the next higher element. If last valid element is smaller, then MAX
615 is returned. */
616
617static int
618find_export_in_list (def_file_export *b, int max,
619 const char *ex_name, const char *in_name,
620 const char *its_name, int ord, int *is_ident)
621{
622 int e, l, r, p;
623
624 *is_ident = 0;
625 if (!max)
626 return 0;
627 if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
d0ac6938
KT
628 {
629 if (!e)
6c19b93b 630 *is_ident = 1;
d0ac6938
KT
631 return 0;
632 }
db17156e
KT
633 if (max == 1)
634 return 1;
635 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
636 return max;
637 else if (!e || max == 2)
d0ac6938
KT
638 {
639 if (!e)
640 *is_ident = 1;
641 return max - 1;
642 }
db17156e
KT
643 l = 0; r = max - 1;
644 while (l < r)
645 {
646 p = (l + r) / 2;
647 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
648 if (!e)
6c19b93b
AM
649 {
650 *is_ident = 1;
651 return p;
652 }
db17156e 653 else if (e < 0)
6c19b93b 654 r = p - 1;
db17156e 655 else if (e > 0)
6c19b93b 656 l = p + 1;
db17156e
KT
657 }
658 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
659 ++l;
660 else if (!e)
661 *is_ident = 1;
662 return l;
663}
664
252b5132 665def_file_export *
91d6fa6a 666def_file_add_export (def_file *fdef,
1579bae1
AM
667 const char *external_name,
668 const char *internal_name,
7fcab871 669 int ordinal,
db17156e
KT
670 const char *its_name,
671 int *is_dup)
252b5132
RH
672{
673 def_file_export *e;
db17156e 674 int pos;
91d6fa6a 675 int max_exports = ROUND_UP(fdef->num_exports, 32);
a35bc64f 676
db17156e
KT
677 if (internal_name && !external_name)
678 external_name = internal_name;
679 if (external_name && !internal_name)
680 internal_name = external_name;
681
682 /* We need to avoid duplicates. */
683 *is_dup = 0;
684 pos = find_export_in_list (fdef->exports, fdef->num_exports,
685 external_name, internal_name,
686 its_name, ordinal, is_dup);
687
688 if (*is_dup != 0)
689 return (fdef->exports + pos);
690
91d6fa6a 691 if (fdef->num_exports >= max_exports)
252b5132 692 {
91d6fa6a
NC
693 max_exports = ROUND_UP(fdef->num_exports + 1, 32);
694 if (fdef->exports)
695 fdef->exports = xrealloc (fdef->exports,
1579bae1 696 max_exports * sizeof (def_file_export));
252b5132 697 else
91d6fa6a 698 fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
252b5132 699 }
db17156e
KT
700
701 e = fdef->exports + pos;
702 if (pos != fdef->num_exports)
703 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
252b5132 704 memset (e, 0, sizeof (def_file_export));
252b5132
RH
705 e->name = xstrdup (external_name);
706 e->internal_name = xstrdup (internal_name);
7fcab871 707 e->its_name = (its_name ? xstrdup (its_name) : NULL);
252b5132 708 e->ordinal = ordinal;
91d6fa6a 709 fdef->num_exports++;
252b5132
RH
710 return e;
711}
712
a35bc64f 713def_file_module *
91d6fa6a 714def_get_module (def_file *fdef, const char *name)
a35bc64f
NC
715{
716 def_file_module *s;
717
91d6fa6a 718 for (s = fdef->modules; s; s = s->next)
a35bc64f
NC
719 if (strcmp (s->name, name) == 0)
720 return s;
721
1579bae1 722 return NULL;
a35bc64f
NC
723}
724
252b5132 725static def_file_module *
91d6fa6a 726def_stash_module (def_file *fdef, const char *name)
252b5132
RH
727{
728 def_file_module *s;
a35bc64f 729
91d6fa6a 730 if ((s = def_get_module (fdef, name)) != NULL)
252b5132 731 return s;
1579bae1 732 s = xmalloc (sizeof (def_file_module) + strlen (name));
b41d91a7 733 s->next = fdef->modules;
91d6fa6a 734 fdef->modules = s;
252b5132
RH
735 s->user_data = 0;
736 strcpy (s->name, name);
737 return s;
738}
739
db17156e
KT
740static int
741cmp_import_elem (const def_file_import *e, const char *ex_name,
742 const char *in_name, const char *module,
743 int ord)
744{
745 int r;
746
6e230cc2
KT
747 if ((r = are_names_equal (module, (e->module ? e->module->name : NULL))))
748 return r;
db17156e
KT
749 if ((r = are_names_equal (ex_name, e->name)) != 0)
750 return r;
751 if ((r = are_names_equal (in_name, e->internal_name)) != 0)
752 return r;
753 if (ord != e->ordinal)
754 return (ord < e->ordinal ? -1 : 1);
6e230cc2 755 return 0;
db17156e
KT
756}
757
758/* Search the position of the identical element, or returns the position
759 of the next higher element. If last valid element is smaller, then MAX
760 is returned. */
761
762static int
763find_import_in_list (def_file_import *b, int max,
764 const char *ex_name, const char *in_name,
765 const char *module, int ord, int *is_ident)
766{
767 int e, l, r, p;
768
769 *is_ident = 0;
770 if (!max)
771 return 0;
772 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
d0ac6938
KT
773 {
774 if (!e)
6c19b93b 775 *is_ident = 1;
d0ac6938
KT
776 return 0;
777 }
db17156e
KT
778 if (max == 1)
779 return 1;
780 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
781 return max;
782 else if (!e || max == 2)
d0ac6938
KT
783 {
784 if (!e)
6c19b93b 785 *is_ident = 1;
d0ac6938
KT
786 return max - 1;
787 }
db17156e
KT
788 l = 0; r = max - 1;
789 while (l < r)
790 {
791 p = (l + r) / 2;
792 e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
793 if (!e)
6c19b93b
AM
794 {
795 *is_ident = 1;
796 return p;
797 }
db17156e 798 else if (e < 0)
6c19b93b 799 r = p - 1;
db17156e 800 else if (e > 0)
6c19b93b 801 l = p + 1;
db17156e
KT
802 }
803 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
804 ++l;
805 else if (!e)
806 *is_ident = 1;
807 return l;
808}
809
9d8e8f44
EB
810static void
811fill_in_import (def_file_import *i,
812 const char *name,
813 def_file_module *module,
814 int ordinal,
815 const char *internal_name,
816 const char *its_name)
817{
818 memset (i, 0, sizeof (def_file_import));
819 if (name)
820 i->name = xstrdup (name);
821 i->module = module;
822 i->ordinal = ordinal;
823 if (internal_name)
824 i->internal_name = xstrdup (internal_name);
825 else
826 i->internal_name = i->name;
827 i->its_name = (its_name ? xstrdup (its_name) : NULL);
828}
829
252b5132 830def_file_import *
91d6fa6a 831def_file_add_import (def_file *fdef,
1579bae1
AM
832 const char *name,
833 const char *module,
834 int ordinal,
7fcab871 835 const char *internal_name,
db17156e
KT
836 const char *its_name,
837 int *is_dup)
252b5132
RH
838{
839 def_file_import *i;
db17156e 840 int pos;
91d6fa6a 841 int max_imports = ROUND_UP (fdef->num_imports, 16);
a35bc64f 842
db17156e
KT
843 /* We need to avoid here duplicates. */
844 *is_dup = 0;
845 pos = find_import_in_list (fdef->imports, fdef->num_imports,
846 name,
847 (!internal_name ? name : internal_name),
848 module, ordinal, is_dup);
849 if (*is_dup != 0)
850 return fdef->imports + pos;
851
91d6fa6a 852 if (fdef->num_imports >= max_imports)
252b5132 853 {
91d6fa6a 854 max_imports = ROUND_UP (fdef->num_imports+1, 16);
a35bc64f 855
91d6fa6a
NC
856 if (fdef->imports)
857 fdef->imports = xrealloc (fdef->imports,
1579bae1 858 max_imports * sizeof (def_file_import));
252b5132 859 else
91d6fa6a 860 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
252b5132 861 }
db17156e
KT
862 i = fdef->imports + pos;
863 if (pos != fdef->num_imports)
9d8e8f44
EB
864 memmove (i + 1, i, sizeof (def_file_import) * (fdef->num_imports - pos));
865
866 fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
867 internal_name, its_name);
868 fdef->num_imports++;
869
870 return i;
871}
872
873int
874def_file_add_import_from (def_file *fdef,
875 int num_imports,
876 const char *name,
877 const char *module,
878 int ordinal,
879 const char *internal_name,
880 const char *its_name ATTRIBUTE_UNUSED)
881{
882 def_file_import *i;
883 int is_dup;
884 int pos;
885 int max_imports = ROUND_UP (fdef->num_imports, 16);
886
887 /* We need to avoid here duplicates. */
888 is_dup = 0;
889 pos = find_import_in_list (fdef->imports, fdef->num_imports,
890 name, internal_name ? internal_name : name,
891 module, ordinal, &is_dup);
892 if (is_dup != 0)
893 return -1;
894 if (fdef->imports && pos != fdef->num_imports)
895 {
896 i = fdef->imports + pos;
897 if (i->module && strcmp (i->module->name, module) == 0)
898 return -1;
899 }
900
901 if (fdef->num_imports + num_imports - 1 >= max_imports)
902 {
903 max_imports = ROUND_UP (fdef->num_imports + num_imports, 16);
904
905 if (fdef->imports)
906 fdef->imports = xrealloc (fdef->imports,
907 max_imports * sizeof (def_file_import));
908 else
909 fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
910 }
911 i = fdef->imports + pos;
912 if (pos != fdef->num_imports)
913 memmove (i + num_imports, i,
914 sizeof (def_file_import) * (fdef->num_imports - pos));
915
916 return pos;
917}
918
919def_file_import *
920def_file_add_import_at (def_file *fdef,
921 int pos,
922 const char *name,
923 const char *module,
924 int ordinal,
925 const char *internal_name,
926 const char *its_name)
927{
928 def_file_import *i = fdef->imports + pos;
929
930 fill_in_import (i, name, def_stash_module (fdef, module), ordinal,
931 internal_name, its_name);
91d6fa6a 932 fdef->num_imports++;
a35bc64f 933
252b5132
RH
934 return i;
935}
936
937struct
938{
939 char *param;
940 int token;
941}
942diropts[] =
943{
944 { "-heap", HEAPSIZE },
8e58566f 945 { "-stack", STACKSIZE_K },
252b5132
RH
946 { "-attr", SECTIONS },
947 { "-export", EXPORTS },
c1711530 948 { "-aligncomm", ALIGNCOMM },
252b5132
RH
949 { 0, 0 }
950};
951
952void
1579bae1 953def_file_add_directive (def_file *my_def, const char *param, int len)
252b5132
RH
954{
955 def_file *save_def = def;
956 const char *pend = param + len;
dc17f155 957 char * tend = (char *) param;
252b5132
RH
958 int i;
959
960 def = my_def;
961
962 while (param < pend)
963 {
1579bae1
AM
964 while (param < pend
965 && (ISSPACE (*param) || *param == '\n' || *param == 0))
252b5132 966 param++;
a35bc64f 967
dc17f155
NC
968 if (param == pend)
969 break;
970
971 /* Scan forward until we encounter any of:
6c19b93b 972 - the end of the buffer
dc17f155 973 - the start of a new option
cb55e96b 974 - a newline separating options
6c19b93b 975 - a NUL separating options. */
dc17f155 976 for (tend = (char *) (param + 1);
1579bae1
AM
977 (tend < pend
978 && !(ISSPACE (tend[-1]) && *tend == '-')
979 && *tend != '\n' && *tend != 0);
a35bc64f
NC
980 tend++)
981 ;
252b5132
RH
982
983 for (i = 0; diropts[i].param; i++)
984 {
91d6fa6a 985 len = strlen (diropts[i].param);
a35bc64f 986
252b5132
RH
987 if (tend - param >= len
988 && strncmp (param, diropts[i].param, len) == 0
989 && (param[len] == ':' || param[len] == ' '))
990 {
991 lex_parse_string_end = tend;
992 lex_parse_string = param + len + 1;
993 lex_forced_token = diropts[i].token;
994 saw_newline = 0;
dc17f155
NC
995 if (def_parse ())
996 continue;
252b5132
RH
997 break;
998 }
999 }
1000
1001 if (!diropts[i].param)
dc17f155 1002 {
3d4a522e
NC
1003 if (tend < pend)
1004 {
1005 char saved;
dc17f155 1006
3d4a522e
NC
1007 saved = * tend;
1008 * tend = 0;
1009 /* xgettext:c-format */
1010 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
1011 * tend = saved;
1012 }
1013 else
1014 {
1015 einfo (_("Warning: corrupt .drectve at end of def file\n"));
1016 }
dc17f155 1017 }
a35bc64f 1018
252b5132
RH
1019 lex_parse_string = 0;
1020 param = tend;
1021 }
1022
1023 def = save_def;
bdca0ea1 1024 def_pool_free ();
252b5132
RH
1025}
1026
a35bc64f 1027/* Parser Callbacks. */
252b5132
RH
1028
1029static void
0a4e6638 1030def_image_name (const char *name, bfd_vma base, int is_dll)
252b5132 1031{
a2877985
DS
1032 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
1033 to do here. We retain the output filename specified on command line. */
1034 if (*name)
1035 {
1036 const char* image_name = lbasename (name);
91d6fa6a 1037
a2877985
DS
1038 if (image_name != name)
1039 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
1040 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
1041 name);
5e2ab612 1042 free (def->name);
e4492aa0 1043 /* Append the default suffix, if none specified. */
a2877985
DS
1044 if (strchr (image_name, '.') == 0)
1045 {
1046 const char * suffix = is_dll ? ".dll" : ".exe";
1047
1048 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
1049 sprintf (def->name, "%s%s", image_name, suffix);
6c19b93b 1050 }
a2877985
DS
1051 else
1052 def->name = xstrdup (image_name);
1053 }
1054
1055 /* Honor a BASE address statement, even if LIBRARY string is empty. */
252b5132 1056 def->base_address = base;
a880c748 1057 def->is_dll = is_dll;
252b5132
RH
1058}
1059
1060static void
1579bae1 1061def_description (const char *text)
252b5132
RH
1062{
1063 int len = def->description ? strlen (def->description) : 0;
a35bc64f 1064
252b5132
RH
1065 len += strlen (text) + 1;
1066 if (def->description)
1067 {
1579bae1 1068 def->description = xrealloc (def->description, len);
252b5132
RH
1069 strcat (def->description, text);
1070 }
1071 else
1072 {
1579bae1 1073 def->description = xmalloc (len);
252b5132
RH
1074 strcpy (def->description, text);
1075 }
1076}
1077
1078static void
1579bae1 1079def_stacksize (int reserve, int commit)
252b5132
RH
1080{
1081 def->stack_reserve = reserve;
1082 def->stack_commit = commit;
1083}
1084
1085static void
1579bae1 1086def_heapsize (int reserve, int commit)
252b5132
RH
1087{
1088 def->heap_reserve = reserve;
1089 def->heap_commit = commit;
1090}
1091
1092static void
1579bae1 1093def_section (const char *name, int attr)
252b5132
RH
1094{
1095 def_file_section *s;
1579bae1 1096 int max_sections = ROUND_UP (def->num_section_defs, 4);
a35bc64f 1097
252b5132
RH
1098 if (def->num_section_defs >= max_sections)
1099 {
1579bae1 1100 max_sections = ROUND_UP (def->num_section_defs+1, 4);
a35bc64f 1101
252b5132 1102 if (def->section_defs)
1579bae1
AM
1103 def->section_defs = xrealloc (def->section_defs,
1104 max_sections * sizeof (def_file_import));
252b5132 1105 else
1579bae1 1106 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
252b5132
RH
1107 }
1108 s = def->section_defs + def->num_section_defs;
1109 memset (s, 0, sizeof (def_file_section));
1110 s->name = xstrdup (name);
1111 if (attr & 1)
1112 s->flag_read = 1;
1113 if (attr & 2)
1114 s->flag_write = 1;
1115 if (attr & 4)
1116 s->flag_execute = 1;
1117 if (attr & 8)
1118 s->flag_shared = 1;
1119
1120 def->num_section_defs++;
1121}
1122
1123static void
1579bae1 1124def_section_alt (const char *name, const char *attr)
252b5132
RH
1125{
1126 int aval = 0;
a35bc64f 1127
252b5132
RH
1128 for (; *attr; attr++)
1129 {
1130 switch (*attr)
1131 {
1132 case 'R':
1133 case 'r':
1134 aval |= 1;
1135 break;
1136 case 'W':
1137 case 'w':
1138 aval |= 2;
1139 break;
1140 case 'X':
1141 case 'x':
1142 aval |= 4;
1143 break;
1144 case 'S':
1145 case 's':
1146 aval |= 8;
1147 break;
1148 }
1149 }
1150 def_section (name, aval);
1151}
1152
1153static void
1579bae1
AM
1154def_exports (const char *external_name,
1155 const char *internal_name,
1156 int ordinal,
7fcab871
KT
1157 int flags,
1158 const char *its_name)
252b5132
RH
1159{
1160 def_file_export *dfe;
db17156e 1161 int is_dup = 0;
252b5132
RH
1162
1163 if (!internal_name && external_name)
1164 internal_name = external_name;
1165#if TRACE
1166 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
1167#endif
1168
7fcab871 1169 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
db17156e
KT
1170 its_name, &is_dup);
1171
1172 /* We might check here for flag redefinition and warn. For now we
1173 ignore duplicates silently. */
1174 if (is_dup)
1175 return;
1176
252b5132
RH
1177 if (flags & 1)
1178 dfe->flag_noname = 1;
1179 if (flags & 2)
1180 dfe->flag_constant = 1;
1181 if (flags & 4)
1182 dfe->flag_data = 1;
1183 if (flags & 8)
1184 dfe->flag_private = 1;
1185}
1186
1187static void
1579bae1
AM
1188def_import (const char *internal_name,
1189 const char *module,
1190 const char *dllext,
1191 const char *name,
7fcab871
KT
1192 int ordinal,
1193 const char *its_name)
252b5132
RH
1194{
1195 char *buf = 0;
db17156e
KT
1196 const char *ext = dllext ? dllext : "dll";
1197 int is_dup = 0;
e4492aa0 1198
1579bae1 1199 buf = xmalloc (strlen (module) + strlen (ext) + 2);
053c44e1
DS
1200 sprintf (buf, "%s.%s", module, ext);
1201 module = buf;
252b5132 1202
db17156e
KT
1203 def_file_add_import (def, name, module, ordinal, internal_name, its_name,
1204 &is_dup);
1205 free (buf);
252b5132
RH
1206}
1207
1208static void
1579bae1 1209def_version (int major, int minor)
252b5132
RH
1210{
1211 def->version_major = major;
1212 def->version_minor = minor;
1213}
1214
1215static void
1579bae1 1216def_directive (char *str)
252b5132 1217{
1579bae1 1218 struct directive *d = xmalloc (sizeof (struct directive));
a35bc64f 1219
252b5132
RH
1220 d->next = directives;
1221 directives = d;
1222 d->name = xstrdup (str);
1223 d->len = strlen (str);
1224}
1225
c1711530
DK
1226static void
1227def_aligncomm (char *str, int align)
1228{
dc204beb 1229 def_file_aligncomm *c, *p;
e4492aa0 1230
dc204beb
KT
1231 p = NULL;
1232 c = def->aligncomms;
1233 while (c != NULL)
1234 {
1235 int e = strcmp (c->symbol_name, str);
1236 if (!e)
1237 {
1238 /* Not sure if we want to allow here duplicates with
1239 different alignments, but for now we keep them. */
1240 e = (int) c->alignment - align;
1241 if (!e)
1242 return;
1243 }
1244 if (e > 0)
6c19b93b 1245 break;
dc204beb
KT
1246 c = (p = c)->next;
1247 }
c1711530 1248
dc204beb 1249 c = xmalloc (sizeof (def_file_aligncomm));
c1711530
DK
1250 c->symbol_name = xstrdup (str);
1251 c->alignment = (unsigned int) align;
dc204beb
KT
1252 if (!p)
1253 {
1254 c->next = def->aligncomms;
1255 def->aligncomms = c;
1256 }
1257 else
1258 {
1259 c->next = p->next;
1260 p->next = c;
1261 }
c1711530
DK
1262}
1263
252b5132 1264static int
1579bae1 1265def_error (const char *err)
252b5132 1266{
1579bae1
AM
1267 einfo ("%P: %s:%d: %s\n",
1268 def_filename ? def_filename : "<unknown-file>", linenumber, err);
252b5132
RH
1269 return 0;
1270}
1271
1272
a35bc64f 1273/* Lexical Scanner. */
252b5132
RH
1274
1275#undef TRACE
1276#define TRACE 0
1277
a35bc64f 1278/* Never freed, but always reused as needed, so no real leak. */
252b5132
RH
1279static char *buffer = 0;
1280static int buflen = 0;
1281static int bufptr = 0;
1282
1283static void
1579bae1 1284put_buf (char c)
252b5132
RH
1285{
1286 if (bufptr == buflen)
1287 {
a35bc64f 1288 buflen += 50; /* overly reasonable, eh? */
252b5132 1289 if (buffer)
1579bae1 1290 buffer = xrealloc (buffer, buflen + 1);
252b5132 1291 else
1579bae1 1292 buffer = xmalloc (buflen + 1);
252b5132
RH
1293 }
1294 buffer[bufptr++] = c;
a35bc64f 1295 buffer[bufptr] = 0; /* not optimal, but very convenient. */
252b5132
RH
1296}
1297
1298static struct
1299{
1300 char *name;
1301 int token;
1302}
1303tokens[] =
1304{
1305 { "BASE", BASE },
1306 { "CODE", CODE },
7c9e78f8
DD
1307 { "CONSTANT", CONSTANTU },
1308 { "constant", CONSTANTL },
1309 { "DATA", DATAU },
1310 { "data", DATAL },
252b5132
RH
1311 { "DESCRIPTION", DESCRIPTION },
1312 { "DIRECTIVE", DIRECTIVE },
1313 { "EXECUTE", EXECUTE },
1314 { "EXPORTS", EXPORTS },
1315 { "HEAPSIZE", HEAPSIZE },
1316 { "IMPORTS", IMPORTS },
1317 { "LIBRARY", LIBRARY },
1318 { "NAME", NAME },
7c9e78f8
DD
1319 { "NONAME", NONAMEU },
1320 { "noname", NONAMEL },
1321 { "PRIVATE", PRIVATEU },
1322 { "private", PRIVATEL },
252b5132
RH
1323 { "READ", READ },
1324 { "SECTIONS", SECTIONS },
1325 { "SEGMENTS", SECTIONS },
1326 { "SHARED", SHARED },
8e58566f 1327 { "STACKSIZE", STACKSIZE_K },
252b5132
RH
1328 { "VERSION", VERSIONK },
1329 { "WRITE", WRITE },
1330 { 0, 0 }
1331};
1332
1333static int
1579bae1 1334def_getc (void)
252b5132
RH
1335{
1336 int rv;
a35bc64f 1337
252b5132
RH
1338 if (lex_parse_string)
1339 {
1340 if (lex_parse_string >= lex_parse_string_end)
1341 rv = EOF;
1342 else
1343 rv = *lex_parse_string++;
1344 }
1345 else
1346 {
1347 rv = fgetc (the_file);
1348 }
1349 if (rv == '\n')
1350 saw_newline = 1;
1351 return rv;
1352}
1353
1354static int
1579bae1 1355def_ungetc (int c)
252b5132
RH
1356{
1357 if (lex_parse_string)
1358 {
1359 lex_parse_string--;
1360 return c;
1361 }
1362 else
1363 return ungetc (c, the_file);
1364}
1365
1366static int
1579bae1 1367def_lex (void)
252b5132
RH
1368{
1369 int c, i, q;
1370
1371 if (lex_forced_token)
1372 {
1373 i = lex_forced_token;
1374 lex_forced_token = 0;
1375#if TRACE
1376 printf ("lex: forcing token %d\n", i);
1377#endif
1378 return i;
1379 }
1380
1381 c = def_getc ();
1382
a35bc64f 1383 /* Trim leading whitespace. */
252b5132
RH
1384 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1385 c = def_getc ();
1386
1387 if (c == EOF)
1388 {
1389#if TRACE
1390 printf ("lex: EOF\n");
1391#endif
1392 return 0;
1393 }
1394
1395 if (saw_newline && c == ';')
1396 {
1397 do
1398 {
1399 c = def_getc ();
1400 }
1401 while (c != EOF && c != '\n');
1402 if (c == '\n')
1403 return def_lex ();
1404 return 0;
1405 }
a35bc64f
NC
1406
1407 /* Must be something else. */
252b5132
RH
1408 saw_newline = 0;
1409
3882b010 1410 if (ISDIGIT (c))
252b5132
RH
1411 {
1412 bufptr = 0;
3882b010 1413 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
252b5132
RH
1414 {
1415 put_buf (c);
1416 c = def_getc ();
1417 }
1418 if (c != EOF)
1419 def_ungetc (c);
bdca0ea1 1420 yylval.digits = def_pool_strdup (buffer);
252b5132 1421#if TRACE
05056a8d 1422 printf ("lex: `%s' returns DIGITS\n", buffer);
252b5132 1423#endif
05056a8d 1424 return DIGITS;
252b5132
RH
1425 }
1426
c9e38879 1427 if (ISALPHA (c) || strchr ("$:-_?@", c))
252b5132
RH
1428 {
1429 bufptr = 0;
c9e38879
NC
1430 q = c;
1431 put_buf (c);
1432 c = def_getc ();
1433
1434 if (q == '@')
1435 {
6c19b93b 1436 if (ISBLANK (c) ) /* '@' followed by whitespace. */
c9e38879 1437 return (q);
6c19b93b
AM
1438 else if (ISDIGIT (c)) /* '@' followed by digit. */
1439 {
c9e38879 1440 def_ungetc (c);
6c19b93b 1441 return (q);
c9e38879
NC
1442 }
1443#if TRACE
1444 printf ("lex: @ returns itself\n");
1445#endif
1446 }
1447
424908eb 1448 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
252b5132
RH
1449 {
1450 put_buf (c);
1451 c = def_getc ();
1452 }
1453 if (c != EOF)
1454 def_ungetc (c);
c9e38879
NC
1455 if (ISALPHA (q)) /* Check for tokens. */
1456 {
6c19b93b 1457 for (i = 0; tokens[i].name; i++)
c9e38879
NC
1458 if (strcmp (tokens[i].name, buffer) == 0)
1459 {
252b5132 1460#if TRACE
c9e38879 1461 printf ("lex: `%s' is a string token\n", buffer);
252b5132 1462#endif
c9e38879
NC
1463 return tokens[i].token;
1464 }
1465 }
252b5132
RH
1466#if TRACE
1467 printf ("lex: `%s' returns ID\n", buffer);
1468#endif
bdca0ea1 1469 yylval.id = def_pool_strdup (buffer);
252b5132
RH
1470 return ID;
1471 }
1472
1473 if (c == '\'' || c == '"')
1474 {
1475 q = c;
1476 c = def_getc ();
1477 bufptr = 0;
a35bc64f 1478
252b5132
RH
1479 while (c != EOF && c != q)
1480 {
1481 put_buf (c);
1482 c = def_getc ();
1483 }
bdca0ea1 1484 yylval.id = def_pool_strdup (buffer);
252b5132
RH
1485#if TRACE
1486 printf ("lex: `%s' returns ID\n", buffer);
1487#endif
1488 return ID;
1489 }
1490
7fcab871
KT
1491 if ( c == '=')
1492 {
1493 c = def_getc ();
1494 if (c == '=')
6c19b93b 1495 {
7fcab871 1496#if TRACE
6c19b93b 1497 printf ("lex: `==' returns EQUAL\n");
7fcab871 1498#endif
6c19b93b
AM
1499 return EQUAL;
1500 }
7fcab871
KT
1501 def_ungetc (c);
1502#if TRACE
1503 printf ("lex: `=' returns itself\n");
1504#endif
1505 return '=';
1506 }
1507 if (c == '.' || c == ',')
252b5132
RH
1508 {
1509#if TRACE
1510 printf ("lex: `%c' returns itself\n", c);
1511#endif
1512 return c;
1513 }
1514
1515 if (c == '\n')
1516 {
1517 linenumber++;
1518 saw_newline = 1;
1519 }
1520
1521 /*printf ("lex: 0x%02x ignored\n", c); */
1522 return def_lex ();
1523}
bdca0ea1
KT
1524
1525static char *
1526def_pool_alloc (size_t sz)
1527{
1528 def_pool_str *e;
1529
1530 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
1531 e->next = pool_strs;
1532 pool_strs = e;
1533 return e->data;
1534}
1535
1536static char *
1537def_pool_strdup (const char *str)
1538{
1539 char *s;
1540 size_t len;
1541 if (!str)
1542 return NULL;
1543 len = strlen (str) + 1;
1544 s = def_pool_alloc (len);
1545 memcpy (s, str, len);
1546 return s;
1547}
1548
1549static void
1550def_pool_free (void)
1551{
1552 def_pool_str *p;
1553 while ((p = pool_strs) != NULL)
1554 {
1555 pool_strs = p->next;
1556 free (p);
1557 }
1558}
This page took 1.030277 seconds and 4 git commands to generate.