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