hotspot/src/share/vm/adlc/adlparse.cpp
changeset 1495 128fe18951ed
parent 1 489c9b5090e2
child 1623 a0dd9009e992
child 1662 76a93a5fb765
--- a/hotspot/src/share/vm/adlc/adlparse.cpp	Tue Oct 21 11:23:52 2008 -0700
+++ b/hotspot/src/share/vm/adlc/adlparse.cpp	Tue Oct 28 09:31:30 2008 -0700
@@ -33,7 +33,6 @@
     _globalNames(archDesc.globalNames()) {
   _AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file
   _AD._warnings    = 0;                      // No warnings either
-  _linenum         = 0;                      // Will increment to first line
   _curline         = _ptr = NULL;            // No pointers into buffer yet
 
   _preproc_depth = 0;
@@ -76,7 +75,7 @@
   }
   if (!_AD._quiet_mode)
     fprintf(stderr,"-----------------------------------------------------------------------------\n");
-  _AD._TotalLines += _linenum-1;     // -1 for overshoot in "nextline" routine
+  _AD._TotalLines += linenum()-1;     // -1 for overshoot in "nextline" routine
 
   // Write out information we have stored
   // // UNIXism == fsync(stderr);
@@ -148,7 +147,7 @@
   if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL )
     return;
   instr = new InstructForm(ident); // Create new instruction form
-  instr->_linenum = _linenum;
+  instr->_linenum = linenum();
   _globalNames.Insert(ident, instr); // Add name to the name table
   // Debugging Stuff
   if (_AD._adl_debug > 1)
@@ -404,7 +403,7 @@
   if( (ident = get_unique_ident(_globalNames,"operand")) == NULL )
     return;
   oper = new OperandForm(ident);        // Create new operand form
-  oper->_linenum = _linenum;
+  oper->_linenum = linenum();
   _globalNames.Insert(ident, oper); // Add name to the name table
 
   // Debugging Stuff
@@ -774,7 +773,7 @@
 
   // Create the RegisterForm for the architecture description.
   RegisterForm *regBlock = new RegisterForm();    // Build new Source object
-  regBlock->_linenum = _linenum;
+  regBlock->_linenum = linenum();
   _AD.addForm(regBlock);
 
   skipws();                       // Skip leading whitespace
@@ -847,7 +846,7 @@
   }
 
   EncClass  *encoding = _AD._encode->add_EncClass(ec_name);
-  encoding->_linenum = _linenum;
+  encoding->_linenum = linenum();
 
   skipws();                      // Skip leading whitespace
   // Check for optional parameter list
