]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - ld/deffilep.y
2009-10-23 Kai Tietz <kai.tietz@onevision.com>
[thirdparty/binutils-gdb.git] / ld / deffilep.y
1 %{ /* deffilep.y - parser for .def files */
2
3 /* Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
4 2007, 2009 Free Software Foundation, Inc.
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23 #include "sysdep.h"
24 #include "libiberty.h"
25 #include "safe-ctype.h"
26 #include "bfd.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 /* 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
40 generators need to be fixed instead of adding those names to this list. */
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
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
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
69 #define yyreds def_reds /* With YYDEBUG defined. */
70 #define yytoks def_toks /* With YYDEBUG defined. */
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
81 static void def_description (const char *);
82 static void def_exports (const char *, const char *, int, int, const char *);
83 static void def_heapsize (int, int);
84 static void def_import (const char *, const char *, const char *, const char *,
85 int, const char *);
86 static void def_image_name (const char *, int, int);
87 static void def_section (const char *, int);
88 static void def_section_alt (const char *, const char *);
89 static void def_stacksize (int, int);
90 static void def_version (int, int);
91 static void def_directive (char *);
92 static void def_aligncomm (char *str, int align);
93 static int def_parse (void);
94 static int def_error (const char *);
95 static int def_lex (void);
96
97 static int lex_forced_token = 0;
98 static const char *lex_parse_string = 0;
99 static const char *lex_parse_string_end = 0;
100
101 %}
102
103 %union {
104 char *id;
105 int number;
106 char *digits;
107 };
108
109 %token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL
110 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL
111 %token PRIVATEU PRIVATEL ALIGNCOMM
112 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE EQUAL
113 %token <id> ID
114 %token <digits> DIGITS
115 %type <number> NUMBER
116 %type <digits> opt_digits
117 %type <number> opt_base opt_ordinal
118 %type <number> attr attr_list opt_number exp_opt_list exp_opt
119 %type <id> opt_name opt_equal_name dot_name anylang_id opt_id
120 %type <id> opt_equalequal_name
121
122 %%
123
124 start: start command
125 | command
126 ;
127
128 command:
129 NAME opt_name opt_base { def_image_name ($2, $3, 0); }
130 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); }
131 | DESCRIPTION ID { def_description ($2);}
132 | STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);}
133 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
134 | CODE attr_list { def_section ("CODE", $2);}
135 | DATAU attr_list { def_section ("DATA", $2);}
136 | SECTIONS seclist
137 | EXPORTS explist
138 | IMPORTS implist
139 | VERSIONK NUMBER { def_version ($2, 0);}
140 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);}
141 | DIRECTIVE ID { def_directive ($2);}
142 | ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);}
143 ;
144
145
146 explist:
147 /* EMPTY */
148 | expline
149 | explist expline
150 ;
151
152 expline:
153 /* The opt_comma is necessary to support both the usual
154 DEF file syntax as well as .drectve syntax which
155 mandates <expsym>,<expoptlist>. */
156 dot_name opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name
157 { def_exports ($1, $2, $3, $5, $7); }
158 ;
159 exp_opt_list:
160 /* The opt_comma is necessary to support both the usual
161 DEF file syntax as well as .drectve syntax which
162 allows for comma separated opt list. */
163 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; }
164 | { $$ = 0; }
165 ;
166 exp_opt:
167 NONAMEU { $$ = 1; }
168 | NONAMEL { $$ = 1; }
169 | CONSTANTU { $$ = 2; }
170 | CONSTANTL { $$ = 2; }
171 | DATAU { $$ = 4; }
172 | DATAL { $$ = 4; }
173 | PRIVATEU { $$ = 8; }
174 | PRIVATEL { $$ = 8; }
175 ;
176 implist:
177 implist impline
178 | impline
179 ;
180
181 impline:
182 ID '=' ID '.' ID '.' ID opt_equalequal_name
183 { def_import ($1, $3, $5, $7, -1, $8); }
184 | ID '=' ID '.' ID '.' NUMBER opt_equalequal_name
185 { def_import ($1, $3, $5, 0, $7, $8); }
186 | ID '=' ID '.' ID opt_equalequal_name
187 { def_import ($1, $3, 0, $5, -1, $6); }
188 | ID '=' ID '.' NUMBER opt_equalequal_name
189 { def_import ($1, $3, 0, 0, $5, $6); }
190 | ID '.' ID '.' ID opt_equalequal_name
191 { def_import( 0, $1, $3, $5, -1, $6); }
192 | ID '.' ID opt_equalequal_name
193 { def_import ( 0, $1, 0, $3, -1, $4); }
194 ;
195
196 seclist:
197 seclist secline
198 | secline
199 ;
200
201 secline:
202 ID attr_list { def_section ($1, $2);}
203 | ID ID { def_section_alt ($1, $2);}
204 ;
205
206 attr_list:
207 attr_list opt_comma attr { $$ = $1 | $3; }
208 | attr { $$ = $1; }
209 ;
210
211 opt_comma:
212 ','
213 |
214 ;
215 opt_number: ',' NUMBER { $$=$2;}
216 | { $$=-1;}
217 ;
218
219 attr:
220 READ { $$ = 1;}
221 | WRITE { $$ = 2;}
222 | EXECUTE { $$=4;}
223 | SHARED { $$=8;}
224 ;
225
226 opt_name: ID { $$ = $1; }
227 | ID '.' ID
228 {
229 char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
230 sprintf (name, "%s.%s", $1, $3);
231 $$ = name;
232 }
233 | { $$ = ""; }
234 ;
235
236 opt_equalequal_name: EQUAL ID { $$ = $2; }
237 | { $$ = 0; }
238 ;
239
240 opt_ordinal:
241 '@' NUMBER { $$ = $2;}
242 | { $$ = -1;}
243 ;
244
245 opt_equal_name:
246 '=' dot_name { $$ = $2; }
247 | { $$ = 0; }
248 ;
249
250 opt_base: BASE '=' NUMBER { $$ = $3;}
251 | { $$ = -1;}
252 ;
253
254 dot_name: ID { $$ = $1; }
255 | dot_name '.' ID
256 {
257 char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
258 sprintf (name, "%s.%s", $1, $3);
259 $$ = name;
260 }
261 ;
262
263 anylang_id: ID { $$ = $1; }
264 | anylang_id '.' opt_digits opt_id
265 {
266 char *id = xmalloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1);
267 sprintf (id, "%s.%s%s", $1, $3, $4);
268 $$ = id;
269 }
270 ;
271
272 opt_digits: DIGITS { $$ = $1; }
273 | { $$ = ""; }
274 ;
275
276 opt_id: ID { $$ = $1; }
277 | { $$ = ""; }
278 ;
279
280 NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); }
281
282 %%
283
284 /*****************************************************************************
285 API
286 *****************************************************************************/
287
288 static FILE *the_file;
289 static const char *def_filename;
290 static int linenumber;
291 static def_file *def;
292 static int saw_newline;
293
294 struct directive
295 {
296 struct directive *next;
297 char *name;
298 int len;
299 };
300
301 static struct directive *directives = 0;
302
303 def_file *
304 def_file_empty (void)
305 {
306 def_file *rv = xmalloc (sizeof (def_file));
307 memset (rv, 0, sizeof (def_file));
308 rv->is_dll = -1;
309 rv->base_address = (bfd_vma) -1;
310 rv->stack_reserve = rv->stack_commit = -1;
311 rv->heap_reserve = rv->heap_commit = -1;
312 rv->version_major = rv->version_minor = -1;
313 return rv;
314 }
315
316 def_file *
317 def_file_parse (const char *filename, def_file *add_to)
318 {
319 struct directive *d;
320
321 the_file = fopen (filename, "r");
322 def_filename = filename;
323 linenumber = 1;
324 if (!the_file)
325 {
326 perror (filename);
327 return 0;
328 }
329 if (add_to)
330 {
331 def = add_to;
332 }
333 else
334 {
335 def = def_file_empty ();
336 }
337
338 saw_newline = 1;
339 if (def_parse ())
340 {
341 def_file_free (def);
342 fclose (the_file);
343 return 0;
344 }
345
346 fclose (the_file);
347
348 for (d = directives; d; d = d->next)
349 {
350 #if TRACE
351 printf ("Adding directive %08x `%s'\n", d->name, d->name);
352 #endif
353 def_file_add_directive (def, d->name, d->len);
354 }
355
356 return def;
357 }
358
359 void
360 def_file_free (def_file *def)
361 {
362 int i;
363
364 if (!def)
365 return;
366 if (def->name)
367 free (def->name);
368 if (def->description)
369 free (def->description);
370
371 if (def->section_defs)
372 {
373 for (i = 0; i < def->num_section_defs; i++)
374 {
375 if (def->section_defs[i].name)
376 free (def->section_defs[i].name);
377 if (def->section_defs[i].class)
378 free (def->section_defs[i].class);
379 }
380 free (def->section_defs);
381 }
382
383 if (def->exports)
384 {
385 for (i = 0; i < def->num_exports; i++)
386 {
387 if (def->exports[i].internal_name
388 && def->exports[i].internal_name != def->exports[i].name)
389 free (def->exports[i].internal_name);
390 if (def->exports[i].name)
391 free (def->exports[i].name);
392 if (def->exports[i].its_name)
393 free (def->exports[i].its_name);
394 }
395 free (def->exports);
396 }
397
398 if (def->imports)
399 {
400 for (i = 0; i < def->num_imports; i++)
401 {
402 if (def->imports[i].internal_name
403 && def->imports[i].internal_name != def->imports[i].name)
404 free (def->imports[i].internal_name);
405 if (def->imports[i].name)
406 free (def->imports[i].name);
407 if (def->imports[i].its_name)
408 free (def->imports[i].its_name);
409 }
410 free (def->imports);
411 }
412
413 while (def->modules)
414 {
415 def_file_module *m = def->modules;
416 def->modules = def->modules->next;
417 free (m);
418 }
419
420 while (def->aligncomms)
421 {
422 def_file_aligncomm *c = def->aligncomms;
423 def->aligncomms = def->aligncomms->next;
424 free (c->symbol_name);
425 free (c);
426 }
427
428 free (def);
429 }
430
431 #ifdef DEF_FILE_PRINT
432 void
433 def_file_print (FILE *file, def_file *def)
434 {
435 int i;
436
437 fprintf (file, ">>>> def_file at 0x%08x\n", def);
438 if (def->name)
439 fprintf (file, " name: %s\n", def->name ? def->name : "(unspecified)");
440 if (def->is_dll != -1)
441 fprintf (file, " is dll: %s\n", def->is_dll ? "yes" : "no");
442 if (def->base_address != (bfd_vma) -1)
443 fprintf (file, " base address: 0x%08x\n", def->base_address);
444 if (def->description)
445 fprintf (file, " description: `%s'\n", def->description);
446 if (def->stack_reserve != -1)
447 fprintf (file, " stack reserve: 0x%08x\n", def->stack_reserve);
448 if (def->stack_commit != -1)
449 fprintf (file, " stack commit: 0x%08x\n", def->stack_commit);
450 if (def->heap_reserve != -1)
451 fprintf (file, " heap reserve: 0x%08x\n", def->heap_reserve);
452 if (def->heap_commit != -1)
453 fprintf (file, " heap commit: 0x%08x\n", def->heap_commit);
454
455 if (def->num_section_defs > 0)
456 {
457 fprintf (file, " section defs:\n");
458
459 for (i = 0; i < def->num_section_defs; i++)
460 {
461 fprintf (file, " name: `%s', class: `%s', flags:",
462 def->section_defs[i].name, def->section_defs[i].class);
463 if (def->section_defs[i].flag_read)
464 fprintf (file, " R");
465 if (def->section_defs[i].flag_write)
466 fprintf (file, " W");
467 if (def->section_defs[i].flag_execute)
468 fprintf (file, " X");
469 if (def->section_defs[i].flag_shared)
470 fprintf (file, " S");
471 fprintf (file, "\n");
472 }
473 }
474
475 if (def->num_exports > 0)
476 {
477 fprintf (file, " exports:\n");
478
479 for (i = 0; i < def->num_exports; i++)
480 {
481 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
482 def->exports[i].name, def->exports[i].internal_name,
483 def->exports[i].ordinal);
484 if (def->exports[i].flag_private)
485 fprintf (file, " P");
486 if (def->exports[i].flag_constant)
487 fprintf (file, " C");
488 if (def->exports[i].flag_noname)
489 fprintf (file, " N");
490 if (def->exports[i].flag_data)
491 fprintf (file, " D");
492 fprintf (file, "\n");
493 }
494 }
495
496 if (def->num_imports > 0)
497 {
498 fprintf (file, " imports:\n");
499
500 for (i = 0; i < def->num_imports; i++)
501 {
502 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
503 def->imports[i].internal_name,
504 def->imports[i].module,
505 def->imports[i].name,
506 def->imports[i].ordinal);
507 }
508 }
509
510 if (def->version_major != -1)
511 fprintf (file, " version: %d.%d\n", def->version_major, def->version_minor);
512
513 fprintf (file, "<<<< def_file at 0x%08x\n", def);
514 }
515 #endif
516
517 def_file_export *
518 def_file_add_export (def_file *def,
519 const char *external_name,
520 const char *internal_name,
521 int ordinal,
522 const char *its_name)
523 {
524 def_file_export *e;
525 int max_exports = ROUND_UP(def->num_exports, 32);
526
527 if (def->num_exports >= max_exports)
528 {
529 max_exports = ROUND_UP(def->num_exports + 1, 32);
530 if (def->exports)
531 def->exports = xrealloc (def->exports,
532 max_exports * sizeof (def_file_export));
533 else
534 def->exports = xmalloc (max_exports * sizeof (def_file_export));
535 }
536 e = def->exports + def->num_exports;
537 memset (e, 0, sizeof (def_file_export));
538 if (internal_name && !external_name)
539 external_name = internal_name;
540 if (external_name && !internal_name)
541 internal_name = external_name;
542 e->name = xstrdup (external_name);
543 e->internal_name = xstrdup (internal_name);
544 e->its_name = (its_name ? xstrdup (its_name) : NULL);
545 e->ordinal = ordinal;
546 def->num_exports++;
547 return e;
548 }
549
550 def_file_module *
551 def_get_module (def_file *def, const char *name)
552 {
553 def_file_module *s;
554
555 for (s = def->modules; s; s = s->next)
556 if (strcmp (s->name, name) == 0)
557 return s;
558
559 return NULL;
560 }
561
562 static def_file_module *
563 def_stash_module (def_file *def, const char *name)
564 {
565 def_file_module *s;
566
567 if ((s = def_get_module (def, name)) != NULL)
568 return s;
569 s = xmalloc (sizeof (def_file_module) + strlen (name));
570 s->next = def->modules;
571 def->modules = s;
572 s->user_data = 0;
573 strcpy (s->name, name);
574 return s;
575 }
576
577 def_file_import *
578 def_file_add_import (def_file *def,
579 const char *name,
580 const char *module,
581 int ordinal,
582 const char *internal_name,
583 const char *its_name)
584 {
585 def_file_import *i;
586 int max_imports = ROUND_UP (def->num_imports, 16);
587
588 if (def->num_imports >= max_imports)
589 {
590 max_imports = ROUND_UP (def->num_imports+1, 16);
591
592 if (def->imports)
593 def->imports = xrealloc (def->imports,
594 max_imports * sizeof (def_file_import));
595 else
596 def->imports = xmalloc (max_imports * sizeof (def_file_import));
597 }
598 i = def->imports + def->num_imports;
599 memset (i, 0, sizeof (def_file_import));
600 if (name)
601 i->name = xstrdup (name);
602 if (module)
603 i->module = def_stash_module (def, module);
604 i->ordinal = ordinal;
605 if (internal_name)
606 i->internal_name = xstrdup (internal_name);
607 else
608 i->internal_name = i->name;
609 i->its_name = (its_name ? xstrdup (its_name) : NULL);
610 def->num_imports++;
611
612 return i;
613 }
614
615 struct
616 {
617 char *param;
618 int token;
619 }
620 diropts[] =
621 {
622 { "-heap", HEAPSIZE },
623 { "-stack", STACKSIZE_K },
624 { "-attr", SECTIONS },
625 { "-export", EXPORTS },
626 { "-aligncomm", ALIGNCOMM },
627 { 0, 0 }
628 };
629
630 void
631 def_file_add_directive (def_file *my_def, const char *param, int len)
632 {
633 def_file *save_def = def;
634 const char *pend = param + len;
635 char * tend = (char *) param;
636 int i;
637
638 def = my_def;
639
640 while (param < pend)
641 {
642 while (param < pend
643 && (ISSPACE (*param) || *param == '\n' || *param == 0))
644 param++;
645
646 if (param == pend)
647 break;
648
649 /* Scan forward until we encounter any of:
650 - the end of the buffer
651 - the start of a new option
652 - a newline seperating options
653 - a NUL seperating options. */
654 for (tend = (char *) (param + 1);
655 (tend < pend
656 && !(ISSPACE (tend[-1]) && *tend == '-')
657 && *tend != '\n' && *tend != 0);
658 tend++)
659 ;
660
661 for (i = 0; diropts[i].param; i++)
662 {
663 int len = strlen (diropts[i].param);
664
665 if (tend - param >= len
666 && strncmp (param, diropts[i].param, len) == 0
667 && (param[len] == ':' || param[len] == ' '))
668 {
669 lex_parse_string_end = tend;
670 lex_parse_string = param + len + 1;
671 lex_forced_token = diropts[i].token;
672 saw_newline = 0;
673 if (def_parse ())
674 continue;
675 break;
676 }
677 }
678
679 if (!diropts[i].param)
680 {
681 char saved;
682
683 saved = * tend;
684 * tend = 0;
685 /* xgettext:c-format */
686 einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
687 * tend = saved;
688 }
689
690 lex_parse_string = 0;
691 param = tend;
692 }
693
694 def = save_def;
695 }
696
697 /* Parser Callbacks. */
698
699 static void
700 def_image_name (const char *name, int base, int is_dll)
701 {
702 /* If a LIBRARY or NAME statement is specified without a name, there is nothing
703 to do here. We retain the output filename specified on command line. */
704 if (*name)
705 {
706 const char* image_name = lbasename (name);
707 if (image_name != name)
708 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
709 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
710 name);
711 if (def->name)
712 free (def->name);
713 /* Append the default suffix, if none specified. */
714 if (strchr (image_name, '.') == 0)
715 {
716 const char * suffix = is_dll ? ".dll" : ".exe";
717
718 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
719 sprintf (def->name, "%s%s", image_name, suffix);
720 }
721 else
722 def->name = xstrdup (image_name);
723 }
724
725 /* Honor a BASE address statement, even if LIBRARY string is empty. */
726 def->base_address = base;
727 def->is_dll = is_dll;
728 }
729
730 static void
731 def_description (const char *text)
732 {
733 int len = def->description ? strlen (def->description) : 0;
734
735 len += strlen (text) + 1;
736 if (def->description)
737 {
738 def->description = xrealloc (def->description, len);
739 strcat (def->description, text);
740 }
741 else
742 {
743 def->description = xmalloc (len);
744 strcpy (def->description, text);
745 }
746 }
747
748 static void
749 def_stacksize (int reserve, int commit)
750 {
751 def->stack_reserve = reserve;
752 def->stack_commit = commit;
753 }
754
755 static void
756 def_heapsize (int reserve, int commit)
757 {
758 def->heap_reserve = reserve;
759 def->heap_commit = commit;
760 }
761
762 static void
763 def_section (const char *name, int attr)
764 {
765 def_file_section *s;
766 int max_sections = ROUND_UP (def->num_section_defs, 4);
767
768 if (def->num_section_defs >= max_sections)
769 {
770 max_sections = ROUND_UP (def->num_section_defs+1, 4);
771
772 if (def->section_defs)
773 def->section_defs = xrealloc (def->section_defs,
774 max_sections * sizeof (def_file_import));
775 else
776 def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
777 }
778 s = def->section_defs + def->num_section_defs;
779 memset (s, 0, sizeof (def_file_section));
780 s->name = xstrdup (name);
781 if (attr & 1)
782 s->flag_read = 1;
783 if (attr & 2)
784 s->flag_write = 1;
785 if (attr & 4)
786 s->flag_execute = 1;
787 if (attr & 8)
788 s->flag_shared = 1;
789
790 def->num_section_defs++;
791 }
792
793 static void
794 def_section_alt (const char *name, const char *attr)
795 {
796 int aval = 0;
797
798 for (; *attr; attr++)
799 {
800 switch (*attr)
801 {
802 case 'R':
803 case 'r':
804 aval |= 1;
805 break;
806 case 'W':
807 case 'w':
808 aval |= 2;
809 break;
810 case 'X':
811 case 'x':
812 aval |= 4;
813 break;
814 case 'S':
815 case 's':
816 aval |= 8;
817 break;
818 }
819 }
820 def_section (name, aval);
821 }
822
823 static void
824 def_exports (const char *external_name,
825 const char *internal_name,
826 int ordinal,
827 int flags,
828 const char *its_name)
829 {
830 def_file_export *dfe;
831
832 if (!internal_name && external_name)
833 internal_name = external_name;
834 #if TRACE
835 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
836 #endif
837
838 dfe = def_file_add_export (def, external_name, internal_name, ordinal,
839 its_name);
840 if (flags & 1)
841 dfe->flag_noname = 1;
842 if (flags & 2)
843 dfe->flag_constant = 1;
844 if (flags & 4)
845 dfe->flag_data = 1;
846 if (flags & 8)
847 dfe->flag_private = 1;
848 }
849
850 static void
851 def_import (const char *internal_name,
852 const char *module,
853 const char *dllext,
854 const char *name,
855 int ordinal,
856 const char *its_name)
857 {
858 char *buf = 0;
859 const char *ext = dllext ? dllext : "dll";
860
861 buf = xmalloc (strlen (module) + strlen (ext) + 2);
862 sprintf (buf, "%s.%s", module, ext);
863 module = buf;
864
865 def_file_add_import (def, name, module, ordinal, internal_name, its_name);
866 if (buf)
867 free (buf);
868 }
869
870 static void
871 def_version (int major, int minor)
872 {
873 def->version_major = major;
874 def->version_minor = minor;
875 }
876
877 static void
878 def_directive (char *str)
879 {
880 struct directive *d = xmalloc (sizeof (struct directive));
881
882 d->next = directives;
883 directives = d;
884 d->name = xstrdup (str);
885 d->len = strlen (str);
886 }
887
888 static void
889 def_aligncomm (char *str, int align)
890 {
891 def_file_aligncomm *c = xmalloc (sizeof (def_file_aligncomm));
892
893 c->symbol_name = xstrdup (str);
894 c->alignment = (unsigned int) align;
895
896 c->next = def->aligncomms;
897 def->aligncomms = c;
898 }
899
900 static int
901 def_error (const char *err)
902 {
903 einfo ("%P: %s:%d: %s\n",
904 def_filename ? def_filename : "<unknown-file>", linenumber, err);
905 return 0;
906 }
907
908
909 /* Lexical Scanner. */
910
911 #undef TRACE
912 #define TRACE 0
913
914 /* Never freed, but always reused as needed, so no real leak. */
915 static char *buffer = 0;
916 static int buflen = 0;
917 static int bufptr = 0;
918
919 static void
920 put_buf (char c)
921 {
922 if (bufptr == buflen)
923 {
924 buflen += 50; /* overly reasonable, eh? */
925 if (buffer)
926 buffer = xrealloc (buffer, buflen + 1);
927 else
928 buffer = xmalloc (buflen + 1);
929 }
930 buffer[bufptr++] = c;
931 buffer[bufptr] = 0; /* not optimal, but very convenient. */
932 }
933
934 static struct
935 {
936 char *name;
937 int token;
938 }
939 tokens[] =
940 {
941 { "BASE", BASE },
942 { "CODE", CODE },
943 { "CONSTANT", CONSTANTU },
944 { "constant", CONSTANTL },
945 { "DATA", DATAU },
946 { "data", DATAL },
947 { "DESCRIPTION", DESCRIPTION },
948 { "DIRECTIVE", DIRECTIVE },
949 { "EXECUTE", EXECUTE },
950 { "EXPORTS", EXPORTS },
951 { "HEAPSIZE", HEAPSIZE },
952 { "IMPORTS", IMPORTS },
953 { "LIBRARY", LIBRARY },
954 { "NAME", NAME },
955 { "NONAME", NONAMEU },
956 { "noname", NONAMEL },
957 { "PRIVATE", PRIVATEU },
958 { "private", PRIVATEL },
959 { "READ", READ },
960 { "SECTIONS", SECTIONS },
961 { "SEGMENTS", SECTIONS },
962 { "SHARED", SHARED },
963 { "STACKSIZE", STACKSIZE_K },
964 { "VERSION", VERSIONK },
965 { "WRITE", WRITE },
966 { 0, 0 }
967 };
968
969 static int
970 def_getc (void)
971 {
972 int rv;
973
974 if (lex_parse_string)
975 {
976 if (lex_parse_string >= lex_parse_string_end)
977 rv = EOF;
978 else
979 rv = *lex_parse_string++;
980 }
981 else
982 {
983 rv = fgetc (the_file);
984 }
985 if (rv == '\n')
986 saw_newline = 1;
987 return rv;
988 }
989
990 static int
991 def_ungetc (int c)
992 {
993 if (lex_parse_string)
994 {
995 lex_parse_string--;
996 return c;
997 }
998 else
999 return ungetc (c, the_file);
1000 }
1001
1002 static int
1003 def_lex (void)
1004 {
1005 int c, i, q;
1006
1007 if (lex_forced_token)
1008 {
1009 i = lex_forced_token;
1010 lex_forced_token = 0;
1011 #if TRACE
1012 printf ("lex: forcing token %d\n", i);
1013 #endif
1014 return i;
1015 }
1016
1017 c = def_getc ();
1018
1019 /* Trim leading whitespace. */
1020 while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
1021 c = def_getc ();
1022
1023 if (c == EOF)
1024 {
1025 #if TRACE
1026 printf ("lex: EOF\n");
1027 #endif
1028 return 0;
1029 }
1030
1031 if (saw_newline && c == ';')
1032 {
1033 do
1034 {
1035 c = def_getc ();
1036 }
1037 while (c != EOF && c != '\n');
1038 if (c == '\n')
1039 return def_lex ();
1040 return 0;
1041 }
1042
1043 /* Must be something else. */
1044 saw_newline = 0;
1045
1046 if (ISDIGIT (c))
1047 {
1048 bufptr = 0;
1049 while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
1050 {
1051 put_buf (c);
1052 c = def_getc ();
1053 }
1054 if (c != EOF)
1055 def_ungetc (c);
1056 yylval.digits = xstrdup (buffer);
1057 #if TRACE
1058 printf ("lex: `%s' returns DIGITS\n", buffer);
1059 #endif
1060 return DIGITS;
1061 }
1062
1063 if (ISALPHA (c) || strchr ("$:-_?@", c))
1064 {
1065 bufptr = 0;
1066 q = c;
1067 put_buf (c);
1068 c = def_getc ();
1069
1070 if (q == '@')
1071 {
1072 if (ISBLANK (c) ) /* '@' followed by whitespace. */
1073 return (q);
1074 else if (ISDIGIT (c)) /* '@' followed by digit. */
1075 {
1076 def_ungetc (c);
1077 return (q);
1078 }
1079 #if TRACE
1080 printf ("lex: @ returns itself\n");
1081 #endif
1082 }
1083
1084 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
1085 {
1086 put_buf (c);
1087 c = def_getc ();
1088 }
1089 if (c != EOF)
1090 def_ungetc (c);
1091 if (ISALPHA (q)) /* Check for tokens. */
1092 {
1093 for (i = 0; tokens[i].name; i++)
1094 if (strcmp (tokens[i].name, buffer) == 0)
1095 {
1096 #if TRACE
1097 printf ("lex: `%s' is a string token\n", buffer);
1098 #endif
1099 return tokens[i].token;
1100 }
1101 }
1102 #if TRACE
1103 printf ("lex: `%s' returns ID\n", buffer);
1104 #endif
1105 yylval.id = xstrdup (buffer);
1106 return ID;
1107 }
1108
1109 if (c == '\'' || c == '"')
1110 {
1111 q = c;
1112 c = def_getc ();
1113 bufptr = 0;
1114
1115 while (c != EOF && c != q)
1116 {
1117 put_buf (c);
1118 c = def_getc ();
1119 }
1120 yylval.id = xstrdup (buffer);
1121 #if TRACE
1122 printf ("lex: `%s' returns ID\n", buffer);
1123 #endif
1124 return ID;
1125 }
1126
1127 if ( c == '=')
1128 {
1129 c = def_getc ();
1130 if (c == '=')
1131 {
1132 #if TRACE
1133 printf ("lex: `==' returns EQUAL\n");
1134 #endif
1135 return EQUAL;
1136 }
1137 def_ungetc (c);
1138 #if TRACE
1139 printf ("lex: `=' returns itself\n");
1140 #endif
1141 return '=';
1142 }
1143 if (c == '.' || c == ',')
1144 {
1145 #if TRACE
1146 printf ("lex: `%c' returns itself\n", c);
1147 #endif
1148 return c;
1149 }
1150
1151 if (c == '\n')
1152 {
1153 linenumber++;
1154 saw_newline = 1;
1155 }
1156
1157 /*printf ("lex: 0x%02x ignored\n", c); */
1158 return def_lex ();
1159 }