Polaris: StmtList.cc Source File

StmtList.cc

Go to the documentation of this file.
00001 //Modification History
00002 ///  97-09-23.2234 evansl
00003 ///    WHAT:
00004 ///      Modified move_block_after & move_block_before by adding DONT_RELABEL to grab call.
00005 ///    WHY:
00006 ///      To avoid the following error:
00007 ///
00008 /// POLARIS: Assertion failed: file /home/polaris/work/evansl/cvdl/base/StmtList.cc, line 2666 :
00009 /// StmtList::grab(): A LabelStmt has been grabbed which is referenced outside the grabbed block.
00010 ///
00011 ///      produced when driverPgm in driverPgm.distLoops.cc was run on
00012 ///      ../inp_dir/multiExit.f.  driverPgm produces a while loop with
00013 ///      multiple exits, then converts the while to a do using while2do
00014 ///      from norm_util.cc.  The error occurred in while2do.
00015 ///  97-08-10.1544 evansl
00016 ///    WHAT:
00017 ///      Created _ins_ELSEIF_or_ELSE_after and rewrote
00018 ///      ins_ELSEIF_after and ins_ELSE_after to use it.
00019 ///    WHY:
00020 ///      To reuse code.
00021 ///  97-08-06.1543 evansl
00022 ///    WHAT:
00023 ///      Completely replaced code for move_block_before and move_block_after.
00024 ///    WHY:
00025 ///      Getting:
00026 ///
00027 //POLARIS: Assertion failed: file Collection/RefWrapper.cc, line 45 :
00028 //RefWrapper::object( ): object to be referenced not in a live structure
00029 ///
00030 ///      at the `possible.ins(*move)` statement.
00031 ///
00032 ///  97-06-20.1022 evansl
00033 ///    WHAT:
00034 ///      Added Iterator<Statement> loop to ins_ELSEIF_after and to
00035 ///      ins_ELSE_after to add ALL ELSE_STMT and ELSEIF_STMT to the
00036 ///      possible variable. 
00037 ///    WHY:
00038 ///      To correct a control flow problem in case more than 1
00039 ///      ELSEIF/ELSE is inserted.
00040 ///  96-11-13.2120 evansl
00041 ///    WHAT:
00042 ///      Added: 
00043 ///        1) ins_DO_END_after
00044 ///        2) ins_WHILE_after
00045 ///      Modified:
00046 ///        3) ins_DO_after
00047 ///    WHY:
00048 ///      1) Provide reusable code for ins_WHILE_after and ins_DO_after
00049 ///      2) enable the insertion of While loops in StmtList.
00050 ///      3) Resuse code in ins_DO_END_after.
00051 #ifdef POLARIS_GNU_PRAGMAS
00052 #pragma implementation
00053 #endif
00054 ///
00055 #include <ctype.h>
00056 #include <stdio.h>
00057 #include <stream.h>
00058 
00059 #include "StmtList.h"
00060 #include "BinRep.h"
00061 #include "Collection/Iterator.h"
00062 #include "Collection/Mutator.h"
00063 #include "Collection/KeyIterator.h"
00064 #include "Collection/RefDatabase.h"
00065 #include "Collection/RefSet.h"
00066 #include "Directive/AssertionList.h"
00067 #include "Directive/Directive.h"
00068 #include "Directive/parse_directives.h"
00069 #include "IntElem.h"
00070 #include "ProgramUnit.h"
00071 #include "Statement/Statement.all.h"
00072 #include "StringElem.h"
00073 #include "utilities/switches_util.h"
00074 
00075 #include "macros.h"
00076 #include "p-assert.h"
00077 
00078 ////////////////////////////////////////////////////////////
00079 
00080 /// Checks for the case of a FlowEntryStmt or FlowExitStmt being inserted into
00081 /// a list when such a statement already exists in the list.  If this case is
00082 /// found, then the statement is deleted and the procedure returns True and
00083 /// sets the pointer to the new statement to be 0 in the calling routine
00084 
00085 static Boolean
00086 redundant_flow_ins(StmtList &sl, Statement *&new_stmt) 
00087 {
00088     p_assert(new_stmt != 0, "Internal Error");
00089 
00090     if (new_stmt->stmt_class() == FLOW_ENTRY_STMT) {
00091         if (sl.first_ref() != 0
00092             && sl.first_ref()->stmt_class() == FLOW_ENTRY_STMT) {
00093             /// ...  Redundant
00094             delete new_stmt;
00095             new_stmt = 0;
00096 
00097             return True;
00098         }
00099     }
00100     else if (new_stmt->stmt_class() == FLOW_EXIT_STMT) {
00101         if (sl.last_ref() != 0
00102             && sl.last_ref()->stmt_class() == FLOW_EXIT_STMT) {
00103             /// ...  Redundant
00104             delete new_stmt;
00105             new_stmt = 0;
00106 
00107             return True;
00108         }
00109     }
00110 
00111     return False;
00112 }
00113 
00114 ////////////////////////////////////////////////////////////
00115 
00116 StmtList::StmtList()
00117 {
00118     #ifdef CLASS_INSTANCE_REGISTRY
00119     register_instance(STMT_LIST, sizeof(StmtList), this);
00120     #endif
00121 
00122     _overflow = new BinRep;
00123     Set<BinRep> *S = new Set<BinRep>;
00124     _overflow->put_set( S );
00125 
00126     _stmt_tag_dict = new Dictionary<VoidPtrDef>;
00127     _tag_count = 0;
00128     _pgm = 0;
00129 
00130     this->ins_first(new FlowEntryStmt("ENTRY"));
00131     this->ins_last(new FlowExitStmt("EXIT"));
00132 
00133     /// ...  build initial control flow information for statements
00134     /// ...  13 Nov 95 Thomas R. Lawrence
00135     this->first().fix_flow(*this);
00136     this->last().fix_flow(*this);
00137 }
00138 
00139 StmtList::StmtList(const StmtList & s)
00140 {
00141     #ifdef CLASS_INSTANCE_REGISTRY
00142     register_instance(STMT_LIST, sizeof(StmtList), this);
00143     #endif
00144 
00145     _overflow = 0;
00146     _stmt_tag_dict = 0;
00147     _tag_count = 0;
00148     _pgm = 0;
00149     
00150     *this = s;
00151 }
00152 
00153 StmtList &
00154 StmtList::operator = (const StmtList & s)
00155 {
00156     /// ...  First remove any existing flow graph
00157     delete_flow_graph();
00158 
00159     clear();
00160     
00161     _tag_count     = s._tag_count;
00162 
00163     _overflow        = s._overflow->clone();
00164 
00165     /// ...  copy s's statements if any exist
00166 
00167     if (s.entries() > 0) {
00168         List<Statement> *temp  
00169             = (s.copy(*s.first_ref(), *s.last_ref(), DONT_RELABEL));
00170 
00171         ins_after(temp, 0);
00172     
00173         create_flow_graph();
00174     }
00175 
00176     return *this;
00177 }
00178 
00179 StmtList *
00180 StmtList::clone() const
00181 {
00182     return new StmtList( *this );
00183 }
00184 
00185 Listable *
00186 StmtList::listable_clone() const
00187 {
00188     return (Listable *) clone();
00189 }
00190 
00191 StmtList::~StmtList()
00192 {
00193     #ifdef CLASS_INSTANCE_REGISTRY
00194     unregister_instance(STMT_LIST, this);
00195     #endif
00196 
00197     delete_flow_graph();  /// ...  Remove pred and succ RefSets
00198 
00199     if (_overflow)
00200         delete _overflow;
00201     if (_stmt_tag_dict)
00202         delete _stmt_tag_dict;
00203 }
00204 
00205 BinRep *
00206 StmtList::overflow_ref() const
00207 {
00208     return _overflow;
00209 }
00210 
00211 const Statement &
00212 StmtList::first() const
00213 {
00214     const Statement *f = first_ref();
00215 
00216     p_assert(f != 0 && f->stmt_class() == FLOW_ENTRY_STMT,
00217              "StmtList::first(): Expected a FLOW_ENTRY_STMT at the beginning");
00218 
00219     return *f;
00220 }
00221 
00222 Statement &
00223 StmtList::first()
00224 {
00225     Statement *f = first_ref();
00226 
00227     p_assert(f != 0 && f->stmt_class() == FLOW_ENTRY_STMT,
00228              "StmtList::first(): Expected a FLOW_ENTRY_STMT at the beginning");
00229 
00230     return *f;
00231 }
00232 
00233 const Statement &
00234 StmtList::last() const
00235 {
00236     const Statement *l = last_ref();
00237 
00238     p_assert( l != 0 && l->stmt_class() == FLOW_EXIT_STMT,
00239               "StmtList::last(): Expected a FLOW_EXIT_STMT at the end" );
00240 
00241     return *l;
00242 }
00243 
00244 Statement &
00245 StmtList::last() 
00246 {
00247     Statement *l = last_ref();
00248 
00249     p_assert( l != 0 && l->stmt_class() == FLOW_EXIT_STMT,
00250               "StmtList::last(): Expected a FLOW_EXIT_STMT at the end" );
00251 
00252     return *l;
00253 }
00254 
00255 
00256 /// make_statement expects the statement name ("S10") and a binstr
00257 /// containing the statement set.  It returns a pointer to the
00258 /// correct statement object with the tag field already filled in.
00259 ///
00260 /// The statement table contains tuples of the from ["tag", { all the
00261 /// statement info}].  One should call make_statement passing the
00262 /// "tag" for the name and a binstr which represents the set.
00263 
00264 Statement      *
00265 make_statement(const char *name, const BinRep & binstr)
00266 {
00267     BinRep insp = binstr;
00268 
00269     p_assert(insp.is_set(), "not a set");
00270 
00271     String          st_type;
00272 
00273     insp["st"].to_string(st_type);
00274 
00275     if (st_type == "ASSIGNMENT")
00276         return new AssignmentStmt(name);
00277     else if (st_type == "DO")
00278         return new DoStmt(name);
00279     else if (st_type == "WHILE")
00280         return new WhileStmt(name);
00281     else if (st_type == "ENDDO")
00282         return new EndDoStmt(name);
00283     else if (st_type == "IF")
00284         return new IfStmt(name);
00285     else if (st_type == "ELSEIF")
00286         return new ElseIfStmt(name);
00287     else if (st_type == "IMPLIED_GOTO")
00288         return new ImpliedGotoStmt(name);
00289     else if (st_type == "ENDIF")
00290         return new EndIfStmt(name);
00291     else if (st_type == "ELSE")
00292         return new ElseStmt(name);
00293     else if (st_type == "ASSIGN")
00294         return new AssignStmt(name);
00295     else if (st_type == "READ")
00296         return new IOStmt(READ_STMT, name);
00297     else if (st_type == "WRITE")
00298         return new IOStmt(WRITE_STMT, name);
00299     else if (st_type == "PRINT")
00300         return new IOStmt(PRINT_STMT, name);
00301     else if (st_type == "OPEN")
00302         return new IOStmt(OPEN_STMT, name);
00303     else if (st_type == "CLOSE")
00304         return new IOStmt(CLOSE_STMT, name);
00305     else if (st_type == "REWIND")
00306         return new IOStmt(REWIND_STMT, name);
00307     else if (st_type == "BACKSPACE")
00308         return new IOStmt(BACKSPACE_STMT, name);
00309     else if (st_type == "ENDFILE")
00310         return new IOStmt(ENDFILE_STMT, name);
00311     else if (st_type == "INQUIRE")
00312         return new IOStmt(INQUIRE_STMT, name);
00313     else if (st_type == "STOP")
00314         return new StopStmt(name);
00315     else if (st_type == "PAUSE")
00316         return new PauseStmt(name);
00317     else if (st_type == "FLOW_ENTRY")
00318         return new FlowEntryStmt(name);
00319     else if (st_type == "FLOW_EXIT")
00320         return new FlowExitStmt(name);
00321     else if (st_type == "ENTRY")
00322         return new EntryStmt(name);
00323     else if (st_type == "CALL")
00324         return new CallStmt(name);
00325     else if (st_type == "ENTRY")
00326         return new EntryStmt(name);
00327     else if (st_type == "RETURN")
00328         return new ReturnStmt(name);
00329     else if (st_type == "LABEL")
00330         return new LabelStmt(name);
00331     else if (st_type == "UNCONDITIONAL_GOTO")
00332         return new GotoStmt(name);
00333     else if (st_type == "ARITHMETIC_IF")
00334         return new ArithmeticIfStmt(name);
00335     else if (st_type == "COMPUTED_GOTO")
00336         return new ComputedGotoStmt(name);
00337     else if (st_type == "ASSIGNED_GOTO")
00338         return new AssignedGotoStmt(name);
00339     else if (st_type == "ALLOCATE")
00340         return new AllocateStmt(name);
00341     else if (st_type == "DEALLOCATE")
00342         return new DeallocateStmt(name);
00343     else if (st_type == "NULLIFY")
00344         return new NullifyStmt(name);
00345 
00346     cerr << "(StmtList.cc) make_statement: unrecognized 'st' field: " ;
00347     cerr << st_type << " in " ;
00348     cerr << insp << endl;
00349 
00350     p_abort( "(see above message)" );
00351 
00352     return 0;
00353 }
00354 
00355 /// Description:
00356 /// Given a string with a series of characters followed by an
00357 /// integer (i.e., "ST35", i.e, a statement tag), return the
00358 /// integer.
00359 
00360 long
00361 get_tag_num(const char *lab)
00362 {
00363     int i;
00364     int maxlen = strlen(lab);
00365     for (i = 0; (i < maxlen) && (!isdigit(lab[i])); ++i);
00366 
00367     if (i < maxlen)
00368         return atoi(lab + i);
00369     else
00370         return -1;
00371 }
00372 
00373 
00374 //--------------------------------------------------------------------//
00375 /// Convert a list of statements.  Put the results in StmtList
00376 /// in their correct order.
00377 /// A complete Expression table, Symbol table and format list are
00378 /// required.  This procedure works in two passes, the first doing the
00379 /// translation and building up a Dictionary relating statement tags
00380 /// to pointers to the statement object.  In this pass, all fields which
00381 /// should be pointers to other statements are set to DummyStatements
00382 /// with the tag of the statement to be linked.  The second pass
00383 /// removes these dummy statements and replaces them with actual pointers.
00384 
00385 void
00386 StmtList::convert(BinRep & stmts, ExprTable & etable, Symtab & symtab,
00387                   const NamelistDict & namelists,
00388                   const FormatDB     & formats,
00389                   const char         * initial_stmt)
00390 {
00391     p_assert(stmts.is_set(), "statements is not a set");
00392 
00393     /// ...  cout << initial_stmt << endl << flush;
00394 
00395     /// ...  Remove any FLOW_ENTRY or FLOW_EXIT statements that may be in the list.
00396 
00397     /// ...  First remove any existing flow graph
00398     delete_flow_graph();
00399     clear();
00400 
00401     _overflow = new BinRep;
00402     Set<BinRep> *S = new Set<BinRep>;
00403     _overflow->put_set( S );
00404 
00405     
00406     /// ...  This dictionary will be used to determine which statement corresponds
00407     /// ...  to the \'next\' field of a given statement when the statements are
00408     /// ...  ordered.
00409 
00410     Dictionary<NextEntry> *next_table = new Dictionary<NextEntry>;
00411 
00412     /// ...  first pass: convert all statements
00413 
00414     for (Iterator<BinRep> iter = stmts.to_set(); iter.valid(); ++iter) {
00415         String          tag;
00416 
00417         iter.current()[0].to_string(tag);
00418         BinRep & StmtSet = iter.current()[1];
00419 
00420         Statement      *newstmt = make_statement(tag, StmtSet);
00421 
00422         newstmt->convert(StmtSet, etable, symtab, namelists,
00423              formats, next_table);
00424 
00425         // build in/out/act _refs (throw away Delta's version)
00426     
00427         newstmt->build_refs();   
00428 
00429     /// ...  Add tag to dictionary (even flow entry and exit tags
00430     /// ...  are needed for conversion pass)
00431 
00432     _stmt_tag_dict->ins(new VoidPtrDef(tag, newstmt));
00433 
00434     }
00435 
00436     /// ...  Second pass: 
00437     /// ...    order the statements and determine the largest value
00438     /// ...    used as the integral suffix to statement tags and build the
00439     /// ...    label database.
00440 
00441     Statement *stmt;
00442     
00443     for (stmt = (Statement *)((*_stmt_tag_dict)[initial_stmt]).ptr_ref(); 
00444                 stmt;) {
00445         List<Statement>::ins_last(stmt);
00446     
00447         /// ...  determine maximum tag number
00448         long tag_num = get_tag_num(stmt->tag());
00449 
00450         if (tag_num > _tag_count)
00451             _tag_count = tag_num;
00452 
00453         /// ...  If label statement, insert entry into label database
00454 
00455         if (stmt->stmt_class() == LABEL_STMT)
00456       _ins_label_stmt(*stmt);
00457 
00458         if (! next_table->find_ref(stmt->tag())) 
00459             stmt = 0;           /// ...  This must have been the last statement
00460         else {
00461             NextEntry & next_ptr = (*next_table)[stmt->tag()];
00462             stmt = (Statement *) 
00463                        ((*_stmt_tag_dict)[next_ptr.next_ref()]).ptr_ref();
00464         }
00465     }
00466 
00467     /// ...  Third pass: 
00468     /// ...  call setptrs on all statements to convert StmtPtrs
00469     /// ...  to pointers to actual statements  (had to do this as a third pass
00470     /// ...  because as the list is built, successor statements wouldn't be on
00471     /// ...  the list until this pass).
00472     
00473     for (stmt = (Statement *)((*_stmt_tag_dict)[initial_stmt]).ptr_ref(); 
00474                 stmt;) {
00475         stmt->_setptrs(*_stmt_tag_dict, formats);
00476 
00477         if (! next_table->find_ref(stmt->tag())) 
00478             stmt = 0;           /// ...  This must have been the last statement
00479         else {
00480             NextEntry & next_ptr = (*next_table)[stmt->tag()];
00481             stmt = (Statement *)
00482                         ((*_stmt_tag_dict)[next_ptr.next_ref()]).ptr_ref();
00483         }
00484     }
00485 
00486     for (Iterator<Statement> s_iter = (*this); s_iter.valid(); ++s_iter) {
00487         Statement & s = s_iter.current();
00488 
00489         switch (s.stmt_class()) {
00490         case ELSE_STMT:
00491         case ELSEIF_STMT:
00492         case ENDIF_STMT:
00493             {
00494                 Statement *t = s.prev_ref();
00495 
00496                 if (t->stmt_class() != IMPLIED_GOTO_STMT) {
00497                     Statement *imp_goto = new ImpliedGotoStmt(new_tag());
00498                     _ins_after( imp_goto, t, "convert" );
00499                 }
00500             }
00501             break;
00502     default: break;
00503         }
00504     }
00505     
00506     delete next_table;
00507 
00508     // Make sure that FLOW_ENTRY and FLOW_EXIT are the first/last
00509     /// ...  statements, if there are statements.  If there are not,
00510     /// ...  then add them (this will be necessary, for instance,
00511     /// ...  for BLOCK DATA program units)
00512 
00513     if (first_ref() == 0 || first_ref()->stmt_class() != FLOW_ENTRY_STMT) 
00514         this->ins_first(new FlowEntryStmt("ENTRY"));
00515 
00516     if (last_ref() == 0 || last_ref()->stmt_class() != FLOW_EXIT_STMT) 
00517         this->ins_last(new FlowExitStmt("EXIT"));
00518 
00519     /// ...  Fix up any pointers in the program blocks.
00520     _set_block_structure( first_ref(), last_ref(), "convert" );
00521 
00522     /// ...  Set lead, matching_if and matching_endif fields
00523     _set_if_block_lead_ptrs();
00524 }
00525 
00526 void 
00527 StmtList::_bad_block_error(Iterator<Statement> &iter, const char *method_name)
00528 {
00529     iter.reset();
00530 
00531     /// ...  Print out each statement until last
00532 
00533     /// ...   int             first = 1;
00534 
00535     while (iter.valid()) {
00536         cerr << iter.current();
00537         ++iter;
00538     }
00539 
00540     cerr << "**** Aborting with error condition in StmtList::" 
00541          << method_name << " ****\n";
00542 
00543     p_abort( "(See above error message.)" );
00544 }
00545 
00546 void 
00547 StmtList::_unbalanced_error(Iterator<Statement> & iter,
00548                                const char *method_name)
00549 {
00550     cerr << "***Error: StmtList: Unbalanced statement block:\n";
00551 
00552     _bad_block_error(iter, method_name);
00553 }
00554 
00555 void 
00556 StmtList::_set_block_structure(const Statement * first_stmt,
00557                                const Statement * last_stmt,
00558                                const char * method_name)
00559 //Purpose:
00560 ///  Set the _outer, _follow, and _lead instance variables for all
00561 ///  statements between first_stmt and last_stmt.    
00562 //Method:
00563 ///  The iter local variable below plays a role similar to a tokens
00564 ///  stream in an LL1 parser.  The case statement in the loop selects the 
00565 ///  parse routine for the current token.
00566 ///
00567 ///  Other LL1 parse routines forming parts of this "parser" are:
00568 ///
00569 ///    _set_if_block_structure
00570 ///    _set_if_subblock_structure
00571 ///    _set_do_block_structure
00572 ///    _set_pair_block_structure      
00573 ///
00574 ///  The "parser" doesn't really parse, it just traverses the parse tree, calculating
00575 ///  the "attributes", _outer, _follow, and _lead.
00576 ///
00577 //Modification History:
00578 ///  97-08-10.2026 evansl
00579 ///    Added comments describing purpose and method. 
00580 {
00581     if (dbx_program_debug_level >= 100) {
00582         cout << "_set_block_structure called for stmts "
00583              << (first_stmt ? first_stmt->tag() : "(First)")
00584              << " .. "
00585              << (last_stmt ? last_stmt->tag() : "(Last)")
00586              << " by method StmtList::" << method_name << endl;
00587     }
00588 
00589     Iterator<Statement>iter = iterator(*first_stmt, *last_stmt);
00590 
00591     if (!iter.valid()) {
00592         /// ...  The iteration space is empty.
00593         /// ...  This could be caused by the statement list being completely
00594         /// ...  empty (valid for BLOCK DATA program units).  If this is
00595         /// ...  the case, then first_stmt and last_stmt had better both
00596         /// ...  be zero.
00597         /// ...  Any other instance would indicate an error.
00598 
00599         p_assert(entries() == 0
00600                  && first_stmt == 0 && last_stmt == 0, "not empty");
00601 
00602         if (dbx_program_debug_level >= 100) {
00603             cout << "_set_block_structure returning immediately because "
00604                  << "the requested block is empty.\n";
00605         }
00606         return;
00607     }
00608 
00609     /// ...  Find the prev statement before first_stmt.  The outer field of this
00610     /// ...  statement (if there is one) will be the outer field of the top-level
00611     /// ...  statements in this block, unless this statement is a DO.  In that
00612     /// ...  case, the DO will be the outer field.  If there is no stmt
00613     /// ...  before last_stmt, the outer field will be zero.
00614 
00615     Statement      *top_level_outer;
00616     Statement      *previous = first_stmt->prev_ref();
00617 
00618     if (previous == 0)
00619         top_level_outer = 0;
00620     else if (previous->stmt_class() == DO_STMT)
00621         top_level_outer = previous;
00622     else if (previous->stmt_class() == WHILE_STMT)
00623         top_level_outer = previous;
00624     else if (previous->stmt_class() == ENDDO_STMT)
00625         top_level_outer = previous->follow_ref()->_outer;
00626     else
00627         top_level_outer = previous->_outer;
00628 
00629     while (iter.valid()) {
00630         switch (iter.current().stmt_class()) {
00631 
00632         case UNDEFINED_STMT:
00633             cerr << "Error: StmtList: "
00634                  << "Found an UNDEFINED_STMT Statement type:\n";
00635             _bad_block_error(iter, method_name);
00636             break;
00637 
00638         case LABEL_STMT:
00639             iter.current()._outer = top_level_outer;
00640             break;
00641 
00642         case BLOCK_ENTRY_STMT:
00643             _set_pair_block_structure(iter, top_level_outer, method_name);
00644             break;
00645 
00646         case DO_STMT:
00647             _set_do_block_structure(iter, top_level_outer, method_name);
00648             break;
00649 
00650         case WHILE_STMT:
00651             _set_do_block_structure(iter, top_level_outer, method_name);
00652             break;
00653 
00654         case IF_STMT:
00655             _set_if_block_structure(iter, top_level_outer, method_name);
00656             break;
00657 
00658         case IMPLIED_GOTO_STMT:
00659         case ENDDO_STMT:
00660         case ELSEIF_STMT:
00661         case ELSE_STMT:
00662         case ENDIF_STMT:
00663             cerr << "Error: StmtList: Unbalanced block:\n";
00664             _bad_block_error(iter, method_name);
00665             break;
00666 
00667         default:
00668             /// ...  Set the outer field of this statement to point to the DO statement.
00669             iter.current()._outer = top_level_outer;
00670             break;
00671         }
00672         ++iter;
00673     }
00674 
00675     if (dbx_program_debug_level >= 100) {
00676         cout << "  _set_block_structure: Done." << endl;
00677     }
00678 }
00679 
00680 /// Expects any part (IF, ELSEIF, or ELSE) of a block structure and
00681 /// sets all pointers up until it finds the IMPLIED_GOTO
00682 /// Pre:  iter is on the IF/ELSEIF/ELSE statement
00683 /// Post: iter is on the IMPLIED_GOTO statement
00684 
00685 void 
00686 StmtList::_set_if_subblock_structure(Iterator<Statement> & iter,
00687                                      RefList<Statement> & fixup_list,
00688                                      const Statement * outer,
00689                                      const char * method_name)
00690 {
00691     if (dbx_program_debug_level >= 100) {
00692         cout << "_set_if_subblock_structure called for stmt "
00693              << iter.current().tag() << endl;
00694     }
00695 
00696     STMT_TYPE       t = iter.current().stmt_class();
00697 
00698     p_assert(t == IF_STMT || t == ELSE_STMT || t == ELSEIF_STMT, "not IF");
00699 
00700     /// ...  Set the outer pointer of this statement
00701 
00702     iter.current()._outer = CASTAWAY(Statement *) outer;
00703 
00704     /// ...  Start with the next statement
00705 
00706     ++iter;
00707 
00708     while (iter.valid()) {
00709         switch (iter.current().stmt_class()) {
00710         case UNDEFINED_STMT:
00711             cerr << "Error: StmtList: "
00712                  << "Found an UNDEFINED_STMT Statement type:\n";
00713             _bad_block_error(iter, method_name);
00714             break;
00715 
00716         case BLOCK_ENTRY_STMT:
00717             _set_pair_block_structure(iter, outer, method_name);
00718             break;
00719 
00720         case DO_STMT:
00721             _set_do_block_structure(iter, outer, method_name);
00722             break;
00723 
00724         case WHILE_STMT:
00725             _set_do_block_structure(iter, outer, method_name);
00726             break;
00727 
00728         case IF_STMT:
00729             _set_if_block_structure(iter, outer, method_name);
00730             break;
00731 
00732         case IMPLIED_GOTO_STMT:
00733             if (dbx_program_debug_level >= 100) {
00734                 cout << "  _set_if_subblock_structure: found IMPLIED_GOTO: "
00735                      << iter.current().tag() << endl;
00736             }
00737 
00738             /// ...  Set outer field
00739 
00740             iter.current()._outer = CASTAWAY(Statement *) outer;
00741 
00742             fixup_list.ins_last(iter.current());
00743             return;
00744 
00745         case ENDDO_STMT:
00746         case ELSEIF_STMT:
00747         case ELSE_STMT:
00748         case ENDIF_STMT:
00749             cerr << "Error: StmtList: Unbalanced block:\n";
00750             _bad_block_error(iter, method_name);
00751             break;
00752 
00753         default:
00754             /// ...  Set the outer field of this statement to point to the DO statement.
00755             iter.current()._outer = CASTAWAY(Statement *) outer;
00756             break;
00757         }
00758         ++iter;
00759     }
00760 
00761     cerr << "Error: StmtList: Unbalanced block:\n";
00762     _bad_block_error(iter, method_name);
00763 
00764     /// ...  Error: No IMPLIED_GOTO found
00765 }
00766 
00767 /// precondition : iter is on the IF statement
00768 /// postcondition: iter is on the ENDIF statment
00769 
00770 void 
00771 StmtList::_set_if_block_structure(Iterator<Statement> & iter,
00772                                   const Statement * outer,
00773                                   const char * method_name)
00774 //Modification History:
00775 ///  07-08-10.2052 evansl
00776 ///    WHAT:
00777 ///      Removed the 'set outer pointer for' initial statement.
00778 ///    WHY:
00779 ///      This is also done by _set_if_subblock_structure.
00780 {
00781     if (dbx_program_debug_level >= 100) {
00782         cout << "_set_if_block_structure called for stmt "
00783         << iter.current().tag() << endl;
00784     }
00785 
00786     p_assert(iter.current().stmt_class() == IF_STMT, "not IF");
00787 
00788     Statement      *main_if = &iter.current();
00789 
00790     /// ...  Set the outer pointer of this statement
00791     iter.current()._outer = CASTAWAY(Statement *) outer;
00792 
00793     Statement      *last_follow_link = &iter.current();
00794 
00795     RefList<Statement> follow_link_fixup;
00796 
00797     /// ...  Do all clauses of the IF block (including those of any ELSEIFs
00798     /// ...  which might show up)
00799     /// ...  Parse and set this THEN block
00800 
00801     _set_if_subblock_structure(iter, follow_link_fixup, outer, method_name);
00802 
00803     /// ...  After the last call, iter should be on an IMPLIED_GOTO
00804     /// ...  Set its outer field, then move to the next statement
00805 
00806     iter.current()._outer = CASTAWAY(Statement *) outer;
00807 
00808     ++iter;
00809 
00810     while (iter.valid()) {
00811         /// ...  Now it should be on an ELSEIF, ELSE, or ENDIF
00812         switch (iter.current().stmt_class()) {
00813 
00814         case UNDEFINED_STMT:
00815             cerr << "Error: StmtList: "
00816                  << "Found an UNDEFINED_STMT Statement type:\n";
00817             _bad_block_error(iter, method_name);
00818             break;
00819 
00820         case LABEL_STMT:
00821             break;
00822 
00823         case ELSEIF_STMT:
00824         case ELSE_STMT:
00825             /// ...  Set the outer pointer of this statement
00826             iter.current()._outer = CASTAWAY(Statement *) outer;
00827 
00828             /// ...  Set the follow pointer from the last structure 
00829             /// ...  (IF, ELSE or ELSEIF) of this IF block to this statement
00830 
00831             switch (last_follow_link->stmt_class()) {
00832             case IF_STMT:
00833                 ((IfStmt *) last_follow_link)->_follow = &iter.current();
00834                 break;
00835             case ELSE_STMT:
00836                 ((ElseStmt *) last_follow_link)->_follow = &iter.current();
00837                 break;
00838             case ELSEIF_STMT:
00839                 ((ElseIfStmt *) last_follow_link)->_follow = &iter.current();
00840                 break;
00841             default:
00842                 p_abort("not an IF statement");
00843             }
00844 
00845             /// ...  Set the lead pointer to the last structure 
00846             /// ...  (IF, ELSE or ELSEIF) of this IF block to this statement
00847 
00848             switch (iter.current().stmt_class()) {
00849             case ELSE_STMT:
00850                 ((ElseStmt *) & iter.current())->_lead = last_follow_link;
00851                 break;
00852             case ELSEIF_STMT:
00853                 ((ElseIfStmt *) & iter.current())->_lead = last_follow_link;
00854                 break;
00855             default:
00856                 p_abort("not an ELSE statement");
00857             }
00858 
00859             last_follow_link = &iter.current();
00860             /// ...  Parse the next block
00861             _set_if_subblock_structure(iter, follow_link_fixup, outer, 
00862                                        method_name);
00863             break;
00864 
00865         case ENDIF_STMT:
00866             if (dbx_program_debug_level >= 100) {
00867                 cout << "  _set_if_block_structure: found ENDIF: "
00868                      << iter.current().tag()
00869                      << " (for IF " << main_if->tag() << ")" << endl;
00870             }
00871 
00872             /// ...  Set the outer pointer of this statement
00873             iter.current()._outer = CASTAWAY(Statement *) outer;
00874 
00875             /// ...  set the matching_if pointer of this statement
00876             ((EndIfStmt *) & iter.current())->_matching_if = main_if;
00877 
00878             /// ...  set the IF statement\'s matching_endif pointer
00879             ((IfStmt *) main_if)->_matching_endif = &iter.current();
00880 
00881             /// ...  Set our lead ptr to the last structure
00882             ((EndIfStmt *) & iter.current())->_lead = last_follow_link;
00883             
00884             /// ...  Set the follow pointer from the last structure 
00885             /// ...   (IF, ELSE or ELSEIF) of this IF block to this statement
00886 
00887             switch (last_follow_link->stmt_class()) {
00888             case IF_STMT:
00889                 ((IfStmt *) last_follow_link)->_follow = &iter.current();
00890                 break;
00891             case ELSE_STMT:
00892                 ((ElseStmt *) last_follow_link)->_follow = &iter.current();
00893                 break;
00894             case ELSEIF_STMT:
00895                 ((ElseIfStmt *) last_follow_link)->_follow = &iter.current();
00896                 break;
00897             default:
00898                 p_abort("not an IF statement");
00899             }
00900 
00901             /// ...  Finally, we need to fix up all IMPLIED_GOTO statements so that
00902             /// ...  their follow fields all point to this ENDIF statement
00903 
00904             {
00905                 Iterator<Statement>fix_iter = follow_link_fixup;
00906                 while (fix_iter.valid()) {
00907                     p_assert(fix_iter.current().stmt_class() == 
00908                              IMPLIED_GOTO_STMT, 
00909                              "not an IMPLIED_GOTO statement");
00910 
00911                     ((ImpliedGotoStmt *) & fix_iter.current())->_follow 
00912                         = &iter.current();
00913                     ++fix_iter;
00914                 }
00915             }
00916 
00917             return;
00918 
00919         default:
00920             cerr << "Error: StmtList: Unbalanced block:\n";
00921             _bad_block_error(iter, method_name);
00922             break;
00923         }
00924 
00925         ++iter;
00926     }
00927 
00928     cerr << "Error: StmtList: Unbalanced block:\n";
00929     _bad_block_error(iter, method_name);
00930 
00931     /// ...  Error: No ENDIF found
00932 }
00933 
00934 /// precondition : StmtList's 'follow' ptrs are all correct
00935 /// postcondition: StmtList's lead, matching_if and matching_endif fields 
00936 ///                are set
00937         
00938 void
00939 StmtList::_set_if_block_lead_ptrs()
00940 {
00941     Iterator<Statement> if_iter = stmts_of_type(IF_STMT);
00942 
00943     while (if_iter.valid()) {
00944 
00945         Statement       *cur_if_part;  /// ...  Iterate over parts of IF
00946 
00947         for (cur_if_part = &if_iter.current();
00948              cur_if_part->stmt_class() != ENDIF_STMT;
00949              cur_if_part = cur_if_part->follow_ref())
00950             {
00951                 
00952                 /// ...  Set the lead ptr from the next IF structure 
00953                 /// ...   (ELSE, ELSEIF or ENDIF) to this statement
00954 
00955                 Statement   *next_if_part = cur_if_part->follow_ref();
00956                 
00957                 switch (next_if_part->stmt_class()) {
00958                 case ENDIF_STMT:
00959                     ((EndIfStmt *) next_if_part)->_lead = &if_iter.current();
00960                     break;
00961 
00962                 case ELSE_STMT:
00963                     ((ElseStmt *) next_if_part)->_lead = &if_iter.current();
00964                     break;
00965 
00966                 case ELSEIF_STMT:
00967                     ((ElseIfStmt *) next_if_part)->_lead = &if_iter.current();
00968                     break;
00969 
00970                 default:
00971                     p_abort("not an IF statement");
00972                 }
00973             }
00974 
00975         /// ...  cur_if_part = ENDIF_STMT
00976 
00977         ((EndIfStmt *) cur_if_part)->_matching_if = &if_iter.current();
00978         ((IfStmt *) & if_iter.current())->_matching_endif = cur_if_part;
00979 
00980         ++if_iter;
00981     }
00982 }
00983 
00984 /// precondition : iter is on the BLOCK_ENTRY stmt
00985 /// postcondition: iter is on the BLOCK_EXIT  stmt
00986 
00987 void 
00988 StmtList::_set_pair_block_structure(Iterator<Statement> & iter,
00989                                     const Statement * outer,
00990                                     const char *method_name )
00991 {
00992     if (dbx_program_debug_level >= 100) {
00993         cout << "_set_pairblock_structure called for stmt "
00994              << iter.current().tag() << endl;
00995     }
00996 
00997     p_assert( iter.current().stmt_class() == BLOCK_ENTRY_STMT, "not a BLOCK" );
00998 
00999     Statement *main_block = CASTAWAY(Statement *) & iter.current();
01000     Statement *main_do    = CASTAWAY(Statement *) outer;
01001 
01002     /// ...  Start with stmt after BLOCK_ENTRY
01003 
01004     for ( ++iter; iter.valid(); ++iter) {
01005         switch (iter.current().stmt_class()) {
01006 
01007         case UNDEFINED_STMT:
01008             cerr << "Error: StmtList: "
01009                  << "Found an UNDEFINED_STMT Statement type:\n";
01010             _bad_block_error(iter, method_name);
01011             break;
01012 
01013         case BLOCK_ENTRY_STMT:
01014             _set_pair_block_structure(iter, main_do, method_name);
01015             break;
01016 
01017         case BLOCK_EXIT_STMT:
01018             {
01019                 Statement *end_block = CASTAWAY(Statement *) & iter.current();
01020 
01021                 ((BlockEntryStmt *) main_block)->_follow = end_block;
01022                 ((BlockExitStmt *) end_block)->_follow = main_block;
01023 
01024         ((BlockEntryStmt *) main_block)->_outer = main_do;
01025         ((BlockExitStmt *) end_block)->_outer = main_do;
01026             }
01027             return;
01028 
01029         case LABEL_STMT:
01030             iter.current()._outer = main_do;
01031             break;
01032 
01033         case DO_STMT:
01034             _set_do_block_structure(iter, main_do, method_name);
01035             break;
01036 
01037         case WHILE_STMT:
01038             _set_do_block_structure(iter, main_do, method_name);
01039             break;
01040 
01041         case IF_STMT:
01042             _set_if_block_structure(iter, main_do, method_name);
01043             break;
01044 
01045         case ELSEIF_STMT:
01046         case IMPLIED_GOTO_STMT:
01047         case ENDIF_STMT:
01048         case ELSE_STMT:
01049         case ENDDO_STMT:
01050             _unbalanced_error(iter, method_name);
01051             break;
01052 
01053         default:
01054             /// ...  Set this statement's 'outer' field to point to the DO statement.
01055             iter.current()._outer = main_do;
01056             break;
01057         }
01058 
01059         /// ...  Go to the next statement and try again
01060     }
01061 
01062     /// ...  Error: No matching ENDDO found
01063 
01064     _unbalanced_error(iter, method_name);
01065 }
01066 
01067 
01068 /// precondition : iter is on the DO stmt
01069 /// postcondition: iter is on the ENDDO stmt
01070 
01071 void 
01072 StmtList::_set_do_block_structure(Iterator<Statement>&iter,
01073                                      const Statement * outer,
01074                                      const char *method_name)
01075 {
01076     if (dbx_program_debug_level >= 100) {
01077         cout << "_set_do_block_structure called for stmt "
01078              << iter.current().tag() << endl;
01079     }
01080 
01081     p_assert( iter.current().stmt_class() == DO_STMT ||
01082               iter.current().stmt_class() == WHILE_STMT, "not a loop" );
01083 
01084     Statement      *main_do = CASTAWAY(Statement *) & iter.current();
01085 
01086     /// ...  Start with stmt after DO
01087     ++iter;
01088 
01089     while (iter.valid()) {
01090         switch (iter.current().stmt_class()) {
01091 
01092         case UNDEFINED_STMT:
01093             cerr << "Error: StmtList: "
01094                  << "Found an UNDEFINED_STMT Statement type:\n";
01095             _bad_block_error(iter, method_name);
01096             break;
01097 
01098         case LABEL_STMT:
01099             iter.current()._outer = main_do;
01100             break;
01101 
01102         case BLOCK_ENTRY_STMT:
01103             _set_pair_block_structure(iter, main_do, method_name);
01104             break;
01105 
01106         case DO_STMT:
01107             _set_do_block_structure(iter, main_do, method_name);
01108             break;
01109 
01110         case WHILE_STMT:
01111             _set_do_block_structure(iter, main_do, method_name);
01112             break;
01113 
01114         case ENDDO_STMT:
01115             {
01116                 if (dbx_program_debug_level >= 100) {
01117                     cout << "  _set_do_block_structure: found ENDDO: "
01118                          << iter.current().tag()
01119                          << " (for DO " << main_do->tag() << ")" << endl;
01120                 }
01121 
01122                 /// ...  Connect the follow's of the DO and ENDDO together
01123                 Statement & do_stmt = *main_do;
01124                 EndDoStmt & enddo_stmt = (EndDoStmt &) iter.current();
01125 
01126                 if (do_stmt.stmt_class() == DO_STMT)
01127                     ((DoStmt &) do_stmt)._follow = &enddo_stmt;
01128                 else if (do_stmt.stmt_class() == WHILE_STMT)
01129                     ((WhileStmt &) do_stmt)._follow = &enddo_stmt;
01130 
01131                 ((EndDoStmt &) enddo_stmt)._follow = &do_stmt;
01132 
01133                 /// ...  Set the outer pointers
01134                 do_stmt._outer = CASTAWAY(Statement *) outer;
01135                 enddo_stmt._outer = &do_stmt;
01136 
01137                 return;
01138             }
01139 
01140         case IF_STMT:
01141             _set_if_block_structure(iter, main_do, method_name);
01142             break;
01143 
01144         case ELSEIF_STMT:
01145         case IMPLIED_GOTO_STMT:
01146         case ENDIF_STMT:
01147         case ELSE_STMT:
01148             _unbalanced_error(iter, method_name);
01149             break;
01150 
01151         default:
01152             /// ...  Set this statement's 'outer' field to point to the DO statement.
01153             iter.current()._outer = main_do;
01154             break;
01155         }
01156         /// ...  Go to the next statement and try again
01157         ++iter;
01158     }
01159 
01160     /// ...  Error: No matching ENDDO found
01161 
01162     _unbalanced_error(iter, method_name);
01163 }
01164 
01165 /// Return a new statement tag
01166 
01167 char           *
01168 StmtList::new_tag()
01169 {
01170     static char     buf[20];
01171 
01172     sprintf(buf, "ST%d", ++_tag_count);
01173 
01174     return buf;
01175 }
01176 
01177 void 
01178 StmtList::retag( const char *old_tag, const char *new_tag )
01179 {
01180   VoidPtrDef  *vp = _stmt_tag_dict->find_ref(old_tag);
01181 
01182   if (vp == 0) 
01183     p_abort( "StmtList::retag: old_tag not found" );
01184   else {
01185 
01186     /// ...  Find new tag number (ignoring exceptional tags)
01187 
01188     long tag_num = get_tag_num(new_tag);
01189 
01190     /// ...  Update tag counter to prevent a duplicate tag assignment
01191 
01192     if (tag_num > _tag_count)
01193       _tag_count = tag_num;
01194 
01195     /// ...  Change statement's existing tag
01196 
01197     Statement *s = (Statement *) vp->ptr_ref();
01198 
01199     _stmt_tag_dict->del(old_tag);
01200 
01201     s->_tag = new_tag;
01202 
01203     _stmt_tag_dict->ins(new VoidPtrDef(s->_tag, s));
01204   }
01205 }
01206 
01207 void
01208 StmtList::_ins_with_retag( Statement *curr_stmt )
01209 {
01210 
01211 /// Check statement tag dictionary
01212 
01213   const char *st = (const char *) curr_stmt->_tag;
01214 
01215   if (!_stmt_tag_dict->find_ref(st)) {
01216 
01217     /// ...  Find tag number (ignoring exceptional tags)
01218 
01219     long tag_num = get_tag_num(st);
01220 
01221     /// ...  Update tag counter to prevent a duplicate tag assignment
01222 
01223     if (tag_num > _tag_count)
01224       _tag_count = tag_num;
01225 
01226   }
01227 
01228   else
01229     curr_stmt->_tag = new_tag();
01230 
01231   _stmt_tag_dict->ins(new VoidPtrDef(curr_stmt->_tag, curr_stmt));
01232 
01233   return;
01234 
01235 }
01236 
01237 
01238 /// Description:
01239 /// return the char* equivalent of a positive integer
01240 
01241 char           *
01242 int_to_string(int n)
01243 {
01244     int             len = 0;
01245 
01246     for (int x = n; x; x = x / 10)
01247         ++len;
01248 
01249     char *st = new char[len + 1];
01250 
01251     st[len--] = '\0';
01252 
01253     do {
01254         st[len--] = ((char)(n % 10) + '0');
01255     } while ((n /= 10)>0);
01256 
01257     return st;
01258 }
01259 
01260 void
01261 StmtList::ins_before(Statement *new_stmt, Statement *ref_stmt)
01262 {
01263     p_assert(new_stmt, "cannot insert NULL statement");
01264 
01265     if (redundant_flow_ins(*this, new_stmt))
01266         return;
01267 
01268     _ins_with_retag(new_stmt);
01269 
01270     List<Statement>::ins_before(new_stmt, ref_stmt);
01271 
01272     /// ...  If label statement, insert entry into label database
01273 
01274     if (new_stmt->stmt_class()==LABEL_STMT)
01275       _ins_label_stmt(*new_stmt);
01276 
01277     new_stmt->build_refs();     // Rebuild the in/out/act _refs
01278 
01279     _set_block_structure(new_stmt, new_stmt, "ins_before");
01280 
01281     /// ...  WARNING: this is a private member access!
01282 
01283     new_stmt->modify_succ().clear();
01284     new_stmt->modify_pred().clear();
01285 
01286     if (ref_stmt == 0) 
01287         last_ref()->fix_flow( *this );
01288     else {
01289         for (Iterator<Statement> iter = ref_stmt->pred();
01290                                  iter.valid(); ++iter) {
01291             iter.current().fix_flow( *this );
01292         }
01293     }
01294 
01295     new_stmt->fix_flow( *this );
01296 }
01297 
01298 void
01299 StmtList::ins_after(Statement *new_stmt, Statement *ref_stmt)
01300 {
01301     p_assert(new_stmt, "cannot insert NULL statement");
01302 
01303     if (redundant_flow_ins(*this, new_stmt))
01304         return;
01305     
01306     _ins_with_retag(new_stmt);
01307 
01308     List<Statement>::ins_after(new_stmt, ref_stmt);
01309 
01310     /// ...  If label statement, insert entry into label database
01311 
01312     if (new_stmt->stmt_class()==LABEL_STMT)
01313       _ins_label_stmt(*new_stmt);
01314 
01315     new_stmt->build_refs();     // Rebuild the in/out/act _refs
01316 
01317     _set_block_structure(new_stmt, new_stmt, "ins_after");
01318 
01319     /// ...  WARNING: this is a private member access!
01320     new_stmt->modify_succ().clear();
01321     new_stmt->modify_pred().clear();
01322 
01323     if (ref_stmt != 0) {
01324         ref_stmt->fix_flow( *this );
01325 
01326         if (ref_stmt->stmt_class() == ENDDO_STMT) 
01327             ref_stmt->follow_ref()->fix_flow( *this );
01328     }
01329 
01330     new_stmt->fix_flow( *this );
01331 }
01332 
01333 void 
01334 StmtList::ins_before(List<Statement> * stmts, Statement * ref_stmt)
01335 {
01336     if (stmts->entries() > 0) {
01337         if (!ref_stmt)
01338             _ins_block_after(stmts, last_ref(), "ins_block_before");
01339         else
01340             _ins_block_before(stmts, ref_stmt, "ins_block_before");
01341     }
01342     else {
01343         /// ...  We need to delete the list itself, even if empty
01344         delete stmts;
01345     }
01346 }
01347 
01348 /// Insert a statement but don't check the block structure.  Needed by
01349 /// the Directive class to insert BLOCK_ENTRY and BLOCK_EXIT statements.
01350 
01351 void
01352 StmtList::_ins_after( Statement *curr_stmt,
01353                       Statement *ref_stmt, 
01354                       char * NOTUSED(method_name) )
01355 {
01356     if (curr_stmt == 0) {
01357         p_abort("StmtList::_ins_after(): insertion routine received "
01358         "NULL statement");
01359     }
01360 
01361     if (redundant_flow_ins(*this, curr_stmt))
01362         return;
01363     
01364     RefSet<Statement>   possible;
01365 
01366     if (ref_stmt != 0) {
01367         possible.ins( *ref_stmt );
01368 
01369         for (Iterator<Statement> iter = ref_stmt->pred(); iter.valid(); ++iter)
01370             possible.ins( iter.current() );
01371 
01372         if (ref_stmt->stmt_class() == ENDDO_STMT)
01373             possible.ins( *ref_stmt->follow_ref() );
01374     }
01375 
01376     /// ...  WARNING: this is a private member access!
01377     curr_stmt->modify_succ().clear();
01378     curr_stmt->modify_pred().clear();
01379 
01380     _ins_with_retag(curr_stmt);
01381 
01382     List<Statement>::ins_after(curr_stmt, ref_stmt);
01383 
01384     /// ...  If label statement, insert entry into label database
01385 
01386     if (curr_stmt->stmt_class()==LABEL_STMT)
01387       _ins_label_stmt(*curr_stmt);
01388 
01389     curr_stmt->build_refs();    // Re-build in/out/act _refs
01390 
01391     possible.ins( *curr_stmt );
01392 
01393     for (Iterator<Statement> rs_iter = possible; rs_iter.valid(); ++rs_iter)
01394         rs_iter.current().fix_flow( *this );
01395 }
01396 
01397 void 
01398 StmtList::_ins_block_after(List<Statement> *stmts,
01399                            Statement *ref_stmt,
01400                            char *method_name)
01401 {
01402     Statement          *list_start = stmts->first_ref();
01403     Statement          *list_fin = stmts->last_ref();
01404     RefSet<Statement>   possible;
01405 
01406     Iterator<Statement> iter = *stmts;
01407 
01408     for (iter.set_to_last(); iter.valid(); --iter) {
01409         /// ...  WARNING: this is a private member access!
01410         iter.current().modify_succ().clear();
01411         iter.current().modify_pred().clear();
01412 
01413     _ins_with_retag(&iter.current());
01414 
01415         Statement *curr_stmt = stmts->grab(iter.current());
01416 
01417         if (! redundant_flow_ins(*this, curr_stmt) ) {
01418             List<Statement>::ins_after(curr_stmt, ref_stmt);
01419 
01420         /// ...  If label statement, insert entry into label database
01421 
01422         if (curr_stmt->stmt_class()==LABEL_STMT)
01423           _ins_label_stmt(*curr_stmt);
01424 
01425             curr_stmt->build_refs();    // Re-build in/out/act _refs
01426             possible.ins( *curr_stmt ); /// ...  Add to the fix-up list.
01427         }
01428     }
01429 
01430     _set_block_structure(list_start, list_fin, method_name);
01431 
01432     if (ref_stmt != 0) {
01433         ref_stmt->fix_flow( *this );
01434 
01435         for (iter = ref_stmt->pred(); iter.valid(); ++iter)
01436             iter.current().fix_flow( *this );
01437     }
01438 
01439     for (Iterator<Statement> rs_iter = possible; rs_iter.valid(); ++rs_iter)
01440         rs_iter.current().fix_flow( *this );
01441 
01442     /// ...  Delete now empty stmts
01443     delete stmts;
01444 }
01445 
01446 void 
01447 StmtList::_ins_block_before(List<Statement> *stmts,
01448                             Statement * ref_stmt,
01449                             char *method_name)
01450 {
01451     Statement          *list_start = stmts->first_ref();
01452     Statement          *list_fin = stmts->last_ref();
01453     RefSet<Statement>   possible;
01454 
01455     for (Iterator<Statement>iter = *stmts; iter.valid(); ++iter) {
01456         /// ...  WARNING: this is a private member access!
01457         iter.current().modify_succ().clear();
01458         iter.current().modify_pred().clear();
01459 
01460     _ins_with_retag(&iter.current());
01461 
01462         Statement *curr_stmt = stmts->grab(iter.current());
01463 
01464         if (! redundant_flow_ins(*this, curr_stmt) ) {
01465             List<Statement>::ins_before(curr_stmt, ref_stmt);
01466 
01467         /// ...  If label statement, insert entry into label database
01468 
01469         if (curr_stmt->stmt_class()==LABEL_STMT)
01470           _ins_label_stmt(*curr_stmt);
01471 
01472             curr_stmt->build_refs();    // Re-build in/out/act _refs.
01473 
01474             possible.ins( *curr_stmt ); /// ...  Add to the fix-up list.
01475         }
01476     }
01477 
01478     _set_block_structure(list_start, list_fin, method_name);
01479 
01480     if (ref_stmt != 0) {
01481         for (Iterator<Statement> iter = ref_stmt->pred(); iter.valid(); ++iter)
01482             iter.current().fix_flow( *this );
01483     }
01484 
01485     for (Iterator<Statement> rs_iter = possible; rs_iter.valid(); ++rs_iter)
01486         rs_iter.current().fix_flow( *this );
01487 
01488     /// ...  delete now empty stmts
01489     delete stmts;
01490 }
01491 
01492 void 
01493 StmtList::ins_after(List<Statement> *stmts, Statement *ref_stmt)
01494 {
01495     if (stmts->entries()>0) {
01496         if (!ref_stmt)
01497             _ins_block_before(stmts, first_ref(), "ins_block_after");
01498         else
01499             _ins_block_after(stmts, ref_stmt, "ins_block_after");
01500     }
01501     else {
01502         /// ...  We need to delete the list itself, even if empty
01503         delete stmts;
01504     }
01505 }
01506 
01507 void
01508 StmtList::ins_first(Statement *stmt)
01509 {
01510     p_assert( stmt && stmt->stmt_class() == FLOW_ENTRY_STMT, 
01511               "not a FLOW_ENTRY");
01512 
01513     ins_after(stmt, (Statement *) 0);
01514 }
01515     
01516 void
01517 StmtList::ins_last(Statement *stmt)
01518 {
01519     p_assert( stmt && stmt->stmt_class() == FLOW_EXIT_STMT, 
01520               "not a FLOW_ENTRY" );
01521 
01522     ins_before(stmt, (Statement *) 0);
01523 }
01524 
01525 void
01526 StmtList::ins(Statement *new_stmt, int loc)
01527 {
01528     if (loc == 0)
01529         ins_after(new_stmt, 0);
01530     else {
01531         Statement &st = (*this)[loc - 1];
01532         ins_after(new_stmt, &st);
01533     }
01534 }
01535 
01536 
01537 Statement&
01538 StmtList::ins_IF_ELSE_after(
01539             Expression * cond_exp,        /// ...  conditional expression of if-stmt
01540             Statement  * ref_stmt GIV(0), /// ...  IF after this stmt
01541             Statement  * last_of_then_clause GIV(0),   /// ...  ELSE after this stmt
01542             Statement  * last GIV(0))                  /// ...  ENDIF after this stmt
01543 {                               
01544     Statement &if_st = ins_IF_after(cond_exp, ref_stmt, last);
01545 
01546     /// ...  Change to If-Else
01547     if (last_of_then_clause != 0) {
01548 
01549         ins_ELSE_after(&if_st, last_of_then_clause);
01550     } else {
01551 
01552         ins_ELSE_after(&if_st, &if_st);
01553     }
01554 
01555     return if_st;
01556 
01557 #if 0
01558     /// ...  old version -- Thomas R. Lawrence (9 August 1994)
01559     /// ...  First create an If-Endif
01560     Statement &if_st = ins_IF_after(cond_exp, ref_stmt, last);
01561 
01562     /// ...  Change to If-Else
01563     ins_ELSE_after(ref_stmt->next_ref(), last_of_then_clause);
01564 
01565     return if_st;
01566 #endif
01567 }
01568 
01569 Statement&
01570 StmtList::ins_IF_after(
01571                 Expression * cond_exp,          /// ...  conditional expr of if-stmt
01572                 Statement * ref_stmt,           /// ...  IF after this stmt
01573                 Statement * last GIV(0))        /// ...  ENDIF after this stmt
01574 {
01575     p_assert(cond_exp, "can not insert NULL statement");    
01576     /// ...  Don't allow any NULL if statements
01577 
01578     RefSet<Statement> possible;
01579 
01580     if (ref_stmt != 0) {
01581         possible.ins( *ref_stmt );
01582 
01583         for (Iterator<Statement> iter = ref_stmt->next_ref()->pred(); 
01584                                  iter.valid(); ++iter) {
01585             possible.ins( iter.current() );
01586         }
01587     }
01588 
01589     if (last != 0) {
01590         possible.ins( *last );
01591         for (Iterator<Statement> iter = last->next_ref()->pred(); 
01592                                  iter.valid(); ++iter) {
01593             possible.ins( iter.current() );
01594         }
01595     }
01596 
01597     Statement      *if_stmt = new IfStmt(new_tag(), cond_exp);
01598 
01599     _stmt_tag_dict->ins(new VoidPtrDef(if_stmt->_tag, if_stmt));
01600 
01601     Statement      *imp_goto1 = new ImpliedGotoStmt(new_tag());
01602 
01603     _stmt_tag_dict->ins(new VoidPtrDef(imp_goto1->_tag, imp_goto1));
01604 
01605     Statement      *endif_stmt = new EndIfStmt(new_tag());
01606 
01607     _stmt_tag_dict->ins(new VoidPtrDef(endif_stmt->_tag, endif_stmt));
01608 
01609     if (!ref_stmt)
01610         List<Statement>::ins_first(if_stmt);
01611     else
01612         List<Statement>::ins_after(if_stmt, ref_stmt);
01613 
01614     if (!last)
01615         last = if_stmt;
01616 
01617     List<Statement>::ins_after(endif_stmt, last);
01618     List<Statement>::ins_after(imp_goto1, last);
01619 
01620     _set_block_structure(if_stmt, endif_stmt, "ins_block_IF_after");
01621 
01622     possible.ins( *if_stmt );
01623     possible.ins( *imp_goto1 );
01624     possible.ins( *last );
01625     possible.ins( *endif_stmt );
01626 
01627     for (Iterator<Statement> rs_iter = possible; rs_iter.valid(); ++rs_iter)
01628         rs_iter.current().fix_flow( *this );
01629 
01630     return *if_stmt;
01631 }
01632 
01633     class ElseIf_Stmt
01634       : public StmtList::ElseIf_or_Else_Stmt
01635       {
01636       public:
01637         ElseIf_Stmt(ElseIfStmt* aStmt)
01638           : _stmt(aStmt)
01639           {}
01640         virtual Statement* stmt(void)const{return _stmt;}
01641         virtual Statement* lead_ref(void)const{return _stmt->lead_ref();}
01642         virtual const char* which(void)const{return "ins_ELSEIF_after";}
01643 
01644         ElseIfStmt* _stmt;
01645       };
01646 
01647     class Else_Stmt
01648       : public StmtList::ElseIf_or_Else_Stmt
01649       {
01650       public:
01651         Else_Stmt(ElseStmt* aStmt)
01652           : _stmt(aStmt)
01653           {}
01654         virtual Statement* stmt(void)const{return _stmt;}
01655         virtual Statement* lead_ref(void)const{return _stmt->lead_ref();}
01656         virtual const char* which(void)const{return "ins_ELSE_after";}
01657 
01658         ElseStmt* _stmt;
01659       };
01660 
01661   Statement&
01662 StmtList::_ins_ELSEIF_or_ELSE_after
01663   ( const ElseIf_or_Else_Stmt& elseif_or_else_stmt
01664   , Statement* if_stmt
01665   , Statement* last_of_then_clause
01666   )
01667 {            
01668     p_assert(if_stmt && (if_stmt->stmt_class() == IF_STMT), 
01669              "not an IF statement");
01670 
01671     Statement* new_stmt=elseif_or_else_stmt.stmt();
01672     const char* which=elseif_or_else_stmt.which();
01673 
01674     /// ...  Find the ENDIF corresponding to the if_stmt
01675     if (if_stmt->follow_ref() == NULL) {
01676         cerr << "StmtList::"<<which<<": "
01677              << "'follow' pointer not set for:" << endl
01678              << *if_stmt;
01679 
01680         p_abort("(see above message)");
01681     }
01682 
01683     Statement      *endif_stmt;
01684 
01685     for ( endif_stmt = if_stmt->follow_ref(); 
01686           endif_stmt->stmt_class() != ENDIF_STMT;
01687           endif_stmt = endif_stmt->follow_ref())
01688         if (endif_stmt->follow_ref() == NULL) {
01689             cerr << "StmtList::"<<which<<": "
01690                  << "'follow' pointer not set for:" << endl
01691                  << *endif_stmt;
01692             p_abort("(see above message)");
01693         }
01694 
01695     _stmt_tag_dict->ins(new VoidPtrDef(new_stmt->_tag, new_stmt));
01696 
01697     Statement      *imp_goto = new ImpliedGotoStmt(new_tag());
01698 
01699     _stmt_tag_dict->ins(new VoidPtrDef(imp_goto->_tag, imp_goto));
01700 
01701     /// ...  if not specified, set to statement before then ENDIF\'s IMPLIED_GOTO
01702 
01703     RefSet<Statement> possible;
01704 
01705     if(!last_of_then_clause){
01706         last_of_then_clause = endif_stmt->prev_ref();
01707 
01708         /// ...  Should now be the implied_goto
01709         p_assert(last_of_then_clause->stmt_class() == IMPLIED_GOTO_STMT, 
01710                  "not an IMPLIED_GOTO statement");
01711 
01712         /// ...  Set to the statement before it
01713         last_of_then_clause = last_of_then_clause->prev_ref();
01714 
01715     };
01716 
01717     {   
01718     Statement* next_ref=last_of_then_clause->next_ref();
01719         /// ... Since the new_stmt will be inserted between
01720         /// ... last_of_then_clause and next_ref, the next_ref->pred()
01721         /// ... may no longer be the predecessors of next_ref.
01722         /// ... Add this set ot possible so that their successors may
01723         /// ... be recalculated.
01724         for (Iterator<Statement> iter = next_ref->pred();
01725                                  iter.valid(); ++iter) {
01726             possible.ins( iter.current() );
01727         }
01728         /// ... !possible.member(last_of_then_clause) iff
01729         /// ... last_of_then_clause is a GotoStmt.
01730     };
01731 
01732     List<Statement>::ins_after(new_stmt, last_of_then_clause);
01733     List<Statement>::ins_after(imp_goto, last_of_then_clause);
01734 
01735     _set_block_structure(if_stmt, endif_stmt, "ins_ELSEIF_block_after");
01736 
01737     /// ... The above call to _set_block_structure made:
01738     /// ...   elseif_or_else_stmt.lead_ref().follow_ref() == new_stmt
01739     /// ... so that it's successors may be recalculated.
01740     possible.ins( *(elseif_or_else_stmt.lead_ref()) );
01741     /// ... Since possible.member(last_of_then_clause), imp_goto->pred()
01742     /// ... will be calculated by the rs_iter loop. 
01743     possible.ins( *imp_goto );
01744     /// ... Since possible.member(imp_goto), new_stmt->pred() will be calculated
01745     /// ... by the rs_iter loop.
01746     possible.ins( *new_stmt );
01747     /// ... Since possible.member(new_stmt), succ.pred() will be calculated by
01748     /// ... rs_iter loop, for all succ in new_stmt->succ()(which will
01749     /// ... also be calculated by the rs_iter loop). 
01750 
01751     for (Iterator<Statement> rs_iter = possible; rs_iter.valid(); ++rs_iter)
01752         rs_iter.current().fix_flow( *this );
01753 
01754     return *new_stmt;
01755 }
01756 
01757 
01758 Statement&
01759 StmtList::ins_ELSEIF_after(
01760                 Expression * cond_expr,     /// ...  conditional expr of elseif-stmt
01761                 Statement * if_stmt,                /// ...  IF statement to augment
01762                 Statement * last_of_then_clause GIV(0))/// ...  ELSE after this stmt
01763 {
01764 
01765     p_assert(cond_expr, "Conditional expression is missing");
01766 
01767     ElseIfStmt      *elseif_stmt = new ElseIfStmt(new_tag(), cond_expr);
01768     ElseIf_Stmt elseIf_Stmt(elseif_stmt);
01769 
01770     return _ins_ELSEIF_or_ELSE_after
01771              ( elseIf_Stmt
01772          , if_stmt
01773          , last_of_then_clause
01774          );
01775 }
01776 
01777 Statement&
01778 StmtList::ins_ELSE_after(
01779              Statement * if_stmt,                    /// ...  IF statement to augment
01780              Statement * last_of_then_clause GIV(0)) /// ...  ELSE after this stmt
01781 {            
01782 
01783     ElseStmt      *else_stmt = new ElseStmt(new_tag());
01784     Else_Stmt else_Stmt(else_stmt);
01785 
01786     return _ins_ELSEIF_or_ELSE_after
01787              ( else_Stmt
01788          , if_stmt
01789          , last_of_then_clause
01790          );
01791 
01792 }
01793 
01794 Statement&
01795 StmtList::ins_DO_after(Expression *index_exp,      /// ...  DO stmt specifications
01796                        Expression *init_exp,
01797                        Expression *limit_exp,
01798                        Expression *step_exp,
01799                        Statement  *ref_stmt GIV(0), /// ...  DO after this stmt
01800                        Statement  *last GIV(0))     /// ...  ENDDO after this stmt
01801 {
01802     Statement *do_stmt 
01803         = new DoStmt(new_tag(), index_exp, init_exp, limit_exp, step_exp);
01804 
01805     return ins_DO_END_after(do_stmt,ref_stmt,last);
01806 }
01807 
01808 Statement&
01809 StmtList::ins_WHILE_after(Expression *cond_exp,      /// ...  conditional expression
01810                        Statement  *ref_stmt GIV(0), /// ...  DO after this stmt
01811                        Statement  *last GIV(0))     /// ...  ENDDO after this stmt
01812 {
01813     Statement *do_stmt 
01814         = new WhileStmt(new_tag(),cond_exp);
01815 
01816     return ins_DO_END_after(do_stmt,ref_stmt,last);
01817 }
01818 
01819 
01820 Statement&
01821 StmtList::ins_DO_END_after(Statement* do_stmt,      /// ...  DO stmt specifications
01822                        Statement  *ref_stmt GIV(0), /// ...  DO after this stmt
01823                        Statement  *last GIV(0))     /// ...  ENDDO after this stmt
01824 {
01825      STMT_TYPE       t = do_stmt->stmt_class();
01826 
01827      p_assert(t == DO_STMT || t == WHILE_STMT , "not DO_END header");
01828 
01829     _stmt_tag_dict->ins(new VoidPtrDef(do_stmt->_tag, do_stmt));
01830 
01831     Statement      *enddo_stmt = new EndDoStmt(new_tag());
01832 
01833     RefSet<Statement> possible;
01834 
01835     if (ref_stmt != 0) {
01836         possible.ins( *ref_stmt );
01837 
01838         for (Iterator<Statement> iter = ref_stmt->next_ref()->pred();
01839                                  iter.valid(); ++iter) {
01840             possible.ins( iter.current() );
01841         }
01842     }
01843 
01844     if (last != 0) {
01845         possible.ins( *last );
01846         for (Iterator<Statement> iter = last->next_ref()->pred();
01847                                  iter.valid(); ++iter) {
01848             possible.ins( iter.current() );
01849         }
01850     }
01851 
01852     _stmt_tag_dict->ins(new VoidPtrDef(enddo_stmt->_tag, enddo_stmt));
01853 
01854     if (ref_stmt)
01855         List<Statement>::ins_after(do_stmt, ref_stmt);
01856     else
01857         List<Statement>::ins_first(do_stmt);
01858 
01859     if (!last)
01860         last = do_stmt;
01861 
01862     List<Statement>::ins_after(enddo_stmt, last);
01863 
01864     _set_block_structure(do_stmt, enddo_stmt, "ins_DO_after");
01865 
01866     possible.ins( *do_stmt );
01867     possible.ins( *last );
01868     possible.ins( *enddo_stmt );
01869 
01870     for (Iterator<Statement> rs_iter = possible; rs_iter.valid(); ++rs_iter)
01871         rs_iter.current().fix_flow( *this );
01872 
01873     return *do_stmt;
01874 }
01875 
01876 Statement&
01877 StmtList::ins_BLOCK_after( Statement *ref_stmt GIV(0), /// ...  ENTRY after this stmt
01878                            Statement *last GIV(0))     /// ...  EXIT  after this stmt
01879 {
01880     Statement *entry_stmt = new BlockEntryStmt(new_tag());
01881 
01882     _stmt_tag_dict->ins(new VoidPtrDef(entry_stmt->_tag, entry_stmt));
01883 
01884     Statement      *exit_stmt = new BlockExitStmt(new_tag());
01885 
01886     _stmt_tag_dict->ins(new VoidPtrDef(exit_stmt->_tag, exit_stmt));
01887 
01888     RefSet<Statement> possible;
01889 
01890     Boolean whole_programunit = False;
01891     
01892     // Are we inserting BLOCKENTRY/EXIT around the whole ProgramUnit?
01893     
01894     if (ref_stmt && last) {
01895     if ((ref_stmt->stmt_class() == FLOW_ENTRY_STMT) &&
01896         (last->next_ref()->stmt_class() == FLOW_EXIT_STMT)) {
01897         whole_programunit = True;
01898     }
01899     }
01900 
01901     if (ref_stmt != 0) {
01902         possible.ins( *ref_stmt );
01903 
01904         for (Iterator<Statement> iter = ref_stmt->next_ref()->pred();
01905                                  iter.valid(); ++iter) {
01906             possible.ins( iter.current() );
01907         }
01908     }
01909 
01910     if (last != 0) {
01911         possible.ins( *last );
01912         for (Iterator<Statement> iter = last->next_ref()->pred();
01913                                  iter.valid(); ++iter) {
01914             possible.ins( iter.current() );
01915         }
01916     }
01917 
01918     if (ref_stmt)
01919         List<Statement>::ins_after(entry_stmt, ref_stmt);
01920     else
01921         List<Statement>::ins_first(entry_stmt);
01922 
01923     if (!last)
01924         last = entry_stmt;
01925 
01926     List<Statement>::ins_after(exit_stmt, last);
01927 
01928     // If we are not putting BLOCK_ENTRY/EXIT
01929     /// ...  around the whole ProgramUnit, do not do _set_block_structure.
01930     
01931     if (! whole_programunit) {
01932     _set_block_structure(entry_stmt, exit_stmt, "ins_BLOCK_after");
01933     }
01934 
01935     possible.ins( *entry_stmt );
01936     possible.ins( *last );
01937     possible.ins( *exit_stmt );
01938 
01939     for (Iterator<Statement> rs_iter = possible; rs_iter.valid(); ++rs_iter)
01940         rs_iter.current().fix_flow( *this );
01941 
01942     return *entry_stmt;
01943 }
01944 
01945 void 
01946 StmtList::move_block_before( Statement &first_stmt, Statement &last_stmt,
01947                              Statement *ref_stmt)
01948 {
01949      List<Statement>* block=grab(first_stmt,last_stmt,DONT_RELABEL);
01950      ins_before(block,ref_stmt);
01951 }
01952 
01953 void 
01954 StmtList::move_block_after( Statement & first_stmt, Statement & last_stmt,
01955                             Statement * ref_stmt GIV(0))
01956 {
01957      List<Statement>* block=grab(first_stmt,last_stmt,DONT_RELABEL);
01958      ins_after(block,ref_stmt);
01959 }
01960 
01961 void 
01962 StmtList::move_before(Statement & stmt, Statement * ref_stmt GIV(0))
01963 {
01964     Statement      *move = List<Statement>::grab(stmt);
01965 
01966     List<Statement>::ins_before(move, ref_stmt);
01967     _set_block_structure(move, move, "move_before");
01968 }
01969 
01970 void 
01971 StmtList::move_after(Statement & stmt, Statement * ref_stmt GIV(0))
01972 {
01973     Statement      *move = List<Statement>::grab(stmt);
01974 
01975     List<Statement>::ins_after(move, ref_stmt);
01976     _set_block_structure(move, move, "move_after");
01977 }
01978 
01979 void
01980 StmtList::_del(int loc)
01981 {
01982   del((*this)[loc]);
01983 }
01984 
01985 void
01986 StmtList::del( RefSet<Statement> & stmt_list )
01987 {
01988     RefSet<Statement> labels;
01989 
01990     Iterator<Statement> iter = stmt_list;
01991 
01992     for (  ; iter.valid(); ++iter) {
01993         if (iter.current_valid()) {
01994             Statement & s = iter.current();
01995 
01996             switch ( s.stmt_class() ) {
01997             case DO_STMT:
01998             case WHILE_STMT:
01999             case ENDDO_STMT:
02000             case BLOCK_ENTRY_STMT:
02001             case BLOCK_EXIT_STMT:
02002                 {
02003                     Statement *f = s.follow_ref();
02004 
02005                     /// ...  Deleting this statement will also delete its _follow,
02006                     /// ...  so mark that statement as already deleted.
02007 
02008                     if (f && stmt_list.member( *f ))
02009                         stmt_list.del( *f );
02010 
02011                     stmt_list.del( s );
02012 
02013                     this->del( s );
02014                 }
02015                 break;
02016 
02017             case IF_STMT:
02018             case ELSEIF_STMT:
02019             case ELSE_STMT:
02020             case ENDIF_STMT:
02021             case IMPLIED_GOTO_STMT:
02022                 {
02023                     /// ...  It's hard to tell if we have already deleted this because
02024                     /// ...  of another deletion, so we will be careful.
02025 
02026                     stmt_list.del( s );
02027 
02028                     if ( this->member( s ) )
02029                         this->del( s );
02030 
02031                 }
02032                 break;
02033 
02034             case LABEL_STMT:
02035                 /// ...  Don't do anything yet.  We will take care of LABEL stmts
02036                 /// ...  in a second pass.
02037                 break;
02038 
02039             default:
02040                 /// ...  A single statement so go ahead and delete it.
02041                 stmt_list.del( s );
02042                 p_assert( s.fingerprint_ok(), 
02043                           "oops, we already deleted this one");
02044                 this->del( s );
02045                 break;
02046             }
02047         }
02048     }
02049 
02050     /// ...  After all of the GOTO's have been removed we can safely remove the
02051     /// ...  LABELS which were the targets of the GOTO's
02052 
02053     for (iter.reset(); iter.valid(); ++iter) {
02054         if (iter.current_valid()) {
02055             Statement & s = iter.current();
02056 
02057             if (s.stmt_class() == LABEL_STMT) {
02058           _labels._grab_ref(s.value());
02059           stmt_list.del( s );
02060           this->del( s );
02061             }
02062         }
02063     }
02064 }
02065 
02066 void 
02067 StmtList::del(Statement &s)
02068 {
02069     RefSet<Statement> possible;
02070 
02071     switch (s.stmt_class()) {
02072     case ENDDO_STMT:
02073     case WHILE_STMT:            /// ...  delete WHILE and matching ENDDO
02074     case DO_STMT:               /// ...  delete DO and matching ENDDO
02075         {
02076             Statement *enddo, *do_stmt;
02077 
02078             if (s.stmt_class() == DO_STMT) {
02079                 enddo = s.follow_ref();
02080                 do_stmt = &s;
02081             }
02082             else if (s.stmt_class() == WHILE_STMT) {
02083                 enddo = s.follow_ref();
02084                 do_stmt = &s;
02085             }
02086             else {
02087                 enddo = &s;
02088                 do_stmt = s.follow_ref();
02089             }
02090 
02091             Statement      *block_begin = do_stmt->prev_ref();
02092             Statement      *block_end = enddo->next_ref();
02093 
02094         Iterator<Statement> iter = do_stmt->pred();
02095 
02096             for (  ; iter.valid(); ++iter)
02097                 if (&iter.current() != enddo)
02098                     possible.ins( iter.current() );
02099 
02100             for (iter = enddo->pred(); iter.valid(); ++iter)
02101                 if (&iter.current() != do_stmt)
02102                     possible.ins( iter.current() );
02103 
02104             do_stmt->del_flow( *this );
02105             _stmt_tag_dict->del(do_stmt->_tag);
02106 
02107             enddo->del_flow( *this );
02108             _stmt_tag_dict->del(enddo->_tag);
02109 
02110             List<Statement>::del(*enddo);
02111             List<Statement>::del(*do_stmt);
02112 
02113             block_begin = block_begin->next_ref();
02114 
02115             if (block_begin != block_end) {
02116                 block_end = block_end->prev_ref();
02117                 _set_block_structure(block_begin, block_end, "del_stmt");
02118             }
02119         }
02120         break;
02121 
02122     case BLOCK_ENTRY_STMT:
02123     case BLOCK_EXIT_STMT:
02124         {
02125             Statement *f = s.follow_ref();
02126 
02127             for (Iterator<Statement> iter = s.pred(); iter.valid(); ++iter)
02128                 possible.ins( iter.current() );
02129 
02130             s.del_flow( *this );
02131             _stmt_tag_dict->del(s._tag);
02132             List<Statement>::del(s);
02133 
02134             if (f != 0) {
02135                 for (Iterator<Statement> iter = f->pred(); iter.valid(); ++iter)
02136                     possible.ins( iter.current() );
02137 
02138                 f->del_flow( *this );
02139                 _stmt_tag_dict->del(f->_tag);
02140                 List<Statement>::del(*f);
02141             }
02142         }
02143         break;
02144 
02145     case IMPLIED_GOTO_STMT:
02146     case ENDIF_STMT:
02147         /// ...   can not delete an ENDIF_STMT or an IMPLIED_GOTO_STMT by itself
02148         /// ...   it must be deleted by removing it's controling statement.
02149         break;
02150 
02151     case ELSEIF_STMT:
02152     case ELSE_STMT:
02153         /// ...  Delete only the ELSE statement and fix up the links.
02154         {
02155             Statement *prev_if = s.lead_ref();
02156             Statement *next_pt = s.follow_ref();
02157             Statement *impl_gt = s.prev_ref();
02158 
02159             p_assert( impl_gt->stmt_class() == IMPLIED_GOTO_STMT, "not right" );
02160 
02161         Iterator<Statement> iter = s.pred();
02162 
02163             for ( ; iter.valid(); ++iter)
02164                 possible.ins( iter.current() );
02165 
02166             for ( iter = impl_gt->pred(); iter.valid(); ++iter)
02167                 possible.ins( iter.current() );
02168 
02169             s.del_flow( *this );
02170             _stmt_tag_dict->del(s._tag);
02171             List<Statement>::del(s);
02172 
02173             impl_gt->del_flow( *this );
02174             _stmt_tag_dict->del(impl_gt->_tag);
02175             List<Statement>::del(*impl_gt);
02176 
02177             switch (prev_if->stmt_class()) {
02178             case IF_STMT:
02179                 ((IfStmt *) prev_if)->_follow = next_pt;
02180                 break;
02181             case ELSEIF_STMT:
02182                 ((ElseIfStmt *) prev_if)->_follow = next_pt;
02183                 break;
02184             default:
02185                 p_abort("not an IF statement part");
02186             }
02187 
02188             switch (next_pt->stmt_class()) {
02189             case ELSE_STMT:
02190                 ((ElseStmt *) next_pt)->_lead = prev_if;
02191                 break;
02192             case ELSEIF_STMT:
02193                 ((ElseIfStmt *) next_pt)->_lead = prev_if;
02194                 break;
02195             case ENDIF_STMT:
02196                 ((EndIfStmt *) next_pt)->_lead = prev_if;
02197                 break;
02198             default:
02199                 p_abort("not an IF statement part");
02200             }
02201         }
02202         /// ...  don't need to reset block structure if this was done correctly
02203         break;
02204 
02205     case IF_STMT:
02206         /// ...  Delete the entire IF-ELSEIF-ELSE-ENDIF and IMPLIED_GOTOs
02207         {
02208             Statement *end_if = &s;  /// ...  Will be set to the final end_if
02209 
02210             while (end_if->stmt_class() != ENDIF_STMT) {
02211                 /// ...  Continue following the _follow pointers
02212                 /// ...  This annoying case statement could be replaced by
02213                 /// ...  protected virtual follow methods
02214                 switch (end_if->stmt_class()) {
02215                 case IF_STMT:
02216                     end_if = ((IfStmt *) end_if)->_follow;
02217                     break;
02218                 case ELSE_STMT:
02219                     end_if = ((ElseStmt *) end_if)->_follow;
02220                     break;
02221                 case ELSEIF_STMT:
02222                     end_if = ((ElseIfStmt *) end_if)->_follow;
02223                     break;
02224                 case IMPLIED_GOTO_STMT:
02225                     end_if = ((ImpliedGotoStmt *) end_if)->_follow;
02226                     break;
02227                 default:
02228                     p_abort("not an IF statement part");
02229                 }
02230             } /// ...  end_if is now the ENDIF_STMT
02231 
02232             /// ...  traverse if structure using if_stmt, deleting all parts 
02233             /// ...  (including IMPLIED_GOTO stmts).
02234 
02235             Statement      *if_part = ((EndIfStmt *) end_if)->_matching_if; 
02236             /// ...  part to be deleted
02237 
02238             Statement      *next_part = if_part->follow_ref();  
02239             /// ...  next part to be deleted
02240 
02241         Iterator<Statement> iter = if_part->pred(); 
02242 
02243             for ( ; iter.valid(); ++iter)
02244                 possible.ins( iter.current() );
02245 
02246             if_part->del_flow( *this );
02247             _stmt_tag_dict->del(if_part->_tag);
02248             List<Statement>::del(*if_part);
02249 
02250             while (next_part) {
02251                 p_assert(next_part->prev_ref()->stmt_class() == 
02252                          IMPLIED_GOTO_STMT, "not an IMPLIED_GOTO statement");
02253 
02254                 for (iter = next_part->prev_ref()->pred(); iter.valid(); ++iter)
02255                     if (&iter.current() != if_part)
02256                         possible.ins( iter.current() );
02257 
02258                 /// ...  delete IMPLIED_GOTO 
02259                 next_part->prev_ref()->del_flow( *this );
02260                 _stmt_tag_dict->del(next_part->prev_ref()->_tag);
02261                 List<Statement>::del(*(next_part->prev_ref()));   
02262 
02263                 if_part = next_part;
02264 
02265                 if (next_part->stmt_class() == ENDIF_STMT)
02266                     next_part = NULL;
02267                 else {
02268                     next_part = if_part->follow_ref();
02269                 }
02270 
02271                 if_part->del_flow( *this );
02272                 _stmt_tag_dict->del(if_part->_tag);
02273                 List<Statement>::del(*if_part);
02274             }
02275             /// ...  don't need to reset block structure if this was done correctly
02276         }
02277         break;
02278 
02279     case LABEL_STMT:
02280     _labels._grab_ref(s.value());
02281     /// ...  Fall through into default case
02282 
02283     default:
02284         {
02285             for (Iterator<Statement> iter = s.pred(); iter.valid(); ++iter)
02286                 possible.ins( iter.current() );
02287 
02288             s.del_flow( *this );
02289             _stmt_tag_dict->del(s._tag);
02290             List<Statement>::del(s);
02291 
02292             /// ...  Don't need to reset block structure
02293         }
02294         break;
02295     }
02296 
02297     for (Iterator<Statement> rs_iter = possible; rs_iter.valid(); ++rs_iter) {
02298         if (rs_iter.current_valid())
02299             rs_iter.current().fix_flow( *this );
02300         else {
02301             cout << "ERROR: invalid possible list" << endl;
02302         }
02303     }
02304 }
02305 
02306 void 
02307 StmtList::del(Statement & first_stmt, Statement & last_stmt)
02308 {
02309     RefSet<Statement> possible;
02310 
02311     /// ...  check if block is well-formed
02312 
02313     _set_block_structure(&first_stmt, &last_stmt, "del_block");
02314 
02315     Iterator<Statement> rs_iter = first_stmt.pred(); 
02316 
02317     for ( ;  rs_iter.valid(); ++rs_iter) {
02318         possible.ins( rs_iter.current() );
02319     }
02320 
02321     for (Iterator<Statement> iter = iterator(first_stmt, last_stmt);
02322                              iter.valid(); ++iter) {
02323         Statement &t = iter.current();
02324 
02325         if (possible.member(t)) 
02326             possible.del( t );
02327 
02328         t.del_flow( *this );
02329         _stmt_tag_dict->del( t._tag);
02330 
02331     if (t.stmt_class()==LABEL_STMT)
02332       _labels._grab_ref(t.value());
02333 
02334         List<Statement>::del( t );
02335     }
02336 
02337     for (rs_iter = possible; rs_iter.valid(); ++rs_iter) {
02338         if (rs_iter.current_valid())
02339             rs_iter.current().fix_flow( *this );
02340     }
02341 }
02342 
02343 void
02344 StmtList::clear()
02345 {
02346     List<Statement>::clear();
02347 
02348     if (_overflow) {
02349         delete _overflow;
02350         _overflow = 0;
02351     }
02352 
02353     _tag_count = 0;
02354 
02355     _stmt_tag_dict->clear();
02356      
02357     _labels._clear();
02358 }
02359 
02360 List<Statement> *
02361 StmtList::_copy_block(const Statement * first_stmt, 
02362               const Statement * last_stmt, 
02363               RE_LABEL relabel) const 
02364 {
02365     List<Statement> *copy = new List<Statement>;
02366 
02367     /// ...  Set of Statements which are prdecessors of LabelStmts
02368     RefSet<Statement> label_preds;
02369 
02370     /// ...  Database of "old labels --> new label stmts"
02371     RefDatabase<int, Statement> dict;
02372 
02373     /// ...  Database of any stmt which has a label for a target in the
02374     /// ...  block and the list of labels--reference with tags
02375     Database<String, VoidPtrDef> goto_stmts;
02376 
02377     Boolean whole_pgm_unit;
02378     
02379     whole_pgm_unit =
02380     (first_stmt->prev_ref() != 0) &&
02381     (last_stmt->next_ref() != 0) &&
02382     ((first_stmt->prev_ref()->stmt_class() == FLOW_ENTRY_STMT) &&
02383      (last_stmt->next_ref()->stmt_class() == FLOW_EXIT_STMT))
02384     ? True : False;
02385 
02386     /// ...  copy the block and create dictionary of LabelStmts
02387 
02388     int target_label = 0;
02389     int new_target_label;
02390 
02391     for (Iterator<Statement> iter = iterator(*first_stmt, *last_stmt);
02392                              iter.valid(); ++iter) {
02393         Statement      *newst;
02394 
02395     newst = iter.current().clone();
02396         
02397         /// ...  WARNING: this is a private member access!
02398         newst->modify_pred().clear();
02399         newst->modify_succ().clear();
02400 
02401         if (relabel) 
02402             newst->_tag = (CASTAWAY(StmtList *) this)->new_tag();
02403 
02404         copy->ins_last(newst);
02405 
02406         if (newst->stmt_class() == LABEL_STMT) {
02407             /// ...  hash LabelStmt copies on the original label number
02408             /// ...  and then create a new label
02409 
02410             dict.ins(newst->value(), *newst);
02411 
02412             if (relabel) {
02413           if (target_label)
02414         new_target_label = new_label(target_label);
02415           else
02416         new_target_label = new_label();
02417           newst->value( new_target_label );
02418           target_label = new_target_label + 1;
02419         }
02420         }
02421     }
02422     
02423     /// ...  Change target statements to the copy if the target is in the block
02424 
02425     for (Iterator<Statement> copyiter = *copy; copyiter.valid(); ++copyiter) {
02426         switch (copyiter.current().stmt_class()) {
02427         case READ_STMT:
02428         case WRITE_STMT:
02429         case PRINT_STMT:
02430         case OPEN_STMT:
02431         case CLOSE_STMT:
02432         case REWIND_STMT:
02433         case BACKSPACE_STMT:
02434         case ENDFILE_STMT:
02435         case INQUIRE_STMT:
02436             {
02437                 /// ...  look for s_controls which have implicit gotos
02438                 /// ...  to statement targets
02439 
02440                 for (Iterator<s_control_type> 
02441                         controls(copyiter.current().s_control_guarded());
02442                         controls.valid(); ++controls) {
02443 
02444                     if (controls.current().expr[0].op() == LABEL_OP) {
02445                         /// ...  This will be the label of an ERR= or END=
02446                         // I/O specifier.  Change target to copy of target.
02447 
02448                         Statement &t = controls.current().expr[0].stmt();
02449 
02450                         /// ...  Original target
02451                         Statement     *c;      /// ...  Copy of original target
02452 
02453                         if ((c = dict.find_ref(t.value())))
02454                             controls.current().expr[0].stmt(* c);
02455                     }
02456                 }
02457             }
02458             break;
02459         
02460         case ASSIGN_STMT:
02461             if (copyiter.current().atype() == EXECUTABLE_ASSIGN) {
02462                 Statement *ct;  /// ...  Copy of target
02463 
02464                 p_assert ( copyiter.current().target_ref(), 
02465                            "ASSIGN of executable label has null label value");
02466 
02467                 if ((ct=dict.find_ref(copyiter.current().target_ref()->value())))
02468                     copyiter.current().target(ct);
02469             }
02470             break;
02471 
02472         case GOTO_STMT:
02473             Statement * c;     /// ...  Copy of target
02474 
02475             p_assert(copyiter.current().target_ref(), "target is missing");
02476 
02477             if ((c = dict.find_ref(copyiter.current().target_ref()->value())))
02478                 copyiter.current().target(c);
02479 
02480             break;
02481             
02482         case ARITHMETIC_IF_STMT:
02483         case COMPUTED_GOTO_STMT:
02484         case ASSIGNED_GOTO_STMT:
02485             {
02486                 /// ...  to see how to use the goto_stmt dict, see Keith
02487                 
02488                 for (Mutator<Statement> labels=copyiter.current().label_list();
02489                                         labels.valid(); ++labels) {
02490                     Statement     *c;  /// ...  Copy of target
02491             
02492                     if ((c = dict.find_ref(labels.current().value()))) {
02493                         /// ...  Copy of LabelStmt exists, so replace 
02494                         /// ...  current() with copy
02495                         labels.modify(* c);
02496                     }
02497                 }
02498             }
02499             break;
02500     default: break;
02501         }
02502     } 
02503 
02504     return copy;
02505 }
02506 
02507 List<Statement> *
02508 StmtList::_extract_block(Statement * first_stmt, Statement * last_stmt, 
02509                          RE_LABEL relabel)
02510 {
02511     p_assert(first_stmt && last_stmt, "can not extract from NULL statement");
02512 
02513     List<Statement> *copy = new List<Statement>;
02514 
02515     /// ...  Set of Statements which are prdecessors of LabelStmts
02516     RefSet<Statement> label_preds;
02517 
02518     /// ...  Database of "old labels --> new label stmts"
02519     RefDatabase<int, Statement> dict;
02520 
02521     /// ...  Database of any stmt which has a label for a target in the
02522     /// ...  block and the list of labels--reference with tags
02523     Database<String, VoidPtrDef> goto_stmts;
02524 
02525     Boolean whole_pgm_unit;
02526     
02527     whole_pgm_unit =
02528     (first_stmt->prev_ref() != 0) &&
02529     (last_stmt->next_ref() != 0) &&
02530     ((first_stmt->prev_ref()->stmt_class() == FLOW_ENTRY_STMT) &&
02531      (last_stmt->next_ref()->stmt_class() == FLOW_EXIT_STMT))
02532     ? True : False;
02533 
02534     RefSet<Statement> preds = first_stmt->pred();
02535     RefList<Statement> stmts_in_block;
02536     
02537     /// ...  We are removing the block from the program, make sure it is
02538     /// ...  well formed.
02539 
02540     _set_block_structure(first_stmt, last_stmt, "grab_block");
02541 
02542     /// ...  Go through the stmts:
02543     /// ...  If it is a Stmt with a target list, must put it
02544     /// ...  in a (list of statement labels) dictionary
02545     /// ...  using tags from the labels.
02546     /// ...  This has to be done now, when we have guaranteed
02547     /// ...  availability of the statements (none have been grabbed)
02548 
02549     for (Iterator<Statement> iter = iterator(*first_stmt, *last_stmt);
02550      iter.valid(); ++iter) {
02551 
02552     /// ...  Collect all stmts in the block to-be-deleted
02553     stmts_in_block.ins_first(iter.current());
02554 
02555     switch (iter.current().stmt_class()) {
02556     case ARITHMETIC_IF_STMT: 
02557     case COMPUTED_GOTO_STMT:
02558     case ASSIGNED_GOTO_STMT:
02559         {
02560         List<IntElem> *intlist = new List<IntElem>;
02561 
02562         Iterator<Statement> label_iter 
02563             = iter.current().label_list();
02564 
02565         for ( ; label_iter.valid(); ++label_iter) 
02566             intlist->ins_last(
02567             new IntElem(label_iter.current().value()));
02568 
02569         goto_stmts.ins(iter.current().tag(), 
02570                    new VoidPtrDef("K", intlist));
02571         }
02572         break;
02573 
02574     case GOTO_STMT:
02575         {
02576         Statement *s = iter.current().target_ref();
02577 
02578         p_assert(s != 0 && s->stmt_class() == LABEL_STMT, 
02579              "not a LABEL statement");
02580 
02581         List<IntElem> *intlist = new List<IntElem>;
02582         
02583         intlist->ins_last(new IntElem(s->value()));
02584 
02585         goto_stmts.ins(iter.current().tag(), 
02586                    new VoidPtrDef("K", intlist));
02587         }
02588         break;
02589 
02590     case ASSIGN_STMT:
02591         {
02592         if (iter.current().atype() == EXECUTABLE_ASSIGN) {
02593             Statement *s = iter.current().target_ref();
02594 
02595             p_assert (s != 0 && s->stmt_class() == LABEL_STMT, 
02596                   "ASSIGN of executable label "
02597                   "has null label value" );
02598 
02599             List<IntElem> *intlist = new List<IntElem>;
02600             
02601             intlist->ins_last(new IntElem(s->value()));
02602 
02603             goto_stmts.ins(iter.current().tag(), 
02604                    new VoidPtrDef("K", intlist));
02605         }
02606         }
02607         break;
02608     default: break;
02609     }
02610     }
02611 
02612     /// ...  copy the block and create dictionary of LabelStmts
02613 
02614     int target_label = 0;
02615     int new_target_label;
02616 
02617     for (Iterator<Statement> iter = iterator(*first_stmt, *last_stmt);
02618                              iter.valid(); ++iter) {
02619     /// ...  Check to see whether each successor of this statement 
02620     /// ...  is in the block-to-be-deleted.  For those successors
02621     /// ...  which are not in the block, we have to remove this
02622     /// ...  statement from *their* predecessors list.
02623 
02624     for (Iterator<Statement> succ_iter = iter.current().succ();
02625          succ_iter.valid();
02626          ++succ_iter) {
02627         
02628         if (!(stmts_in_block.member(succ_iter.current()))) {
02629         succ_iter.current()._predecessors.del(iter.current());
02630         }
02631     }
02632 
02633         Statement      *newst;
02634 
02635     newst = List<Statement>::grab(iter.current());
02636 
02637     if (!whole_pgm_unit) {
02638         
02639         /// ...  Remove statement's tag from tag dictionary
02640             
02641         _stmt_tag_dict->del(newst->tag());
02642         
02643         /// ...  If it is a label stmt, put its predecessors into the
02644         /// ...  RefSet if they are the result of a goto
02645 
02646         if (newst->stmt_class() == LABEL_STMT) {
02647         _labels._grab_ref(newst->value());
02648         Iterator<Statement> pred_iter = newst->pred();
02649                 
02650         for ( ; pred_iter.valid(); ++pred_iter) {
02651             switch (pred_iter.current().stmt_class()) {
02652             case GOTO_STMT: 
02653             case ARITHMETIC_IF_STMT:
02654             case COMPUTED_GOTO_STMT: 
02655             case ASSIGNED_GOTO_STMT:
02656             label_preds.ins(pred_iter.current());
02657             default: break;
02658             }
02659         }
02660         }
02661     }
02662         
02663         /// ...  WARNING: this is a private member access!
02664         newst->modify_pred().clear();
02665         newst->modify_succ().clear();
02666 
02667         if (relabel) 
02668             newst->_tag = new_tag();
02669     
02670         copy->ins_last(newst);
02671 
02672         if (newst->stmt_class() == LABEL_STMT) {
02673             /// ...  hash LabelStmt copies on the original label number
02674             /// ...  and then create a new label
02675 
02676             dict.ins(newst->value(), *newst);
02677 
02678             if (relabel) {
02679         if (target_label)
02680             new_target_label = new_label(target_label);
02681         else
02682             new_target_label = new_label();
02683         newst->value( new_target_label );
02684         target_label = new_target_label + 1;
02685         }
02686         }
02687     }
02688 
02689     /// ...  Fix the flow graph for the original StmtList:
02690     
02691     /// ...      fix the flow graph for all the predecessors of the
02692     /// ...      first statement
02693     for (Iterator<Statement> preds_iter = preds;
02694      preds_iter.valid();
02695      ++preds_iter) {
02696     preds_iter.current().fix_flow(*this);
02697     }
02698 
02699     /// ...  it is an error to delete (grab) a label stmt refered to outside 
02700     /// ...  of the block
02701 
02702     if (!whole_pgm_unit) {
02703     for (Iterator<Statement> ipreds = label_preds; ipreds.valid(); ++ipreds) {
02704         /// ...  Check if label is the target of goto-type-stmt not in
02705         /// ...  the grabbed block
02706 
02707             Statement& cur_stmt=ipreds.current();
02708             String cur_tag=cur_stmt.tag();
02709             VoidPtrDef* vpd=goto_stmts.find_ref(cur_tag);
02710                 
02711         p_assert( vpd,
02712              "StmtList::grab(): A LabelStmt has been grabbed "
02713              "which is referenced outside the grabbed block.");
02714     }
02715     } else {  /// ...  Grabbing the whole program unit (didn't delete them before):
02716 
02717     _stmt_tag_dict->clear();
02718     _labels._clear();
02719     }
02720     
02721     /// ...  Change target statements to the copy if the target is in the block
02722     
02723     for (Iterator<Statement> copyiter = *copy; copyiter.valid(); ++copyiter) {
02724         switch (copyiter.current().stmt_class()) {
02725         case READ_STMT:
02726         case WRITE_STMT:
02727         case PRINT_STMT:
02728         case OPEN_STMT:
02729         case CLOSE_STMT:
02730         case REWIND_STMT:
02731         case BACKSPACE_STMT:
02732         case ENDFILE_STMT:
02733         case INQUIRE_STMT:
02734             {
02735                 /// ...  look for s_controls which have implicit gotos
02736                 /// ...  to statement targets
02737 
02738                 for (Iterator<s_control_type> 
02739                         controls(copyiter.current().s_control_guarded());
02740                         controls.valid(); ++controls) {
02741 
02742                     if (controls.current().expr[0].op() == LABEL_OP) {
02743                         /// ...  This will be the label of an ERR= or END=
02744                         // I/O specifier.  Change target to copy of target.
02745 
02746                         Statement &t = controls.current().expr[0].stmt();
02747 
02748                         /// ...  Original target
02749                         Statement     *c;      /// ...  Copy of original target
02750 
02751                         if ((c = dict.find_ref(t.value())))
02752                             controls.current().expr[0].stmt(* c);
02753                     }
02754                 }
02755             }
02756             break;
02757         
02758         case ASSIGN_STMT:
02759             if (copyiter.current().atype() == EXECUTABLE_ASSIGN) {
02760                 Statement *ct;  /// ...  Copy of target
02761 
02762                 p_assert ( copyiter.current().target_ref(), 
02763                            "ASSIGN of executable label has null label value");
02764 
02765                 if ((ct=dict.find_ref(copyiter.current().target_ref()->value())))
02766                     copyiter.current().target(ct);
02767             }
02768             break;
02769 
02770         case GOTO_STMT:
02771             Statement * c;     /// ...  Copy of target
02772 
02773             p_assert(copyiter.current().target_ref(), "target is missing");
02774 
02775             if ((c = dict.find_ref(copyiter.current().target_ref()->value())))
02776                 copyiter.current().target(c);
02777 
02778             break;
02779             
02780         case ARITHMETIC_IF_STMT:
02781         case COMPUTED_GOTO_STMT:
02782         case ASSIGNED_GOTO_STMT:
02783             {
02784                 /// ...  to see how to use the goto_stmt dict, see Keith
02785                 
02786                 for (Mutator<Statement> labels=copyiter.current().label_list();
02787                                         labels.valid(); ++labels) {
02788                     Statement     *c;  /// ...  Copy of target
02789 
02790                     if ((c = dict.find_ref(labels.current().value()))) {
02791                         /// ...  Copy of LabelStmt exists, so replace 
02792                         /// ...  current() with copy
02793                         labels.modify(* c);
02794                     }
02795                 }
02796             }
02797             break;
02798     default: break;
02799         }
02800     } 
02801     
02802     return copy;
02803 }
02804 
02805 List<Statement> *
02806 StmtList::copy(const Statement & first_stmt,
02807                const Statement & last_stmt,
02808                RE_LABEL relabel GIV(RELABEL)) const
02809 {
02810     return (_copy_block(&first_stmt, &last_stmt, relabel));
02811 }
02812 
02813 List<Statement> *
02814 StmtList::grab(Statement & first_stmt,
02815                Statement & last_stmt,
02816                RE_LABEL relabel GIV(RELABEL))
02817 {
02818     return _extract_block(&first_stmt, &last_stmt, relabel);
02819 }
02820 
02821 
02822 Statement *
02823 StmtList::grab(int loc)
02824 {
02825     return grab((*this)[loc]);
02826 }
02827 
02828 Statement *
02829 StmtList::grab(Statement & stmt)
02830 {
02831     List<Statement> *one = _extract_block(&stmt, &stmt, RELABEL);
02832 
02833     Statement *stmt_ptr = one->grab(0);
02834 
02835     delete one;
02836 
02837     return stmt_ptr;
02838 }
02839 
02840 void
02841 StmtList::modify(Statement & stmt, Statement * replacement)
02842 {
02843     ins_after(replacement,  &stmt);
02844     del(stmt);
02845 }
02846 
02847 void
02848 StmtList::modify(int loc, Statement * replacement)
02849 {
02850     modify((*this)[loc], replacement);
02851 }
02852 
02853 Statement *
02854 StmtList::modify_and_grab(Statement & stmt, Statement * replacement)
02855 {
02856     ins_after(replacement,  &stmt);
02857     return grab(stmt);
02858 }
02859 
02860 /// Procedure passed to sub-list iterator to check Statement
02861 /// against a single statement type
02862 
02863 int 
02864 check_type(void *st, void *stmt_type)
02865 {
02866 /// silvius: avoid memory leak, as class BaseIter does not 
02867 /// delete the extra info it is given in the constructor (see stmts_of_type)
02868   int vp2i=(int)stmt_type;
02869   STMT_TYPE i2e=(STMT_TYPE) vp2i;
02870     return (((Statement *) st)->stmt_class() == i2e);
02871 }
02872 
02873 Iterator<Statement>
02874 StmtList::stmts_of_type(STMT_TYPE type) const
02875 {
02876 /// silvius: avoid memory leak, as class BaseIter does not 
02877 ///     STMT_TYPE      *holdtype = new STMT_TYPE;
02878 
02879 ///     *holdtype = type;
02880 
02881     Iterator<Statement> iter(CASTAWAY(StmtList &) *this,
02882                                 (cond_proc) check_type, (void*)type);
02883 
02884     return iter;
02885 }
02886 
02887 struct five_types {
02888     STMT_TYPE       t1, t2, t3, t4, t5;
02889 };
02890 
02891 int 
02892 check_five_types(void *stmt, void *types)
02893 {
02894     five_types     *ft = (five_types *) types;
02895     Statement      *st = (Statement *) stmt;
02896 
02897     return ((st->stmt_class() == ft->t1) || (st->stmt_class() == ft->t2) ||
02898             (st->stmt_class() == ft->t3) || (st->stmt_class() == ft->t4) ||
02899             (st->stmt_class() == ft->t5));
02900 }
02901 
02902 Iterator<Statement>
02903 StmtList::stmts_of_type( STMT_TYPE type1, STMT_TYPE type2,
02904                          STMT_TYPE type3 GIV(UNDEFINED_STMT),
02905                          STMT_TYPE type4 GIV(UNDEFINED_STMT),
02906                          STMT_TYPE type5 GIV(UNDEFINED_STMT)) const
02907 {
02908     five_types     *types = new five_types;
02909 
02910     types->t1 = type1;
02911     types->t2 = type2;
02912     types->t3 = type3;
02913     types->t4 = type4;
02914     types->t5 = type5;
02915 
02916     Iterator<Statement> iter((StmtList&) *this,
02917                                 (cond_proc)check_five_types, types);
02918 
02919     return iter;
02920 }
02921 
02922 Boolean
02923 StmtList::contains_DO ( Statement & st )
02924 {
02925     p_assert( st.stmt_class() == DO_STMT, "Given statement is not a DO");
02926 
02927     Iterator<Statement> b_iter = iterate_loop_body( &st );
02928 
02929     if (b_iter.valid()) {
02930     ++b_iter;         /// ...  Bypass the initial DO header
02931     for (;
02932         b_iter.valid();
02933          ++b_iter) {
02934         if (b_iter.current().stmt_class() == DO_STMT) {
02935         return True;
02936         }
02937     }
02938     }
02939 
02940     return False;
02941 }
02942 
02943 /// Return the number of statements in a loop, whose header is "st"
02944 int
02945 StmtList::number_of_stmts_in_DO ( Statement & st )
02946 {
02947     p_assert( st.stmt_class() == DO_STMT, "Given statement is not a DO");
02948 
02949     int stmt_count = 0;
02950     
02951     /// ...  Count the DO headers, but not the END_DOs
02952     
02953     for (Iterator<Statement> b_iter = iterate_loop_body( &st );
02954      b_iter.valid();
02955      ++b_iter) {
02956     switch (b_iter.current().stmt_class())
02957         {
02958         case ENDDO_STMT:
02959         case IMPLIED_GOTO_STMT:
02960         case ENDIF_STMT:
02961         case ELSE_STMT:
02962         case FLOW_ENTRY_STMT:
02963         case FLOW_EXIT_STMT:
02964         case BLOCK_ENTRY_STMT:
02965         case BLOCK_EXIT_STMT:
02966         case ENTRY_STMT:
02967         case LABEL_STMT:
02968         break;
02969         default:
02970         stmt_count++;
02971         }
02972     }
02973     return stmt_count;
02974 }
02975 
02976 Iterator<Statement>
02977 StmtList::iterate_loop_body(const Statement * do_stmt) const
02978 {
02979     if (do_stmt && (do_stmt->stmt_class() == DO_STMT)) {
02980     } else {
02981     do_stmt->print(cout);
02982     p_abort( "not a loop" );
02983     }
02984     /// ...  p_assert(do_stmt && (do_stmt->stmt_class() == DO_STMT), "not a loop");
02985 
02986     Iterator<Statement> iter(CASTAWAY(StmtList &) *this, do_stmt, 
02987                              do_stmt->follow_ref());
02988 
02989     return iter;
02990 }
02991 
02992 Iterator<Statement>
02993 StmtList::iterate_entry_points() const
02994 {
02995     Iterator<Statement> entry_stmts = stmts_of_type(ENTRY_STMT);
02996 
02997     if (entry_stmts.valid()) {
02998         /// ...  There are ENTRY statements -- they alone are the entry points
02999         return entry_stmts;
03000     }
03001 
03002     /// ...  There's no entry statement -- the FLOW_ENTRY statement is
03003     /// ...  then the only legal entry point
03004 
03005     return stmts_of_type(FLOW_ENTRY_STMT);
03006 }
03007 
03008 Iterator<Statement>
03009 StmtList::iterator(const Statement &first_stmt, 
03010                   const Statement &last_stmt) const
03011 {
03012     Iterator<Statement> iter(  CASTAWAY(StmtList &) *this, 
03013                              &(CASTAWAY(Statement &)first_stmt),
03014                              &(CASTAWAY(Statement &)last_stmt));
03015 
03016     return iter;
03017 }
03018 
03019 
03020 /// Build the in/out/act _refs sets for each Statement in the StmtList
03021 
03022 
03023 void
03024 StmtList::build_all_refs()
03025 {
03026     Iterator<Statement> iter = iterator();
03027 
03028     for (iter.reset(); iter.valid(); ++iter) 
03029         iter.current().build_refs();
03030 }
03031 
03032 
03033 /// Erase any existing flowgraph from the StmtList and rebuild it.  This might
03034 /// be useful when a program is read in from an external source.
03035 
03036 
03037 void
03038 StmtList::create_flow_graph()
03039 {
03040     /// ...  First remove any existing flow graph
03041     delete_flow_graph();
03042 
03043     Iterator<Statement>iter = iterator();
03044 
03045     /// ...  (Re)Build the flow graph
03046     for (  ; iter.valid(); ++iter)
03047         iter.current().fix_flow(*this);
03048 }
03049 
03050 
03051 
03052 /// Erase any existing flowgraph from the StmtList.
03053 
03054 
03055 void
03056 StmtList::delete_flow_graph()
03057 {
03058     Iterator<Statement>iter = iterator();
03059 
03060     for (  ; iter.valid(); ++iter) {
03061         /// ...  WARNING: this is a private member access!
03062         iter.current().modify_succ().clear();
03063         iter.current().modify_pred().clear();
03064     }
03065 }
03066 
03067 
03068 
03069 /// 
03070 /// 
03071 
03072 
03073 int
03074 StmtList::_all_statement_structures_OK() const
03075 {
03076     int OK = 1;
03077     
03078     for (Iterator<Statement> iter = iterator(); iter.valid(); ++iter) 
03079         if (! iter.current().structures_OK()) 
03080             OK = 0;
03081 
03082     return OK;
03083 }
03084     
03085 int  
03086 StmtList::_flow_graph_structures_OK() const
03087 {
03088     Iterator<Statement> li = iterator();
03089 
03090     for (li.reset(); li.valid(); ++li) {
03091         RefSet<Statement> *new_succ = li.current().build_succ( *this );
03092 
03093         /// ...  Is the current succ() list equal to the correct succ() list??
03094 
03095         if (new_succ->entries() != li.current().succ().entries()) {
03096             cerr << "In context FlowGraph: succ() different size!\n" << endl;
03097             cerr << li.current() << endl;
03098             delete new_succ;
03099             return 0;
03100         }
03101 
03102     Iterator<Statement> iter_a = li.current().succ();
03103 
03104         for (  ; iter_a.valid(); ++iter_a) {
03105             if (! new_succ->member( iter_a.current() )) {
03106                 cerr << "In context FlowGraph: succ() different!\n" << endl;
03107                 cerr << li.current() << endl;
03108                 delete new_succ;
03109                 return 0;
03110             }
03111         }
03112 
03113         /// ...  Do all the succ()'s have a valid pred() ??
03114 
03115         for (iter_a = li.current().succ(); iter_a.valid(); ++iter_a) {
03116             if (! iter_a.current().pred().member( li.current() )) {
03117                 cerr << "In context FlowGraph: invalid pred()!\n";
03118                 cerr << "  all succ()'s don't have valid pred()'s\n" << endl;
03119                 cerr << li.current() << endl;
03120                 return 0;
03121             }
03122         }
03123 
03124         /// ...  Do all the pred()'s have a valid succ() ??
03125 
03126         for (iter_a = li.current().pred(); iter_a.valid(); ++iter_a) {
03127             if (! iter_a.current().succ().member( li.current() )) {
03128                 cerr << "In context FlowGraph: invalid pred()!\n" << endl;
03129                 cerr << "  all pred()'s don't have valid succ()'s\n" << endl;
03130                 cerr << li.current() << endl;
03131                 return 0;
03132             }
03133         }
03134     }
03135 
03136     return 1;
03137 }
03138 
03139 void
03140 StmtList::create_directives()
03141 {
03142     Iterator<Statement> iter = iterator();
03143     DirectiveType       dt = (enum DirectiveType) switch_value("output_lang");
03144     
03145     for (; iter.valid(); ++iter) {
03146         if (iter.current().assertions().entries() > 0) {
03147             Directive dir(iter.current().assertions(), dt);
03148             dir.generate( iter.current() );
03149         }
03150     }
03151 }
03152 
03153 void
03154 StmtList::remove_directives()
03155 {
03156     Iterator<Statement> iter = iterator();
03157 
03158     for (; iter.valid(); ++iter) {
03159         iter.current().pre_directives().clear();
03160         iter.current().post_directives().clear();
03161     }
03162 }
03163 
03164 
03165 void
03166 StmtList::display(ostream & o) const
03167 {
03168     for (Iterator<Statement> siter = iterator(); siter.valid(); ++siter)
03169         o << siter.current();
03170 }
03171 
03172 void
03173 StmtList::write(ostream & o) const
03174 {
03175     (CASTAWAY(StmtList *) this)->create_directives();
03176 
03177     print_stmt_list(o, *this);
03178 
03179     (CASTAWAY(StmtList *) this)->remove_directives();
03180 }
03181 
03182 void
03183 StmtList::print(ostream & o) const
03184 {
03185     display(o);
03186 }
03187 
03188 int
03189 StmtList::structures_OK() const
03190 {
03191     if (   ! _list.structures_OK()
03192         || ! _flow_graph_structures_OK()
03193         || ! _all_statement_structures_OK()
03194        )
03195    {
03196        cerr << "\n\n**** Error found in structure of StmtList:" << flush
03197             << endl;
03198        display(cerr);
03199        
03200        cerr << endl << endl;
03201 
03202        return 0;
03203     }
03204 
03205     return 1;
03206 }
03207         
03208 /// Change the label of a statement with the list from value to new_value
03209 
03210 void
03211 StmtList::relabel(const int value, const int new_value)
03212 {
03213 /// Find existing label statement in data base
03214 
03215   LabelStmt * label_stmt_ref = (LabelStmt *) _labels._grab_ref(value);
03216   p_assert (label_stmt_ref,
03217         "StmtList::relabel: label not found");
03218 
03219 /// WARNING: this is a private member access!
03220 
03221   label_stmt_ref->_value = new_value;
03222 
03223 /// Insert new label into database (failing if it is a duplicate)
03224 
03225   _ins_label_stmt(*label_stmt_ref);
03226 }
03227 
03228 /// PROGRAM UNIT --------------------------------------------------------
03229 
03230 /// Insert label into label database
03231 
03232 void
03233 StmtList::_ins_label_stmt(Statement & new_stmt)
03234 {
03235   int value = new_stmt.value();
03236 
03237 /// Check for duplicates (if not program build)
03238 
03239   if (_pgm) {
03240 
03241     /// ...  Check for duplicate label
03242 
03243     p_assert( !_labels.member(value),
03244           "StmtList: found duplicate label statement");
03245 
03246     /// ...  Check for duplicate format
03247     
03248     p_assert( ! _pgm->formats().find_ref(value),
03249           "StmtList: found duplicate format statement");
03250 
03251   }
03252 
03253 /// Insert label into label database
03254 
03255   _labels._ins(new_stmt);
03256 }
03257 
03258 /// Return a new value for a LabelStmt or Format
03259 
03260 int  
03261 StmtList::new_label( int target GIV(0) ) const
03262 {
03263     p_assert(_pgm, "StmtList::new_label(int ): Method cannot be called unless "
03264              "StmtList is within a ProgramUnit.  Can't resolve Formats.");
03265     
03266     int target_label;
03267 
03268     /// ...  Set target for label scan
03269 
03270     if (target)
03271       target_label = target;
03272     else {
03273       int last_label = _labels.last_ref();
03274 
03275       if (last_label < 99999)
03276     target_label = last_label + 1;
03277       else
03278     target_label = 1;
03279     }
03280 
03281     /// ...  Scan through labels in LabelDB and FormatDB looking for
03282     /// ...  an unassigned one
03283 
03284     while (_labels.member(target_label) ||
03285        _pgm->formats().find_ref(target_label)) {
03286       ++target_label;
03287       if (target_label > 99999)
03288     target_label = 1;
03289     }
03290 
03291     return target_label;
03292 
03293 }
03294 
03295 void
03296 StmtList::create_assertions()
03297 {
03298     p_assert(_pgm, "StmtList::create_assertions: method cannot be called "
03299              "unless StmtList belongs to a ProgramUnit.");
03300     
03301     Iterator<Statement> iter = iterator();
03302 
03303     for (; iter.valid(); ++iter) {
03304         List<StringElem> &pre  = iter.current().pre_directives();
03305 
03306         if (pre.entries() > 0) {
03307             Statement *s_prev = iter.current().prev_ref();
03308             Statement *s_next = &iter.current();
03309         
03310             parse_directives(pre, *_pgm, s_prev, s_next);
03311 
03312             pre.clear();
03313         }
03314 
03315         List<StringElem> &post = iter.current().post_directives();
03316 
03317         if (post.entries() > 0) {
03318             Statement *s_prev = &iter.current();
03319             Statement *s_next = iter.current().next_ref();
03320 
03321             parse_directives(post, *_pgm, s_prev, s_next);
03322 
03323             post.clear();
03324         }
03325     }
03326 
03327     _set_block_structure( first_ref(), last_ref(), "create_assertions" );
03328 }
03329 
03330 void
03331 StmtList::split_elseif( Statement & s )
03332 {
03333     p_assert( s.stmt_class() == ELSEIF_STMT, "not an ELSEIF statement" );
03334 
03335     /// ...  What is the outermost ENDIF at the end of this block.
03336     Statement *outer_endif = s.follow_ref();
03337 
03338     while (outer_endif->stmt_class() != ENDIF_STMT)
03339         outer_endif = outer_endif->follow_ref();
03340 
03341     /// ...  What is the outmost IF at the begining of this block.
03342     Statement *outer_if = outer_endif->matching_if_ref();
03343 
03344     /// ...  What is the IF compoment immediately prior to the ELSEIF.
03345     Statement *prev_if   = s.lead_ref();
03346 
03347     IfStmt          *new_if    = new IfStmt(new_tag());
03348     ElseStmt        *new_else  = new ElseStmt(new_tag());
03349     EndIfStmt       *new_endif = new EndIfStmt(new_tag());
03350     ImpliedGotoStmt *new_imp   = new ImpliedGotoStmt(new_tag());
03351 
03352     new_if->expr( s.expr().clone() );
03353     new_if->build_refs();
03354     new_if->_follow = new_endif;
03355 
03356     new_else->_follow = outer_endif;
03357 
03358     new_imp->_follow = new_endif;
03359 
03360     if (prev_if->stmt_class() == IF_STMT)
03361         ((IfStmt *) prev_if)->_follow = new_else;
03362     else if (prev_if->stmt_class() == ELSEIF_STMT)
03363         ((ElseIfStmt *) prev_if)->_follow = new_else;
03364 
03365     _stmt_tag_dict->ins(new VoidPtrDef(new_else->_tag, new_else));
03366     _stmt_tag_dict->ins(new VoidPtrDef(new_if->_tag, new_if));
03367 
03368     List<Statement>::ins_after( new_else, &s );
03369     List<Statement>::ins_after( new_if,   new_else );
03370 
03371     _stmt_tag_dict->ins(new VoidPtrDef(new_endif->_tag, new_endif));
03372     _stmt_tag_dict->ins(new VoidPtrDef(new_imp->_tag, new_imp));
03373 
03374     List<Statement>::ins_before( new_endif, outer_endif->prev_ref() );
03375     List<Statement>::ins_before( new_imp, new_endif );
03376 
03377     _stmt_tag_dict->del(s._tag);
03378     List<Statement>::del( s );
03379 
03380     _set_block_structure( outer_if, outer_endif, "split_elseif" );
03381 
03382     Iterator<Statement> rs_iter = iterator(*outer_if, *outer_endif);
03383     p_assert(rs_iter.valid() && &rs_iter.current() == outer_if,
03384          "The first Statement must be IF_STMT");
03385     rs_iter.current().modify_succ().clear();  /// ...  do not delete predecessor
03386     for (++rs_iter; rs_iter.valid(); ++rs_iter) {
03387         rs_iter.current().modify_succ().clear();
03388         rs_iter.current().modify_pred().clear();
03389     }
03390 
03391     for (rs_iter.reset(); rs_iter.valid(); ++rs_iter)
03392         rs_iter.current().fix_flow( *this );
03393 }
03394 
03395 void
03396 StmtList::exchange_convert( VDL &vdl )
03397 {
03398     BinRep  *b = CASTAWAY(BinRep *) vdl.data_ref();
03399 
03400     if (b != 0) {
03401         List<BinRep> *L  = new List<BinRep>;
03402         BinRep       *bs;
03403 
03404         bs = new BinRep;
03405         bs->put_string( "statements" );
03406         L->ins_last( bs );
03407 
03408         bs = new BinRep;
03409         bs->put_set( new Set<BinRep> );
03410         L->ins_last( bs );
03411 
03412         BinRep *br = new BinRep;
03413         br->put_tuple( L );
03414         b->to_set().ins( br );
03415     }
03416 
03417     if (first_ref() != 0) {
03418         List<BinRep> *L  = new List<BinRep>;
03419         BinRep       *bs;
03420 
03421         bs = new BinRep;
03422         bs->put_string( "initial_statement" );
03423         L->ins_last( bs );
03424 
03425         bs = new BinRep;
03426         bs->put_string( first_ref()->tag() );
03427         L->ins_last( bs );
03428 
03429         BinRep *br = new BinRep;
03430         br->put_tuple( L );
03431         b->to_set().ins( br );
03432     }
03433 
03434     if (last_ref() != 0) {
03435         List<BinRep> *L  = new List<BinRep>;
03436         BinRep       *bs;
03437 
03438         bs = new BinRep;
03439         bs->put_string( "final_statement" );
03440         L->ins_last( bs );
03441 
03442         bs = new BinRep;
03443         bs->put_string( last_ref()->tag() );
03444         L->ins_last( bs );
03445 
03446         BinRep *br = new BinRep;
03447         br->put_tuple( L );
03448         b->to_set().ins( br );
03449     }
03450 
03451     for (Iterator<Statement> iter = iterator(); iter.valid(); ++iter) 
03452         iter.current().exchange_convert( vdl );
03453 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:13 2005