*** empty log message ***
[platform/upstream/binutils.git] / ld / ldlex.l
index 4710260..7d50ccd 100644 (file)
@@ -28,7 +28,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /*SUPPRESS 529*/
 /*SUPPRESS 26*/
 /*SUPPRESS 29*/
-#define LEXDEBUG
+#define LEXDEBUG 0
 #include "sysdep.h"
 #include "bfd.h"
 
@@ -46,9 +46,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define unput lex_unput
 int debug;
 
-extern boolean ldgram_in_expression;
-extern boolean ldgram_in_defsym;
 
+static boolean ldgram_in_defsym;
+static boolean ldgram_had_equals;
+extern boolean ldgram_in_script;
 static char *command_line;
 
 extern int fgetc();
@@ -61,15 +62,17 @@ int value;
 #define RTOKEN(x)  {  yylval.token = x; return x; }
 keyword_type keywords[] = 
 {
+"/", '/',
 "MEMORY",MEMORY,
 "ORIGIN",ORIGIN,
 "BLOCK",BLOCK,
 "LENGTH",LENGTH,
 "ALIGN",ALIGN_K,
-"SUBSECTION_ALIGN",SUBSECTION_ALIGN,
 "ADDR",ADDR,
 "ENTRY",ENTRY,
 "NEXT",NEXT,
+"sizeof_headers",SIZEOF_HEADERS,
+"SIZEOF_HEADERS",SIZEOF_HEADERS,
 "MAP",MAP,
 "SIZEOF",SIZEOF,
 "TARGET",TARGET_K,
@@ -78,9 +81,12 @@ keyword_type keywords[] =
 "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,
@@ -97,21 +103,20 @@ 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];
-    }
+      {
+       have_pushback --;
+       return thischar = pushback[have_pushback];
+      }
   if (ldlex_input_stack) {
     thischar = fgetc(ldlex_input_stack);
 
@@ -119,14 +124,18 @@ lex_input()
       fclose(ldlex_input_stack);
       ldlex_input_stack = (FILE *)NULL;
       ldfile_input_filename = (char *)NULL;
-      thischar = lex_input();
+      /* 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;
+  else {
+ thischar = 0;
+  }
   if(thischar == '\t') thischar = ' ';
   if (thischar == '\n') { thischar = ' '; lineno++; }
   return thischar ;
@@ -209,68 +218,84 @@ char **av;
 
 }
 
-long number(text, base)
-char *text;
-int base;
+static long 
+DEFUN(number,(default_if_zero,base),
+      int default_if_zero AND
+      int base)
 {
-unsigned  long l = 0;
-  char *p;
-  for (p = text; *p != 0; p++) {
-    if (*p == 'K') {
+  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;
-    }
-    else if(*p== 'M') {
+      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;
     }
-    else {
-      l =l * base;
-      if (isdigit(*p))  {
-       l += *p - '0';
-      }
-      else if (islower(*p)) {
-       l += *p - 'a' + 10;
-      }
-      else {
-       l += *p - 'A' + 10;
-      }
-    }
+ch = input();
   }
-  return l;
 }
 %}
 
 %a 4000
 %o 5000
-FILENAMECHAR   [a-zA-Z0-9\/\.\-\_\+]
+FILENAMECHAR   [a-zA-Z0-9\/\.\-\_\+\=]
 FILENAME       {FILENAMECHAR}+
-
-
-WHITE          [ \t]+
+WHITE          [ \t]+ 
 
 %%
 
-
-"\ -defsym" { return OPTION_defsym; }
-"\ -noinhibit_exec" { return OPTION_noinhibit_exec; }
-"\ -format" { return OPTION_format; }
-"\ -n"         { return OPTION_n; }
-"\ -r"         { 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; }
-"\ -s"            { return OPTION_s; }
-"\ -S"            { return OPTION_S; }
+"@" { 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; 
@@ -280,15 +305,15 @@ WHITE             [ \t]+
                yylval.name = buystring(yytext+3);
                return OPTION_L; 
         }
-"\ -Ttext"  {
+"\ -Ttext"  {
                 yylval.name = ".text";
                 return OPTION_Texp;
               }
-"\ -Tdata"  {
+"\ -Tdata"  {
                 yylval.name = ".data";
                 return OPTION_Texp;
               }
-"\ -Tbss"  {
+"\ -Tbss"  {
                 yylval.name = ".bss";
                 return OPTION_Texp;
               }
@@ -297,14 +322,14 @@ WHITE             [ \t]+
                 yylval.name = buystring(yytext+3);
                 return OPTION_Tfile;
               }
-"\ -T"          {
+"\ -T"          {
                 return OPTION_T;
               }
 
 "\ -F"{FILENAME}  {
                 return OPTION_F;
               }
-"\ -F"          {
+"\ -F"          {
                 return OPTION_F;
               }
 
@@ -312,7 +337,13 @@ WHITE              [ \t]+
                  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);}
@@ -328,7 +359,6 @@ WHITE               [ \t]+
 "/="           { RTOKEN(DIVEQ);}
 "&="           { RTOKEN(ANDEQ);}
 "|="           { RTOKEN(OREQ);}
-
 "&&"           { RTOKEN(ANDAND);}
 ">"            { RTOKEN('>');}
 ","            { RTOKEN(',');}
@@ -340,7 +370,6 @@ WHITE               [ \t]+
 "*"            { RTOKEN('*');}
 "%"            { RTOKEN('%');}
 "<"            { RTOKEN('<');}
-"+"            { RTOKEN('+');}
 ">"            { RTOKEN('>');}
 "}"            { RTOKEN('}') ; }
 "{"            { RTOKEN('{'); }
@@ -349,9 +378,9 @@ WHITE               [ \t]+
 "]"            { RTOKEN(']');}
 "["            { RTOKEN('[');}
 ":"            { RTOKEN(':'); }
-";"            { RTOKEN(';');}
+";"            { RTOKEN('\;');}
 "-"            { RTOKEN('-');}
-"="            { RTOKEN('=');}
+
 
 
 "/*"           { 
@@ -377,79 +406,104 @@ WHITE            [ \t]+
   yylval.name[yyleng-2] = 0; /* Fry final quote */
   return NAME;
 }
