001: /*
002: * Bytecode Analysis Framework
003: * Copyright (C) 2003,2004 University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.ba.bcp;
021:
022: /**
023: * A ByteCodePattern is a pattern matching a sequence of bytecode instructions.
024: *
025: * @author David Hovemeyer
026: * @see PatternElement
027: * @see PatternMatcher
028: */
029: public class ByteCodePattern {
030: private PatternElement first, last;
031: private int interElementWild;
032: private int numElements;
033: private int dummyVariableCount;
034:
035: /**
036: * Add a PatternElement to the end of the pattern.
037: *
038: * @param element the PatternElement
039: * @return this object
040: */
041: public ByteCodePattern add(PatternElement element) {
042: if (first != null)
043: addInterElementWild();
044: addElement(element);
045: return this ;
046: }
047:
048: /**
049: * Add a wildcard to match between 0 and given number of instructions.
050: * If there is already a wildcard at the end of the current pattern,
051: * resets its max value to that given.
052: *
053: * @param numWild maximum number of instructions to be matched by
054: * the wildcard
055: */
056: public ByteCodePattern addWild(int numWild) {
057: Wild wild = isLastWild();
058: if (wild != null)
059: wild.setMinAndMax(0, numWild);
060: else
061: addElement(new Wild(numWild));
062: return this ;
063: }
064:
065: /**
066: * Set number of inter-element wildcards to create between
067: * explicit PatternElements. By default, no implicit wildcards
068: * are created.
069: *
070: * @param numWild the number of wildcard instructions which
071: * may be matched between explicit PatternElements
072: * @return this object
073: */
074: public ByteCodePattern setInterElementWild(int numWild) {
075: this .interElementWild = numWild;
076: return this ;
077: }
078:
079: /**
080: * Get the first PatternElement in the pattern.
081: */
082: public PatternElement getFirst() {
083: return first;
084: }
085:
086: /**
087: * Get a dummy variable name.
088: * The name returned will begin with the <code>'$'</code> character,
089: * and will be different than any previous dummy variable name allocated
090: * by this object. Dummy variable names are useful for creating
091: * PatternElements where you don't care whether the value it uses
092: * is the same as one used by another PatternElement.
093: */
094: public String dummyVariable() {
095: StringBuffer buf = new StringBuffer();
096: buf.append("$_");
097: buf.append(dummyVariableCount++);
098: return buf.toString();
099: }
100:
101: private void addInterElementWild() {
102: if (interElementWild > 0 && isLastWild() == null)
103: addElement(new Wild(interElementWild));
104: }
105:
106: private void addElement(PatternElement element) {
107: element.setIndex(numElements++);
108: if (first == null) {
109: first = last = element;
110: } else {
111: last.setNext(element);
112: last = element;
113: }
114: }
115:
116: private Wild isLastWild() {
117: if (last != null && last instanceof Wild)
118: return (Wild) last;
119: else
120: return null;
121: }
122: }
123:
124: // vim:ts=4
|