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