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