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