%{ /* Copyright (C) 1991 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. GLD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. GLD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GLD; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * $Id$ * */ /*SUPPRESS 529*/ /*SUPPRESS 26*/ /*SUPPRESS 29*/ #define LEXDEBUG 0 #include "sysdep.h" #include "bfd.h" #include #include "ldlex.h" #include "ld.h" #include "ldexp.h" #include "ldgramtb.h" #include "ldmisc.h" #undef input #undef unput #define input lex_input #define unput lex_unput int debug; static boolean ldgram_in_defsym; static boolean ldgram_had_equals; extern boolean ldgram_in_script; static char *command_line; extern int fgetc(); extern int yyparse(); typedef struct { char *name; int value; } keyword_type; #define RTOKEN(x) { yylval.token = x; return x; } keyword_type keywords[] = { "/", '/', "MEMORY",MEMORY, "ORIGIN",ORIGIN, "BLOCK",BLOCK, "LENGTH",LENGTH, "ALIGN",ALIGN_K, "ADDR",ADDR, "ENTRY",ENTRY, "NEXT",NEXT, "sizeof_headers",SIZEOF_HEADERS, "SIZEOF_HEADERS",SIZEOF_HEADERS, "MAP",MAP, "SIZEOF",SIZEOF, "TARGET",TARGET_K, "SEARCH_DIR",SEARCH_DIR, "OUTPUT",OUTPUT, "INPUT",INPUT, "DEFINED",DEFINED, "CREATE_OBJECT_SYMBOLS",CREATE_OBJECT_SYMBOLS, "FORCE_COMMON_ALLOCATION",FORCE_COMMON_ALLOCATION, "SECTIONS",SECTIONS, "FILL",FILL, "STARTUP",STARTUP, "OUTPUT_FORMAT",OUTPUT_FORMAT, "OUTPUT_ARCH", OUTPUT_ARCH, "HLL",HLL, "SYSLIB",SYSLIB, "FLOAT",FLOAT, "LONG", LONG, "SHORT", SHORT, "BYTE", BYTE, "NOFLOAT",NOFLOAT, "o",ORIGIN, "org",ORIGIN, "l", LENGTH, "len", LENGTH, 0,0}; unsigned int lineno; extern boolean hex_mode; FILE *ldlex_input_stack; static unsigned int have_pushback; #define NPUSHBACK 10 int pushback[NPUSHBACK]; int thischar; extern char *ldfile_input_filename; int donehash = 0; int lex_input() { if (have_pushback > 0) { have_pushback --; return thischar = pushback[have_pushback]; } if (ldlex_input_stack) { thischar = fgetc(ldlex_input_stack); if (thischar == EOF) { fclose(ldlex_input_stack); ldlex_input_stack = (FILE *)NULL; ldfile_input_filename = (char *)NULL; /* First char after script eof is a @ so that we can tell the grammer that we've left */ thischar = '@'; } } else if (command_line && *command_line) { thischar = *(command_line++); } else { thischar = 0; } if(thischar == '\t') thischar = ' '; if (thischar == '\n') { thischar = ' '; lineno++; } return thischar ; } void lex_unput(c) int c; { if (have_pushback > NPUSHBACK) { info("%F%P Too many pushbacks\n"); } pushback[have_pushback] = c; have_pushback ++; } int yywrap() { return 1; } /*VARARGS*/ void allprint(x) int x; { fprintf(yyout,"%d",x); } void sprint(x) char *x; { fprintf(yyout,"%s",x); } int thischar; void parse_line(arg) char *arg; { command_line = arg; have_pushback = 0; yyparse(); } void parse_args(ac, av) int ac; char **av; { char *p; int i; size_t size = 0; char *dst; debug = 1; for (i= 1; i < ac; i++) { size += strlen(av[i]) + 2; } dst = p = (char *)ldmalloc(size + 2); /* Put a space arount each option */ for (i =1; i < ac; i++) { unsigned int s = strlen(av[i]); *dst++ = ' '; memcpy(dst, av[i], s); dst[s] = ' '; dst += s + 1; } *dst = 0; parse_line(p); free(p); } static long DEFUN(number,(default_if_zero,base), int default_if_zero AND int base) { unsigned long l = 0; int ch = yytext[0]; if (ch == 0) { base = default_if_zero; } while (1) { switch (ch) { case 'x': base = 16; break; case 'k': case 'K': l =l * 1024; break; case 'm': case 'M': l =l * 1024 * 1024; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': l = l * base + ch - '0'; break; case 'a': case 'b': case 'c' : case 'd' : case 'e': case 'f': l =l *base + ch - 'a' + 10; break; case 'A': case 'B': case 'C' : case 'D' : case 'E': case 'F': l =l *base + ch - 'A' + 10; break; default: unput(ch); yylval.integer = l; return INT; } ch = input(); } } %} %a 4000 %o 5000 FILENAMECHAR [a-zA-Z0-9\/\.\-\_\+\=] FILENAME {FILENAMECHAR}+ WHITE [ \t]+ %% "@" { return '}'; } "\ -defsym\ " { ldgram_in_defsym = true; return OPTION_defsym; } "\ -noinhibit_exec\ " { return OPTION_noinhibit_exec; } "\ -sort_common\ " { return OPTION_sort_common;} "\ -format\ " { return OPTION_format; } "\ -n\ " { return OPTION_n; } "\ -r\ " { return OPTION_r; } "\ -i\ " { return OPTION_r; } "\ -Ur\ " { return OPTION_Ur; } "\ -o\ " { return OPTION_o; } "\ -g\ " { return OPTION_g; } "\ -e\ " { return OPTION_e; } "\ -b\ " { return OPTION_b; } "\ -dc\ " { return OPTION_dc; } "\ -dp\ " { return OPTION_dp; } "\ -d\ " { return OPTION_d; } "\ -v\ " { return OPTION_v; } "\ -M\ " { return OPTION_M; } "\ -t\ " { return OPTION_t; } "\ -X\ " { return OPTION_X; } "\ -x\ " { return OPTION_x; } "\ -c\ " { return OPTION_c; } "\ -R\ " { return OPTION_R; } "\ -u\ " { return OPTION_u; } "\ -s\ " { return OPTION_s; } "\ -S\ " { return OPTION_S; } "\ -B{FILENAME}\ " { /* Ignored */ } "\ -l"{FILENAME} { yylval.name = buystring(yytext+3); return OPTION_l; } "\ -L"{FILENAME} { yylval.name = buystring(yytext+3); return OPTION_L; } "\ -Ttext\ " { yylval.name = ".text"; return OPTION_Texp; } "\ -Tdata\ " { yylval.name = ".data"; return OPTION_Texp; } "\ -Tbss\ " { yylval.name = ".bss"; return OPTION_Texp; } "\ -O"{FILENAME} { yylval.name = buystring(yytext+3); return OPTION_Texp; } "\ -T"{FILENAME} { yylval.name = buystring(yytext+3); return OPTION_Tfile; } "\ -T\ " { return OPTION_T; } "\ -F"{FILENAME} { return OPTION_F; } "\ -F\ " { return OPTION_F; } "\ -A"{FILENAME} { yylval.name = buystring(yytext+3); return OPTION_Aarch; } " " { if (ldgram_had_equals == true) { ldgram_in_defsym = false; ldgram_had_equals = false; } } "<<=" { RTOKEN(LSHIFTEQ);} ">>=" { RTOKEN(RSHIFTEQ);} "||" { RTOKEN(OROR);} "==" { RTOKEN(EQ);} "!=" { RTOKEN(NE);} ">=" { RTOKEN(GE);} "<=" { RTOKEN(LE);} "<<" { RTOKEN(LSHIFT);} ">>" { RTOKEN(RSHIFT);} "+=" { RTOKEN(PLUSEQ);} "-=" { RTOKEN(MINUSEQ);} "*=" { RTOKEN(MULTEQ);} "/=" { RTOKEN(DIVEQ);} "&=" { RTOKEN(ANDEQ);} "|=" { RTOKEN(OREQ);} "&&" { RTOKEN(ANDAND);} ">" { RTOKEN('>');} "," { RTOKEN(',');} "&" { RTOKEN('&');} "|" { RTOKEN('|');} "~" { RTOKEN('~');} "!" { RTOKEN('!');} "?" { RTOKEN('?');} "*" { RTOKEN('*');} "%" { RTOKEN('%');} "<" { RTOKEN('<');} ">" { RTOKEN('>');} "}" { RTOKEN('}') ; } "{" { RTOKEN('{'); } ")" { RTOKEN(')');} "(" { RTOKEN('(');} "]" { RTOKEN(']');} "[" { RTOKEN('[');} ":" { RTOKEN(':'); } ";" { RTOKEN('\;');} "-" { RTOKEN('-');} "/*" { while (1) { int ch; ch = input(); while (ch != '*') { ch = input(); } if (input() == '/') { break; } unput(yytext[yyleng-1]); } } "\""[^\"]*"\"" { yylval.name = buystring(yytext+1); yylval.name[yyleng-2] = 0; /* Fry final quote */ return NAME; } {FILENAMECHAR} { boolean loop = false; int ch; keyword_type *k; /* If we're in hex mode (only after a -T) then all we can see are numbers hex digit we see will be a number. */ if (hex_mode) { return number(16, 16); } /* If we're in a defsym then all things starting with a digit are in hex */ if (isdigit(yytext[0]) && ldgram_in_defsym) { return number(16,16); } /* Otherwise if we're in a script we will parse the numbers normally */ if (ldgram_in_script == true && isdigit(yytext[0])) { return number(8,10); } /* Anywhere not in a script or defsym, an opertor is part of a filename, except / and, which is an operator when on its own */ if (ldgram_in_script == true|| ldgram_in_defsym == true) { switch (yytext[0]) { case '*': RTOKEN('*'); case '=': { ldgram_had_equals = true; RTOKEN('='); } break; case '/': { if (ldgram_in_defsym) RTOKEN('/'); } break; case '+': RTOKEN('+'); case '-': RTOKEN('-'); case '!': RTOKEN('!'); case '~': RTOKEN('~'); } } /* Otherwise this must be a file or a symbol name, and it will continue to be a filename until we get to something strange. In scripts operator looking things are taken to be operators, except /, which will be left */ ch = input(); while (true) { if (ldgram_in_defsym == true) { switch (ch) { case '*': case '=': case '+': case '/': case '-': case '!': case '~': goto quit; } } if(ldgram_in_script == true) { switch (ch) { case '*': case '=': case '+': case '-': case '!': case '~': goto quit; } } if (isalpha(ch) || isdigit(ch) || ch == '.' || ch == '_' || ch == '/' || ch == '.' || ch == '+' || ch == '-' || ch =='=') { yytext[yyleng++] = ch; } else break; ch = input(); } quit:; yytext[yyleng] = 0; unput(ch); for(k = keywords; k ->name != (char *)NULL; k++) { if (strcmp(k->name, yytext)==0) { yylval.token = k->value; return k->value; } } yylval.name = buystring(yytext); return NAME; } %%