1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xalan.internal.xsltc.compiler;
  22 
  23 import com.sun.org.apache.bcel.internal.generic.BranchHandle;
  24 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
  25 import com.sun.org.apache.bcel.internal.generic.InstructionList;
  26 import java.util.ArrayList;
  27 import java.util.Iterator;
  28 import java.util.List;
  29 
  30 /**
  31  * @author Jacek Ambroziak
  32  * @author Santiago Pericas-Geertsen
  33  * @LastModified: Oct 2017
  34  */
  35 public final class FlowList {
  36     private List<InstructionHandle> _elements;
  37 
  38     public FlowList() {
  39         _elements = null;
  40     }
  41 
  42     public FlowList(InstructionHandle bh) {
  43         _elements = new ArrayList<>();
  44         _elements.add(bh);
  45     }
  46 
  47     public FlowList(FlowList list) {
  48         _elements = list._elements;
  49     }
  50 
  51     public FlowList add(InstructionHandle bh) {
  52         if (_elements == null) {
  53             _elements = new ArrayList<>();
  54         }
  55         _elements.add(bh);
  56         return this;
  57     }
  58 
  59     public FlowList append(FlowList right) {
  60         if (_elements == null) {
  61             _elements = right._elements;
  62         }
  63         else {
  64             final List<InstructionHandle> temp = right._elements;
  65             if (temp != null) {
  66                 final int n = temp.size();
  67                 for (int i = 0; i < n; i++) {
  68                     _elements.add(temp.get(i));
  69                 }
  70             }
  71         }
  72         return this;
  73     }
  74 
  75     /**
  76      * Back patch a flow list. All instruction handles must be branch handles.
  77      */
  78     public void backPatch(InstructionHandle target) {
  79         if (_elements != null) {
  80             final int n = _elements.size();
  81             for (int i = 0; i < n; i++) {
  82                 BranchHandle bh = (BranchHandle)_elements.get(i);
  83                 bh.setTarget(target);
  84             }
  85             _elements.clear();          // avoid backpatching more than once
  86         }
  87     }
  88 
  89     /**
  90      * Redirect the handles from oldList to newList. "This" flow list
  91      * is assumed to be relative to oldList.
  92      */
  93     public FlowList copyAndRedirect(InstructionList oldList,
  94         InstructionList newList)
  95     {
  96         final FlowList result = new FlowList();
  97         if (_elements == null) {
  98             return result;
  99         }
 100 
 101         final int n = _elements.size();
 102         final Iterator<InstructionHandle> oldIter = oldList.iterator();
 103         final Iterator<InstructionHandle> newIter = newList.iterator();
 104 
 105         while (oldIter.hasNext()) {
 106             final InstructionHandle oldIh = oldIter.next();
 107             final InstructionHandle newIh = newIter.next();
 108 
 109             for (int i = 0; i < n; i++) {
 110                 if (_elements.get(i) == oldIh) {
 111                     result.add(newIh);
 112                 }
 113             }
 114         }
 115         return result;
 116     }
 117 }