1 #ifdef USE_PRAGMA_IDENT_SRC
   2 #pragma ident "@(#)adlparse.cpp 1.205 07/05/05 17:05:00 JVM"
   3 #endif
   4 /*
   5  * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
   6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   7  *
   8  * This code is free software; you can redistribute it and/or modify it
   9  * under the terms of the GNU General Public License version 2 only, as
  10  * published by the Free Software Foundation.
  11  *
  12  * This code is distributed in the hope that it will be useful, but WITHOUT
  13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15  * version 2 for more details (a copy is included in the LICENSE file that
  16  * accompanied this code).
  17  *
  18  * You should have received a copy of the GNU General Public License version
  19  * 2 along with this work; if not, write to the Free Software Foundation,
  20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21  *
  22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  23  * CA 95054 USA or visit www.sun.com if you need additional information or
  24  * have any questions.
  25  *  
  26  */
  27 
  28 // ADLPARSE.CPP - Architecture Description Language Parser
  29 // Authors: Chris Vick and Mike Paleczny
  30 #include "adlc.hpp"
  31 
  32 //----------------------------ADLParser----------------------------------------
  33 // Create a new ADL parser
  34 ADLParser::ADLParser(FileBuff& buffer, ArchDesc& archDesc)
  35   : _buf(buffer), _AD(archDesc), 
  36     _globalNames(archDesc.globalNames()) {
  37   _AD._syntax_errs = _AD._semantic_errs = 0; // No errors so far this file
  38   _AD._warnings    = 0;                      // No warnings either
  39   _linenum         = 0;                      // Will increment to first line
  40   _curline         = _ptr = NULL;            // No pointers into buffer yet
  41 
  42   _preproc_depth = 0;
  43   _preproc_not_taken = 0;
  44 
  45   // Delimit command-line definitions from in-file definitions:
  46   _AD._preproc_list.add_signal();
  47 }
  48 
  49 //------------------------------~ADLParser-------------------------------------
  50 // Delete an ADL parser.
  51 ADLParser::~ADLParser() {
  52   if (!_AD._quiet_mode)
  53     fprintf(stderr,"---------------------------- Errors and Warnings ----------------------------\n");
  54 #ifndef ASSERT
  55   fprintf(stderr, "**************************************************************\n");
  56   fprintf(stderr, "***** WARNING: ASSERT is undefined, assertions disabled. *****\n");
  57   fprintf(stderr, "**************************************************************\n");
  58 #endif
  59   if( _AD._syntax_errs + _AD._semantic_errs + _AD._warnings == 0 ) {
  60     if (!_AD._quiet_mode)
  61       fprintf(stderr,"No errors or warnings to report from phase-1 parse.\n" );
  62   }
  63   else {
  64     if( _AD._syntax_errs ) {      // Any syntax errors?
  65       fprintf(stderr,"%s:  Found %d syntax error", _buf._fp->_name, _AD._syntax_errs);
  66       if( _AD._syntax_errs > 1 ) fprintf(stderr,"s.\n\n");
  67       else fprintf(stderr,".\n\n");
  68     }
  69     if( _AD._semantic_errs ) {    // Any semantic errors?
  70       fprintf(stderr,"%s:  Found %d semantic error", _buf._fp->_name, _AD._semantic_errs);
  71       if( _AD._semantic_errs > 1 ) fprintf(stderr,"s.\n\n");
  72       else fprintf(stderr,".\n\n");
  73     }
  74     if( _AD._warnings ) {         // Any warnings?
  75       fprintf(stderr,"%s:  Found %d warning", _buf._fp->_name, _AD._warnings);
  76       if( _AD._warnings > 1 ) fprintf(stderr,"s.\n\n");
  77       else fprintf(stderr,".\n\n");
  78     }
  79   }
  80   if (!_AD._quiet_mode)
  81     fprintf(stderr,"-----------------------------------------------------------------------------\n");
  82   _AD._TotalLines += _linenum-1;     // -1 for overshoot in "nextline" routine
  83 
  84   // Write out information we have stored
  85   // // UNIXism == fsync(stderr);
  86 }
  87 
  88 //------------------------------parse------------------------------------------
  89 // Each top-level keyword should appear as the first non-whitespace on a line.
  90 // 
  91 void ADLParser::parse() {
  92   char *ident;
  93 
  94   // Iterate over the lines in the file buffer parsing Level 1 objects
  95   for( next_line(); _curline != NULL; next_line()) {
  96     _ptr = _curline;             // Reset ptr to start of new line
  97     skipws();                    // Skip any leading whitespace 
  98     ident = get_ident();         // Get first token
  99     if (ident == NULL) {         // Empty line
 100       continue;                  // Get the next line
 101     }
 102     if (!strcmp(ident, "instruct"))        instr_parse();
 103     else if (!strcmp(ident, "operand"))    oper_parse();        
 104     else if (!strcmp(ident, "opclass"))    opclass_parse();
 105     else if (!strcmp(ident, "ins_attrib")) ins_attr_parse();
 106     else if (!strcmp(ident, "op_attrib"))  op_attr_parse();
 107     else if (!strcmp(ident, "source"))     source_parse();
 108     else if (!strcmp(ident, "source_hpp")) source_hpp_parse();
 109     else if (!strcmp(ident, "register"))   reg_parse();
 110     else if (!strcmp(ident, "frame"))      frame_parse();
 111     else if (!strcmp(ident, "encode"))     encode_parse();
 112     else if (!strcmp(ident, "pipeline"))   pipe_parse();
 113     else if (!strcmp(ident, "definitions")) definitions_parse();
 114     else if (!strcmp(ident, "peephole"))   peep_parse();
 115     else if (!strcmp(ident, "#define"))    preproc_define();
 116     else if (!strcmp(ident, "#undef"))     preproc_undef();
 117     else {
 118       parse_err(SYNERR, "expected one of - instruct, operand, ins_attrib, op_attrib, source, register, pipeline, encode\n     Found %s",ident);
 119     }
 120   }
 121 
 122   // Done with parsing, check consistency.
 123 
 124   if (_preproc_depth != 0) {
 125     parse_err(SYNERR, "End of file inside #ifdef");
 126   }
 127 
 128   // AttributeForms ins_cost and op_cost must be defined for default behaviour
 129   if (_globalNames[AttributeForm::_ins_cost] == NULL) {
 130     parse_err(SEMERR, "Did not declare 'ins_cost' attribute");
 131   }
 132   if (_globalNames[AttributeForm::_ins_pc_relative] == NULL) {
 133     parse_err(SEMERR, "Did not declare 'ins_pc_relative' attribute");
 134   }
 135   if (_globalNames[AttributeForm::_op_cost] == NULL) {
 136     parse_err(SEMERR, "Did not declare 'op_cost' attribute");
 137   }
 138 }
 139 
 140 // ******************** Private Level 1 Parse Functions ********************
 141 //------------------------------instr_parse------------------------------------
 142 // Parse the contents of an instruction definition, build the InstructForm to
 143 // represent that instruction, and add it to the InstructForm list.
 144 void ADLParser::instr_parse(void) {
 145   char          *ident;
 146   InstructForm  *instr;
 147   MatchRule     *rule;
 148   int            match_rules_cnt = 0;
 149 
 150   // First get the name of the instruction
 151   if( (ident = get_unique_ident(_globalNames,"instruction")) == NULL )
 152     return;
 153   instr = new InstructForm(ident); // Create new instruction form
 154   instr->_linenum = _linenum;
 155   _globalNames.Insert(ident, instr); // Add name to the name table
 156   // Debugging Stuff
 157   if (_AD._adl_debug > 1)
 158     fprintf(stderr,"Parsing Instruction Form %s\n", ident);
 159 
 160   // Then get the operands
 161   skipws();
 162   if (_curchar != '(') {
 163     parse_err(SYNERR, "missing '(' in instruct definition\n");
 164   }
 165   // Parse the operand list
 166   else get_oplist(instr->_parameters, instr->_localNames);
 167   skipws();                        // Skip leading whitespace
 168   // Check for block delimiter
 169   if ( (_curchar != '%') 
 170        || ( next_char(),  (_curchar != '{')) ) { 
 171     parse_err(SYNERR, "missing '%{' in instruction definition\n");
 172     return;
 173   }
 174   next_char();                     // Maintain the invariant
 175   do {
 176     ident = get_ident();           // Grab next identifier
 177     if (ident == NULL) {
 178       parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
 179       continue;
 180     }
 181     if      (!strcmp(ident, "predicate")) instr->_predicate = pred_parse();
 182     else if      (!strcmp(ident, "match")) {
 183       // Allow one instruction have several match rules.
 184       rule = instr->_matrule;
 185       if (rule == NULL) {
 186         // This is first match rule encountered
 187         rule = match_parse(instr->_localNames);
 188         if (rule) {
 189           instr->_matrule = rule;
 190           // Special case the treatment of Control instructions.
 191           if( instr->is_ideal_control() ) {
 192             // Control instructions return a special result, 'Universe'
 193             rule->_result = "Universe";
 194           }
 195           // Check for commutative operations with tree operands.
 196           matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt);
 197         }
 198       } else {
 199         // Find the end of the match rule list
 200         while (rule->_next != NULL)
 201           rule = rule->_next;
 202         // Add the new match rule to the list
 203         rule->_next = match_parse(instr->_localNames);
 204         if (rule->_next) {
 205           rule = rule->_next; 
 206           if( instr->is_ideal_control() ) {
 207             parse_err(SYNERR, "unique match rule expected for %s\n", rule->_name);
 208             return;
 209           }
 210           assert(match_rules_cnt < 100," too many match rule clones");
 211           char* buf = (char*) malloc(strlen(instr->_ident) + 4);
 212           sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++);
 213           rule->_result = buf;
 214           // Check for commutative operations with tree operands.
 215           matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt);
 216         }
 217       }
 218     }
 219     else if (!strcmp(ident, "encode"))  {
 220       parse_err(SYNERR, "Instructions specify ins_encode, not encode\n");
 221     }
 222     else if (!strcmp(ident, "ins_encode"))
 223       instr->_insencode = ins_encode_parse(*instr);
 224     else if (!strcmp(ident, "opcode"))  instr->_opcode = opcode_parse(instr);
 225     else if (!strcmp(ident, "size"))    instr->_size = size_parse(instr);
 226     else if (!strcmp(ident, "effect"))  effect_parse(instr);
 227     else if (!strcmp(ident, "expand"))  instr->_exprule = expand_parse(instr);
 228     else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
 229     else if (!strcmp(ident, "constraint")) {
 230       parse_err(SYNERR, "Instructions do not specify a constraint\n");
 231     }
 232     else if (!strcmp(ident, "construct")) {
 233       parse_err(SYNERR, "Instructions do not specify a construct\n");
 234     }
 235     else if (!strcmp(ident, "format"))  instr->_format  = format_parse();
 236     else if (!strcmp(ident, "interface")) {
 237       parse_err(SYNERR, "Instructions do not specify an interface\n");
 238     }
 239     else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr);
 240     else {  // Done with staticly defined parts of instruction definition
 241       // Check identifier to see if it is the name of an attribute
 242       const Form    *form = _globalNames[ident];
 243       AttributeForm *attr = form ? form->is_attribute() : NULL;
 244       if( attr && (attr->_atype == INS_ATTR) ) {
 245         // Insert the new attribute into the linked list.
 246         Attribute *temp = attr_parse(ident);
 247         temp->_next = instr->_attribs;
 248         instr->_attribs = temp;
 249       } else {
 250         parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of an instruction attribute at %s\n", ident);
 251       }
 252     }
 253     skipws();
 254   } while(_curchar != '%');
 255   next_char();
 256   if (_curchar != '}') {
 257     parse_err(SYNERR, "missing '%}' in instruction definition\n");
 258     return;
 259   }
 260   // Check for "Set" form of chain rule
 261   adjust_set_rule(instr);
 262   if (_AD._pipeline ) {
 263     if( instr->expands() ) {
 264       if( instr->_ins_pipe ) 
 265         parse_err(WARN, "ins_pipe and expand rule both specified for instruction \"%s\"; ins_pipe will be unused\n", instr->_ident); 
 266     } else {
 267       if( !instr->_ins_pipe ) 
 268         parse_err(WARN, "No ins_pipe specified for instruction \"%s\"\n", instr->_ident); 
 269     }
 270   }
 271   // Add instruction to tail of instruction list
 272   _AD.addForm(instr);
 273 
 274   // Create instruction form for each additional match rule
 275   rule = instr->_matrule;
 276   if (rule != NULL) {
 277     rule = rule->_next;
 278     while (rule != NULL) {
 279       ident = (char*)rule->_result;
 280       InstructForm *clone = new InstructForm(ident, instr, rule); // Create new instruction form
 281       _globalNames.Insert(ident, clone); // Add name to the name table
 282       // Debugging Stuff
 283       if (_AD._adl_debug > 1)
 284         fprintf(stderr,"Parsing Instruction Form %s\n", ident);
 285       // Check for "Set" form of chain rule
 286       adjust_set_rule(clone);
 287       // Add instruction to tail of instruction list
 288       _AD.addForm(clone);
 289       rule = rule->_next;
 290       clone->_matrule->_next = NULL; // One match rule per clone
 291     }
 292   }
 293 }
 294 
 295 //------------------------------matchrule_clone_and_swap-----------------------
 296 // Check for commutative operations with subtree operands, 
 297 // create clones and swap operands.
 298 void ADLParser::matchrule_clone_and_swap(MatchRule* rule, const char* instr_ident, int& match_rules_cnt) {
 299   // Check for commutative operations with tree operands.
 300   int count = 0;
 301   rule->count_commutative_op(count);
 302   if (count > 0) {
 303     // Clone match rule and swap commutative operation's operands.
 304     rule->swap_commutative_op(instr_ident, count, match_rules_cnt);
 305   } 
 306 }
 307 
 308 //------------------------------adjust_set_rule--------------------------------
 309 // Check for "Set" form of chain rule
 310 void ADLParser::adjust_set_rule(InstructForm *instr) {
 311   if (instr->_matrule == NULL || instr->_matrule->_rChild == NULL) return;
 312   const char *rch = instr->_matrule->_rChild->_opType;
 313   const Form *frm = _globalNames[rch];
 314   if( (! strcmp(instr->_matrule->_opType,"Set")) &&
 315       frm && frm->is_operand() && (! frm->ideal_only()) ) {
 316     // Previous implementation, which missed leaP*, but worked for loadCon*
 317     unsigned    position = 0;
 318     const char *result   = NULL;
 319     const char *name     = NULL;
 320     const char *optype   = NULL;
 321     MatchNode  *right    = instr->_matrule->_rChild;
 322     if (right->base_operand(position, _globalNames, result, name, optype)) {
 323       position = 1;
 324       const char *result2  = NULL;
 325       const char *name2    = NULL;
 326       const char *optype2  = NULL;
 327       // Can not have additional base operands in right side of match!
 328       if ( ! right->base_operand( position, _globalNames, result2, name2, optype2) ) {
 329         assert( instr->_predicate == NULL, "ADLC does not support instruction chain rules with predicates");
 330         // Chain from input  _ideal_operand_type_, 
 331         // Needed for shared roots of match-trees
 332         ChainList *lst = (ChainList *)_AD._chainRules[optype];
 333         if (lst == NULL) {
 334           lst = new ChainList();
 335           _AD._chainRules.Insert(optype, lst);
 336         }
 337         if (!lst->search(instr->_matrule->_lChild->_opType)) {
 338           const char *cost = instr->cost();
 339           if (cost == NULL) {
 340             cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;
 341           }
 342           // The ADLC does not support chaining from the ideal operand type 
 343           // of a predicated user-defined operand
 344           if( frm->is_operand() == NULL || frm->is_operand()->_predicate == NULL ) {
 345             lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident);
 346           }
 347         }
 348         // Chain from input  _user_defined_operand_type_,
 349         lst = (ChainList *)_AD._chainRules[result];
 350         if (lst == NULL) {
 351           lst = new ChainList();
 352           _AD._chainRules.Insert(result, lst);
 353         }
 354         if (!lst->search(instr->_matrule->_lChild->_opType)) {
 355           const char *cost = instr->cost();
 356           if (cost == NULL) {
 357             cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;
 358           }
 359           // It is safe to chain from the top-level user-defined operand even
 360           // if it has a predicate, since the predicate is checked before 
 361           // the user-defined type is available.
 362           lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident);
 363         }
 364       } else {
 365         // May have instruction chain rule if root of right-tree is an ideal
 366         OperandForm *rightOp = _globalNames[right->_opType]->is_operand();
 367         if( rightOp ) {
 368           const Form *rightRoot = _globalNames[rightOp->_matrule->_opType];
 369           if( rightRoot && rightRoot->ideal_only() ) {
 370             const char *chain_op = NULL;
 371             if( rightRoot->is_instruction() )
 372               chain_op = rightOp->_ident;
 373             if( chain_op ) {
 374               // Look-up the operation in chain rule table
 375               ChainList *lst = (ChainList *)_AD._chainRules[chain_op];
 376               if (lst == NULL) {
 377                 lst = new ChainList();
 378                 _AD._chainRules.Insert(chain_op, lst);
 379               }
 380               // if (!lst->search(instr->_matrule->_lChild->_opType)) {
 381               const char *cost = instr->cost();
 382               if (cost == NULL) {
 383                 cost = ((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;
 384               }
 385               // This chains from a top-level operand whose predicate, if any,
 386               // has been checked.
 387               lst->insert(instr->_matrule->_lChild->_opType,cost,instr->_ident);
 388               // }
 389             }
 390           }
 391         }
 392       } // end chain rule from right-tree's ideal root
 393     }
 394   }
 395 }
 396 
 397 
 398 //------------------------------oper_parse-------------------------------------
 399 void ADLParser::oper_parse(void) {
 400   char          *ident;
 401   OperandForm   *oper;
 402   AttributeForm *attr;
 403   MatchRule     *rule;
 404 
 405   // First get the name of the operand
 406   skipws();
 407   if( (ident = get_unique_ident(_globalNames,"operand")) == NULL )
 408     return;
 409   oper = new OperandForm(ident);        // Create new operand form
 410   oper->_linenum = _linenum;
 411   _globalNames.Insert(ident, oper); // Add name to the name table
 412 
 413   // Debugging Stuff
 414   if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Operand Form %s\n", ident);
 415 
 416   // Get the component operands
 417   skipws();
 418   if (_curchar != '(') {
 419     parse_err(SYNERR, "missing '(' in operand definition\n");
 420     return;
 421   }
 422   else get_oplist(oper->_parameters, oper->_localNames); // Parse the component operand list
 423   skipws();
 424   // Check for block delimiter
 425   if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block
 426     parse_err(SYNERR, "missing '%c{' in operand definition\n","%");
 427     return;
 428   }
 429   next_char(); next_char();        // Skip over "%{" symbol
 430   do {
 431     ident = get_ident();           // Grab next identifier
 432     if (ident == NULL) {
 433       parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
 434       continue;
 435     }
 436     if      (!strcmp(ident, "predicate")) oper->_predicate = pred_parse();
 437     else if (!strcmp(ident, "match"))     {
 438       // Find the end of the match rule list
 439       rule = oper->_matrule;
 440       if (rule) {
 441         while (rule->_next) rule = rule->_next;
 442         // Add the new match rule to the list
 443         rule->_next = match_parse(oper->_localNames);
 444         if (rule->_next) {
 445           rule->_next->_result = oper->_ident;
 446         }
 447       }
 448       else {
 449         // This is first match rule encountered
 450         oper->_matrule = match_parse(oper->_localNames);
 451         if (oper->_matrule) {
 452           oper->_matrule->_result = oper->_ident;
 453         }
 454       }
 455     }
 456     else if (!strcmp(ident, "encode"))    oper->_interface = interface_parse();
 457     else if (!strcmp(ident, "ins_encode")) {
 458       parse_err(SYNERR, "Operands specify 'encode', not 'ins_encode'\n");
 459     }
 460     else if (!strcmp(ident, "opcode"))    {
 461       parse_err(SYNERR, "Operands do not specify an opcode\n");
 462     }   
 463     else if (!strcmp(ident, "effect"))    {
 464       parse_err(SYNERR, "Operands do not specify an effect\n");
 465     }
 466     else if (!strcmp(ident, "expand"))    {
 467       parse_err(SYNERR, "Operands do not specify an expand\n");
 468     }
 469     else if (!strcmp(ident, "rewrite"))   {
 470       parse_err(SYNERR, "Operands do not specify a rewrite\n");
 471     }
 472     else if (!strcmp(ident, "constraint"))oper->_constraint= constraint_parse();
 473     else if (!strcmp(ident, "construct")) oper->_construct = construct_parse();
 474     else if (!strcmp(ident, "format"))    oper->_format    = format_parse();
 475     else if (!strcmp(ident, "interface")) oper->_interface = interface_parse();
 476     // Check identifier to see if it is the name of an attribute
 477     else if (((attr = _globalNames[ident]->is_attribute()) != NULL) &&
 478              (attr->_atype == OP_ATTR))   oper->_attribs   = attr_parse(ident);
 479     else {
 480       parse_err(SYNERR, "expected one of - constraint, predicate, match, encode, format, construct, or the name of a defined operand attribute at %s\n", ident);
 481     }
 482     skipws();
 483   } while(_curchar != '%');
 484   next_char();
 485   if (_curchar != '}') {
 486     parse_err(SYNERR, "missing '%}' in operand definition\n");
 487     return;
 488   }
 489   // Add operand to tail of operand list
 490   _AD.addForm(oper);
 491 }
 492 
 493 //------------------------------opclass_parse----------------------------------
 494 // Operand Classes are a block with a comma delimited list of operand names
 495 void ADLParser::opclass_parse(void) {
 496   char          *ident;
 497   OpClassForm   *opc;
 498   OperandForm   *opForm;
 499 
 500   // First get the name of the operand class
 501   skipws();
 502   if( (ident = get_unique_ident(_globalNames,"opclass")) == NULL )
 503     return;
 504   opc = new OpClassForm(ident);             // Create new operand class form
 505   _globalNames.Insert(ident, opc);  // Add name to the name table
 506 
 507   // Debugging Stuff
 508   if (_AD._adl_debug > 1)
 509     fprintf(stderr,"Parsing Operand Class Form %s\n", ident);
 510 
 511   // Get the list of operands
 512   skipws();
 513   if (_curchar != '(') {
 514     parse_err(SYNERR, "missing '(' in operand definition\n");
 515     return;
 516   }
 517   do {
 518     next_char();                            // Skip past open paren or comma
 519     ident = get_ident();                    // Grab next identifier
 520     if (ident == NULL) {
 521       parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
 522       continue;
 523     }
 524     // Check identifier to see if it is the name of an operand
 525     const Form *form = _globalNames[ident];
 526     opForm     = form ? form->is_operand() : NULL;
 527     if ( opForm ) {
 528       opc->_oplst.addName(ident);           // Add operand to opclass list
 529       opForm->_classes.addName(opc->_ident);// Add opclass to operand list
 530     }
 531     else {
 532       parse_err(SYNERR, "expected name of a defined operand at %s\n", ident);
 533     }
 534     skipws();                               // skip trailing whitespace
 535   } while (_curchar == ',');                // Check for the comma
 536   // Check for closing ')'
 537   if (_curchar != ')') {
 538     parse_err(SYNERR, "missing ')' or ',' in opclass definition\n");
 539     return;
 540   }
 541   next_char();                              // Consume the ')'
 542   skipws();
 543   // Check for closing ';'
 544   if (_curchar != ';') {
 545     parse_err(SYNERR, "missing ';' in opclass definition\n");
 546     return;
 547   }
 548   next_char();                             // Consume the ';'
 549   // Add operand to tail of operand list
 550   _AD.addForm(opc);
 551 }
 552 
 553 //------------------------------ins_attr_parse---------------------------------
 554 void ADLParser::ins_attr_parse(void) {
 555   char          *ident;
 556   char          *aexpr;
 557   AttributeForm *attrib;
 558 
 559   // get name for the instruction attribute
 560   skipws();                      // Skip leading whitespace
 561   if( (ident = get_unique_ident(_globalNames,"inst_attrib")) == NULL )
 562     return;
 563   // Debugging Stuff
 564   if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Ins_Attribute Form %s\n", ident);
 565 
 566   // Get default value of the instruction attribute
 567   skipws();                      // Skip whitespace
 568   if ((aexpr = get_paren_expr("attribute default expression string")) == NULL) {
 569     parse_err(SYNERR, "missing '(' in ins_attrib definition\n");
 570     return;
 571   }
 572   // Debug Stuff
 573   if (_AD._adl_debug > 1) fprintf(stderr,"Attribute Expression: %s\n", aexpr);
 574 
 575   // Check for terminator
 576   if (_curchar != ';') {
 577     parse_err(SYNERR, "missing ';' in ins_attrib definition\n");
 578     return;
 579   }
 580   next_char();                    // Advance past the ';'
 581 
 582   // Construct the attribute, record global name, and store in ArchDesc
 583   attrib = new AttributeForm(ident, INS_ATTR, aexpr);
 584   _globalNames.Insert(ident, attrib);  // Add name to the name table
 585   _AD.addForm(attrib);
 586 }
 587 
 588 //------------------------------op_attr_parse----------------------------------
 589 void ADLParser::op_attr_parse(void) {
 590   char          *ident;
 591   char          *aexpr;
 592   AttributeForm *attrib;
 593 
 594   // get name for the operand attribute
 595   skipws();                      // Skip leading whitespace
 596   if( (ident = get_unique_ident(_globalNames,"op_attrib")) == NULL )
 597     return;
 598   // Debugging Stuff
 599   if (_AD._adl_debug > 1) fprintf(stderr,"Parsing Op_Attribute Form %s\n", ident);
 600 
 601   // Get default value of the instruction attribute
 602   skipws();                      // Skip whitespace
 603   if ((aexpr = get_paren_expr("attribute default expression string")) == NULL) {
 604     parse_err(SYNERR, "missing '(' in op_attrib definition\n");
 605     return;
 606   }
 607   // Debug Stuff
 608   if (_AD._adl_debug > 1) fprintf(stderr,"Attribute Expression: %s\n", aexpr);
 609 
 610   // Check for terminator
 611   if (_curchar != ';') {
 612     parse_err(SYNERR, "missing ';' in op_attrib definition\n");
 613     return;
 614   }
 615   next_char();                    // Advance past the ';'
 616   
 617   // Construct the attribute, record global name, and store in ArchDesc
 618   attrib = new AttributeForm(ident, OP_ATTR, aexpr); 
 619   _globalNames.Insert(ident, attrib);
 620   _AD.addForm(attrib);
 621 }
 622 
 623 //------------------------------definitions_parse-----------------------------------
 624 void ADLParser::definitions_parse(void) {
 625   skipws();                       // Skip leading whitespace
 626   if (_curchar == '%' && *(_ptr+1) == '{') {
 627     next_char(); next_char();     // Skip "%{"
 628     skipws();
 629     while (_curchar != '%' && *(_ptr+1) != '}') {
 630       // Process each definition until finding closing string "%}"
 631       char *token = get_ident();
 632       if (token == NULL) {
 633         parse_err(SYNERR, "missing identifier inside definitions block.\n");
 634         return;
 635       }
 636       if (strcmp(token,"int_def")==0)     { int_def_parse(); }
 637       // if (strcmp(token,"str_def")==0)   { str_def_parse(); }
 638       skipws();
 639     }
 640   }
 641   else {
 642     parse_err(SYNERR, "Missing %%{ ... %%} block after definitions keyword.\n");
 643     return;
 644   }
 645 }
 646 
 647 //------------------------------int_def_parse----------------------------------
 648 // Parse Example: 
 649 // int_def    MEMORY_REF_COST      (         200,  DEFAULT_COST * 2);
 650 // <keyword>  <name>               ( <int_value>,   <description>  );
 651 // 
 652 void ADLParser::int_def_parse(void) {
 653   char *name        = NULL;         // Name of definition
 654   char *value       = NULL;         // its value,
 655   int   int_value   = -1;           // positive values only
 656   char *description = NULL;         // textual description
 657 
 658   // Get definition name
 659   skipws();                      // Skip whitespace
 660   name = get_ident();
 661   if (name == NULL) {
 662     parse_err(SYNERR, "missing definition name after int_def\n");
 663     return;
 664   }
 665 
 666   // Check for value of int_def dname( integer_value [, string_expression ] )
 667   skipws();
 668   if (_curchar == '(') {
 669 
 670     // Parse the integer value.
 671     next_char();
 672     value = get_ident();
 673     if (value == NULL) {
 674       parse_err(SYNERR, "missing value in int_def\n");
 675       return;
 676     }
 677     if( !is_int_token(value, int_value) ) {
 678       parse_err(SYNERR, "value in int_def is not recognized as integer\n");
 679       return;
 680     }
 681     skipws();
 682 
 683     // Check for description
 684     if (_curchar == ',') {
 685       next_char();   // skip ','
 686 
 687       description = get_expr("int_def description", ")");
 688       if (description == NULL) {
 689         parse_err(SYNERR, "invalid or missing description in int_def\n");
 690         return;
 691       }
 692       trim(description);
 693     }
 694 
 695     if (_curchar != ')') {
 696       parse_err(SYNERR, "missing ')' in register definition statement\n");
 697       return;
 698     }
 699     next_char();
 700   }
 701 
 702   // Check for closing ';'
 703   skipws();
 704   if (_curchar != ';') {
 705     parse_err(SYNERR, "missing ';' after int_def\n");
 706     return;
 707   }
 708   next_char();                   // move past ';'
 709 
 710   // Debug Stuff
 711   if (_AD._adl_debug > 1) {
 712     fprintf(stderr,"int_def: %s ( %s, %s )\n", name, 
 713             (value), (description ? description : ""));
 714   }
 715   
 716   // Record new definition.
 717   Expr *expr     = new Expr(name, description, int_value, int_value);
 718   const Expr *old_expr = _AD.globalDefs().define(name, expr);
 719   if (old_expr != NULL) {
 720     parse_err(SYNERR, "Duplicate definition\n");
 721     return;
 722   }
 723 
 724   return;
 725 }
 726 
 727 
 728 //------------------------------source_parse-----------------------------------
 729 void ADLParser::source_parse(void) {
 730   SourceForm *source;             // Encode class for instruction/operand
 731   char   *rule = NULL;            // String representation of encode rule
 732 
 733   skipws();                       // Skip leading whitespace
 734   if ( (rule = find_cpp_block("source block")) == NULL ) {
 735     parse_err(SYNERR, "incorrect or missing block for 'source'.\n");
 736     return;
 737   }
 738   // Debug Stuff
 739   if (_AD._adl_debug > 1) fprintf(stderr,"Source Form: %s\n", rule);
 740 
 741   source = new SourceForm(rule);    // Build new Source object
 742   _AD.addForm(source);
 743   // skipws();
 744 }
 745 
 746 //------------------------------source_hpp_parse-------------------------------
 747 // Parse a source_hpp %{ ... %} block.
 748 // The code gets stuck into the ad_<arch>.hpp file.
 749 // If the source_hpp block appears before the register block in the AD
 750 // file, it goes up at the very top of the ad_<arch>.hpp file, so that
 751 // it can be used by register encodings, etc.  Otherwise, it goes towards
 752 // the bottom, where it's useful as a global definition to *.cpp files.
 753 void ADLParser::source_hpp_parse(void) {
 754   char   *rule = NULL;            // String representation of encode rule
 755 
 756   skipws();                       // Skip leading whitespace
 757   if ( (rule = find_cpp_block("source_hpp block")) == NULL ) {
 758     parse_err(SYNERR, "incorrect or missing block for 'source_hpp'.\n");
 759     return;
 760   }
 761   // Debug Stuff
 762   if (_AD._adl_debug > 1) fprintf(stderr,"Header Form: %s\n", rule);
 763 
 764   if (_AD.get_registers() == NULL) {
 765     // Very early in the file, before reg_defs, we collect pre-headers.
 766     PreHeaderForm* pre_header = new PreHeaderForm(rule);
 767     _AD.addForm(pre_header);
 768   } else {
 769     // Normally, we collect header info, placed at the bottom of the hpp file.
 770     HeaderForm* header = new HeaderForm(rule);
 771     _AD.addForm(header);
 772   }
 773 }
 774 
 775 //------------------------------reg_parse--------------------------------------
 776 void ADLParser::reg_parse(void) {
 777 
 778   // Create the RegisterForm for the architecture description.
 779   RegisterForm *regBlock = new RegisterForm();    // Build new Source object
 780   regBlock->_linenum = _linenum;
 781   _AD.addForm(regBlock);
 782 
 783   skipws();                       // Skip leading whitespace
 784   if (_curchar == '%' && *(_ptr+1) == '{') {
 785     next_char(); next_char();     // Skip "%{"
 786     skipws();
 787     while (_curchar != '%' && *(_ptr+1) != '}') {
 788       char *token = get_ident();
 789       if (token == NULL) {
 790         parse_err(SYNERR, "missing identifier inside register block.\n");
 791         return;
 792       }
 793       if (strcmp(token,"reg_def")==0)     { reg_def_parse(); }
 794       if (strcmp(token,"reg_class")==0)   { reg_class_parse(); }
 795       if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); }
 796       skipws();
 797     }
 798   }
 799   else {
 800     parse_err(SYNERR, "Missing %c{ ... %c} block after register keyword.\n",'%','%');
 801     return;
 802   }
 803   
 804   // Add reg_class spill_regs
 805   regBlock->addSpillRegClass();
 806 }
 807 
 808 //------------------------------encode_parse-----------------------------------
 809 void ADLParser::encode_parse(void) {
 810   EncodeForm *encBlock;         // Information about instruction/operand encoding
 811   char       *desc = NULL;      // String representation of encode rule
 812 
 813   _AD.getForm(&encBlock);
 814   if ( encBlock == NULL) {
 815     // Create the EncodeForm for the architecture description.
 816     encBlock = new EncodeForm();    // Build new Source object
 817     _AD.addForm(encBlock);
 818   }
 819 
 820   skipws();                       // Skip leading whitespace
 821   if (_curchar == '%' && *(_ptr+1) == '{') {
 822     next_char(); next_char();     // Skip "%{"
 823     skipws();
 824     while (_curchar != '%' && *(_ptr+1) != '}') {
 825       char *token = get_ident();
 826       if (token == NULL) {
 827             parse_err(SYNERR, "missing identifier inside encoding block.\n");
 828             return;
 829       }
 830       if (strcmp(token,"enc_class")==0)   { enc_class_parse(); }
 831       skipws();
 832     }
 833   }
 834   else {
 835     parse_err(SYNERR, "Missing %c{ ... %c} block after encode keyword.\n",'%','%');
 836     return;
 837   }
 838 }
 839 
 840 //------------------------------enc_class_parse--------------------------------
 841 void ADLParser::enc_class_parse(void) {
 842   char       *ec_name;           // Name of encoding class being defined
 843 
 844   // Get encoding class name
 845   skipws();                      // Skip whitespace
 846   ec_name = get_ident();
 847   if (ec_name == NULL) {
 848     parse_err(SYNERR, "missing encoding class name after encode.\n");
 849     return;
 850   }
 851 
 852   EncClass  *encoding = _AD._encode->add_EncClass(ec_name);
 853   encoding->_linenum = _linenum;
 854 
 855   skipws();                      // Skip leading whitespace
 856   // Check for optional parameter list
 857   if (_curchar == '(') {
 858     do {
 859       char *pType = NULL;        // parameter type
 860       char *pName = NULL;        // parameter name
 861 
 862       next_char();               // skip open paren & comma characters
 863       skipws();
 864       if (_curchar == ')') break;
 865       
 866       // Get parameter type
 867       pType = get_ident();
 868       if (pType == NULL) {
 869         parse_err(SYNERR, "parameter type expected at %c\n", _curchar);
 870         return;
 871       }
 872 
 873       skipws();
 874       // Get parameter name
 875       pName = get_ident();
 876       if (pName == NULL) {
 877         parse_err(SYNERR, "parameter name expected at %c\n", _curchar);
 878         return;
 879       }
 880 
 881       // Record parameter type and name
 882       encoding->add_parameter( pType, pName );
 883 
 884       skipws();
 885     } while(_curchar == ',');
 886 
 887     if (_curchar != ')') parse_err(SYNERR, "missing ')'\n");
 888     else {
 889       next_char();                  // Skip ')'
 890     }
 891   } // Done with parameter list
 892 
 893   skipws();
 894   // Check for block starting delimiters
 895   if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block
 896     parse_err(SYNERR, "missing '%c{' in enc_class definition\n", '%');
 897     return;
 898   }
 899   next_char();                      // Skip '%'
 900   next_char();                      // Skip '{'
 901 
 902   enc_class_parse_block(encoding, ec_name);
 903 }
 904 
 905 
 906 void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
 907   skipws_no_preproc();              // Skip leading whitespace
 908   // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
 909   if (_AD._adlocation_debug) {
 910     const char* file     = _AD._ADL_file._name;
 911     int         line     = _linenum;
 912     char*       location = (char *)malloc(strlen(file) + 100);
 913     sprintf(location, "#line %d \"%s\"\n", line, file);
 914     encoding->add_code(location);
 915   }
 916       
 917   // Collect the parts of the encode description
 918   // (1) strings that are passed through to output
 919   // (2) replacement/substitution variable, preceeded by a '$'
 920   while ( (_curchar != '%') && (*(_ptr+1) != '}') ) {
 921       
 922     // (1)
 923     // Check if there is a string to pass through to output
 924     char *start = _ptr;       // Record start of the next string
 925     while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
 926       // If at the start of a comment, skip past it
 927       if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
 928         skipws_no_preproc();
 929       } else {
 930         // ELSE advance to the next character, or start of the next line
 931         next_char_or_line();
 932       }
 933     }
 934     // If a string was found, terminate it and record in EncClass
 935     if ( start != _ptr ) {
 936       *_ptr  = '\0';          // Terminate the string
 937       encoding->add_code(start);
 938     }
 939         
 940     // (2)
 941     // If we are at a replacement variable, 
 942     // copy it and record in EncClass
 943     if ( _curchar == '$' ) {
 944       // Found replacement Variable
 945       char *rep_var = get_rep_var_ident_dup();
 946       // Add flag to _strings list indicating we should check _rep_vars
 947       encoding->add_rep_var(rep_var);
 948     }
 949   } // end while part of format description
 950   next_char();                      // Skip '%'
 951   next_char();                      // Skip '}'
 952 
 953   skipws();
 954 
 955   // Debug Stuff
 956   if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
 957 }
 958 
 959 //------------------------------frame_parse-----------------------------------
 960 void ADLParser::frame_parse(void) {
 961   FrameForm  *frame;              // Information about stack-frame layout
 962   char       *desc = NULL;        // String representation of frame
 963 
 964   skipws();                       // Skip leading whitespace
 965 
 966   frame = new FrameForm();        // Build new Frame object
 967   // Check for open block sequence
 968   skipws();                       // Skip leading whitespace
 969   if (_curchar == '%' && *(_ptr+1) == '{') {
 970     next_char(); next_char();     // Skip "%{"
 971     skipws();
 972     while (_curchar != '%' && *(_ptr+1) != '}') {
 973       char *token = get_ident();
 974       if (token == NULL) {
 975             parse_err(SYNERR, "missing identifier inside frame block.\n");
 976             return;
 977       }
 978       if (strcmp(token,"stack_direction")==0) { 
 979         stack_dir_parse(frame);
 980       }
 981       if (strcmp(token,"sync_stack_slots")==0) {
 982         sync_stack_slots_parse(frame);
 983       }
 984       if (strcmp(token,"frame_pointer")==0) {
 985         frame_pointer_parse(frame, false);
 986       }
 987       if (strcmp(token,"interpreter_frame_pointer")==0) {
 988         interpreter_frame_pointer_parse(frame, false);
 989         // Add  reg_class interpreter_frame_pointer_reg
 990         if( _AD._register != NULL ) {
 991           RegClass *reg_class = _AD._register->addRegClass("interpreter_frame_pointer_reg");
 992           char *interpreter_frame_pointer_reg = frame->_interpreter_frame_pointer_reg;
 993           if( interpreter_frame_pointer_reg != NULL ) {
 994             RegDef *regDef = _AD._register->getRegDef(interpreter_frame_pointer_reg);
 995             reg_class->addReg(regDef);     // add regDef to regClass
 996           }
 997         }
 998       }
 999       if (strcmp(token,"inline_cache_reg")==0) {
1000         inline_cache_parse(frame, false);
1001         // Add  reg_class inline_cache_reg
1002         if( _AD._register != NULL ) {
1003           RegClass *reg_class = _AD._register->addRegClass("inline_cache_reg");
1004           char *inline_cache_reg = frame->_inline_cache_reg;
1005           if( inline_cache_reg != NULL ) {
1006             RegDef *regDef = _AD._register->getRegDef(inline_cache_reg);
1007             reg_class->addReg(regDef);     // add regDef to regClass
1008           }
1009         }
1010       }
1011       if (strcmp(token,"compiler_method_oop_reg")==0) {
1012         parse_err(WARN, "Using obsolete Token, compiler_method_oop_reg");
1013         skipws();
1014       }
1015       if (strcmp(token,"interpreter_method_oop_reg")==0) {
1016         interpreter_method_oop_parse(frame, false);
1017         // Add  reg_class interpreter_method_oop_reg
1018         if( _AD._register != NULL ) {
1019           RegClass *reg_class = _AD._register->addRegClass("interpreter_method_oop_reg");
1020           char *method_oop_reg = frame->_interpreter_method_oop_reg;
1021           if( method_oop_reg != NULL ) {
1022             RegDef *regDef = _AD._register->getRegDef(method_oop_reg);
1023             reg_class->addReg(regDef);     // add regDef to regClass
1024           }
1025         }
1026       }
1027       if (strcmp(token,"cisc_spilling_operand_name")==0) {
1028         cisc_spilling_operand_name_parse(frame, false);
1029       }
1030       if (strcmp(token,"stack_alignment")==0) {
1031         stack_alignment_parse(frame);
1032       }
1033       if (strcmp(token,"return_addr")==0) {
1034         return_addr_parse(frame, false);
1035       }
1036       if (strcmp(token,"in_preserve_stack_slots")==0) {
1037         preserve_stack_parse(frame);
1038       }
1039       if (strcmp(token,"out_preserve_stack_slots")==0) {
1040         parse_err(WARN, "Using obsolete token, out_preserve_stack_slots");
1041         skipws();
1042       }
1043       if (strcmp(token,"varargs_C_out_slots_killed")==0) {
1044         frame->_varargs_C_out_slots_killed = parse_one_arg("varargs C out slots killed");
1045       }
1046       if (strcmp(token,"calling_convention")==0) {
1047         frame->_calling_convention = calling_convention_parse();
1048       }
1049       if (strcmp(token,"return_value")==0) {
1050         frame->_return_value = return_value_parse();
1051       }
1052       if (strcmp(token,"c_frame_pointer")==0) {
1053         frame_pointer_parse(frame, true);
1054       }
1055       if (strcmp(token,"c_return_addr")==0) {
1056         return_addr_parse(frame, true);
1057       }
1058       if (strcmp(token,"c_calling_convention")==0) {
1059         frame->_c_calling_convention = calling_convention_parse();
1060       }
1061       if (strcmp(token,"c_return_value")==0) {
1062         frame->_c_return_value = return_value_parse();
1063       }
1064 
1065       skipws();
1066     }
1067   }
1068   else {
1069     parse_err(SYNERR, "Missing %c{ ... %c} block after encode keyword.\n",'%','%');
1070     return;
1071   }
1072   // All Java versions are required, native versions are optional
1073   if(frame->_frame_pointer == NULL) {
1074     parse_err(SYNERR, "missing frame pointer definition in frame section.\n");
1075     return;
1076   }
1077   // !!!!! !!!!!
1078   // if(frame->_interpreter_frame_ptr_reg == NULL) {
1079   //   parse_err(SYNERR, "missing interpreter frame pointer definition in frame section.\n");
1080   //   return;
1081   // }
1082   if(frame->_alignment == NULL) {
1083     parse_err(SYNERR, "missing alignment definition in frame section.\n");
1084     return;
1085   }
1086   if(frame->_return_addr == NULL) {
1087     parse_err(SYNERR, "missing return address location in frame section.\n");
1088     return;
1089   }
1090   if(frame->_in_preserve_slots == NULL) {
1091     parse_err(SYNERR, "missing stack slot preservation definition in frame section.\n");
1092     return;
1093   }
1094   if(frame->_varargs_C_out_slots_killed == NULL) {
1095     parse_err(SYNERR, "missing varargs C out slots killed definition in frame section.\n");
1096     return;
1097   }
1098   if(frame->_calling_convention == NULL) {
1099     parse_err(SYNERR, "missing calling convention definition in frame section.\n");
1100     return;
1101   }
1102   if(frame->_return_value == NULL) {
1103     parse_err(SYNERR, "missing return value definition in frame section.\n");
1104     return;
1105   }
1106   // Fill natives in identically with the Java versions if not present.
1107   if(frame->_c_frame_pointer == NULL) {
1108     frame->_c_frame_pointer = frame->_frame_pointer;
1109   }
1110   if(frame->_c_return_addr == NULL) {
1111     frame->_c_return_addr = frame->_return_addr;
1112     frame->_c_return_addr_loc = frame->_return_addr_loc;
1113   }
1114   if(frame->_c_calling_convention == NULL) {
1115     frame->_c_calling_convention = frame->_calling_convention;
1116   }
1117   if(frame->_c_return_value == NULL) {
1118     frame->_c_return_value = frame->_return_value;
1119   }
1120 
1121   // Debug Stuff
1122   if (_AD._adl_debug > 1) fprintf(stderr,"Frame Form: %s\n", desc);
1123 
1124   // Create the EncodeForm for the architecture description.
1125   _AD.addForm(frame);
1126   // skipws();
1127 }
1128 
1129 //------------------------------stack_dir_parse--------------------------------
1130 void ADLParser::stack_dir_parse(FrameForm *frame) {
1131   char *direction = parse_one_arg("stack direction entry");
1132   if (strcmp(direction, "TOWARDS_LOW") == 0) {
1133     frame->_direction = false;
1134   }
1135   else if (strcmp(direction, "TOWARDS_HIGH") == 0) {
1136     frame->_direction = true;
1137   }
1138   else {
1139     parse_err(SYNERR, "invalid value inside stack direction entry.\n");
1140     return;
1141   }
1142 }
1143 
1144 //------------------------------sync_stack_slots_parse-------------------------
1145 void ADLParser::sync_stack_slots_parse(FrameForm *frame) {
1146     // Assign value into frame form
1147     frame->_sync_stack_slots = parse_one_arg("sync stack slots entry");
1148 }
1149 
1150 //------------------------------frame_pointer_parse----------------------------
1151 void ADLParser::frame_pointer_parse(FrameForm *frame, bool native) {
1152   char *frame_pointer = parse_one_arg("frame pointer entry");
1153   // Assign value into frame form
1154   if (native) { frame->_c_frame_pointer = frame_pointer; }
1155   else        { frame->_frame_pointer   = frame_pointer; }
1156 }
1157 
1158 //------------------------------interpreter_frame_pointer_parse----------------------------
1159 void ADLParser::interpreter_frame_pointer_parse(FrameForm *frame, bool native) {
1160   frame->_interpreter_frame_pointer_reg = parse_one_arg("interpreter frame pointer entry");
1161 }
1162 
1163 //------------------------------inline_cache_parse-----------------------------
1164 void ADLParser::inline_cache_parse(FrameForm *frame, bool native) {
1165   frame->_inline_cache_reg = parse_one_arg("inline cache reg entry");
1166 }
1167 
1168 //------------------------------interpreter_method_oop_parse------------------
1169 void ADLParser::interpreter_method_oop_parse(FrameForm *frame, bool native) {
1170   frame->_interpreter_method_oop_reg = parse_one_arg("method oop reg entry");
1171 }
1172 
1173 //------------------------------cisc_spilling_operand_parse---------------------
1174 void ADLParser::cisc_spilling_operand_name_parse(FrameForm *frame, bool native) {
1175   frame->_cisc_spilling_operand_name = parse_one_arg("cisc spilling operand name");
1176 }
1177 
1178 //------------------------------stack_alignment_parse--------------------------
1179 void ADLParser::stack_alignment_parse(FrameForm *frame) {
1180   char *alignment = parse_one_arg("stack alignment entry");
1181   // Assign value into frame
1182   frame->_alignment   = alignment;
1183 }
1184 
1185 //------------------------------parse_one_arg-------------------------------
1186 char *ADLParser::parse_one_arg(const char *description) {
1187   char *token = NULL;
1188   if(_curchar == '(') {
1189     next_char();
1190     skipws();
1191     token = get_expr(description, ")");
1192     if (token == NULL) {
1193       parse_err(SYNERR, "missing value inside %s.\n", description);
1194       return NULL;
1195     }
1196     next_char();           // skip the close paren
1197     if(_curchar != ';') {  // check for semi-colon
1198       parse_err(SYNERR, "missing %c in.\n", ';', description);
1199       return NULL;
1200     }
1201     next_char();           // skip the semi-colon
1202   }
1203   else {
1204     parse_err(SYNERR, "Missing %c in.\n", '(', description);
1205     return NULL;
1206   }
1207 
1208   trim(token);
1209   return token;
1210 }
1211 
1212 //------------------------------return_addr_parse------------------------------
1213 void ADLParser::return_addr_parse(FrameForm *frame, bool native) {
1214   bool in_register  = true;
1215   if(_curchar == '(') {
1216     next_char();
1217     skipws();
1218     char *token = get_ident();
1219     if (token == NULL) {
1220       parse_err(SYNERR, "missing value inside return address entry.\n");
1221       return;
1222     }
1223     // check for valid values for stack/register
1224     if (strcmp(token, "REG") == 0) {
1225       in_register = true;
1226     }
1227     else if (strcmp(token, "STACK") == 0) {
1228       in_register = false;
1229     }
1230     else {
1231       parse_err(SYNERR, "invalid value inside return_address entry.\n");
1232       return;
1233     }
1234     if (native) { frame->_c_return_addr_loc = in_register; }
1235     else        { frame->_return_addr_loc   = in_register; }
1236 
1237     // Parse expression that specifies register or stack position
1238     skipws();
1239     char *token2 = get_expr("return address entry", ")");
1240     if (token2 == NULL) {
1241       parse_err(SYNERR, "missing value inside return address entry.\n");
1242       return;
1243     }
1244     next_char();           // skip the close paren
1245     if (native) { frame->_c_return_addr = token2; }
1246     else        { frame->_return_addr   = token2; }
1247 
1248     if(_curchar != ';') {  // check for semi-colon
1249       parse_err(SYNERR, "missing %c in return address entry.\n", ';');
1250       return;
1251     }
1252     next_char();           // skip the semi-colon
1253   }
1254   else {
1255     parse_err(SYNERR, "Missing %c in return_address entry.\n", '(');
1256   }
1257 }
1258 
1259 //------------------------------preserve_stack_parse---------------------------
1260 void ADLParser::preserve_stack_parse(FrameForm *frame) {
1261   if(_curchar == '(') {
1262     char *token = get_paren_expr("preserve_stack_slots");
1263     frame->_in_preserve_slots   = token;
1264 
1265     if(_curchar != ';') {  // check for semi-colon
1266       parse_err(SYNERR, "missing %c in preserve stack slot entry.\n", ';');
1267       return;
1268     }
1269     next_char();           // skip the semi-colon
1270   }
1271   else {
1272     parse_err(SYNERR, "Missing %c in preserve stack slot entry.\n", '(');
1273   }
1274 }
1275 
1276 //------------------------------calling_convention_parse-----------------------
1277 char *ADLParser::calling_convention_parse() {
1278   char   *desc = NULL;          // String representation of calling_convention
1279 
1280   skipws();                     // Skip leading whitespace
1281   if ( (desc = find_cpp_block("calling convention block")) == NULL ) {
1282     parse_err(SYNERR, "incorrect or missing block for 'calling_convention'.\n");
1283   }
1284   return desc;
1285 }
1286 
1287 //------------------------------return_value_parse-----------------------------
1288 char *ADLParser::return_value_parse() {
1289   char   *desc = NULL;          // String representation of calling_convention
1290 
1291   skipws();                     // Skip leading whitespace
1292   if ( (desc = find_cpp_block("return value block")) == NULL ) {
1293     parse_err(SYNERR, "incorrect or missing block for 'return_value'.\n");
1294   }
1295   return desc;
1296 }
1297 
1298 //------------------------------ins_pipe_parse---------------------------------
1299 void ADLParser::ins_pipe_parse(InstructForm &instr) {
1300   char * ident;
1301 
1302   skipws();
1303   if ( _curchar != '(' ) {       // Check for delimiter
1304     parse_err(SYNERR, "missing \"(\" in ins_pipe definition\n");
1305     return;
1306   }
1307 
1308   next_char();
1309   ident = get_ident();           // Grab next identifier
1310 
1311   if (ident == NULL) {
1312     parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
1313     return;
1314   }
1315 
1316   skipws();
1317   if ( _curchar != ')' ) {       // Check for delimiter
1318     parse_err(SYNERR, "missing \")\" in ins_pipe definition\n");
1319     return;
1320   }
1321 
1322   next_char();                   // skip the close paren
1323   if(_curchar != ';') {          // check for semi-colon
1324     parse_err(SYNERR, "missing %c in return value entry.\n", ';');
1325     return;
1326   }
1327   next_char();                   // skip the semi-colon
1328 
1329   // Check ident for validity
1330   if (_AD._pipeline && !_AD._pipeline->_classlist.search(ident)) {
1331     parse_err(SYNERR, "\"%s\" is not a valid pipeline class\n", ident);
1332     return;
1333   }
1334 
1335   // Add this instruction to the list in the pipeline class
1336   _AD._pipeline->_classdict[ident]->is_pipeclass()->_instructs.addName(instr._ident);
1337 
1338   // Set the name of the pipeline class in the instruction
1339   instr._ins_pipe = ident;
1340   return;
1341 }
1342 
1343 //------------------------------pipe_parse-------------------------------------
1344 void ADLParser::pipe_parse(void) {
1345   PipelineForm *pipeline;         // Encode class for instruction/operand
1346   char * ident;
1347 
1348   pipeline = new PipelineForm();  // Build new Source object
1349   _AD.addForm(pipeline);
1350 
1351   skipws();                       // Skip leading whitespace
1352   // Check for block delimiter
1353   if ( (_curchar != '%') 
1354        || ( next_char(),  (_curchar != '{')) ) { 
1355     parse_err(SYNERR, "missing '%{' in pipeline definition\n");
1356     return;
1357   }
1358   next_char();                     // Maintain the invariant
1359   do {
1360     ident = get_ident();           // Grab next identifier
1361     if (ident == NULL) {
1362       parse_err(SYNERR, "keyword identifier expected at %c\n", _curchar);
1363       continue;
1364     }
1365     if      (!strcmp(ident, "resources" )) resource_parse(*pipeline);
1366     else if (!strcmp(ident, "pipe_desc" )) pipe_desc_parse(*pipeline);
1367     else if (!strcmp(ident, "pipe_class")) pipe_class_parse(*pipeline);
1368     else if (!strcmp(ident, "define")) {
1369       skipws();
1370       if ( (_curchar != '%') 
1371            || ( next_char(),  (_curchar != '{')) ) { 
1372         parse_err(SYNERR, "expected '%{'\n");
1373         return;
1374       }
1375       next_char(); skipws();
1376 
1377       char *node_class = get_ident();
1378       if (node_class == NULL) {
1379         parse_err(SYNERR, "expected identifier, found \"%c\"\n", _curchar);
1380         return;
1381       }
1382 
1383       skipws();
1384       if (_curchar != ',' && _curchar != '=') {
1385         parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
1386         break;
1387       }
1388       next_char(); skipws();
1389 
1390       char *pipe_class = get_ident();
1391       if (pipe_class == NULL) {
1392         parse_err(SYNERR, "expected identifier, found \"%c\"\n", _curchar);
1393         return;
1394       }
1395       if (_curchar != ';' ) {
1396         parse_err(SYNERR, "expected `;`, found '%c'\n", _curchar);
1397         break;
1398       }
1399       next_char();              // Skip over semi-colon
1400 
1401       skipws();
1402       if ( (_curchar != '%') 
1403            || ( next_char(),  (_curchar != '}')) ) { 
1404         parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar);
1405       }
1406       next_char();
1407 
1408       // Check ident for validity
1409       if (_AD._pipeline && !_AD._pipeline->_classlist.search(pipe_class)) {
1410         parse_err(SYNERR, "\"%s\" is not a valid pipeline class\n", pipe_class);
1411         return;
1412       }
1413 
1414       // Add this machine node to the list in the pipeline class
1415       _AD._pipeline->_classdict[pipe_class]->is_pipeclass()->_instructs.addName(node_class);
1416 
1417       MachNodeForm *machnode = new MachNodeForm(node_class); // Create new machnode form
1418       machnode->_machnode_pipe = pipe_class;
1419 
1420       _AD.addForm(machnode);
1421     }
1422     else if (!strcmp(ident, "attributes")) {
1423       bool vsi_seen = false, bhds_seen = false;
1424 
1425       skipws();
1426       if ( (_curchar != '%') 
1427            || ( next_char(),  (_curchar != '{')) ) { 
1428         parse_err(SYNERR, "expected '%{'\n");
1429         return;
1430       }
1431       next_char(); skipws();
1432 
1433       while (_curchar != '%') {
1434         ident = get_ident();
1435         if (ident == NULL)
1436           break;
1437 
1438         if (!strcmp(ident, "variable_size_instructions")) {
1439           skipws();
1440           if (_curchar == ';') {
1441             next_char(); skipws();
1442           }
1443 
1444           pipeline->_variableSizeInstrs = true;
1445           vsi_seen = true;
1446           continue;
1447         }
1448 
1449         if (!strcmp(ident, "fixed_size_instructions")) {
1450           skipws();
1451           if (_curchar == ';') {
1452             next_char(); skipws();
1453           }
1454 
1455           pipeline->_variableSizeInstrs = false;
1456           vsi_seen = true;
1457           continue;
1458         }
1459 
1460         if (!strcmp(ident, "branch_has_delay_slot")) {
1461           skipws();
1462           if (_curchar == ';') {
1463             next_char(); skipws();
1464           }
1465 
1466           pipeline->_branchHasDelaySlot = true;
1467           bhds_seen = true;
1468           continue;
1469         }
1470 
1471         if (!strcmp(ident, "max_instructions_per_bundle")) {
1472           skipws();
1473           if (_curchar != '=') {
1474             parse_err(SYNERR, "expected `=`\n");
1475             break;
1476             }
1477 
1478           next_char(); skipws();
1479           pipeline->_maxInstrsPerBundle = get_int();
1480           skipws();
1481 
1482           if (_curchar == ';') {
1483             next_char(); skipws();
1484           }
1485 
1486           continue;
1487         }
1488 
1489         if (!strcmp(ident, "max_bundles_per_cycle")) {
1490           skipws();
1491           if (_curchar != '=') {
1492             parse_err(SYNERR, "expected `=`\n");
1493             break;
1494             }
1495 
1496           next_char(); skipws();
1497           pipeline->_maxBundlesPerCycle = get_int();
1498           skipws();
1499 
1500           if (_curchar == ';') {
1501             next_char(); skipws();
1502           }
1503 
1504           continue;
1505         }
1506 
1507         if (!strcmp(ident, "instruction_unit_size")) {
1508           skipws();
1509           if (_curchar != '=') {
1510             parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
1511             break;
1512             }
1513 
1514           next_char(); skipws();
1515           pipeline->_instrUnitSize = get_int();
1516           skipws();
1517 
1518           if (_curchar == ';') {
1519             next_char(); skipws();
1520           }
1521 
1522           continue;
1523         }
1524 
1525         if (!strcmp(ident, "bundle_unit_size")) {
1526           skipws();
1527           if (_curchar != '=') {
1528             parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
1529             break;
1530             }
1531 
1532           next_char(); skipws();
1533           pipeline->_bundleUnitSize = get_int();
1534           skipws();
1535 
1536           if (_curchar == ';') {
1537             next_char(); skipws();
1538           }
1539 
1540           continue;
1541         }
1542 
1543         if (!strcmp(ident, "instruction_fetch_unit_size")) {
1544           skipws();
1545           if (_curchar != '=') {
1546             parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
1547             break;
1548             }
1549 
1550           next_char(); skipws();
1551           pipeline->_instrFetchUnitSize = get_int();
1552           skipws();
1553 
1554           if (_curchar == ';') {
1555             next_char(); skipws();
1556           }
1557 
1558           continue;
1559         }
1560 
1561         if (!strcmp(ident, "instruction_fetch_units")) {
1562           skipws();
1563           if (_curchar != '=') {
1564             parse_err(SYNERR, "expected `=`, found '%c'\n", _curchar);
1565             break;
1566             }
1567 
1568           next_char(); skipws();
1569           pipeline->_instrFetchUnits = get_int();
1570           skipws();
1571 
1572           if (_curchar == ';') {
1573             next_char(); skipws();
1574           }
1575 
1576           continue;
1577         }
1578 
1579         if (!strcmp(ident, "nops")) {
1580           skipws();
1581           if (_curchar != '(') {
1582             parse_err(SYNERR, "expected `(`, found '%c'\n", _curchar);
1583             break;
1584             }
1585 
1586           next_char(); skipws();
1587 
1588           while (_curchar != ')') {
1589             ident = get_ident();
1590             if (ident == NULL) {
1591               parse_err(SYNERR, "expected identifier for nop instruction, found '%c'\n", _curchar);
1592               break;
1593             }
1594 
1595             pipeline->_noplist.addName(ident);
1596             pipeline->_nopcnt++;
1597             skipws();
1598 
1599             if (_curchar == ',') {
1600               next_char(); skipws();
1601             }
1602           }
1603 
1604           next_char(); skipws();
1605 
1606           if (_curchar == ';') {
1607             next_char(); skipws();
1608           }
1609 
1610           continue;
1611         }
1612 
1613         parse_err(SYNERR, "unknown specifier \"%s\"\n", ident);
1614       }
1615 
1616       if ( (_curchar != '%') 
1617            || ( next_char(),  (_curchar != '}')) ) { 
1618         parse_err(SYNERR, "expected '%}', found \"%c\"\n", _curchar);
1619       }
1620       next_char(); skipws();
1621 
1622       if (pipeline->_maxInstrsPerBundle == 0)
1623         parse_err(SYNERR, "\"max_instructions_per_bundle\" unspecified\n");
1624       if (pipeline->_instrUnitSize == 0 && pipeline->_bundleUnitSize == 0)
1625         parse_err(SYNERR, "\"instruction_unit_size\" and \"bundle_unit_size\" unspecified\n");
1626       if (pipeline->_instrFetchUnitSize == 0)
1627         parse_err(SYNERR, "\"instruction_fetch_unit_size\" unspecified\n");
1628       if (pipeline->_instrFetchUnits == 0)
1629         parse_err(SYNERR, "\"instruction_fetch_units\" unspecified\n");
1630       if (!vsi_seen)
1631         parse_err(SYNERR, "\"variable_size_instruction\" or \"fixed_size_instruction\" unspecified\n");
1632     }
1633     else {  // Done with staticly defined parts of instruction definition
1634       parse_err(SYNERR, "expected one of \"resources\", \"pipe_desc\", \"pipe_class\", found \"%s\"\n", ident);
1635       return;
1636     }
1637     skipws();
1638     if (_curchar == ';')
1639       skipws();
1640   } while(_curchar != '%');
1641 
1642   next_char();
1643   if (_curchar != '}') {
1644     parse_err(SYNERR, "missing \"%}\" in pipeline definition\n");
1645     return;
1646   }
1647 
1648   next_char(); 
1649 }
1650 
1651 //------------------------------resource_parse----------------------------
1652 void ADLParser::resource_parse(PipelineForm &pipeline) {
1653   ResourceForm *resource;
1654   char * ident;
1655   char * expr;
1656   unsigned mask;
1657   pipeline._rescount = 0;
1658 
1659   skipws();                       // Skip leading whitespace
1660 
1661   if (_curchar != '(') {
1662     parse_err(SYNERR, "missing \"(\" in resource definition\n");
1663     return;
1664   }
1665 
1666   do {
1667     next_char();                   // Skip "(" or ","
1668     ident = get_ident();           // Grab next identifier
1669 
1670     if (ident == NULL) {
1671       parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
1672       return;
1673     }
1674     skipws();
1675 
1676     if (_curchar != '=') {
1677       mask = (1 << pipeline._rescount++);
1678     }
1679     else {
1680       next_char(); skipws();
1681       expr = get_ident();          // Grab next identifier
1682       if (expr == NULL) {
1683         parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
1684         return;
1685       }
1686       resource = (ResourceForm *) pipeline._resdict[expr];
1687       if (resource == NULL) {
1688         parse_err(SYNERR, "resource \"%s\" is not defined\n", expr);
1689         return;
1690       }
1691       mask = resource->mask();
1692 
1693       skipws();
1694       while (_curchar == '|') {
1695         next_char(); skipws();
1696 
1697         expr = get_ident();          // Grab next identifier
1698         if (expr == NULL) {
1699           parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
1700           return;
1701         }
1702 
1703         resource = (ResourceForm *) pipeline._resdict[expr];   // Look up the value
1704         if (resource == NULL) {
1705           parse_err(SYNERR, "resource \"%s\" is not defined\n", expr);
1706           return;
1707         }
1708 
1709         mask |= resource->mask();
1710         skipws();
1711       }
1712     }
1713 
1714     resource = new ResourceForm(mask);
1715 
1716     pipeline._resdict.Insert(ident, resource);
1717     pipeline._reslist.addName(ident);
1718   } while (_curchar == ',');
1719 
1720   if (_curchar != ')') {
1721       parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
1722       return;
1723   }
1724 
1725   next_char();                 // Skip ")"
1726   if (_curchar == ';')
1727     next_char();               // Skip ";"
1728 }
1729 
1730 //------------------------------resource_parse----------------------------
1731 void ADLParser::pipe_desc_parse(PipelineForm &pipeline) {
1732   char * ident;
1733 
1734   skipws();                       // Skip leading whitespace
1735   
1736   if (_curchar != '(') {
1737     parse_err(SYNERR, "missing \"(\" in pipe_desc definition\n");
1738     return;
1739   }
1740 
1741   do {
1742     next_char();                   // Skip "(" or ","
1743     ident = get_ident();           // Grab next identifier
1744     if (ident == NULL) {
1745       parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
1746       return;
1747     }
1748 
1749     // Add the name to the list
1750     pipeline._stages.addName(ident);
1751     pipeline._stagecnt++;
1752 
1753     skipws();
1754   } while (_curchar == ',');
1755 
1756   if (_curchar != ')') {
1757       parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
1758       return;
1759   }
1760 
1761   next_char();                     // Skip ")"
1762   if (_curchar == ';')
1763     next_char();                   // Skip ";"
1764 }
1765 
1766 //------------------------------pipe_class_parse--------------------------
1767 void ADLParser::pipe_class_parse(PipelineForm &pipeline) {
1768   PipeClassForm *pipe_class;
1769   char * ident;
1770   char * stage;
1771   char * read_or_write;
1772   int is_write;
1773   int is_read;
1774   OperandForm  *oper;
1775 
1776   skipws();                       // Skip leading whitespace
1777   
1778   ident = get_ident();            // Grab next identifier
1779 
1780   if (ident == NULL) {
1781     parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
1782     return;
1783   }
1784 
1785   // Create a record for the pipe_class
1786   pipe_class = new PipeClassForm(ident, ++pipeline._classcnt);
1787   pipeline._classdict.Insert(ident, pipe_class);
1788   pipeline._classlist.addName(ident);
1789 
1790   // Then get the operands
1791   skipws();
1792   if (_curchar != '(') {
1793     parse_err(SYNERR, "missing \"(\" in pipe_class definition\n");
1794   }
1795   // Parse the operand list
1796   else get_oplist(pipe_class->_parameters, pipe_class->_localNames);
1797   skipws();                        // Skip leading whitespace
1798   // Check for block delimiter
1799   if ( (_curchar != '%')
1800        || ( next_char(),  (_curchar != '{')) ) {
1801     parse_err(SYNERR, "missing \"%{\" in pipe_class definition\n");
1802     return;
1803   }
1804   next_char();
1805 
1806   do {
1807     ident = get_ident();           // Grab next identifier
1808     if (ident == NULL) {
1809       parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
1810       continue;
1811     }
1812     skipws();
1813 
1814     if (!strcmp(ident, "fixed_latency")) {
1815       skipws();
1816       if (_curchar != '(') {
1817         parse_err(SYNERR, "missing \"(\" in latency definition\n");
1818         return;
1819       }
1820       next_char(); skipws();
1821       if( !isdigit(_curchar) ) {
1822         parse_err(SYNERR, "number expected for \"%c\" in latency definition\n", _curchar);
1823         return;
1824       }
1825       int fixed_latency = get_int();
1826       skipws();
1827       if (_curchar != ')') {
1828         parse_err(SYNERR, "missing \")\" in latency definition\n");
1829         return;
1830       }
1831       next_char(); skipws();
1832       if (_curchar != ';') {
1833         parse_err(SYNERR, "missing \";\" in latency definition\n");
1834         return;
1835       }
1836 
1837       pipe_class->setFixedLatency(fixed_latency);
1838       next_char(); skipws();
1839       continue;
1840     }
1841 
1842     if (!strcmp(ident, "zero_instructions") ||
1843         !strcmp(ident, "no_instructions")) {
1844       skipws();
1845       if (_curchar != ';') {
1846         parse_err(SYNERR, "missing \";\" in latency definition\n");
1847         return;
1848       }
1849 
1850       pipe_class->setInstructionCount(0);
1851       next_char(); skipws();
1852       continue;
1853     }
1854 
1855     if (!strcmp(ident, "one_instruction_with_delay_slot") ||
1856         !strcmp(ident, "single_instruction_with_delay_slot")) {
1857       skipws();
1858       if (_curchar != ';') {
1859         parse_err(SYNERR, "missing \";\" in latency definition\n");
1860         return;
1861       }
1862 
1863       pipe_class->setInstructionCount(1);
1864       pipe_class->setBranchDelay(true);
1865       next_char(); skipws();
1866       continue;
1867     }
1868 
1869     if (!strcmp(ident, "one_instruction") ||
1870         !strcmp(ident, "single_instruction")) {
1871       skipws();
1872       if (_curchar != ';') {
1873         parse_err(SYNERR, "missing \";\" in latency definition\n");
1874         return;
1875       }
1876 
1877       pipe_class->setInstructionCount(1);
1878       next_char(); skipws();
1879       continue;
1880     }
1881 
1882     if (!strcmp(ident, "instructions_in_first_bundle") ||
1883         !strcmp(ident, "instruction_count")) {
1884       skipws();
1885 
1886       int number_of_instructions = 1;
1887 
1888       if (_curchar != '(') {
1889         parse_err(SYNERR, "\"(\" expected at \"%c\"\n", _curchar);
1890         continue;
1891       }
1892 
1893       next_char(); skipws();
1894       number_of_instructions = get_int();
1895 
1896       skipws();
1897       if (_curchar != ')') {
1898         parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
1899         continue;
1900       }
1901 
1902       next_char(); skipws();
1903       if (_curchar != ';') {
1904         parse_err(SYNERR, "missing \";\" in latency definition\n");
1905         return;
1906       }
1907 
1908       pipe_class->setInstructionCount(number_of_instructions);
1909       next_char(); skipws();
1910       continue;
1911     }
1912 
1913     if (!strcmp(ident, "multiple_bundles")) {
1914       skipws();
1915       if (_curchar != ';') {
1916         parse_err(SYNERR, "missing \";\" after multiple bundles\n");
1917         return;
1918       }
1919 
1920       pipe_class->setMultipleBundles(true);
1921       next_char(); skipws();
1922       continue;
1923     }
1924 
1925     if (!strcmp(ident, "has_delay_slot")) {
1926       skipws();
1927       if (_curchar != ';') {
1928         parse_err(SYNERR, "missing \";\" after \"has_delay_slot\"\n");
1929         return;
1930       }
1931 
1932       pipe_class->setBranchDelay(true);
1933       next_char(); skipws();
1934       continue;
1935     }
1936 
1937     if (!strcmp(ident, "force_serialization")) {
1938       skipws();
1939       if (_curchar != ';') {
1940         parse_err(SYNERR, "missing \";\" after \"force_serialization\"\n");
1941         return;
1942       }
1943 
1944       pipe_class->setForceSerialization(true);
1945       next_char(); skipws();
1946       continue;
1947     }
1948 
1949     if (!strcmp(ident, "may_have_no_code")) {
1950       skipws();
1951       if (_curchar != ';') {
1952         parse_err(SYNERR, "missing \";\" after \"may_have_no_code\"\n");
1953         return;
1954       }
1955 
1956       pipe_class->setMayHaveNoCode(true);
1957       next_char(); skipws();
1958       continue;
1959     }
1960 
1961     const Form *parm = pipe_class->_localNames[ident];
1962     if (parm != NULL) {
1963       oper = parm->is_operand();
1964       if (oper == NULL && !parm->is_opclass()) {
1965         parse_err(SYNERR, "operand name expected at %s\n", ident);
1966         continue;
1967       }
1968 
1969       if (_curchar != ':') {
1970         parse_err(SYNERR, "\":\" expected at \"%c\"\n", _curchar);
1971         continue;
1972       }
1973       next_char(); skipws();
1974       stage = get_ident();
1975       if (stage == NULL) {
1976         parse_err(SYNERR, "pipeline stage identifier expected at \"%c\"\n", _curchar);
1977         continue;
1978       }
1979 
1980       skipws();
1981       if (_curchar != '(') {
1982         parse_err(SYNERR, "\"(\" expected at \"%c\"\n", _curchar);
1983         continue;
1984       }
1985 
1986       next_char();
1987       read_or_write = get_ident();
1988       if (read_or_write == NULL) {
1989         parse_err(SYNERR, "\"read\" or \"write\" expected at \"%c\"\n", _curchar);
1990         continue;
1991       }
1992 
1993       is_read  = strcmp(read_or_write, "read")   == 0;
1994       is_write = strcmp(read_or_write, "write")  == 0;
1995       if (!is_read && !is_write) {
1996         parse_err(SYNERR, "\"read\" or \"write\" expected at \"%c\"\n", _curchar);
1997         continue;
1998       }
1999 
2000       skipws();
2001       if (_curchar != ')') {
2002         parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
2003         continue;
2004       }
2005 
2006       next_char(); skipws();
2007       int more_instrs = 0;
2008       if (_curchar == '+') {
2009           next_char(); skipws();
2010           if (_curchar < '0' || _curchar > '9') {
2011             parse_err(SYNERR, "<number> expected at \"%c\"\n", _curchar);
2012             continue;
2013           }
2014           while (_curchar >= '0' && _curchar <= '9') {
2015             more_instrs *= 10;
2016             more_instrs += _curchar - '0';
2017             next_char();
2018           }
2019           skipws();
2020       }
2021 
2022       PipeClassOperandForm *pipe_operand = new PipeClassOperandForm(stage, is_write, more_instrs);
2023       pipe_class->_localUsage.Insert(ident, pipe_operand);
2024 
2025       if (_curchar == '%')
2026           continue;
2027 
2028       if (_curchar != ';') {
2029         parse_err(SYNERR, "\";\" expected at \"%c\"\n", _curchar);
2030         continue;
2031       }
2032       next_char(); skipws();
2033       continue;
2034     }
2035 
2036     // Scan for Resource Specifier
2037     const Form *res = pipeline._resdict[ident];
2038     if (res != NULL) {
2039       int cyclecnt = 1;
2040       if (_curchar != ':') {
2041         parse_err(SYNERR, "\":\" expected at \"%c\"\n", _curchar);
2042         continue;
2043       }
2044       next_char(); skipws();
2045       stage = get_ident();
2046       if (stage == NULL) {
2047         parse_err(SYNERR, "pipeline stage identifier expected at \"%c\"\n", _curchar);
2048         continue;
2049       }
2050 
2051       skipws();
2052       if (_curchar == '(') {
2053         next_char();
2054         cyclecnt = get_int();
2055 
2056         skipws();
2057         if (_curchar != ')') {
2058           parse_err(SYNERR, "\")\" expected at \"%c\"\n", _curchar);
2059           continue;
2060         }
2061 
2062         next_char(); skipws();
2063       }
2064 
2065       PipeClassResourceForm *resource = new PipeClassResourceForm(ident, stage, cyclecnt);
2066       int stagenum = pipeline._stages.index(stage);
2067       if (pipeline._maxcycleused < (stagenum+cyclecnt))
2068         pipeline._maxcycleused = (stagenum+cyclecnt);
2069       pipe_class->_resUsage.addForm(resource);
2070 
2071       if (_curchar == '%')
2072           continue;
2073 
2074       if (_curchar != ';') {
2075         parse_err(SYNERR, "\";\" expected at \"%c\"\n", _curchar);
2076         continue;
2077       }
2078       next_char(); skipws();
2079       continue;
2080     }
2081 
2082     parse_err(SYNERR, "resource expected at \"%s\"\n", ident);
2083     return;
2084   } while(_curchar != '%');
2085 
2086   next_char();
2087   if (_curchar != '}') {
2088     parse_err(SYNERR, "missing \"%}\" in pipe_class definition\n");
2089     return;
2090   }
2091 
2092   next_char();
2093 }
2094 
2095 //------------------------------peep_parse-------------------------------------
2096 void ADLParser::peep_parse(void) {
2097   Peephole  *peep;                // Pointer to current peephole rule form
2098   char      *desc = NULL;         // String representation of rule
2099 
2100   skipws();                       // Skip leading whitespace
2101 
2102   peep = new Peephole();          // Build new Peephole object
2103   // Check for open block sequence
2104   skipws();                       // Skip leading whitespace
2105   if (_curchar == '%' && *(_ptr+1) == '{') {
2106     next_char(); next_char();     // Skip "%{"
2107     skipws();
2108     while (_curchar != '%' && *(_ptr+1) != '}') {
2109       char *token = get_ident();
2110       if (token == NULL) {
2111         parse_err(SYNERR, "missing identifier inside peephole rule.\n");
2112         return;
2113       }
2114       // check for legal subsections of peephole rule
2115       if (strcmp(token,"peepmatch")==0) {
2116         peep_match_parse(*peep); }
2117       else if (strcmp(token,"peepconstraint")==0) {
2118         peep_constraint_parse(*peep); }
2119       else if (strcmp(token,"peepreplace")==0) {
2120         peep_replace_parse(*peep); }
2121       else {
2122         parse_err(SYNERR, "expected peepmatch, peepconstraint, or peepreplace for identifier %s.\n", token);
2123       }
2124       skipws();
2125     }
2126   }
2127   else {
2128     parse_err(SYNERR, "Missing %%{ ... %%} block after peephole keyword.\n");
2129     return;
2130   }
2131   next_char();                    // Skip past '%'
2132   next_char();                    // Skip past '}'
2133 }
2134 
2135 // ******************** Private Level 2 Parse Functions ********************
2136 //------------------------------constraint_parse------------------------------
2137 Constraint *ADLParser::constraint_parse(void) {
2138   char *func;
2139   char *arg;
2140 
2141   // Check for constraint expression
2142   skipws();
2143   if (_curchar != '(') {
2144     parse_err(SYNERR, "missing constraint expression, (...)\n");
2145     return NULL;
2146   }
2147   next_char();                    // Skip past '('
2148 
2149   // Get constraint function
2150   skipws();
2151   func = get_ident();
2152   if (func == NULL) {
2153     parse_err(SYNERR, "missing function in constraint expression.\n");
2154     return NULL;
2155   }
2156   if (strcmp(func,"ALLOC_IN_RC")==0
2157       || strcmp(func,"IS_R_CLASS")==0) {
2158     // Check for '(' before argument
2159     skipws();
2160     if (_curchar != '(') {
2161       parse_err(SYNERR, "missing '(' for constraint function's argument.\n");
2162       return NULL;
2163     }
2164     next_char();
2165 
2166     // Get it's argument
2167     skipws();
2168     arg = get_ident();
2169     if (arg == NULL) {
2170       parse_err(SYNERR, "missing argument for constraint function %s\n",func);
2171       return NULL;
2172     }
2173     // Check for ')' after argument
2174     skipws();
2175     if (_curchar != ')') {
2176       parse_err(SYNERR, "missing ')' after constraint function argument %s\n",arg);
2177       return NULL;
2178     }
2179     next_char();
2180   } else {
2181     parse_err(SYNERR, "Invalid constraint function %s\n",func);
2182     return NULL;
2183   }
2184 
2185   // Check for closing paren and ';'
2186   skipws();
2187   if (_curchar != ')') {
2188     parse_err(SYNERR, "Missing ')' for constraint function %s\n",func);
2189     return NULL;
2190   }
2191   next_char();
2192   skipws();
2193   if (_curchar != ';') {
2194     parse_err(SYNERR, "Missing ';' after constraint.\n");
2195     return NULL;
2196   }
2197   next_char();
2198 
2199   // Create new "Constraint"
2200   Constraint *constraint = new Constraint(func,arg);
2201   return constraint;
2202 }
2203 
2204 //------------------------------constr_parse-----------------------------------
2205 ConstructRule *ADLParser::construct_parse(void) {
2206   return NULL;
2207 }
2208 
2209 
2210 //------------------------------reg_def_parse----------------------------------
2211 void ADLParser::reg_def_parse(void) {
2212   char *rname;                   // Name of register being defined
2213 
2214   // Get register name
2215   skipws();                      // Skip whitespace
2216   rname = get_ident();
2217   if (rname == NULL) {
2218     parse_err(SYNERR, "missing register name after reg_def\n");
2219     return;
2220   }
2221 
2222   // Check for definition of register calling convention (save on call, ...),
2223   // register save type, and register encoding value.
2224   skipws();
2225   char *callconv  = NULL;
2226   char *c_conv    = NULL;
2227   char *idealtype = NULL;
2228   char *encoding  = NULL;
2229   char *concrete = NULL;
2230   if (_curchar == '(') {
2231     next_char();
2232     callconv = get_ident();
2233     // Parse the internal calling convention, must be NS, SOC, SOE, or AS.
2234     if (callconv == NULL) {
2235       parse_err(SYNERR, "missing register calling convention value\n");
2236       return;
2237     }
2238     if(strcmp(callconv, "SOC") && strcmp(callconv,"SOE") &&
2239        strcmp(callconv, "NS") && strcmp(callconv, "AS")) {
2240       parse_err(SYNERR, "invalid value for register calling convention\n");
2241     }
2242     skipws();
2243     if (_curchar != ',') {
2244       parse_err(SYNERR, "missing comma in register definition statement\n");
2245       return;
2246     }
2247     next_char();
2248 
2249     // Parse the native calling convention, must be NS, SOC, SOE, AS
2250     c_conv = get_ident();
2251     if (c_conv == NULL) {
2252       parse_err(SYNERR, "missing register native calling convention value\n");
2253       return;
2254     }
2255     if(strcmp(c_conv, "SOC") && strcmp(c_conv,"SOE") &&
2256        strcmp(c_conv, "NS") && strcmp(c_conv, "AS")) {
2257       parse_err(SYNERR, "invalid value for register calling convention\n");
2258     }
2259     skipws();
2260     if (_curchar != ',') {
2261       parse_err(SYNERR, "missing comma in register definition statement\n");
2262       return;
2263     }
2264     next_char();
2265     skipws();
2266 
2267     // Parse the ideal save type
2268     idealtype = get_ident();
2269     if (idealtype == NULL) {
2270       parse_err(SYNERR, "missing register save type value\n");
2271       return;
2272     }
2273     skipws();
2274     if (_curchar != ',') {
2275       parse_err(SYNERR, "missing comma in register definition statement\n");
2276       return;
2277     }
2278     next_char();
2279     skipws();
2280 
2281     // Parse the encoding value
2282     encoding = get_expr("encoding", ",");
2283     if (encoding == NULL) {
2284       parse_err(SYNERR, "missing register encoding value\n");
2285       return;
2286     }
2287     trim(encoding);
2288     if (_curchar != ',') {
2289       parse_err(SYNERR, "missing comma in register definition statement\n");
2290       return;
2291     }
2292     next_char();
2293     skipws();
2294     // Parse the concrete name type
2295     // concrete = get_ident();
2296     concrete = get_expr("concrete", ")");
2297     if (concrete == NULL) {
2298       parse_err(SYNERR, "missing vm register name value\n");
2299       return;
2300     }
2301 
2302     if (_curchar != ')') {
2303       parse_err(SYNERR, "missing ')' in register definition statement\n");
2304       return;
2305     }
2306     next_char();
2307   }
2308 
2309   // Check for closing ';'
2310   skipws();
2311   if (_curchar != ';') {
2312     parse_err(SYNERR, "missing ';' after reg_def\n");
2313     return;
2314   }
2315   next_char();                   // move past ';'
2316   
2317   // Debug Stuff
2318   if (_AD._adl_debug > 1) {
2319     fprintf(stderr,"Register Definition: %s ( %s, %s %s )\n", rname, 
2320             (callconv ? callconv : ""), (c_conv ? c_conv : ""), concrete);
2321   }
2322   
2323   // Record new register definition.
2324   _AD._register->addRegDef(rname, callconv, c_conv, idealtype, encoding, concrete);
2325   return;
2326 }
2327 
2328 //------------------------------reg_class_parse--------------------------------
2329 void ADLParser::reg_class_parse(void) {
2330   char *cname;                    // Name of register class being defined
2331 
2332   // Get register class name
2333   skipws();                       // Skip leading whitespace
2334   cname = get_ident();
2335   if (cname == NULL) {
2336     parse_err(SYNERR, "missing register class name after 'reg_class'\n");
2337     return;
2338   }
2339   // Debug Stuff
2340   if (_AD._adl_debug >1) fprintf(stderr,"Register Class: %s\n", cname);
2341 
2342   RegClass *reg_class = _AD._register->addRegClass(cname);
2343 
2344   // Collect registers in class
2345   skipws();
2346   if (_curchar == '(') {
2347     next_char();                  // Skip '('
2348     skipws();
2349     while (_curchar != ')') {
2350       char *rname = get_ident();
2351       if (rname==NULL) {
2352         parse_err(SYNERR, "missing identifier inside reg_class list.\n");
2353         return;
2354       }
2355       RegDef *regDef = _AD._register->getRegDef(rname);
2356       reg_class->addReg(regDef);     // add regDef to regClass
2357 
2358       // Check for ',' and position to next token.
2359       skipws();
2360       if (_curchar == ',') {
2361         next_char();              // Skip trailing ','
2362         skipws();
2363       }
2364     }
2365     next_char();                  // Skip closing ')'
2366   }
2367 
2368   // Check for terminating ';'
2369   skipws();
2370   if (_curchar != ';') {
2371     parse_err(SYNERR, "missing ';' at end of reg_class definition.\n");
2372     return;
2373   }
2374   next_char();                    // Skip trailing ';'
2375 
2376   // Check RegClass size, must be <= 32 registers in class.
2377   
2378   return;
2379 }
2380 
2381 //------------------------------alloc_class_parse------------------------------
2382 void ADLParser::alloc_class_parse(void) {
2383   char *name;                     // Name of allocation class being defined
2384 
2385   // Get allocation class name
2386   skipws();                       // Skip leading whitespace
2387   name = get_ident();
2388   if (name == NULL) {
2389     parse_err(SYNERR, "missing allocation class name after 'reg_class'\n");
2390     return;
2391   }
2392   // Debug Stuff
2393   if (_AD._adl_debug >1) fprintf(stderr,"Allocation Class: %s\n", name);
2394 
2395   AllocClass *alloc_class = _AD._register->addAllocClass(name);
2396 
2397   // Collect registers in class
2398   skipws();
2399   if (_curchar == '(') {
2400     next_char();                  // Skip '('
2401     skipws();
2402     while (_curchar != ')') {
2403       char *rname = get_ident();
2404       if (rname==NULL) {
2405         parse_err(SYNERR, "missing identifier inside reg_class list.\n");
2406         return;
2407       }
2408       // Check if name is a RegDef
2409       RegDef *regDef = _AD._register->getRegDef(rname);
2410       if (regDef) {
2411         alloc_class->addReg(regDef);   // add regDef to allocClass
2412       } else {
2413 
2414         // name must be a RegDef or a RegClass
2415         parse_err(SYNERR, "name %s should be a previously defined reg_def.\n", rname);
2416         return;
2417       }
2418 
2419       // Check for ',' and position to next token.
2420       skipws();
2421       if (_curchar == ',') {
2422         next_char();              // Skip trailing ','
2423         skipws();
2424       }
2425     }
2426     next_char();                  // Skip closing ')'
2427   }
2428 
2429   // Check for terminating ';'
2430   skipws();
2431   if (_curchar != ';') {
2432     parse_err(SYNERR, "missing ';' at end of reg_class definition.\n");
2433     return;
2434   }
2435   next_char();                    // Skip trailing ';'
2436   
2437   return;
2438 }
2439 
2440 //------------------------------peep_match_child_parse-------------------------
2441 InstructForm *ADLParser::peep_match_child_parse(PeepMatch &match, int parent, int &position, int input){
2442   char      *token  = NULL;
2443   int        lparen = 0;          // keep track of parenthesis nesting depth
2444   int        rparen = 0;          // position of instruction at this depth
2445   InstructForm *inst_seen  = NULL;  
2446   InstructForm *child_seen = NULL;
2447 
2448   // Walk the match tree, 
2449   // Record <parent, position, instruction name, input position>
2450   while ( lparen >= rparen ) {
2451     skipws();
2452     // Left paren signals start of an input, collect with recursive call
2453     if (_curchar == '(') {
2454       ++lparen;
2455       next_char();
2456       child_seen = peep_match_child_parse(match, parent, position, rparen);
2457     }
2458     // Right paren signals end of an input, may be more
2459     else if (_curchar == ')') {
2460       ++rparen;
2461       if( rparen == lparen ) { // IF rparen matches an lparen I've seen
2462         next_char();           //    move past ')'
2463       } else {                 // ELSE leave ')' for parent
2464         assert( rparen == lparen + 1, "Should only see one extra ')'");
2465         // if an instruction was not specified for this paren-pair
2466         if( ! inst_seen ) {   // record signal entry
2467           match.add_instruction( parent, position, NameList::_signal, input );
2468           ++position;
2469         }
2470         // ++input;   // TEMPORARY
2471         return inst_seen;
2472       }
2473     }
2474     // if no parens, then check for instruction name
2475     // This instruction is the parent of a sub-tree
2476     else if ((token = get_ident_dup()) != NULL) {
2477       const Form *form = _AD._globalNames[token];
2478       if (form) {
2479         InstructForm *inst = form->is_instruction();
2480         // Record the first instruction at this level
2481         if( inst_seen == NULL ) { 
2482           inst_seen = inst;
2483         }
2484         if (inst) {
2485           match.add_instruction( parent, position, token, input );
2486           parent = position;
2487           ++position;
2488         } else {
2489           parse_err(SYNERR, "instruction name expected at identifier %s.\n",
2490                     token);
2491           return inst_seen;
2492         }
2493       }
2494       else {
2495         parse_err(SYNERR, "missing identifier in peepmatch rule.\n");
2496         return NULL;
2497       }
2498     }
2499     else {
2500       parse_err(SYNERR, "missing identifier in peepmatch rule.\n");
2501       return NULL;
2502     }
2503       
2504   } // end while
2505 
2506   assert( false, "ShouldNotReachHere();");
2507   return NULL;
2508 }
2509 
2510 //------------------------------peep_match_parse-------------------------------
2511 // Syntax for a peepmatch rule 
2512 //
2513 // peepmatch ( root_instr_name [(instruction subtree)] [,(instruction subtree)]* );
2514 //
2515 void ADLParser::peep_match_parse(Peephole &peep) {
2516 
2517   skipws();
2518   // Check the structure of the rule
2519   // Check for open paren
2520   if (_curchar != '(') {
2521     parse_err(SYNERR, "missing '(' at start of peepmatch rule.\n");
2522     return;
2523   }
2524   next_char();   // skip '('
2525 
2526   // Construct PeepMatch and parse the peepmatch rule.
2527   PeepMatch *match = new PeepMatch(_ptr);
2528   int  parent   = -1;                   // parent of root
2529   int  position = 0;                    // zero-based positions
2530   int  input    = 0;                    // input position in parent's operands
2531   InstructForm *root= peep_match_child_parse( *match, parent, position, input);
2532   if( root == NULL ) {
2533     parse_err(SYNERR, "missing instruction-name at start of peepmatch.\n");
2534     return;
2535   }
2536   
2537   if( _curchar != ')' ) {
2538     parse_err(SYNERR, "missing ')' at end of peepmatch.\n");
2539     return;
2540   }
2541   next_char();   // skip ')'
2542 
2543   // Check for closing semicolon
2544   skipws();
2545   if( _curchar != ';' ) {
2546     parse_err(SYNERR, "missing ';' at end of peepmatch.\n");
2547     return;
2548   }
2549   next_char();   // skip ';'
2550 
2551   // Store match into peep, and store peep into instruction
2552   peep.add_match(match);
2553   root->append_peephole(&peep);
2554 }
2555 
2556 //------------------------------peep_constraint_parse--------------------------
2557 // Syntax for a peepconstraint rule
2558 // A parenthesized list of relations between operands in peepmatch subtree
2559 //
2560 // peepconstraint %{
2561 // (instruction_number.operand_name 
2562 //     relational_op 
2563 //  instruction_number.operand_name OR register_name
2564 //  [, ...] );
2565 // 
2566 // // instruction numbers are zero-based using topological order in peepmatch
2567 // 
2568 void ADLParser::peep_constraint_parse(Peephole &peep) {
2569 
2570   skipws();
2571   // Check the structure of the rule
2572   // Check for open paren
2573   if (_curchar != '(') {
2574     parse_err(SYNERR, "missing '(' at start of peepconstraint rule.\n");
2575     return;
2576   }
2577   else {
2578     next_char();                  // Skip '('
2579   }
2580 
2581   // Check for a constraint
2582   skipws();
2583   while( _curchar != ')' ) {
2584     // Get information on the left instruction and its operand
2585     // left-instructions's number
2586     intptr_t   left_inst = get_int();
2587     // Left-instruction's operand
2588     skipws();
2589     if( _curchar != '.' ) {
2590       parse_err(SYNERR, "missing '.' in peepconstraint after instruction number.\n");
2591       return;
2592     }
2593     next_char();                  // Skip '.'
2594     char *left_op = get_ident_dup();
2595 
2596     skipws();
2597     // Collect relational operator
2598     char *relation = get_relation_dup();
2599 
2600     skipws();
2601     // Get information on the right instruction and its operand
2602     intptr_t right_inst;        // Right-instructions's number
2603     if( isdigit(_curchar) ) {
2604       right_inst = get_int();
2605       // Right-instruction's operand
2606       skipws();
2607       if( _curchar != '.' ) {
2608         parse_err(SYNERR, "missing '.' in peepconstraint after instruction number.\n");
2609         return;
2610       }
2611       next_char();              // Skip '.'
2612     } else {
2613       right_inst = -1;          // Flag as being a register constraint
2614     }
2615 
2616     char *right_op = get_ident_dup();
2617 
2618     // Construct the next PeepConstraint
2619     PeepConstraint *constraint = new PeepConstraint( left_inst, left_op, 
2620                                                      relation, 
2621                                                      right_inst, right_op );
2622     // And append it to the list for this peephole rule
2623     peep.append_constraint( constraint );
2624     
2625     // Check for another constraint, or end of rule
2626     skipws();
2627     if( _curchar == ',' ) {
2628       next_char();                // Skip ','
2629       skipws();
2630     }
2631     else if( _curchar != ')' ) {
2632       parse_err(SYNERR, "expected ',' or ')' after peephole constraint.\n");
2633       return;
2634     }
2635   } // end while( processing constraints )
2636   next_char();                    // Skip ')'
2637 
2638   // Check for terminating ';'
2639   skipws();
2640   if (_curchar != ';') {
2641     parse_err(SYNERR, "missing ';' at end of peepconstraint.\n");
2642     return;
2643   }
2644   next_char();                    // Skip trailing ';'
2645 }
2646 
2647 
2648 //------------------------------peep_replace_parse-----------------------------
2649 // Syntax for a peepreplace rule
2650 // root instruction name followed by a 
2651 // parenthesized list of whitespace separated instruction.operand specifiers
2652 //
2653 // peepreplace ( instr_name  ( [instruction_number.operand_name]* ) );
2654 // 
2655 // 
2656 void ADLParser::peep_replace_parse(Peephole &peep) {
2657   int          lparen = 0;        // keep track of parenthesis nesting depth
2658   int          rparen = 0;        // keep track of parenthesis nesting depth
2659   int          icount = 0;        // count of instructions in rule for naming
2660   char        *str    = NULL;
2661   char        *token  = NULL;
2662 
2663   skipws();
2664   // Check for open paren
2665   if (_curchar != '(') {
2666     parse_err(SYNERR, "missing '(' at start of peepreplace rule.\n");
2667     return;
2668   }
2669   else {
2670     lparen++;
2671     next_char();
2672   }
2673 
2674   // Check for root instruction
2675   char       *inst = get_ident_dup();
2676   const Form *form = _AD._globalNames[inst];
2677   if( form == NULL || form->is_instruction() == NULL ) {
2678     parse_err(SYNERR, "Instruction name expected at start of peepreplace.\n");
2679     return;
2680   }
2681 
2682   // Store string representation of rule into replace
2683   PeepReplace *replace = new PeepReplace(str);
2684   replace->add_instruction( inst );
2685 
2686   skipws();
2687   // Start of root's operand-list
2688   if (_curchar != '(') {
2689     parse_err(SYNERR, "missing '(' at peepreplace root's operand-list.\n");
2690     return;
2691   }
2692   else {
2693     lparen++;
2694     next_char();
2695   }
2696 
2697   skipws();
2698   // Get the list of operands
2699   while( _curchar != ')' ) {
2700     // Get information on an instruction and its operand
2701     // instructions's number
2702     int   inst_num = get_int();
2703     // Left-instruction's operand
2704     skipws();
2705     if( _curchar != '.' ) {
2706       parse_err(SYNERR, "missing '.' in peepreplace after instruction number.\n");
2707       return;
2708     }
2709     next_char();                  // Skip '.'
2710     char *inst_op = get_ident_dup();
2711     if( inst_op == NULL ) {
2712       parse_err(SYNERR, "missing operand identifier in peepreplace.\n");
2713       return;
2714     }
2715 
2716     // Record this operand's position in peepmatch
2717     replace->add_operand( inst_num, inst_op );
2718     skipws();
2719   }
2720 
2721   // Check for the end of operands list
2722   skipws();
2723   assert( _curchar == ')', "While loop should have advanced to ')'.");
2724   next_char();  // Skip ')'
2725 
2726   skipws();
2727   // Check for end of peepreplace
2728   if( _curchar != ')' ) {
2729     parse_err(SYNERR, "missing ')' at end of peepmatch.\n");
2730     parse_err(SYNERR, "Support one replacement instruction.\n");
2731     return;
2732   }
2733   next_char(); // Skip ')'
2734 
2735   // Check for closing semicolon
2736   skipws();
2737   if( _curchar != ';' ) {
2738     parse_err(SYNERR, "missing ';' at end of peepreplace.\n");
2739     return;
2740   }
2741   next_char();   // skip ';'
2742 
2743   // Store replace into peep
2744   peep.add_replace( replace );
2745 }
2746 
2747 //------------------------------pred_parse-------------------------------------
2748 Predicate *ADLParser::pred_parse(void) {
2749   Predicate *predicate;           // Predicate class for operand
2750   char      *rule = NULL;         // String representation of predicate
2751 
2752   skipws();                       // Skip leading whitespace
2753   if ( (rule = get_paren_expr("pred expression")) == NULL ) {
2754     parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n");
2755     return NULL;
2756   }
2757   // Debug Stuff
2758   if (_AD._adl_debug > 1) fprintf(stderr,"Predicate: %s\n", rule);
2759   if (_curchar != ';') {
2760     parse_err(SYNERR, "missing ';' in predicate definition\n");
2761     return NULL;
2762   }
2763   next_char();                     // Point after the terminator
2764 
2765   predicate = new Predicate(rule); // Build new predicate object
2766   skipws();
2767   return predicate;
2768 }
2769 
2770 
2771 //------------------------------ins_encode_parse_block-------------------------
2772 // Parse the block form of ins_encode.  See ins_encode_parse for more details
2773 InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
2774   // Create a new encoding name based on the name of the instruction
2775   // definition, which should be unique.
2776   const char * prefix = "__enc_";
2777   char* ec_name = (char*)malloc(strlen(inst._ident) + strlen(prefix) + 1);
2778   sprintf(ec_name, "%s%s", prefix, inst._ident);
2779 
2780   assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
2781   EncClass  *encoding = _AD._encode->add_EncClass(ec_name);
2782   encoding->_linenum = _linenum;
2783 
2784   // synthesize the arguments list for the enc_class from the
2785   // arguments to the instruct definition.
2786   const char * param = NULL;
2787   inst._parameters.reset();
2788   while ((param = inst._parameters.iter()) != NULL) {
2789     OperandForm *opForm = (OperandForm*)inst._localNames[param];
2790     encoding->add_parameter(opForm->_ident, param);
2791   }
2792 
2793   // Add the prologue to create the MacroAssembler
2794   encoding->add_code("\n"
2795   "    // Define a MacroAssembler instance for use by the encoding.  The\n"
2796   "    // name is chosen to match the __ idiom used for assembly in other\n"
2797   "    // parts of hotspot and assumes the existence of the standard\n"
2798   "    // #define __ _masm.\n"
2799   "    MacroAssembler _masm(&cbuf);\n");
2800 
2801   // Parse the following %{ }% block
2802   enc_class_parse_block(encoding, ec_name);
2803 
2804   // Build an encoding rule which invokes the encoding rule we just
2805   // created, passing all arguments that we received.
2806   InsEncode *encrule  = new InsEncode(); // Encode class for instruction
2807   NameAndList *params = encrule->add_encode(ec_name);
2808   inst._parameters.reset();
2809   while ((param = inst._parameters.iter()) != NULL) {
2810     params->add_entry(param);
2811   }
2812 
2813   return encrule;
2814 }
2815 
2816 
2817 //------------------------------ins_encode_parse-------------------------------
2818 // Encode rules have the form 
2819 //   ins_encode( encode_class_name(parameter_list), ... );
2820 //
2821 // The "encode_class_name" must be defined in the encode section
2822 // The parameter list contains $names that are locals.
2823 //
2824 // Alternatively it can be written like this:
2825 //
2826 //   ins_encode %{
2827 //      ... // body
2828 //   %}
2829 // 
2830 // which synthesizes a new encoding class taking the same arguments as
2831 // the InstructForm, and automatically prefixes the definition with:
2832 // 
2833 //    MacroAssembler masm(&cbuf);\n");
2834 // 
2835 //  making it more compact to take advantage of the MacroAssembler and
2836 //  placing the assembly closer to it's use by instructions.
2837 InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
2838 
2839   // Parse encode class name
2840   skipws();                        // Skip whitespace
2841   if (_curchar != '(') {
2842     // Check for ins_encode %{ form
2843     if ((_curchar == '%') && (*(_ptr+1) == '{')) {
2844       next_char();                      // Skip '%'
2845       next_char();                      // Skip '{'
2846 
2847       // Parse the block form of ins_encode
2848       return ins_encode_parse_block(inst);
2849     }
2850 
2851     parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n");
2852     return NULL;
2853   }
2854   next_char();                     // move past '('
2855   skipws();
2856 
2857   InsEncode *encrule  = new InsEncode(); // Encode class for instruction
2858   encrule->_linenum = _linenum;
2859   char      *ec_name  = NULL;      // String representation of encode rule
2860   // identifier is optional.
2861   while (_curchar != ')') {
2862     ec_name = get_ident();
2863     if (ec_name == NULL) {
2864       parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n");
2865       return NULL;
2866     }
2867     // Check that encoding is defined in the encode section
2868     EncClass *encode_class = _AD._encode->encClass(ec_name);
2869     if (encode_class == NULL) {
2870       // Like to defer checking these till later...
2871       // parse_err(WARN, "Using an undefined encode class '%s' in 'ins_encode'.\n", ec_name);
2872     }
2873 
2874     // Get list for encode method's parameters
2875     NameAndList *params = encrule->add_encode(ec_name);
2876 
2877     // Parse the parameters to this encode method.
2878     skipws();
2879     if ( _curchar == '(' ) {
2880       next_char();                 // move past '(' for parameters
2881       
2882       // Parse the encode method's parameters
2883       while (_curchar != ')') {
2884         char *param = get_ident_or_literal_constant("encoding operand");
2885         if ( param != NULL ) {
2886           // Found a parameter:
2887           // Check it is a local name, add it to the list, then check for more
2888           // New: allow hex constants as parameters to an encode method.
2889           // New: allow parenthesized expressions as parameters.
2890           // New: allow "primary", "secondary", "tertiary" as parameters.
2891           // New: allow user-defined register name as parameter
2892           if ( (inst._localNames[param] == NULL) && 
2893                !ADLParser::is_literal_constant(param) && 
2894                (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
2895                ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
2896             parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
2897             return NULL;
2898           }
2899           params->add_entry(param);
2900 
2901           skipws();
2902           if (_curchar == ',' ) {
2903             // More parameters to come
2904             next_char();           // move past ',' between parameters
2905             skipws();              // Skip to next parameter
2906           }
2907           else if (_curchar == ')') {
2908             // Done with parameter list
2909           }
2910           else {
2911             // Only ',' or ')' are valid after a parameter name
2912             parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n",
2913                       ec_name);
2914             return NULL;
2915           }
2916 
2917         } else {
2918           skipws();
2919           // Did not find a parameter
2920           if (_curchar == ',') {
2921             parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name);
2922             return NULL;
2923           }
2924           if (_curchar != ')') {
2925             parse_err(SYNERR, "Expected ')' after encode parameters.\n");
2926             return NULL;
2927           }            
2928         }
2929       } // WHILE loop collecting parameters
2930       next_char();                   // move past ')' at end of parameters
2931     } // done with parameter list for encoding
2932 
2933     // Check for ',' or ')' after encoding
2934     skipws();                      // move to character after parameters
2935     if ( _curchar == ',' ) {
2936       // Found a ','
2937       next_char();                 // move past ',' between encode methods
2938       skipws();
2939     }
2940     else if ( _curchar != ')' ) {
2941       // If not a ',' then only a ')' is allowed
2942       parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name);
2943       return NULL;
2944     }
2945 
2946     // Check for ',' separating parameters
2947     // if ( _curchar != ',' && _curchar != ')' ) {
2948     //   parse_err(SYNERR, "expected ',' or ')' after encode method inside ins_encode.\n");
2949     //   return NULL;
2950     // }
2951 
2952   } // done parsing ins_encode methods and their parameters
2953   if (_curchar != ')') {
2954     parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n");
2955     return NULL;
2956   }
2957   next_char();                     // move past ')'
2958   skipws();                        // Skip leading whitespace
2959 
2960   if ( _curchar != ';' ) {
2961     parse_err(SYNERR, "Missing ';' at end of ins_encode.\n");
2962     return NULL;
2963   }
2964   next_char();                     // move past ';'
2965   skipws();                        // be friendly to oper_parse()
2966   
2967   // Debug Stuff
2968   if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name);
2969 
2970   return encrule;
2971 }
2972 
2973 
2974 //------------------------------size_parse-----------------------------------
2975 char* ADLParser::size_parse(InstructForm *instr) {
2976   char* sizeOfInstr = NULL;
2977 
2978   // Get value of the instruction's size
2979   skipws();
2980   
2981   // Parse size
2982   sizeOfInstr = get_paren_expr("size expression");
2983   if (sizeOfInstr == NULL) {
2984      parse_err(SYNERR, "size of opcode expected at %c\n", _curchar);
2985      return NULL;
2986   }
2987 
2988   skipws();
2989 
2990   // Check for terminator
2991   if (_curchar != ';') {
2992     parse_err(SYNERR, "missing ';' in ins_attrib definition\n");
2993     return NULL;
2994   }
2995   next_char();                     // Advance past the ';'
2996   skipws();                        // necessary for instr_parse()
2997 
2998   // Debug Stuff
2999   if (_AD._adl_debug > 1) {
3000     if (sizeOfInstr != NULL) {
3001       fprintf(stderr,"size of opcode: %s\n", sizeOfInstr);    
3002     }
3003   }
3004   
3005   return sizeOfInstr;
3006 }
3007 
3008 
3009 //------------------------------opcode_parse-----------------------------------
3010 Opcode * ADLParser::opcode_parse(InstructForm *instr) {
3011   char *primary   = NULL;
3012   char *secondary = NULL;
3013   char *tertiary  = NULL;
3014 
3015   char   *val    = NULL;
3016   Opcode *opcode = NULL;
3017 
3018   // Get value of the instruction's opcode
3019   skipws();
3020   if (_curchar != '(') {         // Check for parenthesized operand list
3021     parse_err(SYNERR, "missing '(' in expand instruction declaration\n");
3022     return NULL;
3023   }
3024   next_char();                   // skip open paren 
3025   skipws();
3026   if (_curchar != ')') {
3027     // Parse primary, secondary, and tertiary opcodes, if provided.
3028     if ( ((primary = get_ident_or_literal_constant("primary opcode")) == NULL) ) {
3029         parse_err(SYNERR, "primary hex opcode expected at %c\n", _curchar);
3030         return NULL;
3031     }
3032     skipws();
3033     if (_curchar == ',') {
3034       next_char();
3035       skipws();
3036       // Parse secondary opcode
3037       if ( ((secondary = get_ident_or_literal_constant("secondary opcode")) == NULL) ) {
3038         parse_err(SYNERR, "secondary hex opcode expected at %c\n", _curchar);
3039         return NULL;
3040       }
3041       skipws();
3042       if (_curchar == ',') {
3043         next_char();
3044         skipws();
3045         // Parse tertiary opcode
3046         if ( ((tertiary = get_ident_or_literal_constant("tertiary opcode")) == NULL) ) {
3047           parse_err(SYNERR,"tertiary hex opcode expected at %c\n", _curchar);
3048           return NULL;
3049         }
3050         skipws();
3051       }
3052     }
3053     skipws();
3054     if (_curchar != ')') {
3055       parse_err(SYNERR, "Missing ')' in opcode description\n");
3056       return NULL;
3057     }
3058   }
3059   next_char();                     // Skip ')'
3060   skipws();
3061   // Check for terminator
3062   if (_curchar != ';') {
3063     parse_err(SYNERR, "missing ';' in ins_attrib definition\n");
3064     return NULL;
3065   }
3066   next_char();                     // Advance past the ';'
3067   skipws();                        // necessary for instr_parse()
3068 
3069   // Debug Stuff
3070   if (_AD._adl_debug > 1) {
3071     if (primary   != NULL) fprintf(stderr,"primary   opcode: %s\n", primary);
3072     if (secondary != NULL) fprintf(stderr,"secondary opcode: %s\n", secondary);
3073     if (tertiary  != NULL) fprintf(stderr,"tertiary  opcode: %s\n", tertiary);
3074   }
3075 
3076   // Generate new object and return
3077   opcode = new Opcode(primary, secondary, tertiary);
3078   return opcode;
3079 }
3080 
3081 
3082 //------------------------------interface_parse--------------------------------
3083 Interface *ADLParser::interface_parse(void) {
3084   char *iface_name  = NULL;      // Name of interface class being used
3085   char *iface_code  = NULL;      // Describe components of this class
3086 
3087   // Get interface class name
3088   skipws();                       // Skip whitespace
3089   if (_curchar != '(') {
3090     parse_err(SYNERR, "Missing '(' at start of interface description.\n");
3091     return NULL;
3092   }
3093   next_char();                    // move past '('
3094   skipws();
3095   iface_name = get_ident();
3096   if (iface_name == NULL) {
3097     parse_err(SYNERR, "missing interface name after 'interface'.\n");
3098     return NULL;
3099   }
3100   skipws();
3101   if (_curchar != ')') {
3102     parse_err(SYNERR, "Missing ')' after name of interface.\n");
3103     return NULL;
3104   }
3105   next_char();                    // move past ')'
3106 
3107   // Get details of the interface, 
3108   // for the type of interface indicated by iface_name.
3109   Interface *inter = NULL;
3110   skipws();
3111   if ( _curchar != ';' ) {
3112     if ( strcmp(iface_name,"MEMORY_INTER") == 0 ) {
3113       inter = mem_interface_parse();
3114     }
3115     else if ( strcmp(iface_name,"COND_INTER") == 0 ) {
3116       inter = cond_interface_parse();
3117     }
3118     // The parse routines consume the "%}"
3119       
3120     // Check for probable extra ';' after defining block.
3121     if ( _curchar == ';' ) {
3122       parse_err(SYNERR, "Extra ';' after defining interface block.\n");
3123       next_char();                // Skip ';'
3124       return NULL;
3125     }
3126   } else {
3127     next_char();                  // move past ';'
3128 
3129     // Create appropriate interface object
3130     if ( strcmp(iface_name,"REG_INTER") == 0 ) {
3131       inter = new RegInterface();
3132     }
3133     else if ( strcmp(iface_name,"CONST_INTER") == 0 ) {
3134       inter = new ConstInterface();
3135     }
3136   }
3137   skipws();                       // be friendly to oper_parse()
3138   // Debug Stuff
3139   if (_AD._adl_debug > 1) fprintf(stderr,"Interface Form: %s\n", iface_name);
3140 
3141   // Create appropriate interface object and return.
3142   return inter;
3143 }
3144 
3145 
3146 //------------------------------mem_interface_parse----------------------------
3147 Interface *ADLParser::mem_interface_parse(void) {
3148   // Fields for MemInterface
3149   char *base        = NULL;
3150   char *index       = NULL;
3151   char *scale       = NULL;
3152   char *disp        = NULL;
3153 
3154   if (_curchar != '%') {
3155     parse_err(SYNERR, "Missing '%{' for 'interface' block.\n");
3156     return NULL;
3157   }
3158   next_char();                  // Skip '%'
3159   if (_curchar != '{') {
3160     parse_err(SYNERR, "Missing '%{' for 'interface' block.\n");
3161     return NULL;
3162   }
3163   next_char();                  // Skip '{'
3164   skipws();
3165   do {
3166     char *field = get_ident();
3167     if (field == NULL) {
3168       parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
3169       return NULL;
3170     }
3171     if ( strcmp(field,"base") == 0 ) {
3172       base  = interface_field_parse();
3173     }
3174     else if ( strcmp(field,"index") == 0 ) {
3175       index = interface_field_parse();
3176     }
3177     else if ( strcmp(field,"scale") == 0 ) {
3178       scale = interface_field_parse();
3179     }
3180     else if ( strcmp(field,"disp") == 0 ) {
3181       disp  = interface_field_parse();
3182     }
3183     else {
3184       parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
3185       return NULL;
3186     }
3187   } while( _curchar != '%' );
3188   next_char();                  // Skip '%'
3189   if ( _curchar != '}' ) {
3190     parse_err(SYNERR, "Missing '%}' for 'interface' block.\n");
3191     return NULL;
3192   }
3193   next_char();                  // Skip '}'
3194 
3195   // Construct desired object and return
3196   Interface *inter = new MemInterface(base, index, scale, disp);
3197   return inter;
3198 }
3199 
3200 
3201 //------------------------------cond_interface_parse---------------------------
3202 Interface *ADLParser::cond_interface_parse(void) {
3203   char *equal;
3204   char *not_equal;
3205   char *less;
3206   char *greater_equal;
3207   char *less_equal;
3208   char *greater;
3209   
3210   if (_curchar != '%') {
3211     parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
3212     return NULL;
3213   }
3214   next_char();                  // Skip '%'
3215   if (_curchar != '{') {
3216     parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");
3217     return NULL;
3218   }
3219   next_char();                  // Skip '{'
3220   skipws();
3221   do {
3222     char *field = get_ident();
3223     if (field == NULL) {
3224       parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
3225       return NULL;
3226     }
3227     if ( strcmp(field,"equal") == 0 ) {
3228       equal  = interface_field_parse();
3229     }
3230     else if ( strcmp(field,"not_equal") == 0 ) {
3231       not_equal = interface_field_parse();
3232     }
3233     else if ( strcmp(field,"less") == 0 ) {
3234       less = interface_field_parse();
3235     }
3236     else if ( strcmp(field,"greater_equal") == 0 ) {
3237       greater_equal  = interface_field_parse();
3238     }
3239     else if ( strcmp(field,"less_equal") == 0 ) {
3240       less_equal = interface_field_parse();
3241     }
3242     else if ( strcmp(field,"greater") == 0 ) {
3243       greater = interface_field_parse();
3244     }
3245     else {
3246       parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%}' ending interface.\n");
3247       return NULL;
3248     }
3249   } while( _curchar != '%' );
3250   next_char();                  // Skip '%'
3251   if ( _curchar != '}' ) {
3252     parse_err(SYNERR, "Missing '%}' for 'interface' block.\n");
3253     return NULL;
3254   }
3255   next_char();                  // Skip '}'
3256 
3257   // Construct desired object and return
3258   Interface *inter = new CondInterface(equal, not_equal, less, greater_equal,
3259                                        less_equal, greater);
3260   return inter;
3261 }
3262 
3263 
3264 //------------------------------interface_field_parse--------------------------
3265 char *ADLParser::interface_field_parse(void) {
3266   char *iface_field = NULL;
3267 
3268   // Get interface field
3269   skipws();                      // Skip whitespace
3270   if (_curchar != '(') {
3271     parse_err(SYNERR, "Missing '(' at start of interface field.\n");
3272     return NULL;
3273   }
3274   next_char();                   // move past '('
3275   skipws();
3276   if ( _curchar != '0' && _curchar != '$' ) {
3277     parse_err(SYNERR, "missing or invalid interface field contents.\n");
3278     return NULL;
3279   }
3280   iface_field = get_rep_var_ident();
3281   if (iface_field == NULL) {
3282     parse_err(SYNERR, "missing or invalid interface field contents.\n");
3283     return NULL;
3284   }
3285   skipws();
3286   if (_curchar != ')') {
3287     parse_err(SYNERR, "Missing ')' after interface field.\n");
3288     return NULL;
3289   }
3290   next_char();                   // move past ')'
3291   skipws();
3292   if ( _curchar != ';' ) {
3293     parse_err(SYNERR, "Missing ';' at end of interface field.\n");
3294     return NULL;
3295   }
3296   next_char();                    // move past ';'
3297   skipws();                       // be friendly to interface_parse()
3298 
3299   return iface_field;
3300 }
3301 
3302 
3303 //------------------------------match_parse------------------------------------
3304 MatchRule *ADLParser::match_parse(FormDict &operands) {
3305   MatchRule *match;               // Match Rule class for instruction/operand
3306   char      *cnstr = NULL;        // Code for constructor
3307   int        depth = 0;           // Counter for matching parentheses
3308   int        numleaves = 0;       // Counter for number of leaves in rule
3309 
3310   // Parse the match rule tree
3311   MatchNode *mnode = matchNode_parse(operands, depth, numleaves, true);
3312 
3313   // Either there is a block with a constructor, or a ';' here
3314   skipws();                       // Skip whitespace
3315   if ( _curchar == ';' ) {        // Semicolon is valid terminator
3316     cnstr = NULL;                 // no constructor for this form
3317     next_char();                  // Move past the ';', replaced with '\0'
3318   }
3319   else if ((cnstr = find_cpp_block("match constructor")) == NULL ) {
3320     parse_err(SYNERR, "invalid construction of match rule\n"
3321               "Missing ';' or invalid '%{' and '%}' constructor\n");
3322     return NULL;                  // No MatchRule to return
3323   }
3324   if (_AD._adl_debug > 1) 
3325     if (cnstr) fprintf(stderr,"Match Constructor: %s\n", cnstr);
3326   // Build new MatchRule object
3327   match = new MatchRule(_AD, mnode, depth, cnstr, numleaves); 
3328   skipws();                       // Skip any trailing whitespace
3329   return match;                   // Return MatchRule object
3330 }
3331 
3332 //------------------------------format_parse-----------------------------------
3333 FormatRule* ADLParser::format_parse(void) {
3334   char       *desc   = NULL;    
3335   FormatRule *format = (new FormatRule(desc));
3336 
3337   // Without expression form, MUST have a code block;
3338   skipws();                       // Skip whitespace
3339   if ( _curchar == ';' ) {        // Semicolon is valid terminator
3340     desc  = NULL;                 // no constructor for this form
3341     next_char();                  // Move past the ';', replaced with '\0'
3342   }
3343   else if ( _curchar == '%' && *(_ptr+1) == '{') {
3344     next_char();                  // Move past the '%'
3345     next_char();                  // Move past the '{'
3346 
3347     skipws();
3348     // Check for the opening '"' inside the format description
3349     if ( _curchar == '"' ) {
3350       next_char();              // Move past the initial '"'
3351       if( _curchar == '"' ) {   // Handle empty format string case
3352         *_ptr = '\0';           // Terminate empty string
3353         format->_strings.addName(_ptr);
3354       }
3355 
3356       // Collect the parts of the format description
3357       // (1) strings that are passed through to tty->print
3358       // (2) replacement/substitution variable, preceeded by a '$'
3359       // (3) multi-token ANSIY C style strings
3360       while ( true ) {
3361         if ( _curchar == '%' || _curchar == '\n' ) {
3362           if ( _curchar != '"' ) {
3363             parse_err(SYNERR, "missing '\"' at end of format block");
3364             return NULL;
3365           }
3366         }
3367 
3368         // (1)
3369         // Check if there is a string to pass through to output
3370         char *start = _ptr;       // Record start of the next string
3371         while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
3372           if (_curchar == '\\')  next_char();  // superquote
3373           if (_curchar == '\n')  parse_err(SYNERR, "newline in string");  // unimplemented!
3374           next_char();
3375         }
3376         // If a string was found, terminate it and record in FormatRule
3377         if ( start != _ptr ) {
3378           *_ptr  = '\0';          // Terminate the string
3379           format->_strings.addName(start);
3380         }
3381         
3382         // (2)
3383         // If we are at a replacement variable, 
3384         // copy it and record in FormatRule
3385         if ( _curchar == '$' ) {
3386           next_char();          // Move past the '$'
3387           char* rep_var = get_ident(); // Nil terminate the variable name
3388           rep_var = strdup(rep_var);// Copy the string
3389           *_ptr   = _curchar;     // and replace Nil with original character
3390           format->_rep_vars.addName(rep_var);
3391           // Add flag to _strings list indicating we should check _rep_vars
3392           format->_strings.addName(NameList::_signal);
3393         }
3394 
3395         // (3)
3396         // Allow very long strings to be broken up,
3397         // using the ANSI C syntax "foo\n" <newline> "bar"
3398         if ( _curchar == '"') {
3399           next_char();           // Move past the '"'
3400           skipws();              // Skip white space before next string token
3401           if ( _curchar != '"') {
3402             break;
3403           } else {
3404             // Found one.  Skip both " and the whitespace in between.
3405             next_char();
3406           }
3407         }
3408       } // end while part of format description
3409 
3410       // Check for closing '"' and '%}' in format description
3411       skipws();                   // Move to closing '%}'
3412       if ( _curchar != '%' ) {
3413         parse_err(SYNERR, "non-blank characters between closing '\"' and '%' in format");
3414         return NULL;
3415       }
3416     } // Done with format description inside 
3417 
3418     skipws();
3419     // Past format description, at '%'
3420     if ( _curchar != '%' || *(_ptr+1) != '}' ) {
3421       parse_err(SYNERR, "missing '%}' at end of format block");
3422       return NULL;
3423     }
3424     next_char();                  // Move past the '%'
3425     next_char();                  // Move past the '}'
3426   }
3427   else {  // parameter list alone must terminate with a ';'
3428     parse_err(SYNERR, "missing ';' after Format expression");
3429     return NULL;
3430   }
3431   // Debug Stuff
3432   if (_AD._adl_debug > 1) fprintf(stderr,"Format Rule: %s\n", desc);
3433   
3434   skipws();
3435   return format;
3436 }
3437 
3438 
3439 //------------------------------effect_parse-----------------------------------
3440 void ADLParser::effect_parse(InstructForm *instr) {
3441   char* desc   = NULL;    
3442 
3443   skipws();                      // Skip whitespace
3444   if (_curchar != '(') {
3445     parse_err(SYNERR, "missing '(' in effect definition\n");
3446     return;
3447   }
3448   // Get list of effect-operand pairs and insert into dictionary
3449   else get_effectlist(instr->_effects, instr->_localNames);
3450 
3451   // Debug Stuff
3452   if (_AD._adl_debug > 1) fprintf(stderr,"Effect description: %s\n", desc);
3453   if (_curchar != ';') {
3454     parse_err(SYNERR, "missing ';' in Effect definition\n");
3455   }
3456   next_char();                  // Skip ';'
3457   
3458 }
3459 
3460 //------------------------------expand_parse-----------------------------------
3461 ExpandRule* ADLParser::expand_parse(InstructForm *instr) {
3462   char         *ident, *ident2;
3463   OperandForm  *oper;
3464   InstructForm *ins;
3465   NameAndList  *instr_and_operands = NULL;
3466   ExpandRule   *exp = new ExpandRule();
3467 
3468   // Expand is a block containing an ordered list of instructions, each of
3469   // which has an ordered list of operands.
3470   // Check for block delimiter
3471   skipws();                        // Skip leading whitespace
3472   if ((_curchar != '%') 
3473       || (next_char(), (_curchar != '{')) ) { // If not open block
3474     parse_err(SYNERR, "missing '%{' in expand definition\n");
3475     return(NULL);
3476   }
3477   next_char();                     // Maintain the invariant
3478   do {
3479     ident = get_ident();           // Grab next identifier
3480     if (ident == NULL) {
3481       parse_err(SYNERR, "identifier expected at %c\n", _curchar);
3482       continue;
3483     }                              // Check that you have a valid instruction
3484     const Form *form = _globalNames[ident];
3485     ins = form ? form->is_instruction() : NULL;
3486     if (ins == NULL) {
3487       // This is a new operand
3488       oper = form ? form->is_operand() : NULL;
3489       if (oper == NULL) {
3490         parse_err(SYNERR, "instruction/operand name expected at %s\n", ident);
3491         continue;
3492       }
3493       // Throw the operand on the _newopers list
3494       skipws();
3495       ident = get_unique_ident(instr->_localNames,"Operand");
3496       if (ident == NULL) {
3497         parse_err(SYNERR, "identifier expected at %c\n", _curchar);
3498         continue;
3499       }
3500       exp->_newopers.addName(ident);
3501       // Add new operand to LocalNames
3502       instr->_localNames.Insert(ident, oper);
3503       // Grab any constructor code and save as a string
3504       char *c = NULL;
3505       skipws();
3506       if (_curchar == '%') { // Need a constructor for the operand
3507         c = find_cpp_block("Operand Constructor");
3508         if (c == NULL) {
3509           parse_err(SYNERR, "Invalid code block for operand constructor\n", _curchar);
3510           continue;
3511         }
3512         // Add constructor to _newopconst Dict
3513         exp->_newopconst.Insert(ident, c);
3514       }
3515       else if (_curchar != ';') { // If no constructor, need a ;
3516         parse_err(SYNERR, "Missing ; in expand rule operand declaration\n");
3517         continue;
3518       }
3519       else next_char(); // Skip the ;
3520       skipws();
3521     }
3522     else {
3523       // Add instruction to list
3524       instr_and_operands = new NameAndList(ident);
3525       // Grab operands, build nameList of them, and then put into dictionary
3526       skipws();
3527       if (_curchar != '(') {         // Check for parenthesized operand list
3528         parse_err(SYNERR, "missing '(' in expand instruction declaration\n");
3529         continue;
3530       }
3531       do {
3532         next_char();                 // skip open paren & comma characters
3533         skipws();
3534         if (_curchar == ')') break;
3535         ident2 = get_ident();
3536         skipws();
3537         if (ident2 == NULL) {
3538           parse_err(SYNERR, "identifier expected at %c\n", _curchar);
3539           continue;
3540         }                            // Check that you have a valid operand
3541         const Form *form = instr->_localNames[ident2];
3542         if (!form) {
3543           parse_err(SYNERR, "operand name expected at %s\n", ident2);
3544           continue;
3545         }
3546         oper = form->is_operand();
3547         if (oper == NULL && !form->is_opclass()) {
3548           parse_err(SYNERR, "operand name expected at %s\n", ident2);
3549           continue;
3550         }                            // Add operand to list
3551         instr_and_operands->add_entry(ident2);
3552       } while(_curchar == ',');
3553       if (_curchar != ')') {
3554         parse_err(SYNERR, "missing ')'in expand instruction declaration\n");
3555         continue;
3556       }
3557       next_char();
3558       if (_curchar != ';') {
3559         parse_err(SYNERR, "missing ';'in expand instruction declaration\n");
3560         continue;
3561       }
3562       next_char();
3563 
3564       // Record both instruction name and its operand list 
3565       exp->add_instruction(instr_and_operands);
3566 
3567       skipws();
3568     }
3569 
3570   } while(_curchar != '%');
3571   next_char();
3572   if (_curchar != '}') {
3573     parse_err(SYNERR, "missing '%}' in expand rule definition\n");
3574     return(NULL);
3575   }
3576   next_char();
3577 
3578   // Debug Stuff
3579   if (_AD._adl_debug > 1) fprintf(stderr,"Expand Rule:\n");
3580 
3581   skipws();
3582   return (exp);
3583 }
3584 
3585 //------------------------------rewrite_parse----------------------------------
3586 RewriteRule* ADLParser::rewrite_parse(void) {
3587   char* params = NULL;
3588   char* desc   = NULL;    
3589 
3590 
3591   // This feature targeted for second generation description language.
3592 
3593   skipws();                      // Skip whitespace
3594   // Get parameters for rewrite
3595   if ((params = get_paren_expr("rewrite parameters")) == NULL) {
3596     parse_err(SYNERR, "missing '(' in rewrite rule\n");
3597     return NULL;
3598   }
3599   // Debug Stuff
3600   if (_AD._adl_debug > 1) fprintf(stderr,"Rewrite parameters: %s\n", params);
3601   
3602   // For now, grab entire block;
3603   skipws();
3604   if ( (desc = find_cpp_block("rewrite block")) == NULL ) {
3605     parse_err(SYNERR, "incorrect or missing block for 'rewrite'.\n");
3606     return NULL;
3607   }
3608   // Debug Stuff
3609   if (_AD._adl_debug > 1) fprintf(stderr,"Rewrite Rule: %s\n", desc);
3610   
3611   skipws();
3612   return (new RewriteRule(params,desc));
3613 }
3614 
3615 //------------------------------attr_parse-------------------------------------
3616 Attribute *ADLParser::attr_parse(char* ident) {
3617   Attribute *attrib;              // Attribute class
3618   char      *cost = NULL;         // String representation of cost attribute
3619 
3620   skipws();                       // Skip leading whitespace
3621   if ( (cost = get_paren_expr("attribute")) == NULL ) {
3622     parse_err(SYNERR, "incorrect or missing expression for 'attribute'\n");
3623     return NULL;
3624   }
3625   // Debug Stuff
3626   if (_AD._adl_debug > 1) fprintf(stderr,"Attribute: %s\n", cost);
3627   if (_curchar != ';') {
3628     parse_err(SYNERR, "missing ';' in attribute definition\n");
3629     return NULL;
3630   }
3631   next_char();                   // Point after the terminator
3632 
3633   skipws();
3634   attrib = new Attribute(ident,cost,INS_ATTR); // Build new predicate object
3635   return attrib;
3636 }
3637 
3638 
3639 //------------------------------matchNode_parse--------------------------------
3640 MatchNode *ADLParser::matchNode_parse(FormDict &operands, int &depth, int &numleaves, bool atroot) {
3641   // Count depth of parenthesis nesting for both left and right children
3642   int   lParens = depth;
3643   int   rParens = depth;
3644 
3645   // MatchNode objects for left, right, and root of subtree.
3646   MatchNode *lChild = NULL;
3647   MatchNode *rChild = NULL;
3648   char      *token;               // Identifier which may be opcode or operand
3649 
3650   // Match expression starts with a '('
3651   if (cur_char() != '(')
3652     return NULL;
3653 
3654   next_char();                    // advance past '('
3655 
3656   // Parse the opcode
3657   token = get_ident();            // Get identifier, opcode 
3658   if (token == NULL) {
3659     parse_err(SYNERR, "missing opcode in match expression\n");
3660     return NULL;
3661   }
3662 
3663   // Take note if we see one of a few special operations - those that are
3664   // treated differently on different architectures in the sense that on
3665   // one architecture there is a match rule and on another there isn't (so
3666   // a call will eventually be generated).
3667 
3668   for (int i = _last_machine_leaf + 1; i < _last_opcode; i++) {
3669     if (strcmp(token, NodeClassNames[i]) == 0) {
3670       _AD.has_match_rule(i, true);
3671     }
3672   }
3673 
3674   // Lookup the root value in the operands dict to perform substitution
3675   const char  *result    = NULL;  // Result type will be filled in later
3676   const char  *name      = token; // local name associated with this node
3677   const char  *operation = token; // remember valid operation for later
3678   const Form  *form      = operands[token];
3679   OpClassForm *opcForm = form ? form->is_opclass() : NULL;
3680   if (opcForm != NULL) {
3681     // If this token is an entry in the local names table, record its type
3682     if (!opcForm->ideal_only()) {
3683       operation = opcForm->_ident;
3684       result = operation;         // Operands result in their own type
3685     }
3686     // Otherwise it is an ideal type, and so, has no local name
3687     else                        name = NULL;
3688   }
3689 
3690   // Parse the operands
3691   skipws();
3692   if (cur_char() != ')') {
3693     
3694     // Parse the left child
3695     if (strcmp(operation,"Set"))
3696       lChild = matchChild_parse(operands, lParens, numleaves, false);
3697     else
3698       lChild = matchChild_parse(operands, lParens, numleaves, true);
3699 
3700     skipws();
3701     if (cur_char() != ')' ) {
3702       if(strcmp(operation, "Set"))
3703         rChild = matchChild_parse(operands,rParens,numleaves,false);
3704       else
3705         rChild = matchChild_parse(operands,rParens,numleaves,true);
3706     }
3707   }
3708 
3709   // Check for required ')'
3710   skipws();
3711   if (cur_char() != ')') {
3712     parse_err(SYNERR, "missing ')' in match expression\n");
3713     return NULL;
3714   }
3715   next_char();                    // skip the ')'
3716 
3717   MatchNode* mroot = new MatchNode(_AD,result,name,operation,lChild,rChild);
3718 
3719   // If not the root, reduce this subtree to an internal operand
3720   if (!atroot) {
3721     mroot->build_internalop();
3722   }
3723   // depth is greater of left and right paths.
3724   depth = (lParens > rParens) ? lParens : rParens;
3725 
3726   return mroot;
3727 }
3728   
3729 
3730 //------------------------------matchChild_parse-------------------------------
3731 MatchNode *ADLParser::matchChild_parse(FormDict &operands, int &parens, int &numleaves, bool atroot) {
3732   MatchNode  *child  = NULL;
3733   const char *result = NULL;
3734   const char *token  = NULL;
3735   const char *opType = NULL;
3736 
3737   if (cur_char() == '(') {         // child is an operation
3738     ++parens;
3739     child = matchNode_parse(operands, parens, numleaves, atroot);
3740   }
3741   else {                           // child is an operand
3742     token = get_ident();
3743     const Form  *form    = operands[token];
3744     OpClassForm *opcForm = form ? form->is_opclass() : NULL;
3745     if (opcForm != NULL) {
3746       opType = opcForm->_ident;
3747       result = opcForm->_ident;    // an operand's result matches its type
3748     } else {
3749       parse_err(SYNERR, "undefined operand %s in match rule\n", token);
3750       return NULL;
3751     }
3752 
3753     if (opType == NULL) {
3754       parse_err(SYNERR, "missing type for argument '%s'\n", token);
3755     }
3756 
3757     child = new MatchNode(_AD, result, token, opType);
3758     ++numleaves;
3759   }
3760 
3761   return child;
3762 }
3763 
3764 
3765 
3766 // ******************** Private Utility Functions *************************
3767 
3768 
3769 char* ADLParser::find_cpp_block(const char* description) {
3770   char *next;                     // Pointer for finding block delimiters
3771   char* cppBlock = NULL;          // Beginning of C++ code block
3772 
3773   if (_curchar == '%') {          // Encoding is a C++ expression
3774     next_char();
3775     if (_curchar != '{') {
3776       parse_err(SYNERR, "missing '{' in %s \n", description);
3777       return NULL;
3778     }
3779     next_char();                  // Skip block delimiter
3780     skipws_no_preproc();          // Skip leading whitespace
3781     cppBlock = _ptr;              // Point to start of expression
3782     const char* file = _AD._ADL_file._name;
3783     int         line = _linenum;
3784     next = _ptr + 1;
3785     while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
3786       next_char_or_line();
3787       next = _ptr+1;              // Maintain the next pointer
3788     }                             // Grab string
3789     if (_curchar == '\0') {
3790       parse_err(SYNERR, "invalid termination of %s \n", description);
3791       return NULL;
3792     }
3793     *_ptr = '\0';                 // Terminate string
3794     _ptr += 2;                    // Skip block delimiter
3795     _curchar = *_ptr;             // Maintain invariant
3796 
3797     // Prepend location descriptor, for debugging.
3798     char* location = (char *)malloc(strlen(file) + 100);
3799     *location = '\0';
3800     if (_AD._adlocation_debug)
3801       sprintf(location, "#line %d \"%s\"\n", line, file);
3802     char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + 1);
3803     strcpy(result, location);
3804     strcat(result, cppBlock);
3805     cppBlock = result;
3806     free(location);
3807   }
3808 
3809   return cppBlock;
3810 }
3811 
3812 // Move to the closing token of the expression we are currently at,
3813 // as defined by stop_chars.  Match parens and quotes.
3814 char* ADLParser::get_expr(const char *desc, const char *stop_chars) {
3815   char* expr = NULL;
3816   int   paren = 0;
3817 
3818   expr = _ptr;
3819   while (paren > 0 || !strchr(stop_chars, _curchar)) {
3820     if (_curchar == '(') {        // Down level of nesting
3821       paren++;                    // Bump the parenthesis counter
3822       next_char();                // maintain the invariant
3823     }
3824     else if (_curchar == ')') {   // Up one level of nesting
3825       if (paren == 0) {
3826         // Paren underflow:  We didn't encounter the required stop-char.
3827         parse_err(SYNERR, "too many )'s, did not find %s after %s\n",
3828                   stop_chars, desc);
3829         return NULL;
3830       }
3831       paren--;                    // Drop the parenthesis counter
3832       next_char();                // Maintain the invariant
3833     }
3834     else if (_curchar == '"' || _curchar == '\'') {
3835       int qchar = _curchar;
3836       while (true) {
3837         next_char();
3838         if (_curchar == qchar) { next_char(); break; }
3839         if (_curchar == '\\')  next_char();  // superquote
3840         if (_curchar == '\n' || _curchar == '\0') {
3841           parse_err(SYNERR, "newline in string in %s\n", desc);
3842           return NULL;
3843         }
3844       }
3845     }
3846     else if (_curchar == '%' && (_ptr[1] == '{' || _ptr[1] == '}')) {
3847       // Make sure we do not stray into the next ADLC-level form.
3848       parse_err(SYNERR, "unexpected %%%c in %s\n", _ptr[1], desc);
3849       return NULL;
3850     }
3851     else if (_curchar == '\0') {
3852       parse_err(SYNERR, "unexpected EOF in %s\n", desc);
3853       return NULL;
3854     }
3855     else {
3856       // Always walk over whitespace, comments, preprocessor directives, etc.
3857       char* pre_skip_ptr = _ptr;
3858       skipws();
3859       // If the parser declined to make progress on whitespace,
3860       // skip the next character, which is therefore NOT whitespace.
3861       if (pre_skip_ptr == _ptr) {
3862         next_char();
3863       } else if (pre_skip_ptr+strlen(pre_skip_ptr) != _ptr+strlen(_ptr)) {
3864         parse_err(SYNERR, "unimplemented: preprocessor must not elide subexpression in %s", desc);
3865       }
3866     }
3867   }
3868 
3869   assert(strchr(stop_chars, _curchar), "non-null return must be at stop-char");
3870   *_ptr = '\0';               // Replace ')' or other stop-char with '\0'
3871   return expr;
3872 }
3873 
3874 // Helper function around get_expr
3875 // Sets _curchar to '(' so that get_paren_expr will search for a matching ')'
3876 char *ADLParser::get_paren_expr(const char *description) {
3877   if (_curchar != '(')            // Escape if not valid starting position
3878     return NULL;
3879   next_char();                    // Skip the required initial paren.
3880   char *token2 = get_expr(description, ")");
3881   if (_curchar == ')')
3882     next_char();                  // Skip required final paren.
3883   return token2;
3884 }
3885 
3886 //------------------------------get_ident_common-------------------------------
3887 // Looks for an identifier in the buffer, and turns it into a null terminated
3888 // string(still inside the file buffer).  Returns a pointer to the string or
3889 // NULL if some other token is found instead.
3890 char *ADLParser::get_ident_common(bool do_preproc) {
3891   register char c;
3892   char *start;                    // Pointer to start of token
3893   char *end;                      // Pointer to end of token
3894 
3895   if( _curline == NULL )          // Return NULL at EOF.
3896     return NULL;
3897 
3898   skipws_common(do_preproc);      // Skip whitespace before identifier
3899   start = end = _ptr;             // Start points at first character
3900   end--;                          // unwind end by one to prepare for loop
3901   do {
3902     end++;                        // Increment end pointer
3903     c = *end;                     // Grab character to test
3904   } while ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))
3905             || ((c >= '0') && (c <= '9'))
3906             || ((c == '_')) || ((c == ':')) || ((c == '#')) );
3907   if (start == end) {             // We popped out on the first try
3908     parse_err(SYNERR, "identifier expected at %c\n", c);
3909     start = NULL;
3910   }
3911   else {
3912     _curchar = c;                 // Save the first character of next token
3913     *end = '\0';                  // NULL terminate the string in place
3914   }
3915   _ptr = end;                     // Reset _ptr to point to next char after token
3916 
3917   // Make sure we do not try to use #defined identifiers.  If start is
3918   // NULL an error was already reported.
3919   if (do_preproc && start != NULL) {
3920     const char* def = _AD.get_preproc_def(start);
3921     if (def != NULL && strcmp(def, start)) {
3922       const char* def2 = _AD.get_preproc_def(def);
3923       if (def2 != NULL && strcmp(def2, def)) {
3924         parse_err(SYNERR, "unimplemented: using %s defined as %s => %s",
3925                   start, def, def2);
3926       }
3927       start = strdup(def);
3928     }
3929   }
3930 
3931   return start;                   // Pointer to token in filebuf
3932 }
3933 
3934 //------------------------------get_ident_dup----------------------------------
3935 // Looks for an identifier in the buffer, and returns a duplicate 
3936 // or NULL if some other token is found instead.
3937 char *ADLParser::get_ident_dup(void) {
3938   char *ident = get_ident();
3939 
3940   // Duplicate an identifier before returning and restore string.
3941   if( ident != NULL ) {
3942     ident = strdup(ident);  // Copy the string 
3943     *_ptr   = _curchar;         // and replace Nil with original character
3944   }
3945 
3946   return ident;
3947 }
3948 
3949 //----------------------get_ident_or_literal_constant--------------------------
3950 // Looks for an identifier in the buffer, or a parenthesized expression.
3951 char *ADLParser::get_ident_or_literal_constant(const char* description) {
3952   char* param = NULL;
3953   skipws();
3954   if (_curchar == '(') {
3955     // Grab a constant expression.
3956     param = get_paren_expr(description);
3957     if (param[0] != '(') {
3958       char* buf = (char*) malloc(strlen(param) + 3);
3959       sprintf(buf, "(%s)", param);
3960       param = buf;
3961     }
3962     assert(is_literal_constant(param),
3963            "expr must be recognizable as a constant");
3964   } else {
3965     param = get_ident();
3966   }
3967   return param;
3968 }
3969 
3970 //------------------------------get_rep_var_ident-----------------------------
3971 // Do NOT duplicate, 
3972 // Leave nil terminator in buffer
3973 // Preserve initial '$'(s) in string
3974 char *ADLParser::get_rep_var_ident(void) {
3975   // Remember starting point
3976   char *rep_var = _ptr;
3977 
3978   // Check for replacement variable indicator '$' and pass if present
3979   if ( _curchar == '$' ) {
3980     next_char();
3981   }
3982   // Check for a subfield indicator, a second '$', and pass if present
3983   if ( _curchar == '$' ) {
3984     next_char();
3985   }
3986 
3987   // Check for a control indicator, a third '$':
3988   if ( _curchar == '$' ) {
3989     next_char();
3990   }
3991 
3992   // Check for more than three '$'s in sequence, SYNERR
3993   if( _curchar == '$' ) {
3994     parse_err(SYNERR, "Replacement variables and field specifiers can not start with '$$$$'");
3995     next_char();
3996     return NULL;
3997   }
3998 
3999   // Nil terminate the variable name following the '$'
4000   char *rep_var_name = get_ident();
4001   assert( rep_var_name != NULL, 
4002           "Missing identifier after replacement variable indicator '$'");
4003   
4004   return rep_var;
4005 }
4006 
4007 
4008 
4009 //------------------------------get_rep_var_ident_dup-------------------------
4010 // Return the next replacement variable identifier, skipping first '$'
4011 // given a pointer into a line of the buffer.
4012 // Null terminates string, still inside the file buffer, 
4013 // Returns a pointer to a copy of the string, or NULL on failure
4014 char *ADLParser::get_rep_var_ident_dup(void) {
4015   if( _curchar != '$' ) return NULL;
4016 
4017   next_char();                // Move past the '$'
4018   char *rep_var = _ptr;       // Remember starting point
4019 
4020   // Check for a subfield indicator, a second '$':
4021   if ( _curchar == '$' ) {
4022     next_char();
4023   }
4024 
4025   // Check for a control indicator, a third '$':
4026   if ( _curchar == '$' ) {
4027     next_char();
4028   }
4029 
4030   // Check for more than three '$'s in sequence, SYNERR
4031   if( _curchar == '$' ) {
4032     parse_err(SYNERR, "Replacement variables and field specifiers can not start with '$$$$'");
4033     next_char();
4034     return NULL;
4035   }
4036 
4037   // Nil terminate the variable name following the '$'
4038   char *rep_var_name = get_ident();
4039   assert( rep_var_name != NULL, 
4040           "Missing identifier after replacement variable indicator '$'");
4041   rep_var = strdup(rep_var);  // Copy the string 
4042   *_ptr   = _curchar;         // and replace Nil with original character
4043   
4044   return rep_var;
4045 }
4046 
4047 
4048 //------------------------------get_unique_ident------------------------------
4049 // Looks for an identifier in the buffer, terminates it with a NULL, 
4050 // and checks that it is unique
4051 char *ADLParser::get_unique_ident(FormDict& dict, const char* nameDescription){
4052   char* ident = get_ident();
4053 
4054   if (ident == NULL) {
4055     parse_err(SYNERR, "missing %s identifier at %c\n", nameDescription, _curchar);
4056   }
4057   else {
4058     if (dict[ident] != NULL) {
4059       parse_err(SYNERR, "duplicate name %s for %s\n", ident, nameDescription);
4060       ident = NULL;
4061     }
4062   }
4063 
4064   return ident;
4065 }
4066 
4067 
4068 //------------------------------get_int----------------------------------------
4069 // Looks for a character string integer in the buffer, and turns it into an int
4070 // invokes a parse_err if the next token is not an integer.
4071 // This routine does not leave the integer null-terminated.
4072 int ADLParser::get_int(void) {
4073   register char c;
4074   char         *start;            // Pointer to start of token
4075   char         *end;              // Pointer to end of token
4076   int           result;           // Storage for integer result
4077 
4078   if( _curline == NULL )          // Return NULL at EOF.
4079     return NULL;
4080 
4081   skipws();                       // Skip whitespace before identifier
4082   start = end = _ptr;             // Start points at first character
4083   c = *end;                       // Grab character to test
4084   while ((c >= '0') && (c <= '9')
4085          || ((c == '-') && (end == start))) {
4086     end++;                        // Increment end pointer
4087     c = *end;                     // Grab character to test
4088   }
4089   if (start == end) {             // We popped out on the first try
4090     parse_err(SYNERR, "integer expected at %c\n", c);
4091     result = 0;
4092   }
4093   else {
4094     _curchar = c;                 // Save the first character of next token
4095     *end = '\0';                  // NULL terminate the string in place
4096     result = atoi(start);         // Convert the string to an integer
4097     *end = _curchar;              // Restore buffer to original condition
4098   }
4099 
4100   // Reset _ptr to next char after token
4101   _ptr = end;
4102 
4103   return result;                   // integer 
4104 }
4105 
4106 
4107 //------------------------------get_relation_dup------------------------------
4108 // Looks for a relational operator in the buffer
4109 // invokes a parse_err if the next token is not a relation
4110 // This routine creates a duplicate of the string in the buffer.
4111 char *ADLParser::get_relation_dup(void) {
4112   char         *result = NULL;    // relational operator being returned
4113 
4114   if( _curline == NULL )          // Return NULL at EOF.
4115     return  NULL;
4116 
4117   skipws();                       // Skip whitespace before relation
4118   char *start = _ptr;             // Store start of relational operator
4119   char first  = *_ptr;            // the first character
4120   if( (first == '=') || (first == '!') || (first == '<') || (first == '>') ) {
4121     next_char();
4122     char second = *_ptr;          // the second character
4123     if( (second == '=') ) {
4124       next_char();
4125       char tmp  = *_ptr;
4126       *_ptr = '\0';               // NULL terminate
4127       result = strdup(start);     // Duplicate the string
4128       *_ptr = tmp;                // restore buffer
4129     } else {
4130       parse_err(SYNERR, "relational operator expected at %s\n", _ptr);
4131     }
4132   } else {
4133     parse_err(SYNERR, "relational operator expected at %s\n", _ptr);
4134   }
4135 
4136   return result;
4137 }
4138 
4139 
4140 
4141 //------------------------------get_oplist-------------------------------------
4142 // Looks for identifier pairs where first must be the name of an operand, and
4143 // second must be a name unique in the scope of this instruction.  Stores the
4144 // names with a pointer to the OpClassForm of their type in a local name table.
4145 void ADLParser::get_oplist(NameList &parameters, FormDict &operands) {
4146   OpClassForm *opclass = NULL;
4147   char        *ident   = NULL;
4148 
4149   do {
4150     next_char();             // skip open paren & comma characters
4151     skipws();
4152     if (_curchar == ')') break;
4153 
4154     // Get operand type, and check it against global name table
4155     ident = get_ident();
4156     if (ident == NULL) {
4157       parse_err(SYNERR, "optype identifier expected at %c\n", _curchar);
4158       return;
4159     }
4160     else {
4161       const Form  *form = _globalNames[ident];
4162       if( form == NULL ) {
4163         parse_err(SYNERR, "undefined operand type %s\n", ident);
4164         return;
4165       }
4166       
4167       // Check for valid operand type
4168       OpClassForm *opc  = form->is_opclass();
4169       OperandForm *oper = form->is_operand();
4170       if((oper == NULL) && (opc == NULL)) {
4171         parse_err(SYNERR, "identifier %s not operand type\n", ident);
4172         return;
4173       }
4174       opclass = opc;
4175     }
4176     // Debugging Stuff
4177     if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Type: %s\t", ident);
4178 
4179     // Get name of operand and add it to local name table
4180     if( (ident = get_unique_ident(operands, "operand")) == NULL) {
4181       return;
4182     }
4183     // Parameter names must not be global names.
4184     if( _globalNames[ident] != NULL ) {
4185          parse_err(SYNERR, "Reuse of global name %s as operand.\n",ident);
4186          return;
4187     }
4188     operands.Insert(ident, opclass);
4189     parameters.addName(ident);
4190 
4191     // Debugging Stuff
4192     if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident);
4193     skipws();
4194   } while(_curchar == ',');
4195 
4196   if (_curchar != ')') parse_err(SYNERR, "missing ')'\n");
4197   else {
4198     next_char();  // set current character position past the close paren
4199   }
4200 }
4201 
4202 
4203 //------------------------------get_effectlist---------------------------------
4204 // Looks for identifier pairs where first must be the name of a pre-defined,
4205 // effect, and the second must be the name of an operand defined in the
4206 // operand list of this instruction.  Stores the names with a pointer to the
4207 // effect form in a local effects table.
4208 void ADLParser::get_effectlist(FormDict &effects, FormDict &operands) {
4209   OperandForm *opForm;
4210   Effect      *eForm;
4211   char        *ident;
4212 
4213   do {
4214     next_char();             // skip open paren & comma characters
4215     skipws();
4216     if (_curchar == ')') break;
4217 
4218     // Get effect type, and check it against global name table
4219     ident = get_ident();
4220     if (ident == NULL) {
4221       parse_err(SYNERR, "effect type identifier expected at %c\n", _curchar);
4222       return;
4223     }
4224     else {
4225       // Check for valid effect type
4226       const Form *form = _globalNames[ident];
4227       if( form == NULL ) {
4228         parse_err(SYNERR, "undefined effect type %s\n", ident);
4229         return;
4230       }
4231       else {
4232         if( (eForm = form->is_effect()) == NULL) {
4233           parse_err(SYNERR, "identifier %s not effect type\n", ident);
4234           return;
4235         }
4236       }
4237     }
4238       // Debugging Stuff
4239     if (_AD._adl_debug > 1) fprintf(stderr, "\tEffect Type: %s\t", ident);
4240     skipws();
4241     // Get name of operand and check that it is in the local name table
4242     if( (ident = get_unique_ident(effects, "effect")) == NULL) {
4243       parse_err(SYNERR, "missing operand identifier in effect list\n");
4244       return;
4245     }
4246     const Form *form = operands[ident];
4247     opForm = form ? form->is_operand() : NULL;
4248     if( opForm == NULL ) {
4249       if( form && form->is_opclass() ) {
4250         const char* cname = form->is_opclass()->_ident;
4251         parse_err(SYNERR, "operand classes are illegal in effect lists (found %s %s)\n", cname, ident);
4252       } else {
4253         parse_err(SYNERR, "undefined operand %s in effect list\n", ident);
4254       }
4255       return;
4256     }
4257     // Add the pair to the effects table
4258     effects.Insert(ident, eForm);
4259     // Debugging Stuff
4260     if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident);
4261     skipws();
4262   } while(_curchar == ',');
4263 
4264   if (_curchar != ')') parse_err(SYNERR, "missing ')'\n");
4265   else {
4266     next_char();  // set current character position past the close paren
4267   }
4268 }
4269 
4270 
4271 //------------------------------preproc_define---------------------------------
4272 // A "#define" keyword has been seen, so parse the rest of the line.
4273 void ADLParser::preproc_define(void) {
4274   char* flag = get_ident_no_preproc();
4275   skipws_no_preproc();
4276   // only #define x y is supported for now
4277   char* def = get_ident_no_preproc();
4278   _AD.set_preproc_def(flag, def);
4279   skipws_no_preproc();
4280   if (_curchar != '\n') {
4281     parse_err(SYNERR, "non-identifier in preprocessor definition\n");
4282   }
4283 }
4284 
4285 //------------------------------preproc_undef----------------------------------
4286 // An "#undef" keyword has been seen, so parse the rest of the line.
4287 void ADLParser::preproc_undef(void) {
4288   char* flag = get_ident_no_preproc();
4289   skipws_no_preproc();
4290   ensure_end_of_line();
4291   _AD.set_preproc_def(flag, NULL);
4292 }
4293 
4294 
4295 
4296 //------------------------------parse_err--------------------------------------
4297 // Issue a parser error message, and skip to the end of the current line
4298 void ADLParser::parse_err(int flag, const char *fmt, ...) {
4299   va_list args;
4300 
4301   va_start(args, fmt);
4302   if (flag == 1)
4303     _AD._syntax_errs += _AD.emit_msg(0, flag, _linenum, fmt, args);
4304   else if (flag == 2)
4305     _AD._semantic_errs += _AD.emit_msg(0, flag, _linenum, fmt, args);
4306   else
4307     _AD._warnings += _AD.emit_msg(0, flag, _linenum, fmt, args);
4308 
4309   int error_char = _curchar;
4310   char* error_ptr = _ptr+1;
4311   for(;*_ptr != '\n'; _ptr++) ; // Skip to the end of the current line
4312   _curchar = '\n';
4313   va_end(args);
4314   _AD._no_output = 1;
4315 
4316   if (flag == 1) {
4317     char* error_tail = strchr(error_ptr, '\n');
4318     char tem = *error_ptr;
4319     error_ptr[-1] = '\0';
4320     char* error_head = error_ptr-1;
4321     while (error_head > _curline && *error_head)  --error_head;
4322     if (error_tail)  *error_tail = '\0';
4323     fprintf(stderr, "Error Context:  %s>>>%c<<<%s\n",
4324             error_head, error_char, error_ptr);
4325     if (error_tail)  *error_tail = '\n';
4326     error_ptr[-1] = tem;
4327   }
4328 }
4329 
4330 //---------------------------ensure_start_of_line------------------------------
4331 // A preprocessor directive has been encountered.  Be sure it has fallen at
4332 // the begining of a line, or else report an error.
4333 void ADLParser::ensure_start_of_line(void) {
4334   assert( _ptr >= _curline && _ptr < _curline+strlen(_curline),
4335           "Must be able to find which line we are in" );
4336   
4337   for (char *s = _curline; s < _ptr; s++) {
4338     if (*s > ' ') {
4339       parse_err(SYNERR, "'%c' must be at beginning of line\n", _curchar);
4340       break;
4341     }
4342   }
4343 }
4344 
4345 //---------------------------ensure_end_of_line--------------------------------
4346 // A preprocessor directive has been parsed.  Be sure there is no trailing
4347 // garbage at the end of this line.  Set the scan point to the beginning of
4348 // the next line.
4349 void ADLParser::ensure_end_of_line(void) {
4350   skipws_no_preproc();
4351   if (_curchar != '\n' && _curchar != '\0') {
4352     parse_err(SYNERR, "garbage char '%c' at end of line\n", _curchar);
4353   } else {
4354     next_char_or_line();
4355   }
4356 }
4357 
4358 //---------------------------handle_preproc------------------------------------
4359 // The '#' character introducing a preprocessor directive has been found.
4360 // Parse the whole directive name (e.g., #define, #endif) and take appropriate
4361 // action.  If we are in an "untaken" span of text, simply keep track of
4362 // #ifdef nesting structure, so we can find out when to start taking text
4363 // again.  (In this state, we "sort of support" C's #if directives, enough
4364 // to disregard their associated #else and #endif lines.)  If we are in a
4365 // "taken" span of text, there are two cases:  "#define" and "#undef"
4366 // directives are preserved and passed up to the caller, which eventually
4367 // passes control to the top-level parser loop, which handles #define and
4368 // #undef directly.  (This prevents these directives from occurring in
4369 // arbitrary positions in the AD file--we require better structure than C.)
4370 // In the other case, and #ifdef, #ifndef, #else, or #endif is silently
4371 // processed as whitespace, with the "taken" state of the text correctly
4372 // updated.  This routine returns "false" exactly in the case of a "taken"
4373 // #define or #undef, which tells the caller that a preprocessor token
4374 // has appeared which must be handled explicitly by the parse loop.
4375 bool ADLParser::handle_preproc_token() {
4376   assert(*_ptr == '#', "must be at start of preproc");
4377   ensure_start_of_line();
4378   next_char();
4379   skipws_no_preproc();
4380   char* start_ident = _ptr;
4381   char* ident = (_curchar == '\n') ? NULL : get_ident_no_preproc();
4382   if (ident == NULL) {
4383     parse_err(SYNERR, "expected preprocessor command, got end of line\n");
4384   } else if (!strcmp(ident, "ifdef") ||
4385              !strcmp(ident, "ifndef")) {
4386     char* flag = get_ident_no_preproc();
4387     ensure_end_of_line();
4388     // Test the identifier only if we are already in taken code:
4389     bool flag_def  = preproc_taken() && (_AD.get_preproc_def(flag) != NULL);
4390     bool now_taken = !strcmp(ident, "ifdef") ? flag_def : !flag_def;
4391     begin_if_def(now_taken);
4392   } else if (!strcmp(ident, "if")) {
4393     if (preproc_taken())
4394       parse_err(SYNERR, "unimplemented: #%s %s", ident, _ptr+1);
4395     next_line();
4396     // Intelligently skip this nested C preprocessor directive:
4397     begin_if_def(true);
4398   } else if (!strcmp(ident, "else")) {
4399     ensure_end_of_line();
4400     invert_if_def();
4401   } else if (!strcmp(ident, "endif")) {
4402     ensure_end_of_line();
4403     end_if_def();
4404   } else if (preproc_taken()) {
4405     // pass this token up to the main parser as "#define" or "#undef"
4406     _ptr = start_ident;
4407     _curchar = *--_ptr;
4408     if( _curchar != '#' ) {
4409       parse_err(SYNERR, "no space allowed after # in #define or #undef");
4410       assert(_curchar == '#', "no space allowed after # in #define or #undef");
4411     }
4412     return false;
4413   }
4414   return true;
4415 }
4416 
4417 //---------------------------skipws_common-------------------------------------
4418 // Skip whitespace, including comments and newlines, while keeping an accurate
4419 // line count.
4420 // Maybe handle certain preprocessor constructs: #ifdef, #ifndef, #else, #endif
4421 void ADLParser::skipws_common(bool do_preproc) {
4422   char *start = _ptr;
4423   char *next = _ptr + 1;
4424 
4425   if (*_ptr == '\0') {
4426     // Check for string terminator
4427     if (_curchar > ' ')  return;
4428     if (_curchar == '\n') {
4429       if (!do_preproc)  return;            // let caller handle the newline
4430       next_line();
4431       _ptr = _curline; next = _ptr + 1;
4432     }
4433     else if (_curchar == '#' ||
4434         (_curchar == '/' && (*next == '/' || *next == '*'))) {
4435       parse_err(SYNERR, "unimplemented: comment token in a funny place");
4436     }
4437   }
4438   while(_curline != NULL) {                // Check for end of file
4439     if (*_ptr == '\n') {                   // keep proper track of new lines
4440       if (!do_preproc)  break;             // let caller handle the newline
4441       next_line(); 
4442       _ptr = _curline; next = _ptr + 1;
4443     }
4444     else if ((*_ptr == '/') && (*next == '/'))      // C++ comment
4445       do { _ptr++; next++; } while(*_ptr != '\n');  // So go to end of line
4446     else if ((*_ptr == '/') && (*next == '*')) {    // C comment
4447       _ptr++; next++;
4448       do { 
4449         _ptr++; next++;
4450         if (*_ptr == '\n') {               // keep proper track of new lines
4451           next_line();                     // skip newlines within comments
4452           if (_curline == NULL) {          // check for end of file
4453             parse_err(SYNERR, "end-of-file detected inside comment\n");
4454             break;
4455           }
4456           _ptr = _curline; next = _ptr + 1;
4457         }
4458       } while(!((*_ptr == '*') && (*next == '/'))); // Go to end of comment
4459       _ptr = ++next; next++;               // increment _ptr past comment end
4460     }
4461     else if (do_preproc && *_ptr == '#') {
4462       // Note that this calls skipws_common(false) recursively!
4463       bool preproc_handled = handle_preproc_token(); 
4464       if (!preproc_handled) {
4465         if (preproc_taken()) {
4466           return;  // short circuit
4467         }
4468         ++_ptr;    // skip the preprocessor character
4469       }
4470       next = _ptr+1;
4471     } else if(*_ptr > ' ' && !(do_preproc && !preproc_taken())) {
4472       break;
4473     }
4474     else if (*_ptr == '"' || *_ptr == '\'') {
4475       assert(do_preproc, "only skip strings if doing preproc");
4476       // skip untaken quoted string
4477       int qchar = *_ptr;
4478       while (true) {
4479         ++_ptr;
4480         if (*_ptr == qchar) { ++_ptr; break; }
4481         if (*_ptr == '\\')  ++_ptr;
4482         if (*_ptr == '\n' || *_ptr == '\0') {
4483           parse_err(SYNERR, "newline in string");
4484           break;
4485         }
4486       }
4487       next = _ptr + 1;
4488     }
4489     else { ++_ptr; ++next; }
4490   }
4491   if( _curline != NULL )            // at end of file _curchar isn't valid
4492     _curchar = *_ptr;               // reset _curchar to maintain invariant
4493 }
4494 
4495 //---------------------------cur_char-----------------------------------------
4496 char ADLParser::cur_char() {
4497   return (_curchar);
4498 }
4499 
4500 //---------------------------next_char-----------------------------------------
4501 void ADLParser::next_char() {
4502   _curchar = *++_ptr;
4503   // if ( _curchar == '\n' ) {
4504   //   next_line();
4505   // }
4506 } 
4507 
4508 //---------------------------next_char_or_line---------------------------------
4509 void ADLParser::next_char_or_line() {
4510   if ( _curchar != '\n' ) {
4511     _curchar = *++_ptr;
4512   } else {
4513     next_line();
4514     _ptr = _curline;
4515     _curchar = *_ptr;  // maintain invariant
4516   }
4517 } 
4518 
4519 //---------------------------next_line-----------------------------------------
4520 void ADLParser::next_line() {
4521   _curline = _buf.get_line(); _linenum++; 
4522 }
4523 
4524 //-------------------------is_literal_constant---------------------------------
4525 bool ADLParser::is_literal_constant(const char *param) {
4526   if (param[0] == 0)     return false;  // null string
4527   if (param[0] == '(')   return true;   // parenthesized expression
4528   if (param[0] == '0' && (param[1] == 'x' || param[1] == 'X')) {
4529     // Make sure it's a hex constant.
4530     int i = 2;
4531     do {
4532       if( !ADLParser::is_hex_digit(*(param+i)) )  return false;
4533       ++i;
4534     } while( *(param+i) != 0 );
4535     return true;
4536   }
4537   return false;
4538 }
4539 
4540 //---------------------------is_hex_digit--------------------------------------
4541 bool ADLParser::is_hex_digit(char digit) {
4542   return ((digit >= '0') && (digit <= '9'))
4543        ||((digit >= 'a') && (digit <= 'f')) 
4544        ||((digit >= 'A') && (digit <= 'F'));
4545 }
4546 
4547 //---------------------------is_int_token--------------------------------------
4548 bool ADLParser::is_int_token(const char* token, int& intval) {
4549   const char* cp = token;
4550   while (*cp != '\0' && *cp <= ' ')  cp++;
4551   if (*cp == '-')  cp++;
4552   int ndigit = 0;
4553   while (*cp >= '0' && *cp <= '9')  { cp++; ndigit++; }
4554   while (*cp != '\0' && *cp <= ' ')  cp++;
4555   if (ndigit == 0 || *cp != '\0') {
4556     return false;
4557   }
4558   intval = atoi(token);
4559   return true;
4560 }
4561 
4562 //-------------------------------trim------------------------------------------
4563 void ADLParser::trim(char* &token) {
4564   while (*token <= ' ')  token++;
4565   char* end = token + strlen(token);
4566   while (end > token && *(end-1) <= ' ')  --end;
4567   *end = '\0';
4568 }