1 %
{/* nlmheader.y - parse NLM header specification keywords.
2 Copyright 1993, 1994, 1995, 1997, 1998, 2001, 2002, 2003, 2007
3 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
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.
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.
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. */
22 /* Written by Ian Lance Taylor <ian@cygnus.com>.
24 This bison file parses the commands recognized by the NetWare NLM
25 linker, except for lists of object files. It stores the
26 information in global variables.
28 This implementation is based on the description in the NetWare Tool
29 Maker Specification manual, edition 1.0. */
32 #include "safe-ctype.h"
34 #include "nlm/common.h"
35 #include "nlm/internal.h"
39 /* Information is stored in the structures pointed to by these
42 Nlm_Internal_Fixed_Header
*fixed_hdr
;
43 Nlm_Internal_Variable_Header
*var_hdr
;
44 Nlm_Internal_Version_Header
*version_hdr
;
45 Nlm_Internal_Copyright_Header
*copyright_hdr
;
46 Nlm_Internal_Extended_Header
*extended_hdr
;
48 /* Procedure named by CHECK. */
49 char *check_procedure
;
50 /* File named by CUSTOM. */
52 /* Whether to generate debugging information (DEBUG). */
53 bfd_boolean debug_info
;
54 /* Procedure named by EXIT. */
56 /* Exported symbols (EXPORT). */
57 struct string_list
*export_symbols
;
58 /* List of files from INPUT. */
59 struct string_list
*input_files
;
60 /* Map file name (MAP, FULLMAP). */
62 /* Whether a full map has been requested (FULLMAP). */
64 /* File named by HELP. */
66 /* Imported symbols (IMPORT). */
67 struct string_list
*import_symbols
;
68 /* File named by MESSAGES. */
70 /* Autoload module list (MODULE). */
71 struct string_list
*modules
;
72 /* File named by OUTPUT. */
74 /* File named by SHARELIB. */
76 /* Start procedure name (START). */
77 char *start_procedure
;
80 /* RPC description file (XDCDATA). */
83 /* The number of serious errors that have occurred. */
86 /* The current symbol prefix when reading a list of import or export
88 static char *symbol_prefix
;
90 /* Parser error message handler. */
91 #define yyerror(msg) nlmheader_error (msg);
93 /* Local functions. */
94 static int yylex (void);
95 static void nlmlex_file_push
(const char *);
96 static bfd_boolean nlmlex_file_open
(const char *);
97 static int nlmlex_buf_init
(void);
98 static char nlmlex_buf_add
(int);
99 static long nlmlex_get_number
(const char *);
100 static void nlmheader_identify
(void);
101 static void nlmheader_warn
(const char *, int);
102 static void nlmheader_error
(const char *);
103 static struct string_list
* string_list_cons
(char *, struct string_list
*);
104 static struct string_list
* string_list_append
(struct string_list
*,
105 struct string_list
*);
106 static struct string_list
* string_list_append1
(struct string_list
*,
108 static char *xstrdup
(const char *);
115 struct string_list
*list
;
118 /* The reserved words. */
120 %token CHECK CODESTART COPYRIGHT CUSTOM DATE DEBUG DESCRIPTION EXIT
121 %token EXPORT FLAG_ON FLAG_OFF FULLMAP HELP IMPORT INPUT MAP MESSAGES
122 %token MODULE MULTIPLE OS_DOMAIN OUTPUT PSEUDOPREEMPTION REENTRANT
123 %token SCREENNAME SHARELIB STACK START SYNCHRONIZE
124 %token THREADNAME TYPE VERBOSE VERSIONK XDCDATA
128 %token
<string> STRING
129 %token
<string> QUOTED_STRING
131 /* Typed non-terminals. */
132 %type
<list
> symbol_list_opt symbol_list string_list
133 %type
<string> symbol
137 /* Keywords must start in the leftmost column of the file. Arguments
138 may appear anywhere else. The lexer uses this to determine what
139 token to return, so we don't have to worry about it here. */
141 /* The entire file is just a list of commands. */
147 /* A possibly empty list of commands. */
154 /* A single command. There is where most of the work takes place. */
159 check_procedure
= $2;
163 nlmheader_warn
(_
("CODESTART is not implemented; sorry"), -1);
166 | COPYRIGHT QUOTED_STRING
170 strncpy
(copyright_hdr
->stamp
, "CoPyRiGhT=", 10);
172 if
(len
>= NLM_MAX_COPYRIGHT_MESSAGE_LENGTH
)
174 nlmheader_warn
(_
("copyright string is too long"),
175 NLM_MAX_COPYRIGHT_MESSAGE_LENGTH
- 1);
176 len
= NLM_MAX_COPYRIGHT_MESSAGE_LENGTH
- 1;
178 copyright_hdr
->copyrightMessageLength
= len
;
179 strncpy
(copyright_hdr
->copyrightMessage
, $2, len
);
180 copyright_hdr
->copyrightMessage
[len
] = '\0';
187 | DATE STRING STRING STRING
189 /* We don't set the version stamp here, because we use the
190 version stamp to detect whether the required VERSION
191 keyword was given. */
192 version_hdr
->month
= nlmlex_get_number
($2);
193 version_hdr
->day
= nlmlex_get_number
($3);
194 version_hdr
->year
= nlmlex_get_number
($4);
198 if
(version_hdr
->month
< 1 || version_hdr
->month
> 12)
199 nlmheader_warn
(_
("illegal month"), -1);
200 if
(version_hdr
->day
< 1 || version_hdr
->day
> 31)
201 nlmheader_warn
(_
("illegal day"), -1);
202 if
(version_hdr
->year
< 1900 || version_hdr
->year
> 3000)
203 nlmheader_warn
(_
("illegal year"), -1);
209 | DESCRIPTION QUOTED_STRING
214 if
(len
> NLM_MAX_DESCRIPTION_LENGTH
)
216 nlmheader_warn
(_
("description string is too long"),
217 NLM_MAX_DESCRIPTION_LENGTH
);
218 len
= NLM_MAX_DESCRIPTION_LENGTH
;
220 var_hdr
->descriptionLength
= len
;
221 strncpy
(var_hdr
->descriptionText
, $2, len
);
222 var_hdr
->descriptionText
[len
] = '\0';
231 symbol_prefix
= NULL
;
235 export_symbols
= string_list_append
(export_symbols
, $3);
239 fixed_hdr
->flags |
= nlmlex_get_number
($2);
244 fixed_hdr
->flags
&=~ nlmlex_get_number
($2);
263 symbol_prefix
= NULL
;
267 import_symbols
= string_list_append
(import_symbols
, $3);
271 input_files
= string_list_append
(input_files
, $2);
287 modules
= string_list_append
(modules
, $2);
291 fixed_hdr
->flags |
= 0x2;
295 fixed_hdr
->flags |
= 0x10;
299 if
(output_file
== NULL
)
302 nlmheader_warn
(_
("ignoring duplicate OUTPUT statement"), -1);
306 fixed_hdr
->flags |
= 0x8;
310 fixed_hdr
->flags |
= 0x1;
312 | SCREENNAME QUOTED_STRING
317 if
(len
>= NLM_MAX_SCREEN_NAME_LENGTH
)
319 nlmheader_warn
(_
("screen name is too long"),
320 NLM_MAX_SCREEN_NAME_LENGTH
);
321 len
= NLM_MAX_SCREEN_NAME_LENGTH
;
323 var_hdr
->screenNameLength
= len
;
324 strncpy
(var_hdr
->screenName
, $2, len
);
325 var_hdr
->screenName
[NLM_MAX_SCREEN_NAME_LENGTH
] = '\0';
334 var_hdr
->stackSize
= nlmlex_get_number
($2);
339 start_procedure
= $2;
343 fixed_hdr
->flags |
= 0x4;
345 | THREADNAME QUOTED_STRING
350 if
(len
>= NLM_MAX_THREAD_NAME_LENGTH
)
352 nlmheader_warn
(_
("thread name is too long"),
353 NLM_MAX_THREAD_NAME_LENGTH
);
354 len
= NLM_MAX_THREAD_NAME_LENGTH
;
356 var_hdr
->threadNameLength
= len
;
357 strncpy
(var_hdr
->threadName
, $2, len
);
358 var_hdr
->threadName
[len
] = '\0';
363 fixed_hdr
->moduleType
= nlmlex_get_number
($2);
370 | VERSIONK STRING STRING STRING
374 strncpy
(version_hdr
->stamp
, "VeRsIoN#", 8);
375 version_hdr
->majorVersion
= nlmlex_get_number
($2);
376 val
= nlmlex_get_number
($3);
377 if
(val
< 0 || val
> 99)
378 nlmheader_warn
(_
("illegal minor version number (must be between 0 and 99)"),
381 version_hdr
->minorVersion
= val
;
382 val
= nlmlex_get_number
($4);
384 nlmheader_warn
(_
("illegal revision number (must be between 0 and 26)"),
387 version_hdr
->revision
= 0;
389 version_hdr
->revision
= val
;
394 | VERSIONK STRING STRING
398 strncpy
(version_hdr
->stamp
, "VeRsIoN#", 8);
399 version_hdr
->majorVersion
= nlmlex_get_number
($2);
400 val
= nlmlex_get_number
($3);
401 if
(val
< 0 || val
> 99)
402 nlmheader_warn
(_
("illegal minor version number (must be between 0 and 99)"),
405 version_hdr
->minorVersion
= val
;
406 version_hdr
->revision
= 0;
416 /* A possibly empty list of symbols. */
429 /* A list of symbols in an import or export list. Prefixes may appear
430 in parentheses. We need to use left recursion here to avoid
431 building up a large import list on the parser stack. */
436 $$
= string_list_cons
($1, NULL
);
444 $$
= string_list_append1
($1, $2);
446 | symbol_list symbol_prefix
452 /* A prefix for subsequent symbols. */
457 if
(symbol_prefix
!= NULL
)
458 free
(symbol_prefix
);
463 /* A single symbol. */
468 if
(symbol_prefix
== NULL
)
472 $$
= xmalloc
(strlen
(symbol_prefix
) + strlen
($1) + 2);
473 sprintf
($$
, "%s@%s", symbol_prefix
, $1);
479 /* A list of strings. */
488 $$
= string_list_cons
($1, $2);
494 /* If strerror is just a macro, we want to use the one from libiberty
495 since it will handle undefined values. */
497 extern
char *strerror PARAMS
((int));
499 /* The lexer is simple, too simple for flex. Keywords are only
500 recognized at the start of lines. Everything else must be an
501 argument. A comma is treated as whitespace. */
503 /* The states the lexer can be in. */
507 /* At the beginning of a line. */
509 /* In the middle of a line. */
513 /* We need to keep a stack of files to handle file inclusion. */
517 /* The file to read from. */
519 /* The name of the file. */
521 /* The current line number. */
523 /* The current state. */
524 enum lex_state state
;
525 /* The next file on the stack. */
529 /* The current input file. */
531 static struct input current
;
533 /* The character which introduces comments. */
534 #define COMMENT_CHAR '#'
536 /* Start the lexer going on the main input file. */
539 nlmlex_file
(const char *name
)
542 return nlmlex_file_open
(name
);
545 /* Start the lexer going on a subsidiary input file. */
548 nlmlex_file_push
(const char *name
)
552 push
= (struct input
*) xmalloc
(sizeof
(struct input
));
554 if
(nlmlex_file_open
(name
))
563 /* Start lexing from a file. */
566 nlmlex_file_open
(const char *name
)
568 current.file
= fopen
(name
, "r");
569 if
(current.file
== NULL
)
571 fprintf
(stderr
, "%s:%s: %s\n", program_name
, name
, strerror
(errno
));
575 current.name
= xstrdup
(name
);
577 current.state
= BEGINNING_OF_LINE
;
581 /* Table used to turn keywords into tokens. */
583 struct keyword_tokens_struct
589 static struct keyword_tokens_struct keyword_tokens
[] =
592 { "CODESTART", CODESTART
},
593 { "COPYRIGHT", COPYRIGHT
},
594 { "CUSTOM", CUSTOM
},
597 { "DESCRIPTION", DESCRIPTION
},
599 { "EXPORT", EXPORT
},
600 { "FLAG_ON", FLAG_ON
},
601 { "FLAG_OFF", FLAG_OFF
},
602 { "FULLMAP", FULLMAP
},
604 { "IMPORT", IMPORT
},
607 { "MESSAGES", MESSAGES
},
608 { "MODULE", MODULE
},
609 { "MULTIPLE", MULTIPLE
},
610 { "OS_DOMAIN", OS_DOMAIN
},
611 { "OUTPUT", OUTPUT
},
612 { "PSEUDOPREEMPTION", PSEUDOPREEMPTION
},
613 { "REENTRANT", REENTRANT
},
614 { "SCREENNAME", SCREENNAME
},
615 { "SHARELIB", SHARELIB
},
617 { "STACKSIZE", STACK
},
619 { "SYNCHRONIZE", SYNCHRONIZE
},
620 { "THREADNAME", THREADNAME
},
622 { "VERBOSE", VERBOSE
},
623 { "VERSION", VERSIONK
},
624 { "XDCDATA", XDCDATA
}
627 #define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0]))
629 /* The lexer accumulates strings in these variables. */
630 static char *lex_buf
;
634 /* Start accumulating strings into the buffer. */
636 ((void) (lex_buf
!= NULL ? lex_pos
= 0 : nlmlex_buf_init
()))
639 nlmlex_buf_init
(void)
642 lex_buf
= xmalloc
(lex_size
+ 1);
647 /* Finish a string in the buffer. */
648 #define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0'))
650 /* Accumulate a character into the buffer. */
652 ((void) (lex_pos
< lex_size \
653 ? lex_buf
[lex_pos
++] = (c
) \
654 : nlmlex_buf_add
(c
)))
657 nlmlex_buf_add
(int c
)
659 if
(lex_pos
>= lex_size
)
662 lex_buf
= xrealloc
(lex_buf
, lex_size
+ 1);
665 return lex_buf
[lex_pos
++] = c
;
668 /* The lexer proper. This is called by the bison generated parsing
678 c
= getc
(current.file
);
680 /* Commas are treated as whitespace characters. */
681 while
(ISSPACE
(c
) || c
== ',')
683 current.state
= IN_LINE
;
687 current.state
= BEGINNING_OF_LINE
;
689 c
= getc
(current.file
);
692 /* At the end of the file we either pop to the previous file or
696 fclose
(current.file
);
698 if
(current.next
== NULL
)
711 /* A comment character always means to drop everything until the
713 if
(c
== COMMENT_CHAR
)
717 c
= getc
(current.file
);
721 current.state
= BEGINNING_OF_LINE
;
725 /* An '@' introduces an include file. */
730 c
= getc
(current.file
);
736 while
(! ISSPACE
(c
) && c
!= EOF
)
739 c
= getc
(current.file
);
743 ungetc
(c
, current.file
);
745 nlmlex_file_push
(lex_buf
);
749 /* A non-space character at the start of a line must be the start of
751 if
(current.state
== BEGINNING_OF_LINE
)
754 while
(ISALNUM
(c
) || c
== '_')
756 BUF_ADD
(TOUPPER
(c
));
757 c
= getc
(current.file
);
761 if
(c
!= EOF
&& ! ISSPACE
(c
) && c
!= ',')
763 nlmheader_identify
();
764 fprintf
(stderr
, _
("%s:%d: illegal character in keyword: %c\n"),
765 current.name
, current.lineno
, c
);
771 for
(i
= 0; i
< KEYWORD_COUNT
; i
++)
773 if
(lex_buf
[0] == keyword_tokens
[i
].keyword
[0]
774 && strcmp
(lex_buf
, keyword_tokens
[i
].keyword
) == 0)
776 /* Pushing back the final whitespace avoids worrying
778 ungetc
(c
, current.file
);
779 current.state
= IN_LINE
;
780 return keyword_tokens
[i
].token
;
784 nlmheader_identify
();
785 fprintf
(stderr
, _
("%s:%d: unrecognized keyword: %s\n"),
786 current.name
, current.lineno
, lex_buf
);
790 /* Treat the rest of this line as a comment. */
791 ungetc
(COMMENT_CHAR
, current.file
);
795 /* Parentheses just represent themselves. */
796 if
(c
== '(' || c
== ')')
799 /* Handle quoted strings. */
800 if
(c
== '"' || c
== '\'')
806 start_lineno
= current.lineno
;
808 c
= getc
(current.file
);
810 while
(c
!= quote
&& c
!= EOF
)
815 c
= getc
(current.file
);
821 nlmheader_identify
();
822 fprintf
(stderr
, _
("%s:%d: end of file in quoted string\n"),
823 current.name
, start_lineno
);
827 /* FIXME: Possible memory leak. */
828 yylval.
string = xstrdup
(lex_buf
);
829 return QUOTED_STRING
;
832 /* Gather a generic argument. */
841 c
= getc
(current.file
);
845 ungetc
(c
, current.file
);
847 /* FIXME: Possible memory leak. */
848 yylval.
string = xstrdup
(lex_buf
);
852 /* Get a number from a string. */
855 nlmlex_get_number
(const char *s
)
860 ret
= strtol
(s
, &send
, 10);
862 nlmheader_warn
(_
("bad number"), -1);
866 /* Prefix the nlmconv warnings with a note as to where they come from.
867 We don't use program_name on every warning, because then some
868 versions of the emacs next-error function can't recognize the line
872 nlmheader_identify
(void)
878 fprintf
(stderr
, _
("%s: problems in NLM command language input:\n"),
884 /* Issue a warning. */
887 nlmheader_warn
(const char *s
, int imax
)
889 nlmheader_identify
();
890 fprintf
(stderr
, "%s:%d: %s", current.name
, current.lineno
, s
);
892 fprintf
(stderr
, " (max %d)", imax
);
893 fprintf
(stderr
, "\n");
896 /* Report an error. */
899 nlmheader_error
(const char *s
)
901 nlmheader_warn
(s
, -1);
905 /* Add a string to a string list. */
907 static struct string_list
*
908 string_list_cons
(char *s
, struct string_list
*l
)
910 struct string_list
*ret
;
912 ret
= (struct string_list
*) xmalloc
(sizeof
(struct string_list
));
918 /* Append a string list to another string list. */
920 static struct string_list
*
921 string_list_append
(struct string_list
*l1
, struct string_list
*l2
)
923 register
struct string_list
**pp
;
925 for
(pp
= &l1
; *pp
!= NULL
; pp
= &(*pp
)->next
)
931 /* Append a string to a string list. */
933 static struct string_list
*
934 string_list_append1
(struct string_list
*l
, char *s
)
936 struct string_list
*n
;
937 register
struct string_list
**pp
;
939 n
= (struct string_list
*) xmalloc
(sizeof
(struct string_list
));
942 for
(pp
= &l
; *pp
!= NULL
; pp
= &(*pp
)->next
)
948 /* Duplicate a string in memory. */
951 xstrdup
(const char *s
)
957 ret
= xmalloc
(len
+ 1);