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