@@ -905,7 +904,7 @@
   // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
   if (_AD._adlocation_debug) {
     const char* file     = _AD._ADL_file._name;
-    int         line     = _linenum;
+    int         line     = linenum();
     char*       location = (char *)malloc(strlen(file) + 100);
     sprintf(location, "#line %d \"%s\"\n", line, file);
     encoding->add_code(location);
@@ -2776,7 +2775,7 @@
 
   assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
   EncClass  *encoding = _AD._encode->add_EncClass(ec_name);
-  encoding->_linenum = _linenum;
+  encoding->_linenum = linenum();
 
   // synthesize the arguments list for the enc_class from the
   // arguments to the instruct definition.
@@ -2852,7 +2851,7 @@
   skipws();
 
   InsEncode *encrule  = new InsEncode(); // Encode class for instruction
-  encrule->_linenum = _linenum;
+  encrule->_linenum = linenum();
   char      *ec_name  = NULL;      // String representation of encode rule
   // identifier is optional.
   while (_curchar != ')') {
@@ -3203,6 +3202,12 @@
   char *greater_equal;
   char *less_equal;
   char *greater;
+  const char *equal_format = "eq";
+  const char *not_equal_format = "ne";
+  const char *less_format = "lt";
+  const char *greater_equal_format = "ge";
+  const char *less_equal_format = "le";
+  const char *greater_format = "gt";
 
   if (_curchar != '%') {
     parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
@@ -3222,22 +3227,22 @@
       return NULL;
     }
     if ( strcmp(field,"equal") == 0 ) {
-      equal  = interface_field_parse();
+      equal  = interface_field_parse(&equal_format);
     }
     else if ( strcmp(field,"not_equal") == 0 ) {
-      not_equal = interface_field_parse();
+      not_equal = interface_field_parse(&not_equal_format);
     }
     else if ( strcmp(field,"less") == 0 ) {
-      less = interface_field_parse();
+      less = interface_field_parse(&less_format);
     }
     else if ( strcmp(field,"greater_equal") == 0 ) {
-      greater_equal  = interface_field_parse();
+      greater_equal  = interface_field_parse(&greater_equal_format);
     }
     else if ( strcmp(field,"less_equal") == 0 ) {
-      less_equal = interface_field_parse();
+      less_equal = interface_field_parse(&less_equal_format);
     }
     else if ( strcmp(field,"greater") == 0 ) {
-      greater = interface_field_parse();
+      greater = interface_field_parse(&greater_format);
     }
     else {
       parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
@@ -3252,14 +3257,18 @@
   next_char();                  // Skip '}'
 
   // Construct desired object and return
-  Interface *inter = new CondInterface(equal, not_equal, less, greater_equal,
-                                       less_equal, greater);
+  Interface *inter = new CondInterface(equal,         equal_format,
+                                       not_equal,     not_equal_format,
+                                       less,          less_format,
+                                       greater_equal, greater_equal_format,
+                                       less_equal,    less_equal_format,
+                                       greater,       greater_format);
   return inter;
 }
 
 
 //------------------------------interface_field_parse--------------------------
-char *ADLParser::interface_field_parse(void) {
+char *ADLParser::interface_field_parse(const char ** format) {
   char *iface_field = NULL;
 
   // Get interface field
@@ -3280,6 +3289,32 @@
     return NULL;
   }
   skipws();
+  if (format != NULL && _curchar == ',') {
+    next_char();
+    skipws();
+    if (_curchar != '"') {
+      parse_err(SYNERR, "Missing '\"' in field format .\n");
+      return NULL;
+    }
+    next_char();
+    char *start = _ptr;       // Record start of the next string
+    while ((_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
+      if (_curchar == '\\')  next_char();  // superquote
+      if (_curchar == '\n')  parse_err(SYNERR, "newline in string");  // unimplemented!
+      next_char();
+    }
+    if (_curchar != '"') {
+      parse_err(SYNERR, "Missing '\"' at end of field format .\n");
+      return NULL;
+    }
+    // If a string was found, terminate it and record in FormatRule
+    if ( start != _ptr ) {
+      *_ptr  = '\0';          // Terminate the string
+      *format = start;
+    }
+    next_char();
+    skipws();
+  }
   if (_curchar != ')') {
     parse_err(SYNERR, "Missing ')' after interface field.\n");
     return NULL;
@@ -3342,6 +3377,12 @@
     next_char();                  // Move past the '{'
 
     skipws();
+    if (_curchar == '$') {
+      char* ident = get_rep_var_ident();
+      if (strcmp(ident, "$$template") == 0) return template_parse();
+      parse_err(SYNERR, "Unknown \"%s\" directive in format", ident);
+      return NULL;
+    }
     // Check for the opening '"' inside the format description
     if ( _curchar == '"' ) {
       next_char();              // Move past the initial '"'
@@ -3433,6 +3474,131 @@
 }
 
 
+//------------------------------template_parse-----------------------------------
+FormatRule* ADLParser::template_parse(void) {
+  char       *desc   = NULL;
+  FormatRule *format = (new FormatRule(desc));
+
+  skipws();
+  while ( (_curchar != '%') && (*(_ptr+1) != '}') ) {
+
+    // (1)
+    // Check if there is a string to pass through to output
+    char *start = _ptr;       // Record start of the next string
+    while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
+      // If at the start of a comment, skip past it
+      if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
+        skipws_no_preproc();
+      } else {
+        // ELSE advance to the next character, or start of the next line
+        next_char_or_line();
+      }
+    }
+    // If a string was found, terminate it and record in EncClass
+    if ( start != _ptr ) {
+      *_ptr  = '\0';          // Terminate the string
+      // Add flag to _strings list indicating we should check _rep_vars
+      format->_strings.addName(NameList::_signal2);
+      format->_strings.addName(start);
+    }
+
+    // (2)
+    // If we are at a replacement variable,
+    // copy it and record in EncClass
+    if ( _curchar == '$' ) {
+      // Found replacement Variable
+      char *rep_var = get_rep_var_ident_dup();
+      if (strcmp(rep_var, "$emit") == 0) {
+        // switch to normal format parsing
+        next_char();
+        next_char();
+        skipws();
+        // Check for the opening '"' inside the format description
+        if ( _curchar == '"' ) {
+          next_char();              // Move past the initial '"'
+          if( _curchar == '"' ) {   // Handle empty format string case
+            *_ptr = '\0';           // Terminate empty string
+            format->_strings.addName(_ptr);
+          }
+
+          // Collect the parts of the format description
+          // (1) strings that are passed through to tty->print
+          // (2) replacement/substitution variable, preceeded by a '$'
+          // (3) multi-token ANSIY C style strings
+          while ( true ) {
+            if ( _curchar == '%' || _curchar == '\n' ) {
+              parse_err(SYNERR, "missing '\"' at end of format block");
+              return NULL;
+            }
+
+            // (1)
+            // Check if there is a string to pass through to output
+            char *start = _ptr;       // Record start of the next string
+            while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
+              if (_curchar == '\\')  next_char();  // superquote
+              if (_curchar == '\n')  parse_err(SYNERR, "newline in string");  // unimplemented!
+              next_char();
+            }
+            // If a string was found, terminate it and record in FormatRule
+            if ( start != _ptr ) {
+              *_ptr  = '\0';          // Terminate the string
+              format->_strings.addName(start);
+            }
+
+            // (2)
+            // If we are at a replacement variable,
+            // copy it and record in FormatRule
+            if ( _curchar == '$' ) {
+              next_char();          // Move past the '$'
+              char* rep_var = get_ident(); // Nil terminate the variable name
+              rep_var = strdup(rep_var);// Copy the string
+              *_ptr   = _curchar;     // and replace Nil with original character
+              format->_rep_vars.addName(rep_var);
+              // Add flag to _strings list indicating we should check _rep_vars
+              format->_strings.addName(NameList::_signal);
+            }
+
+            // (3)
+            // Allow very long strings to be broken up,
+            // using the ANSI C syntax "foo\n" <newline> "bar"
+            if ( _curchar == '"') {
+              next_char();           // Move past the '"'
+              skipws();              // Skip white space before next string token
+              if ( _curchar != '"') {
+                break;
+              } else {
+                // Found one.  Skip both " and the whitespace in between.
+                next_char();
+              }
+            }
+          } // end while part of format description
+        }
+      } else {
+        // Add flag to _strings list indicating we should check _rep_vars
+        format->_rep_vars.addName(rep_var);
+        // Add flag to _strings list indicating we should check _rep_vars
+        format->_strings.addName(NameList::_signal3);
+      }
+    } // end while part of format description
+  }
+
+  skipws();
+  // Past format description, at '%'
+  if ( _curchar != '%' || *(_ptr+1) != '}' ) {
+    parse_err(SYNERR, "missing '%}' at end of format block");
+    return NULL;
+  }
+  next_char();                  // Move past the '%'
+  next_char();                  // Move past the '}'
+
+  // Debug Stuff
+  if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc);
+
+  skipws();
+  return format;
+}
+
+
 //------------------------------effect_parse-----------------------------------
 void ADLParser::effect_parse(InstructForm *instr) {
   char* desc   = NULL;
@@ -3777,7 +3943,7 @@
     skipws_no_preproc();          // Skip leading whitespace
     cppBlock = _ptr;              // Point to start of expression
     const char* file = _AD._ADL_file._name;
-    int         line = _linenum;
+    int         line = linenum();
     next = _ptr + 1;
     while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
       next_char_or_line();
@@ -4297,11 +4463,11 @@
 
   va_start(args, fmt);
   if (flag == 1)
-    _AD._syntax_errs += _AD.emit_msg(0, flag, _linenum, fmt, args);
+    _AD._syntax_errs += _AD.emit_msg(0, flag, linenum(), fmt, args);
   else if (flag == 2)
-    _AD._semantic_errs += _AD.emit_msg(0, flag, _linenum, fmt, args);
+    _AD._semantic_errs += _AD.emit_msg(0, flag, linenum(), fmt, args);
   else
-    _AD._warnings += _AD.emit_msg(0, flag, _linenum, fmt, args);
+    _AD._warnings += _AD.emit_msg(0, flag, linenum(), fmt, args);
 
   int error_char = _curchar;
   char* error_ptr = _ptr+1;
@@ -4515,7 +4681,7 @@
 
 //---------------------------next_line-----------------------------------------
 void ADLParser::next_line() {
-  _curline = _buf.get_line(); _linenum++;
+  _curline = _buf.get_line();
 }
 
 //-------------------------is_literal_constant---------------------------------