2 /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2001.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 elfutils is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
37 /* We sure use no threads to read the stream, so use the _unlocked
38 variants of the functions. */
40 #define getc(s) getc_unlocked (s)
42 #define ferror(s) ferror_unlocked (s)
44 #define fread(b, m, n, s) fread_unlocked (b, m, n, s)
46 #define fwrite(b, m, n, s) fwrite_unlocked (b, m, n, s)
48 /* ECHO must be redefined since the default implementation ignores
49 the return value of fwrite_unlocked. */
50 #define ECHO do { size_t n__ __attribute__ ((unused)) \
51 = fwrite (yytext, yyleng, 1, yyout); } while (0)
53 /* Defined in ld.c. */
54 extern int ld_scan_version_script;
56 #define MAX_PREPDEPTH 20
62 } prepstate[MAX_PREPDEPTH];
65 static void eat_comment (void);
66 static void eat_to_eol (bool empty);
67 static int attrib_convert (int c);
68 static void push_state (enum prepstate);
69 static int pop_state (void);
70 static int handle_ifdef (void);
71 static void invalid_char (int ch);
74 ID [a-zA-Z0-9_.*?][a-zA-Z0-9_.*?-]*
75 FILENAMECHAR1 [a-zA-Z0-9_/.\\~]
76 FILENAMECHAR [^][{}[:space:]():;]+
77 HEX 0[xX][0-9a-fA-F]+[kKmM]?
83 %option never-interactive
89 if (unlikely (ld_scan_version_script))
91 ld_scan_version_script = -1;
92 return kVERSION_SCRIPT;
95 ^"#"ifdef/[[:space:]] { BEGIN (handle_ifdef ()); }
96 ^"#"else/[[:space:]\n] { eat_to_eol (true);
97 push_state (skip_to_endif);
99 ^"#"elifdef/[[:space:]] { eat_to_eol (false);
100 push_state (skip_to_endif);
102 ^"#"endif/[[:space:]\n] { eat_to_eol (true) ; }
104 <IGNORE>^"#"ifdef/[[:space:]\n] { eat_to_eol (false);
105 push_state (skip_to_endif); }
106 <IGNORE>^"#"else/[[:space:]\n] { eat_to_eol (true);
107 assert (prepdepth > 0);
108 if (prepstate[prepdepth - 1] == skip_if)
110 /* Back to normal processing. */
111 assert (prepdepth == 1);
112 BEGIN (pop_state ());
115 <IGNORE>^"#"elifdef/[[:space:]] { assert (prepdepth > 0);
116 if (prepstate[prepdepth - 1] == skip_if)
118 /* Maybe this symbol is defined. */
120 BEGIN (handle_ifdef ());
123 <IGNORE>^"#"endif/[[:space:]\n] { eat_to_eol (true);
124 BEGIN (pop_state ()); }
125 <IGNORE>.|\n { /* nothing */ }
128 "/*" { eat_comment (); }
130 ALIGN { return kALIGN; }
131 AS_NEEDED { return kAS_NEEDED; }
132 ENTRY { return kENTRY; }
133 EXCLUDE_FILE { return kEXCLUDE_FILE; }
134 "global:" { return kGLOBAL; }
135 GROUP { return kGROUP; }
136 INPUT { return kINPUT; }
137 INTERP { return kINTERP; }
138 KEEP { return kKEEP; }
139 "local:" { return kLOCAL; }
140 OUTPUT_FORMAT { return kOUTPUT_FORMAT; }
141 PAGESIZE { return kPAGESIZE; }
142 PROVIDE { return kPROVIDE; }
143 SEARCH_DIR { return kSEARCH_DIR; }
144 SEGMENT { return kSEGMENT; }
145 SIZEOF_HEADERS { return kSIZEOF_HEADERS; }
146 SORT { return kSORT; }
147 VERSION { return kVERSION; }
149 "["([RWX]){0,3}"]" { int cnt = 1 ;
151 while (cnt < yyleng - 1)
152 ldlval.num |= attrib_convert (yytext[cnt++]);
162 "+" { ldlval.op = exp_plus; return kADD_OP; }
163 "-" { ldlval.op = exp_minus; return kADD_OP; }
165 "/" { ldlval.op = exp_div; return kMUL_OP; }
166 "%" { ldlval.op = exp_mod; return kMUL_OP; }
172 {HEX}|{OCT}|{DEC} { char *endp;
173 ldlval.num = strtoumax (yytext, &endp, 0);
176 if (tolower (*endp) == 'k')
180 assert (tolower (*endp) == 'm');
181 ldlval.num *= 1024 * 1024;
186 {ID} { ldlval.str = obstack_strndup (&ld_state.smem,
190 {FILENAMECHAR1}{FILENAMECHAR} { ldlval.str = obstack_strndup (&ld_state.smem,
194 {WHITE} { /* IGNORE */ }
196 . { invalid_char (*yytext); }
207 while (c != '*' && c != EOF)
221 /* XXX Use the setjmp buffer and signal EOF in comment */
222 error (0, 0, gettext ("EOF in comment"));
230 eat_to_eol (bool empty)
246 if (empty && ! isspace (c) && ! warned)
248 error (0, 0, gettext ("%d: garbage at end of line"), yylineno);
256 attrib_convert (int c)
268 push_state (enum prepstate state)
270 if (prepdepth >= MAX_PREPDEPTH)
271 error (EXIT_FAILURE, 0, gettext ("%d: conditionals nested too deep"),
274 prepstate[prepdepth++] = state;
282 error (0, 0, gettext ("%d: unexpected #endif"), yylineno);
286 return prepdepth == 0 ? INITIAL : IGNORE;
296 size_t idmax = sizeof (idbuf);
297 bool ignore_ws = true;
298 bool defined = false;
305 if (isspace (c) && ignore_ws)
308 if (c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z')
309 && (idlen == 0 || c < '0' || c > '9'))
317 char *newp = (char *) alloca (idmax *= 2);
318 id = memcpy (newp, id, idlen);
325 /* XXX Compare in a better way. */
326 if (idlen == 6 && strncmp (id, "SHARED", 6) == 0)
327 defined = ld_state.file_type == dso_file_type;
333 push_state (skip_if);
342 invalid_char (int ch)
344 error (0, 0, (isascii (ch)
345 ? gettext ("invalid character '%c' at line %d; ignored")
346 : gettext ("invalid character '\\%o' at line %d; ignored")),