]> Git Repo - binutils.git/blob - ld/ldlex.l
Fixed some bugs.
[binutils.git] / ld / ldlex.l
1 %{
2 /* Copyright (C) 1991 Free Software Foundation, Inc.
3
4 This file is part of GLD, the Gnu Linker.
5
6 GLD 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 1, or (at your option)
9 any later version.
10
11 GLD is distributed in the hope that it will be useful,
12 but 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.
15
16 You should have received a copy of the GNU General Public License
17 along with GLD; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /*
21  *  $Id$ 
22
23  *
24 */
25
26
27
28 /*SUPPRESS 529*/
29 /*SUPPRESS 26*/
30 /*SUPPRESS 29*/
31 #define LEXDEBUG 0
32 #include "sysdep.h"
33 #include "bfd.h"
34
35 #include <ctype.h>
36 #include "ldlex.h"
37
38 #include "ld.h"
39 #include "ldexp.h"
40 #include "ldgram.tab.h"
41 #include "ldmisc.h"
42
43 #undef input
44 #undef unput
45 #define input lex_input
46 #define unput lex_unput
47 int debug;
48
49 extern boolean ldgram_in_expression;
50 extern boolean ldgram_in_defsym;
51 extern boolean ldgram_in_script;
52 static char *command_line;
53
54 extern int fgetc();
55 extern int yyparse();
56
57 typedef struct {
58         char *name;     
59 int value;
60 } keyword_type;
61 #define RTOKEN(x)  {  yylval.token = x; return x; }
62 keyword_type keywords[] = 
63 {
64 "MEMORY",MEMORY,
65 "ORIGIN",ORIGIN,
66 "BLOCK",BLOCK,
67 "LENGTH",LENGTH,
68 "ALIGN",ALIGN_K,
69 "SUBSECTION_ALIGN",SUBSECTION_ALIGN,
70 "ADDR",ADDR,
71 "ENTRY",ENTRY,
72 "SCRIPT", SCRIPT,
73 "ENDSCRIPT", ENDSCRIPT,
74 "NEXT",NEXT,
75 "MAP",MAP,
76 "SIZEOF",SIZEOF,
77 "TARGET",TARGET_K,
78 "SEARCH_DIR",SEARCH_DIR,
79 "OUTPUT",OUTPUT,
80 "INPUT",INPUT,
81 "DEFINED",DEFINED,
82 "CREATE_OBJECT_SYMBOLS",CREATE_OBJECT_SYMBOLS,
83 "FORCE_COMMON_ALLOCATION",FORCE_COMMON_ALLOCATION,
84 "SECTIONS",SECTIONS,
85 "FILL",FILL,
86 "STARTUP",STARTUP,
87 "OUTPUT_FORMAT",OUTPUT_FORMAT,
88 "HLL",HLL,
89 "SYSLIB",SYSLIB,
90 "FLOAT",FLOAT,
91 "LONG", LONG,
92 "SHORT", SHORT,
93 "BYTE", BYTE,
94 "NOFLOAT",NOFLOAT,
95 "o",ORIGIN,
96 "org",ORIGIN,
97 "l", LENGTH,
98 "len", LENGTH,
99 0,0};
100 unsigned int lineno;
101 extern boolean hex_mode;
102 FILE *ldlex_input_stack;
103 static unsigned int have_pushback;
104 #define NPUSHBACK 10
105 int pushback[NPUSHBACK];
106 int thischar;
107 extern char *ldfile_input_filename;
108 int donehash = 0;
109 int
110 lex_input()
111 {
112   if (have_pushback > 0) 
113       {
114         have_pushback --;
115         return thischar = pushback[have_pushback];
116       }
117   if (ldlex_input_stack) {
118     thischar = fgetc(ldlex_input_stack);
119
120     if (thischar == EOF)  {
121       fclose(ldlex_input_stack);
122       ldlex_input_stack = (FILE *)NULL;
123       ldfile_input_filename = (char *)NULL;
124       /* First char after script eof is a @ so that we can tell the grammer
125          that we've eft */
126       thischar = '@';
127
128     }
129   }
130   else if (command_line && *command_line)  {
131     thischar = *(command_line++);
132   }
133   else {
134  thischar = 0;
135   }
136   if(thischar == '\t') thischar = ' ';
137   if (thischar == '\n') { thischar = ' '; lineno++; }
138   return thischar ;
139 }
140
141 void
142 lex_unput(c)
143 int c;
144 {
145   if (have_pushback > NPUSHBACK) {
146     info("%F%P Too many pushbacks\n");
147   }
148
149   pushback[have_pushback] = c;
150   have_pushback ++;
151 }
152
153
154         int
155 yywrap()
156          { return 1; }
157 /*VARARGS*/
158
159 void
160 allprint(x) 
161 int x;
162 {
163 fprintf(yyout,"%d",x);
164 }
165
166 void
167 sprint(x) 
168 char *x;
169 {
170 fprintf(yyout,"%s",x);
171 }
172
173 int  thischar;
174
175 void parse_line(arg)
176 char *arg;
177 {
178   command_line = arg;
179   have_pushback = 0;
180   yyparse();
181 }
182
183
184
185 void
186 parse_args(ac, av)
187 int ac;
188 char **av;
189 {
190   char *p;
191   int i;
192   size_t size = 0;
193   char *dst;
194   debug = 1;
195   for (i= 1; i < ac; i++) {
196     size += strlen(av[i]) + 2; 
197   }
198   dst = p = (char *)ldmalloc(size + 2);
199 /* Put a space arount each option */
200
201
202   for (i =1; i < ac; i++) {
203
204     unsigned int s = strlen(av[i]);
205   *dst++ = ' ';
206     memcpy(dst, av[i], s);
207     dst[s] = ' ';
208     dst += s + 1;
209   }
210   *dst  = 0;
211   parse_line(p);
212
213   free(p);
214
215
216 }
217
218 long number(text, base)
219 char *text;
220 int base;
221 {
222   unsigned  long l = 0;
223   char *p;
224   for (p = text; *p != 0; p++) {
225     if (*p == 'K') {
226       l =l * 1024;
227     }
228     else if(*p== 'M') {
229       l =l * 1024 * 1024;
230     }
231     else {
232       l =l * base;
233       if (isdigit(*p))  {
234         l += *p - '0';
235       }
236       else if (islower(*p)) {
237         l += *p - 'a' + 10;
238       }
239       else {
240         l += *p - 'A' + 10;
241       }
242     }
243   }
244   return l;
245 }
246 %}
247
248 %a 4000
249 %o 5000
250 FILENAMECHAR    [a-zA-Z0-9\/\.\-\_\+\=]
251 FILENAME        {FILENAMECHAR}+
252
253
254 WHITE           [ \t]+
255
256 %%
257
258 "@" { return ENDSCRIPT; }
259 "\ -defsym\ " { return OPTION_defsym; }
260 "\ -noinhibit_exec\ " { return OPTION_noinhibit_exec; }
261 "\ -format\ " { return OPTION_format; }
262 "\ -n\ "                { return OPTION_n; }
263 "\ -r\ "                { return OPTION_r; }
264 "\ -Ur\ "               { return OPTION_Ur; }
265 "\ -o\ "                { return OPTION_o; }
266 "\ -g\ "                { return OPTION_g; }
267 "\ -e\ "                { return OPTION_e; }
268 "\ -b\ "                { return OPTION_b; }
269 "\ -dc\ "               { return OPTION_dc; }
270 "\ -dp\ "               { return OPTION_dp; }
271 "\ -d\ "                { return OPTION_d; }
272 "\ -v\ "                { return OPTION_v; }
273 "\ -M\ "                { return OPTION_M; }
274 "\ -t\ "                { return OPTION_t; }
275 "\ -X\ "                { return OPTION_X; }
276 "\ -x\ "                { return OPTION_x; }
277 "\ -c\ "                { return OPTION_c; }
278 "\ -R\ "                { return OPTION_R; }
279 "\ -u\ "                { return OPTION_u; }
280 "\ -s\ "            { return OPTION_s; }
281 "\ -S\ "            { return OPTION_S; }
282 "\ -l"{FILENAME} {
283                 yylval.name = buystring(yytext+3);
284                 return OPTION_l; 
285         }
286
287 "\ -L"{FILENAME}        { 
288                 yylval.name = buystring(yytext+3);
289                 return OPTION_L; 
290          }
291 "\ -Ttext\ "  {
292                  yylval.name = ".text";
293                  return OPTION_Texp;
294                }
295 "\ -Tdata\ "  {
296                  yylval.name = ".data";
297                  return OPTION_Texp;
298                }
299 "\ -Tbss\ "  {
300                  yylval.name = ".bss";
301                  return OPTION_Texp;
302                }
303
304 "\ -T"{FILENAME}  {
305                  yylval.name = buystring(yytext+3);
306                  return OPTION_Tfile;
307                }
308 "\ -T\ "          {
309                  return OPTION_T;
310                }
311
312 "\ -F"{FILENAME}  {
313                  return OPTION_F;
314                }
315 "\ -F\ "          {
316                  return OPTION_F;
317                }
318
319 "\ -A"{FILENAME} {
320                  yylval.name = buystring(yytext+3);
321                  return OPTION_Aarch;
322                }
323 " " { }
324 "<<="           { RTOKEN(LSHIFTEQ);}
325 ">>="           { RTOKEN(RSHIFTEQ);}
326 "||"            { RTOKEN(OROR);}
327 "=="            { RTOKEN(EQ);}
328 "!="            { RTOKEN(NE);}
329 ">="            { RTOKEN(GE);}
330 "<="            { RTOKEN(LE);}
331 "<<"            { RTOKEN(LSHIFT);}
332 ">>"            { RTOKEN(RSHIFT);}
333 "+="            { RTOKEN(PLUSEQ);}
334 "-="            { RTOKEN(MINUSEQ);}
335 "*="            { RTOKEN(MULTEQ);}
336 "/="            { RTOKEN(DIVEQ);}
337 "&="            { RTOKEN(ANDEQ);}
338 "|="            { RTOKEN(OREQ);}
339 "&&"            { RTOKEN(ANDAND);}
340 ">"             { RTOKEN('>');}
341 ","             { RTOKEN(',');}
342 "&"             { RTOKEN('&');}
343 "|"             { RTOKEN('|');}
344 "~"             { RTOKEN('~');}
345 "!"             { RTOKEN('!');}
346 "?"             { RTOKEN('?');}
347 "*"             { RTOKEN('*');}
348 "%"             { RTOKEN('%');}
349 "<"             { RTOKEN('<');}
350 ">"             { RTOKEN('>');}
351 "}"             { RTOKEN('}') ; }
352 "{"             { RTOKEN('{'); }
353 ")"             { RTOKEN(')');}
354 "("             { RTOKEN('(');}
355 "]"             { RTOKEN(']');}
356 "["             { RTOKEN('[');}
357 ":"             { RTOKEN(':'); }
358 ";"             { RTOKEN('\;');}
359 "-"             { RTOKEN('-');}
360
361
362
363 "/*"            { 
364   while (1) {
365     int ch;
366     ch = input();
367     while (ch != '*') {
368       ch = input();
369     }
370
371
372
373     if (input() == '/') {
374       break;
375     }
376     unput(yytext[yyleng-1]);
377   }
378 }
379
380 "\""[^\"]*"\"" {
381
382   yylval.name = buystring(yytext+1);
383   yylval.name[yyleng-2] = 0; /* Fry final quote */
384   return NAME;
385 }
386
387 "\#"{WHITE}*{FILENAMECHAR}+ {
388   char *p = yytext+1;
389   while(*p ==' ' || *p == '\t') p++;
390   yylval.name = buystring(p);
391   return NAME;
392 }
393 {FILENAMECHAR} {
394
395   boolean loop = false;
396   /*
397     Tokenize a name, this is really pain, since a name can be a
398     filename or a symbol name. filenames have slashes and stuff whist
399     in an expression those things are seperate tokens. We hack this by
400     setting ldlang_in_script when we are expecting a symbol, so that
401     [/+-] get taken to be seperate tokens. An extra gotcha is
402     expressions after defsyms, we only allow +s and -s in a defsym
403     expression, so -defsym foo=bar+9 /file.o is parsed ok.
404     
405     The more I think about this the more I hate it. I've got a problem
406     now with the = sign, what should I do ? imagine:
407     __start=.;
408     You'd think that was pretty unambiguous wouldn't you. Well it's
409     not since __start=. is (at the moment) a perfectly valid
410     filename. And in some cases we don't know what's going on. I'm
411     going to have to hack this. If we see a '/' before the = sign then
412     we say we've got an = in a filename, otherwise it's an operator.
413     (later)
414     That's it, I've had enough. From now on, an =s on a command line
415     will be taken to be part of a file name unless its in a defsym,
416     and an = in a file will be taken to be an operator.
417     */
418   int ch;
419   keyword_type *k;
420
421   if ((hex_mode && isxdigit(yytext[0]))
422       ||
423       (isdigit(yytext[0]) && (ldgram_in_expression == true || ldgram_in_script == true))) {
424     char *start = yytext;
425     unsigned int base = 10;
426     if (hex_mode == true) base = 16;
427     if (yytext[0] == '0') {
428       base = 8;
429     }
430     ch = input();
431     while (isxdigit(ch) 
432            || ch == 'x'
433            || ch == 'X'
434            || ch == 'M'         
435            )
436         {
437           if (ch == 'x' || ch == 'X') {
438             base = 16;
439             start = yytext + yyleng;
440           }
441           else {
442             yytext[yyleng++] = ch;
443           }
444           ch = input();
445         }
446     yytext[yyleng] = 0;
447     unput(ch);
448     yylval.integer = number(start, base);
449     return INT;
450   }
451
452   if (ldfile_input_filename) {
453     /* We're inside a file */
454     if (yytext[0]== '=') {
455       RTOKEN('=');
456     }
457   }
458
459     
460
461   /* Otherwise we only notice special things if were in an
462      expression */
463
464   if (ldgram_in_expression) {
465     if (yytext[0] != '/' ||  ldgram_in_defsym == false)  {
466       switch (yytext[0]) {
467       case '/': RTOKEN('/');
468       case '=': RTOKEN('=');
469       case '+': RTOKEN('+');
470       case '-': RTOKEN('-');
471       }
472     }
473   }
474
475   ch = input();
476   while (true)
477       {
478         if (isalpha(ch) || isdigit(ch) || ch == '.'  || ch == '_' ) {
479           yytext[yyleng++] = ch;
480         }
481         else if (ch == '=' && ldgram_in_script) {
482           /* An = within a script is always taken to be an operator */
483           break;
484         }
485         else if (ch == '+' || ch == '-' || ch == '/' || ch == '=') {
486           if (ldgram_in_expression) break;
487           yytext[yyleng++] = ch;
488         }
489         else 
490           break;
491         ch = input();
492       }
493
494   yytext[yyleng] = 0;
495   unput(ch);
496   /* Filenames  of just =signs are tokens */
497   if (yyleng == 1 && yytext[0] == '=') {
498     RTOKEN('=');
499   }
500   for(k = keywords; k ->name != (char *)NULL; k++) {
501
502     if (strcmp(k->name, yytext)==0) {
503       yylval.token = k->value;
504       return k->value;
505     }
506   }
507   yylval.name = buystring(yytext);
508   return NAME;
509 }
510
511
512
513
514
515 %%
This page took 0.087282 seconds and 4 git commands to generate.