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