2 /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2001.
6 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
10 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
19 Red Hat elfutils is an included package of the Open Invention Network.
20 An included package of the Open Invention Network is a package for which
21 Open Invention Network licensees cross-license their patents. No patent
22 license is granted, either expressly or impliedly, by designation as an
23 included package. Should you wish to participate in the Open Invention
24 Network licensing program, please visit www.openinventionnetwork.com
25 <http://www.openinventionnetwork.com>. */
45 /* We sure use no threads to read the stream, so use the _unlocked
46 variants of the functions. */
48 #define getc(s) getc_unlocked (s)
50 #define ferror(s) ferror_unlocked (s)
52 #define fread(b, m, n, s) fread_unlocked (b, m, n, s)
54 #define fwrite(b, m, n, s) fwrite_unlocked (b, m, n, s)
56 /* ECHO must be redefined since the default implementation ignores
57 the return value of fwrite_unlocked. */
58 #define ECHO do { size_t n__ __attribute__ ((unused)) \
59 = fwrite (yytext, yyleng, 1, yyout); } while (0)
61 /* Defined in ld.c. */
62 extern int ld_scan_version_script;
64 #define MAX_PREPDEPTH 20
70 } prepstate[MAX_PREPDEPTH];
73 static void eat_comment (void);
74 static void eat_to_eol (bool empty);
75 static int attrib_convert (int c);
76 static void push_state (enum prepstate);
77 static int pop_state (void);
78 static int handle_ifdef (void);
79 static void invalid_char (int ch);
82 ID [a-zA-Z0-9_.*?][a-zA-Z0-9_.*?-]*
83 FILENAMECHAR1 [a-zA-Z0-9_/.\\~]
84 FILENAMECHAR [^][{}[:space:]():;]+
85 HEX 0[xX][0-9a-fA-F]+[kKmM]?
91 %option never-interactive
97 if (unlikely (ld_scan_version_script))
99 ld_scan_version_script = -1;
100 return kVERSION_SCRIPT;
103 ^"#"ifdef/[[:space:]] { BEGIN (handle_ifdef ()); }
104 ^"#"else/[[:space:]\n] { eat_to_eol (true);
105 push_state (skip_to_endif);
107 ^"#"elifdef/[[:space:]] { eat_to_eol (false);
108 push_state (skip_to_endif);
110 ^"#"endif/[[:space:]\n] { eat_to_eol (true) ; }
112 <IGNORE>^"#"ifdef/[[:space:]\n] { eat_to_eol (false);
113 push_state (skip_to_endif); }
114 <IGNORE>^"#"else/[[:space:]\n] { eat_to_eol (true);
115 assert (prepdepth > 0);
116 if (prepstate[prepdepth - 1] == skip_if)
118 /* Back to normal processing. */
119 assert (prepdepth == 1);
120 BEGIN (pop_state ());
123 <IGNORE>^"#"elifdef/[[:space:]] { assert (prepdepth > 0);
124 if (prepstate[prepdepth - 1] == skip_if)
126 /* Maybe this symbol is defined. */
128 BEGIN (handle_ifdef ());
131 <IGNORE>^"#"endif/[[:space:]\n] { eat_to_eol (true);
132 BEGIN (pop_state ()); }
133 <IGNORE>.|\n { /* nothing */ }
136 "/*" { eat_comment (); }
138 ALIGN { return kALIGN; }
139 AS_NEEDED { return kAS_NEEDED; }
140 ENTRY { return kENTRY; }
141 EXCLUDE_FILE { return kEXCLUDE_FILE; }
142 "global:" { return kGLOBAL; }
143 GROUP { return kGROUP; }
144 INPUT { return kINPUT; }
145 INTERP { return kINTERP; }
146 KEEP { return kKEEP; }
147 "local:" { return kLOCAL; }
148 OUTPUT_FORMAT { return kOUTPUT_FORMAT; }
149 PAGESIZE { return kPAGESIZE; }
150 PROVIDE { return kPROVIDE; }
151 SEARCH_DIR { return kSEARCH_DIR; }
152 SEGMENT { return kSEGMENT; }
153 SIZEOF_HEADERS { return kSIZEOF_HEADERS; }
154 SORT { return kSORT; }
155 VERSION { return kVERSION; }
157 "["([RWX]){0,3}"]" { int cnt = 1 ;
159 while (cnt < yyleng - 1)
160 ldlval.num |= attrib_convert (yytext[cnt++]);
170 "+" { ldlval.op = exp_plus; return kADD_OP; }
171 "-" { ldlval.op = exp_minus; return kADD_OP; }
173 "/" { ldlval.op = exp_div; return kMUL_OP; }
174 "%" { ldlval.op = exp_mod; return kMUL_OP; }
180 {HEX}|{OCT}|{DEC} { char *endp;
181 ldlval.num = strtoumax (yytext, &endp, 0);
184 if (tolower (*endp) == 'k')
188 assert (tolower (*endp) == 'm');
189 ldlval.num *= 1024 * 1024;
194 {ID} { ldlval.str = obstack_strndup (&ld_state.smem,
198 {FILENAMECHAR1}{FILENAMECHAR} { ldlval.str = obstack_strndup (&ld_state.smem,
202 {WHITE} { /* IGNORE */ }
204 . { invalid_char (*yytext); }
215 while (c != '*' && c != EOF)
229 /* XXX Use the setjmp buffer and signal EOF in comment */
230 error (0, 0, gettext ("EOF in comment"));
238 eat_to_eol (bool empty)
254 if (empty && ! isspace (c) && ! warned)
256 error (0, 0, gettext ("%d: garbage at end of line"), yylineno);
264 attrib_convert (int c)
276 push_state (enum prepstate state)
278 if (prepdepth >= MAX_PREPDEPTH)
279 error (EXIT_FAILURE, 0, gettext ("%d: conditionals nested too deep"),
282 prepstate[prepdepth++] = state;
290 error (0, 0, gettext ("%d: unexpected #endif"), yylineno);
294 return prepdepth == 0 ? INITIAL : IGNORE;
304 size_t idmax = sizeof (idbuf);
305 bool ignore_ws = true;
306 bool defined = false;
313 if (isspace (c) && ignore_ws)
316 if (c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z')
317 && (idlen == 0 || c < '0' || c > '9'))
325 char *newp = (char *) alloca (idmax *= 2);
326 id = memcpy (newp, id, idlen);
333 /* XXX Compare in a better way. */
334 if (idlen == 6 && strncmp (id, "SHARED", 6) == 0)
335 defined = ld_state.file_type == dso_file_type;
341 push_state (skip_if);
350 invalid_char (int ch)
352 error (0, 0, (isascii (ch)
353 ? gettext ("invalid character '%c' at line %d; ignored")
354 : gettext ("invalid character '\\%o' at line %d; ignored")),