-[0][0-7KM]* {
 
-  yylval.integer = number(yytext+1, 8);
- return INT;
-}
+{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. */
 
-[0-9]+[KM]? {
-  if (hex_mode == true) {
-    yylval.integer = number(yytext, 16);
+  if (hex_mode) {      
+    return number(16, 16);
   }
-  else {
-    yylval.integer = number(yytext, 10);
+
+  /* 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);
   }
-  return INT;
-}
 
-0[Xx][0-9a-fA-FKM]+ {
-  yylval.integer = number(yytext+2,16);        
-  return INT;
-}
 
-"\#"{WHITE}*{FILENAMECHAR}+ {
-  char *p = yytext+1;
-  while(*p ==' ' || *p == '\t') p++;
-  yylval.name = buystring(p);
-  return NAME;
-}
-{FILENAMECHAR} {
+  /* Otherwise if we're in a script we will parse the numbers
+     normally */
 
-  boolean loop = false;
-  /*
-    Tokenize a name, this is really pain, since a name can be a
-    filename or a symbol name. filenames have slashes and stuff whist
-    in an expression those things are seperate tokens. We hack this by
-    setting lang_in_expression when we are expecting a symbol, so that
-    [/+-] get taken to be seperate tokens. An extra gotcha is
-    expressions after defsyms, we only allow +s and -s in a defsym
-    expression, so -defsym foo=bar+9 /file.o is parsed ok.
-    
-    */
-  int ch;
-  keyword_type *k;
-  if (ldgram_in_expression) {
-    if (yytext[0] != '/' ||  ldgram_in_defsym == false)  {
-      switch (yytext[0]) {
-      case '/': RTOKEN('/');
+  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 (isalpha(ch) || isdigit(ch) || ch == '.'  || ch == '_') {
-         yytext[yyleng++] = ch;
+       if (ldgram_in_defsym == true) {
+         switch (ch) {
+         case '*': 
+         case '=': 
+         case '+': 
+         case '/': 
+         case '-': 
+         case '!': 
+         case '~': 
+           goto quit;
+         }
+         
        }
-       else if (ch == '+' || ch == '-' || ch == '/') {
-         if (ldgram_in_expression) break;
+       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;