A Feasibility Study of Loop Bound Analysis for Loops with Disjunctive Guards Nick Gubbels Student Number: 0710288 [email protected]Master Thesis Computer Science Thesis Number: 666 November 2012 Supervisors: Prof. dr. Marko van Eekelen Rody Kersten MSc Dr. Sjaak Smetsers (Reader)
142
Embed
A Feasibility Study of Loop Bound Analysis for Loops with ...
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
A Feasibility Study of Loop BoundAnalysis for Loops with Disjunctive
In software engineering a program needs to do what it is supposed to do. Toensure this, software should be tested thoroughly. However, for safety-critical,real-time and embedded systems, more aspects of software have to be consideredin order to be sure the software is correct. A small bug in the program couldlead to fatal situations, e.g. if the software of an air plane reach an error state.
Testing gives insight in what the output will be for given input, but onlyfor the input which is used in the test cases. To get information about morecases, a model of the program can be created and tested for some properties.This is called Model-based testing or model checking and it gives informationover larger sets of input/output. However, in the case of safety critical softwaresystems, it is even desirable to have proofs of certain properties.Tthis is doneby theorem proving. Even though theorem proving is most desirable, it takesmore effort than model checking, which by itself takes more effort than testing.For this reason most software systems are only tested.
Additionally, testing only addresses the functional aspects of the software,i.e. does the software do what it is supposed to do given this input? However,in the case of safety-critical, real-time and embedded systems, the resources ofthe system are most likely to be limited; such systems are in general scarceof memory and processing power. It is important that the software of thosesystems does not exceed the boundaries of its resources, since that could leadto a system crash.
Therefore, it is important to test the system’s use of the resources, or more-over even prove that the system does not exceed its boundaries. This is calledresource analysis. One such analysis is Loop Bound Analysis, which focuses onthe number of iterations of a given loop and tries to infer an upper bound forthat. This information gives insight in the processing time used by the program.Furthermore, it can be used as a base for a termination proof, since if a loophas an upper bound in the number of iterations, it will not iterate infinite manytimes.
In the following sections a few projects on resource analysis are described.
1
2 CHAPTER 1. INTRODUCTION
1.1 AHA project
Amortised Heap Analysis (AHA) project (as described in [32]) was a projectwhich focused on heap consumption. The target of the project was to developa method to infer non-linear bounds on the heap consumption of a (lazy) func-tional language.
In [30], [33], [29], [31] and [28] Shkaravska et al. describe a method for sizeanalysis. This method introduces a type system with size annotations. Forexample, consider the following function type:
Ln Lm → Ln+m
This represents a function, which has two lists as input, which contain n andm elements respectively. The result is a list of size n+m. This type is typicalfor an append function.
The type system with size annotations has been created for a small functionallanguage presented in [30, 33, 29, 31, 28]. The size analysis method consists oftwo parts: type inference and type checking. Note that a type in this contextcontains the size in the number of elements. For type inference the authorsdescribe a method using testing and polynomial interpolation. To infer the typeof some functions, test nodes with known types are created and the functionsare executed for those test nodes. Then the results of the functions are used toinfer a polynomial, which specifies the type of the function.
Since the method above depends on the selection of test nodes, the methodis not sound. Therefore, a type checking method is developed by the authors.They specify formal rules for type checking with size annotations of programs inthe functional language presented in [30, 33, 29, 31, 28]. These rules constructa formal derivation tree, which is a proof of the types and sizes of the functions.
1.2 CHARTER project
The CHARTER (Critical and High Assurance Requirements Transformed throughEngineering Rigour) project 1 was an ARTEMIS Embedded Computing Sys-tems Initiative project. The target of the project was to develop concepts,methods and tools to assist developers of critical systems to improve the devel-opment, verification and certification of software.
Results of the project vary from theoretical methods to fully usable toolsfor both development and verification of software. JamaicaVM, for example,is one of the development tools. It is a Java virtual machine implementationdeveloped by Aicas especially designed for real-time software 2 and can be usedto run and compile Java software. Verification tools are for example ResAna andKeY, which are explained in more depth in the following sections.
The contribution of the Radboud University in the CHARTER project con-sisted of two parts: 1) develop a method for resource analysis and 2) to createa formal specification of Real-Time Java Libraries. The first will be explainedin more detail in the following sections.
1For more information: http://charterproject.ning.com/2For more information, see http://www.aicas.com/jamaica.html
One of the results of the CHARTER project is the ResAna tool, as presentedby Kersten et al. in [20]. The ResAna tool consists of various resource analysismethods, e.g. heap/stack size analysis and Loop Bound Analysis. For the heapand stack size analysis, it makes use of a tool called COSTA (COst and Termi-nation Analyser) to extract the heap size and another tool Veriflux to extractstack size. Veriflux is an industrial tool by Aicas and is like ResAna part of theCHARTER Project. Veriflux is an automatic static code analysis tool.
The method behind COSTA is described in an article by Albert et al. [3].The method analyses Java byte code to extract certain properties, e.g. it doescost analysis given various cost models. One of such models is the heap costmodel, i.e. what is an upper bound for the size of the heap given a piece ofcode? Another cost model is the number of instructions, this is a model onexecution length of a piece of code, i.e. what is an upper bound on the numberof instructions executed. In combination with the cost analysis, the tool triesto prove termination as well. Indeed if an upper bound on the number ofinstructions exists and it is finite, termination can be guaranteed. An extensionof this method is proposed by Montenegro et al. in [24], using the polynomialinterpolation method of [30, 33, 29, 31, 28]. In [4], Albert et al. present amethod to use COSTA in combination with verification tool KeY [1, 6].
1.4 Loop Bound Analysis
Loop Bound Analysis is another part of the ResAna tool and methods. Thisfocuses on the number of iterations of loops. A basic method of Loop BoundAnalysis using polynomial interpolation is presented by Shkaravska et al. in[27] and it is inspired by the method of the same authors for polynomial sizeanalysis described in [30, 33, 29, 31, 28]. This method extracts a loop fromthe source code and instruments it with variables in order to do tests on thenumber of iterations. Given the results it infers a symbolic ranking function,which specifies an upper bound on the number of iterations of the loop. Sincepolynomial interpolation is used, the method in not limited to inferring linearbounds, unlike most other methods (presented in Section 1.6), which are limitedto linear bounds. The loop bound analysis method by Shkaravska et al. [27] isimplemented as a prototype in the ResAna tool.
The basic Loop Bound Analysis method with polynomial interpolation onlyinfers upper bounds for loops with conditions over conjunctions of numerical(in)equalities. In order to handle disjunctions as well, the method is extendedwith piece-wise ranking functions, which in essence splits the disjunctions in setsof conjunctions (pieces) for every possible case. However, in [21] Kersten andVan Eekelen describe a challenge with this method: condition jumping. Themethod assumes the different pieces obtained by splitting to be independent.However, this is not true in some cases. Therefore, a solution to this problemis described in [21].
4 CHAPTER 1. INTRODUCTION
1.5 Goal of the thesis
This research focuses on Loop Bound Analysis on loops with disjunctive guardsin practice. As described above, methods have been proposed, but how accurateand applicable are they in practice and what is needed to improve/extend thosemethods?
In this study the feasibility of Loop Bound Analysis for loops with disjunc-tive guards is examined. In other words how feasible is Loop Bound Analysisfor loops with disjunctive guards? The base of this study is the Loop BoundAnalysis method using polynomial interpolation by Shkaravska et al. [27] andthe extension for disjunctive guards by Kersten and Van Eekelen [21].
The following steps have been performed in order to answer the question:how feasible is Loop Bound Analysis for loops with disjunctive guards?
• Implement the method by Kersten and Van Eekelen [21] in the ResAna tool.
• A global study on loops with disjunctive guards: how many loops containdisjunctive guards?
• A detailed study on loops with disjunctive guards from a large Java pro-gram: what would be the optimal ranking function for the loop and howcan it be derived?
• Given the results of the detailed study, the loops have been sorted intocategories and for each category a solution has been proposed in order toderive a ranking function for loops in that category, if possible. Otherwisean explanation of why this is impossible has been given.
1.6 Related work on Loop Bound Analysis
De Michiel et al. present a method for Loop Bound Analysis for C programs in[11]. It is very different in comparison with the method described here. Insteadof a test-based approach, this method analyses the syntax and creates a contexttree. Using that it performs execution flow analysis and abstract interpretation.
Ermedahl et al. describe another method for Loop Bound Analysis in [13].It uses program slicing, abstract interpretation and invariant analysis. It hasbeen implemented in the SWEET tool (SWEdish Execution time Tool), whichanalyses ANSI-C programs.
Gulwani et al. present in [17] a series of different methods for loop boundanalysis. These methods include methods for nested loops and loops dependingon data structures. In [16] Gulwani et al. describe loop bound analysis basedon control-flow refinement and progress invariants. In [18] Gulwani and Zulegerpresent another method for loop bound analysis using abstract interpretationand a non-iterative proof-based technique.
Fulara and Jakubczyk describe in [15] a method to derive ranking functionsfor for-loops. The method uses pattern recognition and derives the rankingfunctions using predefined patterns. Therefore, this method is less general thanthe method presented by Shkaravska et al. [27], which is considered for thisresearch.
Hunt et al. describe a method for Worst Case Execution Time Analysis usingData Flow in [19]. It also addresses ranking function and their description in
1.7. THESIS OUTLINE 5
Java Modeling Language(JML) and the verification of those ranking functionsusing KeY [1, 6].
Podelski and Rybalchenko describe in [25] a method for deriving linear rank-ing functions for loops. This method is complete, i.e. if there exists a linearranking function for a loop, the method will find it.
Lokuciejewski et al. present in [23] a static analysis method for Loop BoundAnalysis using abstract interpretation. It also uses program slicing for efficiency.However, the result of this method for a loop is a concrete/numerical boundinstead of a symbolic bound.
1.7 Thesis outline
In Chapter 2 basic Loop Bound Analysis using polynomial interpolation [27]is described. This is followed by a description of loop bound analysis usingpolynomial interpolation for loops with disjunctive guards [21] in Chapter 3.Then a feasibility study has been done in Chapter 4. This feasibility study isdivided in three main parts: a) a global study in Section 4.1, b) a detailed studyin Section 4.2 and c) a study on what extensions are needed to derive rankingfunctions for loops with disjunctive guards in Section 4.3. Followed by futurework in Chapter 5 and finally in Chapter 6 the conclusion.
6 CHAPTER 1. INTRODUCTION
Chapter 2
Loop Bound Analysis withPolynomial Interpolation
The purpose of Loop Bound Analysis is deriving a ranking function for a givenloop. In this context a ranking function is a symbolic upper bound on thenumber of iterations of a loop. A method to derive a ranking function for agiven loop is described by Shkaravska et al. in [27].
The basic method will be described first, followed by an introduction to someextensions and this chapter concludes with some working examples.
2.1 Basic method
Consider the loop in Listing 2.1.
Listing 2.1: Example class
1 public class Example{2 public void method1 ( int i ) {3 //do something4 while ( i < 10)5 i ++;6 //do something e l s e7 }8 }
A ranking function for this loop is:
{10− i if i > 00 otherwise
This means that if, e.g., i = 0, that there will be at most 10 iterationsaccording to the ranking function. This is the most precise upper bound forthis loop. However, the following ranking function, which overestimates thenumber of iterations, is also valid, since it is an upper bound:
7
8 CHAPTER 2. L.B.A. WITH POLYNOMIAL INTERPOLATION
{100− i if i > 00 otherwise
In [27] a method is described to derive ranking functions for loops automat-ically. This method is based on testing, i.e. executing the loop given certaininput values in order to infer a ranking function. The method consists of thefollowing steps:
1. Extract and instrument the loop
2. Test node generation
3. Inferring a ranking function
In the following sections the method will be explained using the loop inListing 2.1.
2.1.1 Extract and instrument the loop
Since the loop will be executed to test the number of iterations given certaininput values, the loop is extracted from its context, i.e. remove all statementsbefore and after the loop. By extracting the loop and placing it in a testingsetting, there is more control over the variables on which the loop dependsthan there would be when executing the whole program. Since in this case thevariables used in the loop can be manipulated directly. However, this is notpossible when the whole program is executed, since the variables in the loop,can be dependent of other variables, i.e. the variables used in the loop cannot bemanipulated directly, but through manipulating other variables, which makesit more difficult. Moreover it creates a weaker testing method, because thevariables can only be manipulated indirectly, i.e. the values of the variables arerestricted to which values are possible through the variables they depend on.For example, variable j is created using variable i: j = 2i. Then the values ofj are restricted to even numbers.
After extracting it from its context, the loop is instrumented with a counter,which will be returned when the loop is finished, i.e. after finishing the loop itreturns the number of iterations. Therefore, a new version of the class will begenerated, this is shown in Listing 2.2.
Listing 2.2: Instrumented loop
1 public class Example{2 public void method1 ( int i ) {3 int count = 0 ;4 while ( i < 10) {5 i ++;6 count++;7 }8 return count ;9 }
10 }
2.1. BASIC METHOD 9
2.1.2 Polynomial interpolation
Before explaining the next step, test node generation, some explanation is neededabout polynomial interpolation. Polynomial interpolation is the interpolationof given data points by a polynomial, i.e. derive a polynomial that goes throughthose points. Polynomial interpolation itself will be used in the last step of themethod: deriving the polynomial, but the conditions presented below are usedin the next step.
Deriving a polynomial is finding values for the coefficients of the polynomial.For example, for a polynomial with one variable and degree d
p(z) = a0 + a1z + · · ·+ adzd
it is finding values for a1, . . . , ad, in such a way that polynomial p interpolatesthe test results.
However, there are certain conditions on the test data, in order for thepolynomial to exist and to be unique. In the case of a polynomial with onevariable and of degree d (as in the polynomial shown above), at least d + 1different data points are needed. The system of d + 1 pairwise different pointscan be written as follows in a matrix form:
1 z0 . . . zd−10 zd01 z1 . . . zd−11 zd1...
.... . .
......
1 zd−1 . . . zd−1d−1 zdd−11 zd . . . zd−1d zdd
a0a1...
ad−1ad
=
p(z0)p(z1)
...p(zd−1)p(zd)
A matrix in the form of Ai,j = zj−1i , like the matrix above, is called a
Vandermonde matrix. For pairwise different points z0, . . . , zd, the matrix has anon-zero determinant, which is called a Vandermonde determinant. Because thedeterminant has a non-zero value, there exists a unique solution to the system,i.e. a unique polynomial, which interpolates the data points.
However, for multivariate systems the test data need to satisfy more complexconditions in order to get a unique interpolating polynomial. First of all apolynomial p(z1, . . . , zk) of degree d and with k variables, i.e. dimension k, has
Nkd =
(d+ kk
)coefficients. In [8] three node configurations are introduced,
under which the Vandermonde determinant is non-zero. The simplest one isNode Configuration A. For the 2-dimensional case NCA is defined as follows:
Set W ⊂ R2 exists of N2d nodes. W lies in a 2-dimensional NCA if there
exists lines γ1, . . . , γd+1 in R2, in such a way that d+ 1 nodes of W lie on γd+1,d nodes on γd\γd+1, . . . , and 1 node lies on line γ1\(γ2 ∪ · · · ∪ γd+1).
NCA for any k > 2 is defined by induction on k:
Set W ⊂ Rk exists of Nkd nodes. W lies in a k-dimensional NCA if, for
any 0 ≤ i ≤ d, there is a (k − 1)-dimensional hyperplane, in such a way that it
10 CHAPTER 2. L.B.A. WITH POLYNOMIAL INTERPOLATION
contains Nk−1d−i nodes, which are on a (k− 1)-dimensional NCA for degree d− i
and these nodes are not lying on any other hyperplane.
2.1.3 Test node generation
The next step in the process of inferring a ranking function, is to generatetest nodes. In the previous step, the loop was instrumented with a counter.Therefore it can be executed with different input values and it will return thenumber of iterations of the loop for each test node, which is a set of input valuesused for one test execution.
As said in the previous section, in order to have a unique solution for thesystem of equations using polynomial interpolation, the test data needs to bein NCA. However, for test nodes used to derive a ranking function, there isone extra condition. The test nodes need to satisfy the loop guard as well.Otherwise it would have no sense to execute the test, as it would result in noiterations.
The example (in Listing 2.1) has a loop (guard) with just one variable.Therefore, the only requirement is, that there need to be d+ 1 different nodes,where d is the expected degree of the polynomial. Given the loop conditioni < 10, it is reasonable to expect a degree of 1, i.e. linear. Therefore, twodifferent nodes are needed:
i number of iterations0 101 9
2.1.4 Inferring a ranking function
After the test nodes are generated and the tests are executed, a polynomial canbe inferred, i.e. the system of equations need to be solved. The example hasone variable and is of degree 1, so the polynomial has the following form:
a0 + a1i = p(i)
Therefore, the system is as follows:
a0 = 10
a0 + a1 = 9
This gives that a0 = 10 and a1 = −1. Therefore, the polynomial interpolat-ing the test nodes is:
p(i) = 10− i
This is the main part of the inferred ranking function. However, there isstill another case for which this ranking function is not correct. This is the case
2.2. EXTENSIONS 11
where the loop is never entered, i.e. when the loop condition is not satisfied.Therefore, the inferred ranking function is:
{10− i if i > 00 otherwise
The method is also implemented in a tool: ResAna, which is part of theCHARTER Project1.
2.2 Extensions
In this section some extensions are presented as given in [27].
2.2.1 Step size
In the example in listing 2.1 the loop variable is incremented by 1. However,there are cases where the loop variable is incremented (or decremented) withanother value. The loop in Listing 2.3 is such a case.
Listing 2.3: A loop with step size 4
1 while ( i < 20)2 i += 4 ;
Since there is only one variable in the loop and the expected degree is 1,there need to be N1
1 = 2 test nodes to interpolate the following polynomial inthe data:
ai+ b = p(i)
The following test nodes could be used:
i = 0
i = 1
This would give the following results:
i p(i)0 51 5
This results in the following polynomial:
p(i) = 5
1For more information see http://charterproject.ning.com/
12 CHAPTER 2. L.B.A. WITH POLYNOMIAL INTERPOLATION
However, this is not a correct ranking function, since the number of iterationsof the loop is not constant. It is a correct upper bound for any i >= 0, but itis incorrect for any i < 0, e.g. i = −1 results in 6 iterations.
The problem is that the test nodes that are chosen for this example are tooclose to each other. The loop variable is incremented by 4, i.e. the step size ofthe loop is 4. Therefore, the differences of the values of i in the test nodes needto be a factor of 4. For example the following test nodes:
i = 0
i = 4
This would give the following results:
i p(i)0 54 4
This results in the following system of equations:
d = 5
4a+ d = 4
This gives that a = − 14 and d = 5. However, the number of iterations needs
to be an integer, so the polynomial needs to be ceiled:
{d5− 1
4 ie if i < 200 otherwise
2.2.2 Branch-splitting
Another extension mentioned in [27] handles if-statements inside the loop. Con-sider the loop in 2.4.
Listing 2.4: Loop with if-statements as given in [27]
1 while ( i > 0) {2 i f ( i > 100)3 i −= 10 ;4 else5 i−−;6 }
The loop contains two branches, which affect the upper bound differently:when i > 100 the value of i drops faster every iteration.
Branh-splitting is a solution to this problem for loops, which have the fol-lowing worst-case computation branch property :
2.3. WORKING EXAMPLES 13
“For each loop body, there is an execution path such that, for anycollections of values of the loop variables, if one follows this executionpath in every loop iteration one reaches the worst-case, i.e. the upperbound.” [27]
To do this, multiple new loops are created form the original, one for eachbranch, as shown in listings 2.5 and 2.6. For all those loops a ranking functionis computed and then because of the property described above it is possible touse the maximum of both as a general ranking function for the original loop.Therefore, a ranking function for the loop in listing 2.4 is i.
Listing 2.5: A branch from the loop in listing 2.4
1 while ( i > 0) {2 i−−;3 }
Listing 2.6: Another branch from the loop in listing 2.4
1 while ( i > 0) {2 i −=10;3 }
2.3 Working examples
2.3.1 Linear multivariate example
In this section a multivariate version of the example in the previous section willbe given. The loop used in this example is shown in Listing 2.7.
Listing 2.7: Example loop with 3 variables
1 public class Example2{2 public void method2 ( int i ) {3 //do something4 while ( x < 10 && y < 10 && z < 10) {5 z++;6 i f ( z == 10) {7 y++;8 z = 0 ;9 i f ( y == 10) {
14 CHAPTER 2. L.B.A. WITH POLYNOMIAL INTERPOLATION
Extract and instrument loop
First the loop is extracted from its context and is instrumented with a counter,as shown in Listing 2.8.
Listing 2.8: Example loop with 3 variables
1 public class Example2{2 public void method2 ( int i ) {3 int count = 0 ;4 while ( x < 10 && y < 10 && z < 10) {5 z++;6 i f ( z == 10) {7 y++;8 z = 0 ;9 i f ( y == 10) {
The example has three variables and it is expected to be linear, i.e. the expected
degree is 1. Therefore, there have to be N31 =
(43
)= 4 test nodes in NCA,
in order to be sure there is a (unique) ranking function.
For a multivariate case with k > 2 the definition for nodes to be in NCA isgiven inductively. In this case k = 3, so for any 0 ≤ i ≤ d, there have to bea (k − 1)-dimensional hyperplane, with Nk−1
d−1 nodes, which are on a (k − 1)-dimensional NCA for degree d− i and are not on any other hyperplane. In thiscase there have to be two 2-dimensional hyperplanes in NCA: one of degree 1(Hyperplane A), with 3 nodes, and one of degree 0 (Hyperplane B), with 1 node.
In order to have a 2-dimensional hyperplane in NCA, it exists of N2d nodes
and there exist lines γ1, . . . , γd+1, in such a way that d + 1 nodes are on lineγd+1, . . . , and 1 nodes lies on line γ1\(γ2∪ · · ·∪γd+1). For Hyperplane A, thereare two lines γ1 and γ2. Two nodes are on line γ2:
x y z0 0 01 0 0
and one node is on line γ1:
2.3. WORKING EXAMPLES 15
x y z0 1 0
For Hyperplane B, there is one line γ′1, with one node:
x y z0 0 1
Inferring a ranking function
The loop has three variables and the ranking function has an expected degreeof 1. Therefore, the polynomial of the ranking function has the following form:
ax+ by + cz + d = p(x, y, z)
Given the test nodes, the following results are found:
x y z p(x, y, z)0 0 0 10001 0 0 9000 1 0 9900 0 1 999
This gives the following system of equations:
d = 1000
a+ d = 900
b+ d = 990
c+ d = 999
This results in:
a = −100
b = −10
c = −1
d = 1000
Therefore a ranking function for the loop in Listing 2.7 is:
{1000− 100x− 10y − z if x < 10 ∧ y < 10 ∧ z < 100 otherwise
16 CHAPTER 2. L.B.A. WITH POLYNOMIAL INTERPOLATION
2.3.2 Quadratic example
The examples above were all of degree 1, i.e. linear. The following example willshow that the method can also handle higher degrees, in this case degree 2, i.e.quadratic.
Listing 2.9: Loop with a quadratic ranking function
1 while ( x < n && y < n) {2 y++;3 i f ( y == n) {4 y = 0 ;5 x++;6 }7 }
As said before, the ranking function for the loop will be quadratic. However,to show what happens when the degree is too low, first a ranking function withdegree 1 will be inferred.
Degree 1
The loop has three variables. Therefore, there need to be N31 = 4 nodes. The
polynomial will have the following form:
ax+ by + cn+ d = p(x, y, n)
The following test nodes, which are in NCA, could be used:
x y n p(x, y, n)0 0 2 41 0 2 20 1 2 30 0 1 1
This gives the following system of equations:
2c+ d = 4
a+ 2c+ d = 2
b+ 2c+ d = 3
c+ d = 1
This results in the following polynomial:
3n− 2x− y − 2 = p(x, y, n)
However, it can easily be shown that this ranking function is incorrect. Forexample when x = 0, y = 0 and n = 3, the loop has 9 iterations, but according tothe polynomial only 7. This underestimates the number of iterations. Thereforeit is an incorrect upper bound.
2.3. WORKING EXAMPLES 17
Degree 2
For three variables and a degree of 2, N32 = 10 test nodes are needed. The in
the following 10 test nodes, which are in NCA, are shown with the number ofiteration as a result of those values.
ax2 + by2 + cn2 + dxy + exn+ fyn+ gx+ hy + in+ j = p(x, y, n)
This gives the following system of equations:
9c+ 3i+ j = 9
a+ 9c+ 3e+ g + 3i+ j = 6
4a+ 9c+ 6e+ 2g + 3i+ j = 3
b+ 9c+ 3f + h+ 3i+ j = 8
a+ b+ 9c+ d+ 3e+ 3f + g + h+ 3i+ j = 5
4b+ 9c+ 6f + 2h+ 3i+ j = 7
4c+ 2i+ j = 4
a+ 4c+ 2e+ g + 2i+ j = 2
b+ 4c+ 2f + h+ 2i+ j = 3
c+ i+ j = 1
This results in the following polynomial:
n2 − xn− y = p(x, y, n)
Therefore, a ranking function for the loop in Listing 2.9 is:
{n2 − xn− y if x < n ∧ y < n0 otherwise
As shown above, the inferred ranking function will be incorrect, when theexpected degree is too low. However, a degree higher than needed, will lead to acorrect ranking function, though it leads to more calculations, since the numberof test nodes that are needed grows.
18 CHAPTER 2. L.B.A. WITH POLYNOMIAL INTERPOLATION
2.4 Soundness
The ranking functions found by the method described in this chapter is dependon which test nodes are used. Therefore, the method is not sound. However,the inferred ranking functions can be added to the Java code by using the JMLclause: @decreases, as shown in Listing 2.10.
Listing 2.10: Example class with decreases clause
1 //@ ensure s t rue ;2 public class Example{3 //@ a s s i g n a b l e i ;4 //@ l o o p i n v a r i a n t t rue ;5 //@ de c r e a s e s i<10 ? i−10 : 0 ;6 public void method1 ( int i ) {7 //do something8 while ( i < 10)9 i ++;
10 //do something e l s e11 }12 }
By adding this to the code, it is possible to prove the ranking function, i.e.prove that the loop will never have more iterations than given in the rankingfunction. There is a tool available that can do this (partly) automatically. Thetool is called KeY and is introduced in the article by Ahrendt et al. [1] and ismore detailed described by Beckert et al. in [6]. The KeY tool can be used toprove that certain JML clauses are correct given the Java code.
Note that this is the same method as used by Shkaravska et al. [30, 33, 29,31, 28]. Using polynomial interpolation for inference and use a formal methodto verify the polynomial returned by the inference.
Another tool which uses JML annotations is Extended Static Checker forJava (ESC/Java), as described in [14] and with its JML extension in [9]: ES-C/Java2. The main purpose of ESC/Java was to find common programmingerrors. However, ESC/Java2 can prove as well, since it is enhanced with JMLand theorem provers.
Chapter 3
Loop Bound Analysis forLoops with DisjunctiveGuards
The basic loop bound analysis method as described in section 2.1 handles loopswith conditions of the following form:
n∧i=1
(eli b eri)
where b ∈ {<,>,=, 6=,≤,≥}.However, in [27] an extension to the basic loop bound analysis method is
given, in order for the method to handle loops “with as exit condition anypropositional logical expression over arithmetical (in)equalities” [21], includingdisjunctions. This is done by the use of piecewise ranking functions. These areranking functions consisting of different pieces. The ranking function given atthe end of section 2.1.4, is a simple example of a piecewise ranking function:
{10− i if i > 00 otherwise
It consist of two pieces: 1) the loop condition is true and the computedranking function for the loop is given and 2) when the loop condition is falseand the is never entered, i.e. no iterations.
3.1 Piece-wise ranking functions
To allow disjunctions in the loop condition, Shkaravska et al. created the fol-lowing extension to the basic loop bound analysis method [27, 21].
The first step is to transform the loop condition to disjunctive normal form(DNF):
19
20 CHAPTER 3. L.B.A. FOR LOOPS WITH DISJUNCTIVE GUARDS
n∨i=1
(
mi∧i=1
(elijberij))
where b ∈ {<,>,=, 6=,≤,≥}.Then the transformed condition is spit into several conditions with the func-
tion DNFSplit :: Cd → {Cnd}, where Cd is a loop condition in DNF and Cnd
is a loop in the form as given at the beginning of this chapter (a conjunction ofarithmetical (in)equalities). The function DNFsplit is defined in [21] as follows:
This function transforms the condition in DNF to a set of 2n − 1 pieces (con-junctive conditions, as defined at the beginning of this chapter). The piecesare of a type that can be handled by the basic method (described in Chapter2). The ranking function is then calculated as follows: for every piece in theset a ranking function is calculated, which are then combined to one rankingfunction:
RFp1
if p1. . . if . . .RFpm
if pm0 else
Consider the example in Listing 3.1. The loop condition in DNF is:
(start < end ∧ end < 40) ∨ (start < end ∧ end > 100)
Using DNFsplit will result in the following pieces:
(start < end ∧ end < 40) ∧ ¬(start < end ∧ end > 100)
¬(start < end ∧ end < 40) ∧ (start < end ∧ end > 100)
(start < end ∧ end < 40) ∧ (start < end ∧ end > 100)
However, the last piece can be omitted, since there is no value for end <40∧ end > 100. Using the basic method for the other two pieces, gives for boththe following ranking function: end− start.
Therefore a ranking function for the loop in listing 3.1 is:
end− start if (start < end ∧ end < 40) ∧ ¬(start < end ∧ end > 100)end− start if (start < end ∧ end > 100) ∧ ¬(start < end ∧ end < 40)0 otherwise
3.2. THE CHALLENGE 21
Listing 3.1: Example of a loop condition with a disjunction (as given by Shkar-avska et al. in [27])
1 while ( s t a r t < end && ( end < 40 | | end > 100) )2 s t a r t ++;
3.1.1 Condition Jumping
In the previous section, piecewise ranking functions were introduced as a solu-tion to the challenge that arises when using disjunctions in the loop condition(Section 3.1). However, another challenge arises when using this method. Thisis mentioned by Kersten and Van Eekelen in [21]. When splitting the disjunc-tive condition into different pieces, each piece is considered independent, i.e.for every execution of the loop just one piece is true. However, it is possiblethat during the execution of the loop another piece becomes true. This is calledcondition jumping. In the first section of this chapter the challenge will beexplained and in the last section two solutions will be presented.
3.2 The challenge
As said above, condition jumping is a challenge that arises when disjunctiveloop conditions are used, e.g. a ∨ b, which results in the following pieces:
1. a ∧ ¬b
2. ¬a ∧ b
3. a ∧ b
The piece ¬a ∧ ¬b is omitted, since it represents the case where the loop isnot entered and thus has a ranking function of 0.
Condition jumping arises when at some point in execution one piece is trueand after the next iteration another piece is true, e.g. at some point a ∧ ¬bholds, but after the next iteration of the loop ¬a ∧ b holds. The challenge isthat the pieces created for piecewise ranking functions, can be underestimatingthe actual number of iterations, since the pieces are assumed to be independent.However, when condition jumping arises, this assumption is wrong.
Note that in every (finite) loop some sort of condition jumping arises, thejumping to the piece, for which the loop will be exited (¬a ∧ ¬b). However,this will not be considered condition jumping, since this jumping will result inexiting the loop and will therefore add no difference to the number of iterations.
3.2.1 Example of condition jumping
The loop in Listing 3.2 (as given in [21]) shows an example of condition jumping.
Listing 3.2: Condition jumping example
1 while ( ( i > 0 && i < 20) | | i > 22) {2 i f ( i > 22)
22 CHAPTER 3. L.B.A. FOR LOOPS WITH DISJUNCTIVE GUARDS
3 i−−;4 else5 i += 4 ;6 }
Using piecewise ranking functions, the following pieces will be created:
1. (i > 0 ∧ i < 20) ∧ ¬(i > 22)
2. ¬(i > 0 ∧ i < 20) ∧ (i > 22)
3. (i > 0 ∧ i < 20) ∧ (i > 22)
As above, the piece for which the loop is not entered (¬(i > 0∧ i < 20)∧¬(i >22)) is omitted. Moreover, the third piece can be omitted as well, since thereexists no i such that (i > 0 ∧ i < 20) ∧ (i > 22).
3.2.2 Solution
An algorithm to compute all the states which lead to condition jumping frompiece pi to piece pj is described below [21].
In the following a state s represents a set of values for the variables used inthe loop. s → s′ represents one iteration of the loop with s as the state beforethe iteration and s′ the state after the iteration. s ⇒ s′ represents that it ispossible to go from state s to state s′ in one or more iterations.
1. Check whether there is a state s for which holds: s → s′, where piece piis true in state s and piece pj is true in state s′. If there is such a state,add it to the list CASES.
2. Repeat the previous step to find other states s /∈ CASES, until there areno such states any more.
3. Pop a state from CASES: s
4. Check whether there are states which lead to that state and are not alreadycondition jumping cases: s′ → s and s′ /∈ CASES.
5. If so, add the state to CASES. Repeat until no new state is found, thenadd s to DONE and go back to step 3 until CASES is empty. Finally allstates that lead eventually to condition jumping are in DONE.
Steps 1 and 2 search for states which directly lead to condition jumping, i.e.in one step. Steps 3, 4 and 5 search for cases which lead eventually to conditionjumping, i.e. s⇒ s′, where in s piece pi is true and in s′ piece pj is true.
Executing this algorithm on the example above gives the following: in step1, the state where i = 19 results in condition jumping, since in that state thefirst piece is true, but after one iteration the second piece is true, since theni = 23. This is the only direct case of condition jumping. Therefore, the setCASES is as follows, when reaching step 3: {i = 19}. The next step is to checkif there is a state that reaches i = 19 after one iteration. This is only the casein the state i = 15. The following step is to check if there are states reachingi = 15 etc.
Finally the following cases of condition jumping are found:
3.3. IMPLEMENTATION 23
• i = 19
• i = 15
• i = 11
• i = 7
• i = 3
Note that these are all condition jumping cases from the first piece to the second.The cases for condition jumping from the second piece to the first have to becalculated as well. However, for this example, there are no such cases.
These states can be put into one new piece, since there is one case of conditionjumping and the other cases lead to that case. However, it is possible that thereare more cases of condition jumping, which will result in multiple pieces. Thepieces for the example will then be as follows:
• i > 0 ∧ i < 20 ∧ i mod 4 6= 3
• i > 0 ∧ i < 20 ∧ i mod 4 = 3
• i > 22∧
Using the basic method for each of these pieces, results in the followingranking function:
d(20− i)/4e+ 1 if (i > 0) ∧ (i < 20) ∧ i mod 4 = 3d(20− i)/4e if (i > 0) ∧ (i < 20) ∧ i mod 4 6= 3i− 22 if i > 220 else
3.2.3 Multi-jumping
The algorithm above defines how to detect condition jumping from one piece toanother. However, it is necessary to check every pair of conditions for conditionjumping:
1. DNF-split (see Section 3.1) the loop condition to n pieces.
2. Apply the algorithm above for any pairwise different pi and pj pieces inboth ways, i.e. condition jumping from pi to pj and condition jumpingfrom pj to pi.
3.3 Implementation
In the previous section an algorithm to detect condition jumping is given. Inthis section two different solutions to implement this algorithm are given andcompared.
24 CHAPTER 3. L.B.A. FOR LOOPS WITH DISJUNCTIVE GUARDS
3.3.1 Symbolic Execution and SMT solvers
In [21] Kersten et al. describe a method for detecting condition jumping ina loop using symbolic execution and a Satisfiability Modulo Theories (SMT)solver.
Symbolic Execution
Symbolic execution will be used to obtain update functions, which define how avariable is updated after one iteration of a given loop.
Symbolic execution is described by King in [22]. It is executing a pieceof code in a symbolical way, i.e. instead of executing the program with vari-ables, execute it with symbols. Then the result is not a set of values for inputsymbols/variables, but a set of symbolic formulas over input symbols.
The update functions obtained with symbolic execution are defined as fol-lows:
nextvi :: Tv1 → · · · → Tvi → · · · → Tvn → Tvi
where Tvi is the type of variable vi ∈ LV and n = |LV | and LV is the set ofprogram variables inside the loop.
These update functions are obtained using symbolic execution [21]. Thefirst step is to gives the variables v1, . . . , vn the symbolic values α1, . . . , αn.After the symbolic execution each variable v1, . . . , vn will have a symbolic value:polynomials over α1, . . . , αn, constants and path conditions (to handle branchinginside the loop). Update functions can then be derived by substituting thesymbolic values α1, . . . , αn by their corresponding program variables v1, . . . , vn.
For example for the loop in Listing 3.2, φi is the result of symbolic executionof the loop with αi used as symbolic value for i:
φi(αi) =
{αi − 1 if αi > 22αi + 4 if ¬(αi > 22)
When substituting i for αi results in the following update function:
nexti(i) =
{i− 1 if i > 22i+ 4 if ¬(i > 22)
These update functions will be used to determine a value for the variablesfor which condition jumping occurs. Let con1 and con2 be functions repre-senting the two pieces to check for condition jumping with the following type:v1 . . . vn → Bool. If there are values for the variables vc1 . . . vcm ∈ CV , whereCV is the set of program variables in the condition and m = |CV |, such thatthe following holds, then condition jumping occurs:
To calculate all values for which condition jumping occurs, an SMT solver canbe used. An SMT solver1 solves Satisfiability Modulo Theories problems, whichare a generalisation of boolean satisfiability (SAT) problems. The goal for SATproblems is to determine given a certain set of boolean variables and formulas,if there is a valuation for those variables such that the formulas evaluate totrue. SMT problems generalise this by using underlying theories like equalityreasoning and arithmetics [7, 12].
SMT-LIB is a standard scripting language for SMT solvers, which is describesby Barrett et al. in [5]. The SMT-LIB script in Listing 3.3 is an example scriptfor the loop in Listing 3.2.
Listing 3.3: First SMT-LIB script
1 ( s e t l o g i c QF LIA)2 ( dec la re−fun i ( ) Int )3 ( de f ine−fun next i ( ( x Int ) ) Int ( i t e (> x 22) (− x 1) (+
x 4) ) )4 ( a s s e r t ( and ( and (> i 0) (< i 20) ) (> ( nex t i i ) 22) ) )5 ( check−sa t )6 ( e x i t )
The script does the following:
1. A variable i of type Int is created.
2. A function nexti is created, which contains the update function for variablei.
3. The assertion is made that there is a value for i, for which holds that0 < i < 20 and that after the next iteration i > 22, i.e. nexti(i) > 22.
4. The SMT solver then checks this assertion.
If the assertion holds,(get-value (i)) can be added to the script to getthe value of i for which condition jumping occurs.
The result of running this script will be that for i = 19 condition jumpingoccurs. In the next script it will be checked whether there are more values of ifor which condition jumping occurs. This is shown in Listing 3.4.
Listing 3.4: First SMT-LIB script
1 ( s e t l o g i c QF LIA)2 ( dec la re−fun i ( ) Int )3 ( de f ine−fun next i ( ( x Int ) ) Int ( i t e (> x 22) (− x 1) (+
x 4) ) )4 ( a s s e r t ( and ( and (> i 0) (< i 20) ) (> ( nex t i i ) 22) ) )5 ( a s s e r t ( d i s t i n c t i 19) )6 ( check−sa t )7 ( get−value ( i ) )8 ( e x i t )
1For example Z3 http://research.microsoft.com/en-us/um/redmond/projects/z3/
26 CHAPTER 3. L.B.A. FOR LOOPS WITH DISJUNCTIVE GUARDS
For this example, there are no other cases of condition jumping, so thisscript is unsatisfiable, i.e. the SMT solver can not find another i that leads tocondition jumping.
The next step is to check if there are values of i which lead to i = 19 afterthe next iteration. This is shown in Listing 3.5.
Listing 3.5: First SMT-LIB script
1 ( s e t l o g i c QF LIA)2 ( dec la re−fun i ( ) Int )3 ( de f ine−fun next i ( ( x Int ) ) Int ( i t e (> x 22) (− x 1) (+
x 4) ) )4 ( a s s e r t ( and ( and (> i 0) (< i 20) ) (= ( next i i ) 19) ) )5 ( a s s e r t ( d i s t i n c t i 19) )6 ( check−sa t )7 ( get−value ( i ) )8 ( e x i t )
This script will return i = 15. Then this step needs to be repeated for i = 15to check whether there are values of i, that will be after the next iteration i = 15and so on, until no new values can be added.
3.3.2 Binary Decision Diagrams
In this section a second solution to the detection of condition jumping willbe presented. The difference with the previous solution, is that it uses BinaryDecision Diagrams (BDDs), which are described by Akers in [2], instead of SMTscripts.
BDDs are used to find satisfying assignments for a given formula, like SMTsolvers. However, they use different methods. SMT solvers use logic to checkthe satisfiability of the assumption, whereas BDDs create a decision diagramconsidering every possible value for each variable and use logic to prune thedecision tree, as described in [10].
In this section the same example of condition jumping will be used as in theprevious sections, which is shown in Listing 3.2.
One of the challenges of the solution using SMT scripts is the generation ofthe update functions, which was implemented by the nexti function, to calculatethe value of i after one iteration. Kersten and Van Eekelen propose in [21] touse symbolic execution of the loop body.
However, this is not necessary when using BDDs, since the syntax of theloop body can be used in the update functions. This is possible, because thereare libraries for using BDDs in a programming language, like Java or C(++), sothe update functions can contain the original code of the loop body. Although,there are similar libraries available for SMT solvers2, it is not possible to usethe code of the loop body for update functions, since SMT libraries use theirown implementations for data structures for better performance.
In Listing 3.6 a C++ program is given to check if condition jumping occursin the loop in Listing 3.2 using the BDD library package BuDDy 3.
2For example the Java API for Z3 http://research.microsoft.com/en-us/um/redmond/
projects/z3/3A C++ library is used, since Java libraries were incomplete and had to be extended first.
Listing 3.6: A C++ program using BDDs to check for condition jumping
1 #inc lude <s t d l i b . h>2 #inc lude <s t r i n g . h>3 #inc lude ”bdd . h”4 #inc lude ”bvec . h”56 const int VECTOR LENGTH = 6 ;78 us ing namespace std ;9
10 int next i ( int i ) {11 i f ( i > 22)12 i−−;13 else14 i += 4 ;15 return i ;16 }1718 bvec update i ( bvec vec )19 {20 int i = bvec va l ( vec ) ;21 i = next i ( i ) ;22 int d i f = i − bvec va l ( vec ) ;23 i f ( d i f == 0)24 return i ;25 else i f ( d i f > 0)26 return bvec add ( vec , bvec con (
VECTOR LENGTH, d i f ) ) ;27 else28 return bvec sub ( vec , bvec con (
VECTOR LENGTH, d i f ∗−1) ) ;29 }3031 bdd con1 ( bvec i )32 {33 return bdd and ( bvec gth ( i , bvec con (VECTOR LENGTH
, 0 ) ) , bve c l t h ( i , bvec con (VECTOR LENGTH, 2 0 ) ) ) ;34 }3536 bdd con2 ( bvec i )37 {38 return bvec gth ( i , bvec con (VECTOR LENGTH, 2 2 ) ) ;39 }4041 int main ( )42 {43 int domain [ 1 ] = {64} ;4445 b d d i n i t (100 ,100) ;
28 CHAPTER 3. L.B.A. FOR LOOPS WITH DISJUNCTIVE GUARDS
46 fdd extdomain ( domain , 1 ) ;4748 bvec i = bvec var fdd (0 ) ;49 bdd r e s u l t = bdd and ( con1 ( i ) , con2 ( update i ( i ) ) ) ;5051 cout << f dd s e t << r e s u l t << endl ;5253 return 0 ;54 }
In the following, the different functions of the C++ program will be ex-plained. In BDDs integers are implemented using a bit vector.
The pieces of the loop guard are implemented in the con1 and con2 functions.For example con2 is defined as
bvec gth(i, bvec con(VECTOR LENGTH, 22))
where bvec_gth is the > operator for bit vectors and bvec_con creates a con-stant bit vector of length VECTOR LENGTH with value 22, i.e. con2 returns:i > 22, and similar for con1: i > 0 ∧ i < 20.
The update function consists of two parts: update_i and nexti. The nexti
function consists of the loop body and returns an integer value of i after oneiteration. The update_i function updates the bit vectors according to the nextifunction. It first calculates the current integer value of the bit vector, passes iton to the nexti function and calculates the difference after one iteration andadds/subtracts the difference to the bit vector. It is also possible to create anexti function for bit vectors, so the update_i function is not needed anymore.However, this results in the same challenge as with SMT scripts, since theupdates of a variable need to be analysed and transformed to another formate.g. using update functions, which is not needed in the example above, sincethe loop body is used.
The main statement in the example is:
bdd result = bdd_and(con1(i), con2(update_i(i)));
which calculates the values of i for which con1 is true and in the next state con2is true.
3.3.3 Comparison
In this section a comparison between the two solutions is made and using thiscomparison a solution will be chosen to be implemented in the prototype ResAna.
The BDD approach has some advantages over the SMT approach. Themain advantage of the BDD approach is the use of the loop body of the originalcode, or at least the statements involving the variable that needs to be updated,instead of doing symbolic execution to analyse the new value after one iteration.In other words, the loop body can be used by itself, whereas update functionsfirst have to be calculated.
Another advantage is that is calculates all satisfiable cases at once. In theexample, i = 19 is a satisfiable case, i.e. condition jumping occurs. When using
the SMT approach, a check has to be done if there is another case of conditionjumping, where i 6= 19. However, the BDD approach will return them all atonce, so less executions need to be done.
Another advantage, especially when using a Java library, is that testing byexecuting a Java program is already used for the Loop Bound Analysis and caneasily be extended to execute condition jumping tests as well.
However, the BDD approach has some disadvantages as well. The maindisadvantage is that Integers are not used in BDDs, only boolean values. Thiscan be solved by using bit vectors, as is done in the BuDDy package for C(++).However, the implementation of bit vectors is incomplete for the C(++) pack-age, since only unsigned integers are supported. Other libraries for BDDs, likeJDD or JavaBDD (two Java implementations of BDDs), do not have bit vectorimplementations. Therefore, the BDD libraries all have to be extended to use(signed) integers as bit vectors.
Moreover, using bit vectors rises the assumption that execution time growsexponentially, with the size the integers used. Therefore, an execution timecomparison is made between the SMT and BDD approach.
Execution time comparison
An execution time comparison has been made, in order to test the extra timeneeded for running SMT or BDD scripts with increasing the size of the variables.
For both SMT and BDD the size of the condition jumping case 19 has beenincreased to 119, 1019, . . . , 10000019 for both one variable and two variables. InTable 3.1 the result for the approach SMT are shown. In Table 3.2 the resultsfor BDD approach are shown. Note that these results only involve running thescripts, i.e. the SMT results do not contain the execution time of the symbolicexecution, which takes a few seconds for these examples.
However, the results are quite clear. When using larger numbers BDDsbecome slow and it is assumed that it grows exponentially, whereas the executiontime of SMT is static and does not change much for larger values. Therefore, forthese timing issues, the SMT approach is regarded as better to create a generalimplementation. It will be slower for small values, because of symbolic executionand more executions of the SMT scripts. However, the execution time will notgrow exponentially and will perform better for larger values than BDDs.
Therefore, the SMT approach is used to solve the condition jumping chal-lenge in the ResAna prototype. Analysing the loop in Listing 3.2, results in the
30 CHAPTER 3. L.B.A. FOR LOOPS WITH DISJUNCTIVE GUARDS
6 if (i > 0) ∧ (i < 20) ∧ (i = 19 ∨ i = 15 ∨ i = 11 ∨ i = 7 ∨ i = 3)5 if (i > 0) ∧ (i < 20)i− 22 if i > 220 else
This is not the precise ranking function as given before. However, it is avalid upper bound.
Chapter 4
Feasibility of Loop BoundAnalysis for Loops withDisjunctive Guards inPractice
In this chapter a feasibility study of Loop Bound Analysis for loops with dis-junctive guards will be performed. First a global study will be performed on16 Java projects. This global evaluation will focus on the number of disjunctiveloops in Java projects and will give an answer to the question: how many loopscontain disjunctive guards?
The second study will be a detailed loop bound analysis on the loops withdisjunctive guards in the source code of Eclipse IDE. Each loop will be exam-ined and a ranking function, if any, will be derived manually. In this chapter anevaluation of the basic method and condition jumping extension will be given.First an analysis of the ratio of condition jumping loops in existing Java pro-grams/projects will be made. This study will give an answer to the question:which loops can be analysed given the current methods?
Given the results of the detailed study the loops will be categorised andfor each category an extension, if possible, will be proposed to infer rankingfunctions for those loops.
4.1 Global Evaluation
In the following sections different Java programs/projects from practice areanalysed in order to find out how many loops contain disjunctive guards. Thisis done by counting first all while-loops and all for-loops and then for both counthow many contain disjunctive guards.
4.1.1 Apache harmony
Apache harmony is a Java runtime environment implementation. The sourcecode can be downloaded at http://harmony.apache.org/.
Number of loops Number of disjunctive loopswhile-loops 3792 39for-loops 14105 5Total 17897 44
4.1.2 Caliper
Caliper is a framework for microbenchmarks. The source code can be down-loaded at http://code.google.com/p/caliper/.
Number of loops Number of disjunctive loopswhile-loops 20 0for-loops 287 0Total 307 0
4.1.3 CDx
Collision Detector (CDx) is a real-time Java benchmark. The source code canbe downloaded at http://sss.cs.purdue.edu/projects/cdx/.
Number of loops Number of disjunctive loopswhile-loops 171 1for-loops 382 0Total 553 1
4.1.4 Eclipse IDE
Eclipse is an open-source Integrated Development Environment (IDE) for Java,but through the use of plug-ins several other programming and scripting lan-guages, like C(++) and python, are supported as well. The source code can bedownloaded at http://www.eclipse.org/.
Number of loops Number of disjunctive loopswhile-loops 9577 125for-loops 35672 9Total 45249 134
4.1.5 GA-Playground
GA-Playground is a toolkit for genetic algorithms written in Java. The sourcecode can be downloaded at http://www.aridolan.com/ofiles/ga/gaa/gaa.
aspx.
Number of loops Number of disjunctive loopswhile-loops 19 1for-loops 222 0Total 241 1
Weka is a collection of machine learning algorithms written in Java for datamining tasks. The source code can be downloaded at http://www.cs.waikato.ac.nz/ml/weka/.
Number of loops Number of disjunctive loopswhile-loops 1155 22for-loops 6026 2Total 7181 24
4.1.17 Totals
In total there were 97664 loops in the projects described above, from which only253 contained disjunctions in their condition, which is less than 0.26%. Thisshows that loops in which condition jumping can occur are very rare.
4.2 Detailed Feasibility Study
None of the loops in the Java programs/projects described in the previous exam-ple, were applicable for the method described in Chapter 3. Therefore, a manualderivation of ranking function will be done for the loops with disjunctive guardsof the Eclipse IDE.
The loops used in this detailed feasibility study are listed in Appendix A.
4.2.1 Detailed Loop Discussion
Listing A.1
The loop is bounded by the number of characters returned by nextChar(), whichis bounded by the size of the array fSmap. However, the function nextChar()is not well defined: the integer fPointer is only checked for equality with thelength of fSmap. Therefore, it is assuming that fPointer is always less thanor equal to the length of fSmap, resulting in an exception, when this is nottrue. It would be better to add an extra check, e.g. using >= or add an extraif-statement.
Upper bound:fSmap.lengthRanking function: fSmap.length− fPointer if fPointer < fSmap.length
1 if fPointer = fSmap.lengthundefined/exception otherwise
Listing A.2
The loop is bounded by the integer length, which is set to the length of string,i.e. the loop is bounded by the length of String string. There is no check inthe loop if i is negative, which would result in an exception, since i is out of thebounds of string. However, this check is not necessary, since i is set to −1 rightbefore the loop is entered.
The loop is bounded by the length of the array lexem. However, there is no checkif index i exceeds the boundaries of the array, which results in an exception.This happens when the array is filled with only spaces (’ ’) and tabs (’\t’).Moreover, the first assignment of variable c is not checked as well, i.e. if lexemis empty, the assignment would result in an exception as well. There is no checkfor i being negative, but this is not strictly necessary, since it is set to 0.
Upper bound:lexem.lenthRanking function:{lexem.length− i if i < lexem.lengthundefined/exception otherwise
The loop is better defined in the following way:
Listing 4.1: Improvement of Listing A.3
1 i f ( lexem . l ength > 0) {2 int i = 0 ;3 char c = lexem [ 0 ] ;4 while(++i < lexem . l ength && ( c == ’ ’ | | c == ’ \ t
’ ) ) {5 c = lexem [ i ] ;6 }7 }
Listing A.4
No upper bound/ranking function can be defined, since the exiting of theloop is defined by the type of the current state, e.g. if the current state isa HttpParser.STATE END state, the loop will be exited.
Listing A.5
No upper bound/ranking function can be defined, since the variables now andend depend on time.
Listing A.6
No upper bound/ranking function can be defined, since it is not possible topredict the value of len in each iteration, it is set using a switch on the variableto flush of which the value is not known statically, i.e. runtime information isneeded.
4.2. DETAILED FEASIBILITY STUDY 37
Listing A.7
No upper bound/ranking function can be defined, since it depends on non-numerical values. Moreover, the check if id is a null-pointer can only be doneat runtime.
Listing A.8
No upper bound/ranking function can be defined. The loop depends on theelements in cache; the loop iterates until cache is empty. However, how manyelements are removed each iteration is unpredictable, since it depends on otherobjects, from which the value is only known at runtime.
Listing A.9
The number of iteration of this loop is bounded by the size of that data structurefor which iter has been created, i.e. destinationRepos.
Upper bound:destinationRepos.size()
It is not possible to define a ranking function given the current loop. It hasto be extended with a counter, which will be explained in Section 4.3.3.
Listing A.10
The number of iterations is bound by the number of elements in the data struc-ture for which iteratorIterator is created. The explanation given in the com-ments of the Java class, show that it is expected that iteratorIterator to con-tain iterators of a certain data type. However, the only type known is Iterator.Therefore, it is not possible to give a concrete upper bound or ranking function,since the Iterator class does not have a size method or field.
Listing A.11
The loop itself shows that the number of iterations is probably bound bythe number of tokens to be processed: nextToken(). However, the functionnextToken(), as defined in the superclass ExpressionParser, gives more infor-mation on the number of tokens, which is bounded by the length of the Stringexpression.
Upper bound:expression.length()Ranking function:{expression.length()− tokenPos if tokenPos < expression.length()0 otherwise
Note that in the function nextToken() the variable top is used to store thevalue of expression.length(). The latter is used in the upper bound and rankingfunction, since expression is a field and is globally accessible, whereas top isjust a local variable.
Listing A.12
The loop is bounded by the length of filterString. However, there is no check ifposition is in the right range, i.e. there should be a check of position is positive
38 CHAPTER 4. FEASIBILITY STUDY
and less than the length of filterString.In the following pos is the notation for the variable position.Upper bound:filterString.length()Ranking function: filterString.length()− pos if pos > 0 ∧ pos < filterString.length()
undefined/exception if pos > 0 ∧ pos > filterString.length()undefined/exception otherwise
A better loop would be:
Listing 4.2: Improvement of Listing A.12
1 i f ( p o s i t i o n > 0 && p o s i t i o n < f i l t e r S t r i n g . l ength ( ) ) {2 int begin = p o s i t i o n ;3 int end = p o s i t i o n ;4 char c = f i l t e r S t r i n g . charAt ( begin ) ;5 while ( p o s i t i o n++ < f i l t e r S t r i n g . l ength ( ) && ! ( c
== ’ ˜ ’ | | c == ’< ’ | | c == ’> ’ | | c == ’=’ | |c == ’ ( ’ | | c == ’ ) ’ ) ) {
6 i f ( ! Character . i sWhitespace ( c ) )7 end = p o s i t i o n ;8 c = f i l t e r S t r i n g . charAt ( p o s i t i o n ) ;9 }
10 }
Listing A.13
The loop itself shows that the number of iterations is probably bound bythe number of tokens to be processed: nextToken(). However, the functionnextToken(), as defined in the superclass ExpressionParser, gives more infor-mation on the number of tokens, which is bounded by the length of the Stringexpression.
Upper bound:expression.length()Ranking function:{expression.length()− tokenPos if tokenPos < expression.length()0 otherwise
Note that in the function nextToken() the variable top is used to store thevalue of expression.length(). The latter is used in the upper bound and rankingfunction, since expression is a field and is globally accessible, whereas top isjust a local variable.
Listing A.14
No upper bound/ranking function can be defined, since the variable delay de-pends on time.
Listing A.15
The loop condition consists of a conjunction. Therefore, both sides of the con-junction can be used as an upper bound. When only using the right part
4.2. DETAILED FEASIBILITY STUDY 39
(readCnt < len) a ranking function can be found using the method describedin Section 2.1.
Upper bound:lenRanking function:{len− readCnt if readCnt < len0 otherwise
The left part of the conjunction can then be used to make the rankingfunction as described above more precise. However, in this case this is notpossible, since both pos and buffer depend on values, which are only availableat runtime.
Listing A.16
No upper bound/ranking function can be defined, since it depends on the exe-cution of other threads.
Listing A.17
No upper bound/ranking function can be defined, since it depends on the exe-cution of other threads.
Listing A.18
No upper bound/ranking function can be defined, since the update of j is re-stricted by some conditions, which depend on values which are only present atruntime. There is the value of j unpredictable.
Listing A.19
The loop is bounded by the number of elements in resources. This is an iteratordefined on selection, which is of the type IStructuredSelection. This has amethod size(), which returns the number of elements in selection.
Upper bound:selection.size()
It is not possible to define a ranking function given the current loop. It hasto be extended with a counter, which will be explained in Section 4.3.3.
Listing A.20
The loop is bound by index+ 1, since index decreases with one every iteration.Upper bound:index+ 1Ranking function:{index+ 1 if index > −10 otherwise
Listing A.21
No upper bound/ranking function can be defined, since scanner depends on astream, for which the number of elements are unknown.
40 CHAPTER 4. FEASIBILITY STUDY
Listing A.22
The number of iterations is bounded by the depth of node in the tree, i.e. thenumber of parents of node. The height/depth of the full tree is the upper bound.However, these numbers can only be specified at runtime, by checking for thisobject, how many times getParent() can be performed until arriving at the rootof the tree.
Listing A.23
The loop is bounded by the number of characters returned by nextChar().However, the number of characters this method returns depends on a stream.Therefore, no concrete upper bound/ranking function can be given.
Listing A.24
The number of iterations of this loop depends on the values of idx and ptr.However, ptr only updates given some constraints, which depend on runtimevalues, which make ptr unpredictable.
Listing A.25
To find a ranking function for this loop, the loop condition has to be split intodifferent pieces. For better understanding, consider the simplified version of theloop:
Listing 4.3: Simplified version of Listing A.25
1 do {2 i f ( f i e l d S t a r t < methodStart && f i e l d S t a r t <
typeStar t ) {3 f i e l d I n d e x ++;4 } else i f ( methodStart < f i e l d S t a r t &&
methodStart < typeStar t ) {5 methodIndex++;6 } else {7 typeIndex++;8 }9 } while ( ( f i e l d I n d e x < f i e ldCount ) | | ( typeIndex <
typeCount ) | | ( methodIndex < methodCount ) ) ;
The following notation will be used for the conditions and variables: A =(fieldIndex < fieldCount), B = (typeIndex < typeCount), C = (methodIndex <methodCount), fC = fieldCount, fI = fieldIndex, tC = typeCount, tI =typeIndex, mC = methodCount and mI = methodIndex.
fC − fI if A ∧ ¬B ∧ ¬CtC − tI if ¬A ∧B ∧ ¬CmC −mI if ¬A ∧ ¬B ∧ C(fC − fI) + (tC − tI) if A ∧B ∧ ¬C(fC − fI) + (mC −mI) if A ∧ ¬B ∧ C(tC − tI) + (mC −mI) if ¬A ∧B ∧ C(fC − fI) + (tC − tI) + (mC −mI) if A ∧B ∧ C1 otherwise
Listing A.26
The loop is bounded by the number of tokens, which are subsets of the stringfContent. Assuming each token contains at least one character, the loop isbounded by the length of fContent.
Upper bound:fContent.length
Listing A.27
The loop is bounded by the number of characters returned by nextChar(), whichis the same as in Listing A.23. However, the number of characters this methodreturns depends on a stream. Therefore, no concrete upper bound/rankingfunction can be given.
Listing A.28
The loop iterates over the characters returned by reader.read(). In the sourcecode it is shown that it either returns a character from fDocument or EOF ,which is −1 after which the loop is exited.
Upper bound:fDocument.getLength() + 1
In the current situation no ranking function can be defined. However, withthe use of a special counter it is possible, as will be explained in Section 4.3.3.
Listing A.29
The number of iterations is bounded by the depth of node in the tree, i.e. thenumber of parents of node. The height/depth of the full tree is the upper bound.However, these numbers can only be specified at runtime, by checking for thisobject how many times getParent() can be performed until arriving at the rootof the tree.
Listing A.30
The number of iterations is bounded by the depth of node in the tree, i.e. thenumber of parents of node. The height/depth of the full tree is the upper bound.However, these numbers can only be specified at runtime, by checking for thisobject how many times getParent() can be performed until arriving at the rootof the tree.
42 CHAPTER 4. FEASIBILITY STUDY
Listing A.31
Similar to Listing A.28. The loop iterates over the characters returned byreader.read(). In the source code it is shown that it either returns a characterfrom fDocument or EOF , which is −1 after which the loop is exited.
Upper bound:fDocument.getLength() + 1
In the current situation no ranking function can be defined. However, withthe use of a special counter it is possible, as will be explained in Section 4.3.3.
Listing A.32
The loop condition consists of two booleans. However, the loop can be simplifiedto the following:
Listing 4.4: Simplified version of Listing A.32
1 while ( i l o c a l < maxLocals | | i s c o p e < maxScopes ) {2 i f ( i s c o p e < maxScopes3 && ( i l o c a l >= maxLocals | | ( this .
subscopes [ i s c o p e ] . s t a r t Index ( ) <=i l o c a l ) ) ) {
4 i s c o p e++;5 } else {6 i l o c a l ++;7 }8 }
This makes the loop similar to the one in Listing A.25. The following no-tations will be used: iL = ilocal, mL = maxLocals, iS = iscope, mS =maxScopes, hasMoreV ariables = ilocal < maxLocals and hasMoreScopes =iscope < maxScopes.
Upper bound:max(0,mL− iL) +max(0,mS − iS)Ranking function:
mL− iL if hasMoreV ariables ∧ ¬hasMoreScopesmS − iS if ¬hasMoreV ariables ∧ hasMoreScopes(mL− iL) + (mS − iS) if hasMoreV ariables ∧ hasMoreScopes0 otherwise
Listing A.33
See Listing A.32.
Listing A.34
The loop iterates through the array unitSource. Therefore, the length of thatarray is the upper bound on the number of iterations. However, it should bechecked that the index begin does not exceed the boundaries of the array.
4.2. DETAILED FEASIBILITY STUDY 43
Upper bound:unitSource.lengthRanking function: Undefined/exception if begin < 0
unitSource.length− begin if begin >= 0 ∧ begin < unitSource.lengthUndefined/exception otherwise
A better loop would be:
Listing 4.5: Improvement of Listing A.34
1 while ( begin > 0 && begin < uni tSource . l ength &&((c =unitSource [ begin ] ) == ’ ’ | | c == ’ \ t ’ ) ) begin++;
Listing A.35
No upper bound/ranking function can be defined, since it depends on non-numerical objects: unclaimedAnnotations.
Listing A.36
The loop iterates through the array unitSource. Therefore, the length of thatarray is the upper bound on the number of iterations. However, it should bechecked that the index begin does not exceed the boundaries of the array.
Upper bound:unitSource.lengthRanking function: Undefined/exception if begin < 0unitSource.length
unitSource.length− begin if begin >= 0 ∧ begin < unitSource.lengthUndefined/exception otherwise
A better loop would be:
Listing 4.6: Improvement of Listing A.36
1 while ( begin > 0 && begin < uni tSource . l ength &&((c =unitSource [ begin ] ) == ’ ’ | | c == ’ \ t ’ ) ) begin++;
Listing A.37
No upper bound/ranking function can be defined, since it depends on non-numerical objects: constructorBinding and enclosingTypeBinding.
Listing A.38
No upper bound/ranking function can be defined, since it depends on non-numerical objects: constructorBinding and enclosingTypeBinding.
Listing A.39
No upper bound/ranking function can be defined, since it depends on non-numerical objects: constructorBinding and enclosingTypeBinding.
44 CHAPTER 4. FEASIBILITY STUDY
Listing A.40
No upper bound/ranking function can be defined, since the variables in the loopcondition are assigned by objects instead of updated, which makes the variablesunpredictable.
Listing A.41
The loop iterates over an array this.source with this.currentPosition as astarting point.
Upper bound:this.source.lengthRanking function: Undefined/exception if pos < 0
where pos = this.currentPosition and length = this.source.length.The loop would be better defined with the following loop condition:
Listing 4.7: Improvement of Listing A.41
1 while ( this . c u r r e n t P o s i t i o n > 0 && this . c u r r e n t P o s i t i o n <this . source . l ength && ( ( this . cur rentCharacter != ’ / ’ )| | ( ! s t a r ) ) )
Listing A.42
See Listing A.41.
Listing A.43
No upper bound/ranking function can be defined, since the variables in the loopcondition are assigned by objects instead of updated, which makes the variablesunpredictable.
Listing A.44
No upper bound/ranking function can be defined, since it depends on a non-numerical object: result.
Listing A.45
It seems that this loop searches for a given value inside an array, possibly startingin the middle of the array and work to the end and repeating at the beginningof the array. However, if the value does not exists in the array, the loop will notstop, since there is no check if a value is checked twice.
A better loop would be:
Listing 4.8: Improvement of Listing A.45
1 int s t a r t P o s i t i o n = index ;
4.2. DETAILED FEASIBILITY STUDY 45
2 while ( index < this . keyTable . l ength && ( ( this . keyTable [index ] != 0) | | ( ( this . keyTable [ index ] == 0) &&(this .valueTable [ index ] != 0) ) ) ) {
3 i f ( this . keyTable [ index ] == key )4 return true ;5 i f (++index == length ) {6 index = 0 ;7 }8 else i f ( index == s t a r t P o s i t i o n )9 break ;
10 }
When arriving at the saved position the loop breaks, since that value has al-ready been checked. The extra check in the loop condition prevents an exceptionin the first iteration.
Upper bound:length
To define a ranking function, an extra counter has to be created, since theindex counter does not grow monotonically, it switches to 0 if it reaches the endof the array. This method will be explained in Section 4.3.3.
Listing A.46
See Listing A.45.
Listing A.47
See Listing A.45.
Listing A.48
See Listing A.45.
Listing A.49
See Listing A.45.
Listing A.50
See Listing A.45.
Listing A.51
The loop iterates through the array unitSource. Therefore, the length of thatarray is the upper bound on the number of iterations. However, it should bechecked that the index begin does not exceed the boundaries of the array.
Upper bound:unitSource.lengthRanking function: Undefined/exception if begin < 0unitSource.length
unitSource.length− begin if begin >= 0 ∧ begin < unitSource.lengthUndefined/exception otherwise
46 CHAPTER 4. FEASIBILITY STUDY
A better loop would be:
Listing 4.9: Improvement of Listing A.51
1 while ( begin > 0 && begin < uni tSource . l ength &&((c =unitSource [ begin ] ) == ’ ’ | | c == ’ \ t ’ ) ) begin++;
Listing A.52
See Listing A.51.
Listing A.53
See Listing A.51.
Listing A.54
The loop iterates through the array unitSource. Therefore, the length of thatarray is the upper bound on the number of iterations. However, it should bechecked that the index end does not exceed the boundaries of the array.
Upper bound:unitSource.lengthRanking function: Undefined/exception if end < 0unitSource.length
unitSource.length− end if end >= 0 ∧ end < unitSource.lengthUndefined/exception otherwise
A better loop would be:
Listing 4.10: Improvement of Listing A.54
1 while ( end > 0 && end < uni tSource . l ength &&((c =unitSource [ end ] ) == ’ ’ | | c == ’ \ t ’ ) ) end++;
Listing A.55
The loop by itself should contain some checks to prevent index out of boundsexception. However, these checks are not needed, since the entering conditionis obtained in the outer loop and the exit condition inside the loop.
Upper bound:length1− index1Ranking function:{length1− index1 if index1 < length11 otherwise
Listing A.56
The loop by itself should contain some checks to prevent index out of boundsexception. However, these checks are not needed, since the entering conditionis obtained in the outer loop and the exit condition inside the loop.
4.2. DETAILED FEASIBILITY STUDY 47
Upper bound:length2− index2Ranking function:{length2− index2 if index2 < length21 otherwise
Listing A.57
The loop iterates over an array this.source with this.currentPosition as astarting point.
Upper bound:this.source.lengthRanking function: Undefined/exception if pos < 0
where pos = this.currentPosition and length = this.source.length.The loop would be better defined with the following loop condition:
Listing 4.11: Improvement of Listing A.57
1 while ( this . c u r r e n t P o s i t i o n > 0 && this . c u r r e n t P o s i t i o n <this . source . l ength && ( ( this . cur rentCharacter != ’ / ’ )| | ( ! s t a r ) ) )
Listing A.58
No upper bound/ranking function can be defined, since it depends on a non-numerical object: field.
Listing A.59
The loop iterates over an array this.source with this.index as a starting point.Upper bound:this.source.lengthRanking function: Undefined/exception if this.index < 0
where length = this.source.length.The loop would be better defined with the following loop condition:
Listing 4.12: Improvement of Listing A.59
1 while ( this . index > 0 && this . index < this . source . l ength&& ( ( this . cur rentCharacter != ’ / ’ ) | | ( ! s t a r ) ) )
Listing A.60
See Listing A.59.
48 CHAPTER 4. FEASIBILITY STUDY
Listing A.61
See Listing A.59.
Listing A.62
No upper bound/ranking function can be defined, since the variables in the loopcondition are assigned by objects instead of updated, which makes the variablesunpredictable.
Listing A.63
The loop iterates over a number of tokens returned by the variable fScanner,which is an IScanner object. An IScanner object cannot return the number oftokens it contains. However, it can return the source of the scanner, which is anarray of characters. Assuming, that one token represents one or more charactersin the source, the following upper bound can be defined:
Upper bound:fScanner.getSource().length
Listing A.64
The loop iterates as long i is smaller than the length of the array cleanUps,where i is used as index for the array, i.e. the loop iterates over the contents ofan array. However, it is never checked whether i >= 0.
Upper bound:cleanUps.lengthRanking function: Undefined/exception if i < 0
cleanUps.length if i >= 0 ∧ i < cleanUps.length0 otherwise
Listing A.65
No upper bound/ranking function can be defined, since it depends on a non-numerical object: javaElem.
Listing A.66
The number of iterations is bounded by the depth of container in the tree, i.e.the number of parents of node. The height/depth of the full tree is the upperbound. However, these numbers can only be specified at runtime, by checkingfor this object how many times getParent() can be performed until arriving atthe root of the tree.
Listing A.67
The number of iterations is bounded by the depth of node in the tree, i.e. thenumber of parents of node. The height/depth of the full tree is the upper bound.However, these numbers can only be specified at runtime, by checking for thisobject how many times getParent() can be performed until arriving at the rootof the tree.
4.2. DETAILED FEASIBILITY STUDY 49
Listing A.68
No upper bound/ranking function can be defined, since it depends on a non-numerical object: id.
Listing A.69
The loop iterates over the contents of the array ZigZag8x8, until the index karrives at end, which probably contains the value of ZigZag8x8.length. How-ever, it would be better to check on ZigZag8x8.length itself instead of end or atleast whether end < ZigZag8x8.length and a check should be added for k > 0.
Upper bound:end+ 1Ranking function:
Undefined/exception if k < 0(end− k) + 1 if k >= 0 ∧ k <= end ∧ end < ZigZag8x8.endUndefined/exception if k >= 0 ∧ k <= end ∧ end >= ZigZag8x8.end0 otherwise
Listing A.70
The loop iterates until h < j. However, those variables are used to access anarray, so it should be checked that j < lengths.length and j > 0.
Upper bound:
d jheRanking function:
Undefined/exception if j < 0 ∧ j >= hif j > 0 ∧ j < lengths.lenth ∧ j >= h
Undefined/exception if j >= lengths.length ∧ j >= h0 otherwise
Listing A.71
No upper bound/ranking function can be defined, since it depends on a non-numerical object: cinfo.
Listing A.72
The loop iterates over the characters in fDocument, in the following abbreviatedto fDoc. However, the index end is not checked to be inside the boundaries, i.e.end > 0 ∧ end < fDoc.getLength().
Upper bound:fDoc.getLength()Ranking function:
Undefined/exception if end < 0fDoc.getLength()− end if end > 0 ∧ end < fDoc.getLength()Undefined/exception if end >= fDoc.getLength()0 otherwise
50 CHAPTER 4. FEASIBILITY STUDY
Listing A.73
No upper bound/ranking function can be defined, since it depends on non-numerical objects: e and p.
Listing A.74
The loop has to be divided in to three different pieces.Upper bound:max(max(0, back + 1),max(0, size− forth))Ranking function:
back + 1 if back >= 0 ∧ ¬(forth < size)size− forth if ¬(back ≥ 0) ∧ forth < sizemax(back + 1, size− forth) if back ≥ 0 ∧ forth < size0 otherwise
Listing A.75
No upper bound/ranking function can be defined, since the variables in the loopcondition are assigned by objects instead of updated, which makes the variablesunpredictable.
Listing A.76
The loop is bounded by l >= min.Upper bound:l −min+ 1Ranking function:{l −min+ 1 if l >= min0 otherwise
Listing A.77
The loop is bounded by l <= max.Upper bound:max− l + 1Ranking function:{max− l + 1 if max <= l0 otherwise
Listing A.78
The loop is bounded by the number of characters returned by nextChar(), whichis the same as in Listing A.23. However, the number of characters this methodreturns depends on a stream. Therefore, no concrete upper bound/rankingfunction can be given.
Listing A.79
No upper bound/ranking function can be defined, since the variables in the loopcondition are assigned by objects instead of updated, which makes the variablesunpredictable.
4.2. DETAILED FEASIBILITY STUDY 51
Listing A.80
The loop iterates until count reaches 0.Upper bound:countRanking function:{count if count > 00 otherwise
Listing A.81
The loop is bounded by the number of tokens returned by the tokenizer. How-ever, the number of tokens is not accessible. This can only be known at runtimeby going through all tokens and count them. The number of tokens is likelybounded by the number of characters in the original text. This text is storedin an array of characters in the Tokenizer. Assuming one token consists of oneor more characters, it is an upper bound to the number of tokens. However,the variable value is marked as protected and is not accessible in this loop.Therefore, upper bound tokenize.value.length cannot be used, unless a getterwill be created for the value field.
Listing A.82
No upper bound/ranking function can be defined, since it depends on a non-numerical object: file.
Listing A.83
No upper bound/ranking function can be defined, since it depends on a non-numerical object: testShell.
Listing A.84
Variable it is a CharacterIterator, which has methods for returning the beginand end index
Upper bound:it.getEndIndex()− it.getBeginIndex()
Listing A.85
No upper bound/ranking function can be defined, since it depends on objects:myIter and yourIter.
Listing A.86
The number of iterations is bounded by the depth of superClass in the tree, i.e.the number of parents of node. The height/depth of the full tree is the upperbound. However, these numbers can only be specified at runtime, by checkingfor this object how many times getSuperclassName() can be performed untilarriving at the root of the tree.
52 CHAPTER 4. FEASIBILITY STUDY
Listing A.87
The number of iterations is bounded by the depth of o in the tree, i.e. thenumber of parents of node. The height/depth of the full tree is the upperbound. However, these numbers can only be specified at runtime, by checkingfor this object how many times getParent() can be performed until arriving atthe root of the tree.
Listing A.88
The loop is bounded by the number of lines in the IDocument doc.Upper bound:doc.getLength()
Listing A.89
The loop is bounded by the number of lines in the IDocument doc.Upper bound:doc.getLength()
Listing A.90
The loop is bounded by the number of characters in newStream. However, itis an input stream, for which the end is only known when its reached, i.e. thenumber of characters can only be known at runtime.
Listing A.91
The loop is bounded by the number of characters in oldStream. However, itis an input stream, for which the end is only known when its reached, i.e. thenumber of characters can only be known at runtime.
Listing A.92
The number of iterations is bounded by the depth of parentPath in the tree,i.e. the number of parents of node. The height/depth of the full tree is theupper bound. However, these numbers can only be specified at runtime, bychecking for this object how many times getParentPath() can be performeduntil arriving at the root of the tree.
Listing A.93
No upper bound/ranking function can be defined, since it depends on a non-numerical object: listener.
Listing A.94
The loop is bounded by the number of lines in reader. However, it is a readerover an input stream, for which the end is only known when its reached, i.e. thenumber of characters can only be known at runtime.
4.2. DETAILED FEASIBILITY STUDY 53
Listing A.95
The loop is bounded by the number of existing names and reserved names.Upper bound:reservednames.size() + contents.length
Listing A.96
The loop is bounded by the number of Items i. The class Item is implementedas a linked list, i.e. adding a pointer to the next Item to the objects. However,the number of items can only be known by iterating all the items and countingthem, which can only be done at runtime.
Listing A.97
The loop iterates of the elements of the array a, using i as its index. However,there is no check on i for being larger than the length of the array. Moreover,the check i 6= −1 should be i > −1, since that would exclude negative numbers,which lead to an exception.
Upper bound:a.lengthRanking function:
Undefined/exception if i < −1Undefined/exception if i = −1i+ 1 if i > −1 ∧ i < a.lengthUndefined/exception otherwise
Listing A.98
See Listing A.97.
Listing A.99
See Listing A.97.
Listing A.100
See Listing A.97.
Listing A.101
See Listing A.97.
Listing A.102
See Listing A.97.
Listing A.103
The loop is bounded by the number of characters in reader.Upper bound:reader.size
54 CHAPTER 4. FEASIBILITY STUDY
Listing A.104
The loop is bounded by the number of characters in reader.Upper bound:reader.size
Listing A.105
No upper bound/ranking function can be defined, since it depends on updatesdone in other threads.
Listing A.106
No upper bound/ranking function can be defined, since it depends on updatesdone in other threads.
Listing A.107
No upper bound/ranking function can be defined, since it depends on updatesdone in other threads.
Listing A.108
No upper bound/ranking function can be defined, since it depends on updatesdone in other threads.
Listing A.109
No upper bound/ranking function can be defined, since the variables in the loopcondition are assigned by objects instead of updated, which makes the variablesunpredictable.
Listing A.110
No upper bound/ranking function can be defined, since it depends on a non-numerical object: current.
Listing A.111
No upper bound/ranking function can be defined, since it depends on a non-numerical object: bucketTable.
Listing A.112
The loop iterates over an array. Therefore, it should have more checks in theloop condition: offset > 0 and offset < b.length.
Two different ranking functions can be given for this loop.Upper bound:remainingRanking function:{remaining if remaining > 00 otherwise
The following ranking function uses the array b and its index offset.
4.2. DETAILED FEASIBILITY STUDY 55
Upper bound:b.lengthRanking function:
Undefined/exception if offset < 0.¯length− offset if offset > 0 ∧ offset < b.lengthUndefined/exception if offset >= b.length0 otherwise
Listing A.113
No upper bound/ranking function can be defined, since the variables in the loopcondition are assigned by objects instead of updated, which makes the variablesunpredictable.
Listing A.114
No upper bound/ranking function can be defined, since it depends on updatesdone in other threads, since t is an object of the class Thread.
Listing A.115
The loop is bounded by the number of tokens in the StringTokenizer st.Upper bound:st.countTokens()
Listing A.116
The number of iterations is bounded by the number of readers returned bygetReader(), which is bounded by readerSources. However, that is an iteratorfor which the number of items has to be calculated at runtime.
Listing A.117
The loop is bounded by the number of lines in the reader in. However, this isa stream. Therefore, no upper bound/ranking functions can be defined.
Listing A.118
The loop is bounded by the number of lines in the reader in. However, this isa stream. Therefore, no upper bound/ranking functions can be defined.
Listing A.119
The loop is bounded by the number of lines in the reader in. However, this isa stream. Therefore, no upper bound/ranking functions can be defined.
Listing A.120
The loop iterates over an array. Therefore, it should have more checks in theloop condition: offset > 0 and offset < b.length.
Two different ranking functions can be given for this loop.
56 CHAPTER 4. FEASIBILITY STUDY
Upper bound:remainingRanking function:{remaining if remaining > 00 otherwise
The following ranking function uses the array b and its index offset.
Upper bound:b.lengthRanking function:
Undefined/exception if offset < 0b.length− offset if offset > 0 ∧ offset < b.lengthUndefined/exception if offset >= b.length0 otherwise
Listing A.121
The loop iterates through two arrays. However, there are no checks if the indexis out of boundary, which should be there.
Undefined/exception if index < 0Undefined/exception if ri < 0max(rl − ri,ml − index) if index > 0 ∧ index < ml ∧ rl >= ml ∧ ri < rlUndefined/exception if ri >= rltextUndefined/exception if index >= ml0 otherwise
where ri = rindex, rl = result.length and ml = m key .length.
Listing A.122
The loop is bounded by strength.
Upper bound:strengthRanking function: Undefined/exception if strength < 0
strength if strength > 0otherwise
Listing A.123
The loop needs to be divided in pieces.
In the following: m0 = m uitlIntBuffer [0], m1 = m uitlIntBuffer [1],m2 = m uitlIntBuffer [2], A = (cei << 1) < m0, B = cei < m1 andC = cei < m2.
4.2. DETAILED FEASIBILITY STUDY 57
Upper bound:max(0,max(dm0− cei
2 e,max(m1− cei,m2− cei)))Ranking function:
dm0− cei2 e if A ∧ ¬B ∧ ¬C
m1− cei if ¬A ∧B ∧ ¬Cm2− cei if ¬A ∧ ¬B ∧ Cmax(dm0− cei
2 e,m1− cei) if A ∧B ∧ ¬Cmax(dm0− cei
2 e,m2− cei) if A ∧ ¬B ∧ Cmax(m1− cei,m2− cei) if ¬A ∧B ∧ Cmax(dm0− cei
2 e,max(m1− cei,m2− cei)) if A ∧B ∧ C0 otherwise
Listing A.124
The loop iterates until m optionarg is greater or equal to optionend.Upper bound:max(0, optionend−m optionarg )Ranking function:{optionend−m optionarg if m optionarg < optionend0 otherwise
Listing A.125
No upper bound/ranking function can be defined, since it depends on objects:the loop condition contains two booleans, which are set depending on runtimevalues.
Listing A.126
The loop is bounded by the number of items in the list changedItem.parent.children.Upper bound:changedItem.parent.children.size()
Listing A.127
The loop iterates over the array providers starting with index i = 0.Upper bound:providers.lengthRanking function:{providers.length− i if providers.length > 00 otherwise
Listing A.128
No upper bound/ranking function can be defined, since the variables in the loopcondition are assigned by objects instead of updated, which makes the variablesunpredictable.
Listing A.129
The loop is similar to the following:
58 CHAPTER 4. FEASIBILITY STUDY
Listing 4.13: Similar version of Listing A.129
1 int column = 0 ;2 do{3 column++;4 } while ( column < columnCount )
In the following cC = columnCount and c = column.Upper bound:columnCountRanking function: 1 if cC = 0
cC − c if cC > 0 ∧ c < cC0 otherwise
Listing A.130
See Listing A.129.
Listing A.131
See Listing A.129.
Listing A.132
The loop is similar to the following:
Listing 4.14: Similar version of Listing A.132
1 int i = 0 ;2 do{3 i ++;4 } while ( i < count )
Upper bound:columnCountRanking function: 1 if count = 0
count− i if count > 0 ∧ i < count0 otherwise
Listing A.133
The loop iterates over the array toSort starting with index i = 0.Upper bound:toSort.lengthRanking function:{toSort.length− i if toSort.length > 00 otherwise
4.3. CATEGORIES OF LOOPS WITH DISJUNCTIVE GUARDS 59
Listing A.134
No upper bound/ranking function can be defined, since it depends on objects:the variables in the loop condition are assigned by objects instead of updated.
4.3 Categories of Loops with Disjunctive Guards
The loops analysed in the previous section can be sorted into different categories:
• Conjunctive Normal Form Elimination: A.2, A.15, A.76, A.77, A.80,A.112, A.122, A.124.
In the following sections those categories are defined and will be presentedwith an explanation of a possible solution and/or future work/research on thetopic.
4.3.1 Conjunctive Normal Form Elimination
The current method (as presented in Chapter 2) only deals with numerical loopconditions. However, many loop conditions contain non-numerical elements,which cannot be handled by the original method, e.g. in the loop in ListingA.2.
In this loop a character c is used. The use of a character is not the problemhere, since characters can be regarded as a numerical value, e.g. using its ASCIIcode. The problem is that the value of character c is unpredictable given thecode, since the next value for c depends on the character in String string atposition i, but the value of string can only be determined at runtime.
Although c cannot be used to determine a ranking function, a part of thecondition does not contain the variable c: + + i < length. Moreover this isconnected to the other parts of the condition using a conjunction. This meansthat to determine an upper bound on the number of iterations, either side ofthe conjunction can be used, since if either the left or the right part is false theloop is exited. Therefore, for loop bound analysis the loop can be transformedto:
Listing 4.15: Conjunctive Normal Form Elimination
1 while (++i < l ength )2 ;
This results in a ranking function of:
{length− (i− 1) if (i− 1) < length0 otherwise
General solution
In general if the loop condition contains parts, which cannot be used for deter-mining a ranking function, the following algorithm can be used:
1. Convert the loop condition to Conjunctive Normal Form (CNF).
2. Check which parts of the condition can be used for the loop bound analysis.For example by using a syntactical analysis to check if the which parts areof the following form:
n∨i=1
(eli b eri)
where b ∈ {<,>,=, 6=,≤,≥}.
3. For the analysis, remove any parts from the loop condition that cannotbe used.
4.3. CATEGORIES OF LOOPS WITH DISJUNCTIVE GUARDS 61
4.3.2 Condition Jumping check error
In Section 3.3.1 a method is given to check for condition jumping in a loop.However, during the detailed study, this method showed insufficient in somecases. The problem is best to be shown with an example. The following is aslightly changed version of the loop in Listing 3.2.
Listing 4.16: Multivariate condition jumping
1 while ( ( i > 0 && i < ( var − 1) ) | | i > ( var + 1) ) {2 i f ( i > ( var + 1) )3 i−−;4 else5 i += 4 ;6 }
In the original version the variable var was a constant with the value 21,which leads to condition jumping when i = 19. Therefore, the SMT solver will(eventually) find the model (i = 19, var = 21) as a case of condition jumping.However, it will also find (i = 1, var = 3), (i = 2, var = 4), (i = 3, var = 5),(i = 4, var = 6), (i = 5, var = 7), (i = 6, var = 8) etc. In theory the listof condition jumping cases would be endless, since for any value of var > 2i = var − 2 will result in condition jumping. However, in reality this would bebounded by the maximum integer value for the SMT solver.
The problem is that var is used as a constant in the loop, since it does notchange during the loop. However, when checking for condition jumping it isregarded as a normal variable, so all the different cases will be summed up.To solve this problem another method should be used, since condition jumpingoccurs when i = var−2, which contains the symbol var and SMT solvers cannothandle symbolic variables by itself.
A possible solution could be to use the SMT solver in combination withpolynomial interpolation as described in Section 2.1.2, i.e. instead of constantcondition jumping cases, use a polynomial to define a set of condition jumpingcases. Let there be the possibility to mark a variable as constant, for examplevar in the example above and use that as a variable in the polynomial. Then tryto interpolate a polynomial for condition jumping cases of a chosen degree. Forthe example above a polynomial of degree one (with one variable var) suffices,i.e. two nodes are needed. Then use the SMT solver to get two models. In thecase of the example above the SMT solvers returns for example: (i = 1, var = 3)and (i = 2, var = 4). Then do polynomial interpolation to find the followingpolynomial: a · var + b = i.
3a+ b = 1
4a+ b = 2
Then a = 1 and b = −2, i.e. i = var − 2.
62 CHAPTER 4. FEASIBILITY STUDY
4.3.3 Iterating through data structures with size field ormethod
This category includes loops that iterate over elements of a data structure. Thiscan be any data structure, but the data structure needs a function or accessiblefield which represents its length, e.g. String.length(). This category is split intotwo subcategories, depending on the use of an index variable, since an index isused to derive a ranking function from the upper bound, i.e. the size of the datastructure.
Since these loops iterate over a data structure, its size will be an upperbound on the number of iterations. Using for example a syntactical analysismethod to check whether a data structure has a field/method which defines itssize, e.g. check if there is an accessible field size or length or a method length()etc.
Instead of using a syntactical analysis method, an annotation can be given tothe data structure, which points to the field or method which contains the sizeinformation of the data structure. This solution works better than a syntacticalanalysis, since it is possible to store the size of a data structure in a field whichis badly named, i.e. the name of the variable does not suggest a size value.However, this will move the responsibility of finding a size field or method fromthe analysis method (or tool) to the author of the code.
In the detailed study a difference is made between local data structuresand iterating through a method call. For the first an analysis can be done asdescribed above. However, for the latter the analysis becomes more complicated,since the data structure is hidden in a method call, which returns the nextvalue. Therefore, a more complex syntactical analysis is needed, which searchesthrough method calls for the iterating data structure and then use the methodabove to find the size of that data structure. However, in this case it is alsopossible to give the responsibility of finding the correct field or method to theauthor of the code, by using an annotation to the loop.
Another distinction made in the evaluation is iteration through a data struc-ture using an iterator. This subcategory contains the loops using an iterator,for which the iterator is created using a data structure. It is not possible to getthe size of standard iterators, since they mainly do not contain size information.However, using the declaration of the iterator, it is possible to derive the datastructure through which it iterates. Then use the method above to find the sizeof that data structure.
With an index variable
When an index variable is present, the derivation of a ranking function is trivial:just subtract the index from the upper bound given by the size of the datastructure.
Without an index variable
To obtain a ranking function, when there is no index variable, it is possible tocreate a new variable which will initial be 0 and increases with 1 every iteration,i.e. this variable simulates an index.
This can be done in two ways:
4.3. CATEGORIES OF LOOPS WITH DISJUNCTIVE GUARDS 63
• add an extra variable which simulates the index. Define a variable beforethe loop and set it to 0 and increase its value every iteration with 1. Forexample in Listing A.9:
Listing 4.17: Index with variables
1 int index = 0 ;2 I t e r a t o r<Repos i toryDescr iptor> i t e r =
dest inat ionRepos . i t e r a t o r ( ) ;3 while ( i t e r . hasNext ( ) && ( a r t i f a c t R e p o D e s c r i p t o r ==
null | | metadataRepoDescriptor == null ) ) {4 Repos i to ryDesc r ip to r repo = i t e r . next ( ) ;5 i f ( repo . i s A r t i f a c t ( ) &&
a r t i f a c t R e p o D e s c r i p t o r == null )6 a r t i f a c t R e p o D e s c r i p t o r = repo ;7 i f ( repo . isMetadata ( ) &&
Note that the solutions above work when the iteration through a data struc-ture visits each element only once. If this is not true the upper bound may
64 CHAPTER 4. FEASIBILITY STUDY
be too small, for example when using both previous() and next() functions initerators. Using syntactical analysis, it is possible to detect this. Then extrapieces can be added, for which an element will be visited more than once.
4.3.4 Iterating through other data structures
This category contains data structures for which no method or field definingthe size of the data structure is available. This category is derived in foursubcategories.
Plain iterators
This subcategory contains loops using an iterator for which the type of the datastructure it iterates is not known. For example in Listing A.10, iteratorIteratoris set in the constructor of the class. However, it is set by an argument of thatconstructor, for which the only type known is Iterator, i.e. the original datastructure could be of any type that can return an Iterator.
The problem with plain iterators is that they do not contain size information,i.e. no upper bound is present. The only way to derive the size of an iterator isby counting the number of elements by iterating. A way to get an upper bound isto extend the iterator with an extra method, which saves the current location inthe data structure, iterates to the end of the data structures, while counting theelements, and then returns to the saved location. Then this function can be usedto in the upper bound. For example, if a variable iter is of the type Iterator,which has been extended with a method getSize(), iter.getSize() would be theupper bound. To obtain a ranking function an index variable needs to be addedas described in the previous section.
Streams
This subcategory contains streams. However, it is not possible to derive anupper bound on the length of a stream. Since the end of a stream is only knownwhen it is reached and it is not possible to go back. Moreover a stream cangrow in time, e.g. when using a stream for user import through the keyboard,it is unpredictable when new input will arrive. Therefore it is not possible tocalculate the length of the stream beforehand.
Other data structures
The last subcategory contains user defined classes which can be iterated. In thiscase, the author of the classes is responsible for creating a size method or field.However, the following generic approach could be used as well.
Generic approach
A generic approach to find the size of a data structure, e.g. linked lists or trees,is to extend the class of the data structure with an extra method. This methodcounts the number of elements in the data structure reachable from this element(including this element). For example in the case of the following class:
4.3. CATEGORIES OF LOOPS WITH DISJUNCTIVE GUARDS 65
Listing 4.19: DataStructure Class
1 public class DataStructure {2 private DataStructure l e f t ;3 private DataStructure r i g h t ;4 }
This data structure is a tree. The following method calculates the number ofelements reachable from an element:
Listing 4.20: Size functions
1 public int g e t S i z e ( ) {2 1 + l e f t . g e t S i z e ( ) + r i g h t . g e t S i z e ( ) ;3 }
In general, the method to calculate the size, or the number of elementsreachable from a given node, is to calculate the recursive sum of 1 (for thiselement) and the size (or number of elements reachable) from the nodes whichthis elements points to, i.e. field pointers of the same type as the current element(in the example represented by variables left and right).
However, since this counts all elements, this can result in a overestimationof the upper bound of the number of iterations. For example in a tree structure,iterating through the nodes is mostly a path from root to leaf. Therefore, insuch cases the depth of the data structure is more useful than the number ofelements. This can be done using the following length function:
Listing 4.21: Max. size functions
1 public int g e t S i z e ( ) {2 1 + max( l e f t . g e t S i z e ( ) , r i g h t . g e t S i z e ( ) ) ;3 }
The Tree examples in the detailed feasibility study started at a node in thetree and would iterate to the root. The previous method would work, if thegetSize() function would be performed on the root. However, the followingwould be the applicable for the current node and would be the most precise:
Listing 4.22: Tree
1 public class DataStructure {2 private DataStructure parent ;3 }
Listing 4.23: Tree size
1 public int g e t S i z e ( ) {2 1 + parent . g e t S i z e ( ) ;3 }
A problem arises when cyclic data structures are used, i.e. if an elementof a data structure can be reached more than once when iterating through the
66 CHAPTER 4. FEASIBILITY STUDY
data structure. The solutions presented above will not terminate in the case ofcyclic data structures. A solution would be to save which elements already arecounted, so they can be skipped. However, in most cases cyclic data structuresare not desirable and are likely to be a bug.
4.3.5 Breaks
This section contains loops, which make use of breaks in the loop body, e.g.Listing A.55. The loop condition contains two statements, which are non-numerical, i.e. this cannot be used to determine a ranking function. However,since the loop contains a break statement, a possibility to derive a rankingfunction is to disregard the loop condition and try to make use of the breakinginside the loop, i.e. change the loop condition to true:
Listing 4.24: Replace loop guard
1 while ( true ) {2 i f (++index1 >= length1 ) break end ;3 }
This simplification can be made, since it will only overestimate the upperbound. However, this kind of loop can be derived using a program transforma-tion:
Listing 4.25: Program transformation
1 do {2 } while(++index1 < l ength1 ) ;
This loop can be derived using the basic method presented in Section 2.1,which results in the following:{
length1− index1 if index1 < length11 otherwise
4.3.6 Time
It is not possible to define an upper bound on loops that depend on time, sincetime is an uncontrollable external factor.
4.3.7 Threads
The same holds for loops that depend on the execution of threads, since waitingfor the execution of other threads is unpredictable.
4.3.8 Unpredictable updates
This category contains loops, which use numerical variables, but those are up-dated in an unpredictable way. For example, an integer is updated using thevalue of an object which can only be determined at runtime or a variable isonly updated given certain constraints, which can only be determined giventheir runtime values. The first is the case in Listing A.6, where integer len isupdated using a switch. The second is the case in Listing A.24, where ptr is
4.4. SUMMARY OF THE PROPOSED IMPROVEMENTS/EXTENSIONS67
only updated when some if-statements are true. However, the values of some ofthe variables in the if-statements are only available at runtime, for example thecontents of an array.
4.3.9 Loops depending on non-numerical values
This category consists of loops, which depend on non-numerical objects. There-fore, no upper bound can be defined.
For example, the loop in Listing A.4 depends on the fact if the current stateis a HttpParser.STATE SEEKING EOF.
4.4 Summary of the proposed improvements/ex-tensions
When parts of the loop condition are not usable for Loop Bound Analysis tryto simplify the loop condition by using Conjunctive Normal Form. If the loopcondition in CNF consists of different parts, check if at least one of the partsis useful. If so, remove all the parts that are not usable and simplify the loopcondition in such a way that loop bound analysis is possible.
When using multiple variables when checking for condition jumping, a prob-lem could occur, since it is possible that the number of condition jumping casesis infinite in theory. However, instead of checking for all distinct condition jump-ing cases, use polynomial interpolation to infer a polynomial which representthe set of condition jumping cases.
When iterating over a data structure, the upper bound on the number ofiterations is the size of that data structure. However, this is not defined for alldata structures. Therefore, it is sometimes needed to extend the code with amethod or field containing the size of a data structure. However, there are alsodata structures for which no upper bound can be given, e.g. streams. When theupper bound is inferred, transform it to a ranking function by using an index,which increases with each iteration.
When the loop condition is not usable and the CNF method cannot beapplied, but the loop can be exited by a break-statement in the loop. Thefollowing program transformation can be applied: create a do-while loop, wherethe loop condition contains the branch-condition of the break-statement.
4.5 Feasibility
In the detailed feasibility study (presented in Section 4.2), none of the loops wereapplicable to the original methods described in Chapters 2 and 3. Therefore, amanual derivation of ranking function was done for 134 loops with disjunctiveguards. This was possible for 84 of those loops. For all those loops a solutionis proposed, raising the number of loops with disjunctive guards for which aranking function can be inferred, from 0 to 84, i.e. from 0% to 62, 7%. Since thenumber of loops with disjunctive guards is 0, 26% of all loops, the gain for theLoop Bound Analysis method is 0, 26%×62, 7% ≈ 0.16% of all loops. Note thatthis only considers the use of the proposed solutions for loops with disjunctiveguards. However, some of the solutions are also applicable to loops without
68 CHAPTER 4. FEASIBILITY STUDY
disjunctive guards, e.g. loops that iterate over data structures, resulting in abigger gain.
The solution with the maximum gain in the detailed study was the solutionconsidering data structures with a size field or method. This solution will raisethe number of applicable loops with disjunctive guards to 52, which is 38, 8%of the total number of loops considered in the detailed study and 61, 9% of themaximum number of loops in the detailed study for which a ranking functioncan be inferred. In other words, more than half of the gain possible by analysingloops with disjunctive guards can be obtained by the proposed solution consid-ering data structures with a size field or method. Note that the total gain willeven be more.
The answer to the question if it is feasible to do Loop Bound Analysis onloops with disjunctive guard, is: yes, it is feasible. However, it is not possiblein all the cases, since it is not possible to define an upper bound on the numberof iterations in certain cases.
Chapter 5
Future work
This chapter contains other future work as an addition to the future work pre-sented in Section 4.3
5.1 Improved branch-splitting
In section 2.2.2 branch-splitting is explained. It is used to handle if-statementsin the loop body. Consider the following loop:
Listing 5.1: Branch-splitting example
1 while ( i > 0) {2 i f ( i > 100)3 i−−;4 else5 i −=10;6 }
Using the original method branch-splitting a ranking function would be d i10e.
However, this is an overestimation for any i > 100. More precise would be:
di10e if i > 0 ∧ i <= 100
(i− 100) + 10 if i > 1000 otherwise
This can be done by altering the node generation instead of splitting theif-statements in the loop. Divide the loop into different pieces, for each branchone and generate nodes for which the initial state satisfies the loop conditionand the branch-condition. However, this method generates some problems, e.g.for the loop in Listing 5.2. The upper bound of the loop is shown in Figure 5.1.
Listing 5.2: Loop with if-statements as given in [27]
1 while ( i > 0) {2 i f ( i > 100)3 i −= 10 ;
69
70 CHAPTER 5. FUTURE WORK
4 else5 i−−;6 }
Figure 5.1: Graph of the upper bound of Listing 2.4
In the previous example, the transition between two branches was with astep of 1. However, in the example shown in Figure 5.1 the transition betweenthe two branches uses a step of 10, resulting in a saw-like graph of the upperbound, called branch jumping. The result is that the precise upper bound of thebranch with i > 100 cannot be expressed in a polynomial. However, by choosingthe right test notes, the polynomial going through the tips of the saw can becalculated. Therefore, to get more precise ranking functions when using branch-splitting, branch jumping needs to be determined and the node generator hasto be altered to choose the right test nodes to get the right polynomial.
5.1.1 Using update functions
The original branch-splitting method, splits the loop on if-statements. How-ever, when calculating update functions (which are needed to determine whethercondition jumping occurs) the branches in the program are calculated, whichin some cases will result in less branches, since multiple if-statements could becombined into one branch.
Moreover, the updates in the loop can be transformed to the updates inupdate functions, since that will have the same effect.
5.2 Loop context
As explained in the basic method (presented in Section 2.1), one of the stepsof the main method is extracting the loop from its context, to place it into atesting context. However, this cannot be applied to every loop, e.g. the loop inListing 5.3.
Listing 5.3: A loop, which needs its context
5.2. LOOP CONTEXT 71
1 public void contextExample ( int i ) {2 Object o = new Object ( ) ;3 while ( i < 10) {4 o . t oS t r i ng ( ) ;5 i ++;6 }7 }
If this loop is extracted from its context, i.e. remove the declaration ofObject o, there will be compilation errors inside the loop, since the object usedinside the loop, o, is not declared then. A simple solution is to remove thestatement with object o inside the loop as well. However, this may lead toincorrect ranking functions. This is not the case for the example in Listing 5.3.However, it is possible that the loop variable is altered by an object declaredoutside the loop (as shown in the examples in Listings 5.4 and 5.5), so thenumber of iterations is dependent on the object and can for that reason notbe removed outside the loop, since it will lead to a wrong ranking function.However, it also does not have the context information it needs, since the objectis declared outside the loop and it may be dependent on values that are onlyavailable at runtime.
Listing 5.4: Loop counter incremented with object
1 public void Example ( int i ) {2 Incrementor incrementor = new Incrementor (2 ) ;3 while ( i < 10) {4 i = incrementor . inc ( i ) ;5 }6 }
Listing 5.5: Incrementor class
1 public class Incrementor {2 int incValue ;34 public Incrementor ( int incValue ) {5 this . incValue = incValue ;6 }78 public i n c ( int i ) {9 return i + incValue ;
10 }11 }
To solve this, two solutions have been devised. The first solution is addingJava Modelling Language (JML) contracts to the methods of the object, whichcontain information about what the function does to the loop variable, or moregenerally give information about what the method returns, since numerical loopvariables can only be changed through an assignment.
The second solution is creating a new testing environment, which will notextract the loop from its context, but will execute the program in such a way
72 CHAPTER 5. FUTURE WORK
that the loop will be entered and such that the runtime context information isavailable.
Chapter 6
Conclusion
In this thesis, the feasibility of Loop Bound Analysis for loops with disjunctiveguards has been researched. This gave the following results.
In the global evaluation the number of loops with disjunctive guards is lessthan 0.26% of all loops, i.e. loops with disjunctive guards are uncommon. There-fore, by adding method to analyse loops with disjunctive guards, result in a smallgain in the number of applicable loops.
A solution to the condition jumping challenge (as described in Chapter 3)has been implemented in the ResAna tool. However, none of the loops withdisjunctive guards in the global evaluation (Section 4.1) were applicable to themethods described in Chapters 2 and 3. In other words, loops with guards overdisjunctions and conjunctions of (in)equalities are even more uncommon.
In the detailed feasibility study, a ranking function and/or upper bound onthe number of iterations could be assigned to 62, 7% of the loops with disjunc-tive guards. The other 37, 3% of the loops with disjunctive guards were de-pendent of time, used threads, had unpredictable variable updates or involvednon-numerical objects.
Some extensions to the Loop Bound Analysis methods by Shkaravska et al.[27] and Kersten and Van Eekelen [21] have been proposed. Those extensionsinvolved: 1) Conjunctive Normal Form Elimination, which removes unusableparts of the loop guards, 2) polynomial interpolation on condition jumpingcases to handle more variables, 3) counting the number of elements of a datastructure and 4) do program transformation, in order to use break-statementsas exit condition.
The overall gain when adding methods to analyse loops with disjunctiveguards is approximately 0.16% of all loops. However, the methods used forloops with disjunctive guards are not exclusive to loops with disjunctive guard,i.e. other loops could be applicable as well. Therefore, the overall gain will bebigger, when considering the gain of loops without disjunctive guards as well.For example, the proposed solution to iterating over data structures is applicableto any loop which involves iterating over a data structure.
Therefore, Loop Bound Analysis on loops with disjunctive guards is feasiblefor certain cases. Adding methods to analyse loops with disjunctive guard,results in a small gain of analysable loops.
73
74 CHAPTER 6. CONCLUSION
Bibliography
[1] Wolfgang Ahrendt, Thomas Baar, Bernhard Beckert, Richard Bubel, Mar-tin Giese, Reiner Hahnle, Wolfram Menzel, Wojciech Mostowski, AndreasRoth, Steffen Schlager, and Peter H. Schmitt. The KeY tool. Software andSystem Modeling, 4:32–54, 2005.
[2] S. B. Akers. Binary decision diagrams. IEEE Trans. Comput., 27(6):509–516, June 1978.
[3] Elvira Albert, Puri Arenas, Samir Genaim, German Puebla, and DamianoZanardini. Cost Analysis of Object-Oriented Bytecode Programs. Theoret-ical Computer Science (Special Issue on Quantitative Aspects of Program-ming Languages), 413(1):142–159, 2012.
[4] Elvira Albert, Richard Bubel, Samir Genaim, Reiner Hahnle, GermanPuebla, and Guillermo Roman-Dıez. Verified resource guarantees usingCOSTA and KeY. In Proceedings of the 20th ACM SIGPLAN workshopon Partial evaluation and program manipulation, PEPM ’11, pages 73–76,New York, NY, USA, 2011. ACM.
[5] Clark Barrett, Aaron Stump, and Cesare Tinelli. The SMT-LIB standard:Version 2.0, September 2012.
[6] Bernhard Beckert, Reiner Hahnle, and Peter H. Schmitt. Verification ofobject-oriented software: The KeY approach. Springer-Verlag, Berlin, Hei-delberg, 2007.
[7] A. Biere, A. Biere, M. Heule, H. van Maaren, and T. Walsh. Handbook ofSatisfiability: Volume 185 Frontiers in Artificial Intelligence and Applica-tions. IOS Press, Amsterdam, The Netherlands, The Netherlands, 2009.
[8] C.K. Chui and M.J. Lai. Vandermonde determinant and langrange inter-polation in Rs. In Nonlinear and convex analysis, pages 23–35, 1987.
[9] David Cok and Joseph Kiniry. ESC/Java2: Uniting ESC/Java and JML.In Gilles Barthe, Lilian Burdy, Marieke Huisman, Jean-Louis Lanet, andTraian Muntean, editors, Construction and Analysis of Safe, Secure, andInteroperable Smart Devices, volume 3362 of Lecture Notes in ComputerScience, pages 108–128. Springer Berlin / Heidelberg, 2005.
[10] K. Czarnecki and A. Wasowski. Feature diagrams and logics: There andback again. In Software Product Line Conference, 2007. SPLC 2007. 11thInternational, pages 23–34, 2007.
75
76 BIBLIOGRAPHY
[11] Marianne de Michiel, Armelle Bonenfant, Hugues Casse, and Pascal Sain-rat. Static loop bound analysis of c programs based on flow analysis andabstract interpretation. In Proceedings of the 2008 14th IEEE Interna-tional Conference on Embedded and Real-Time Computing Systems andApplications, RTCSA ’08, pages 161–166, Washington, DC, USA, 2008.IEEE Computer Society.
[12] Leonardo de Moura and Nikolaj Bjrner. Z3: An efficient SMT solver. InC. Ramakrishnan and Jakob Rehof, editors, Tools and Algorithms for theConstruction and Analysis of Systems, volume 4963 of Lecture Notes inComputer Science, pages 337–340. Springer Berlin / Heidelberg, 2008.
[13] A. Ermedahl, C. Sandberg, J. Gustafsson, S. Bygde, and B. Lisper. Loopbound analysis based on a combination of program slicing, abstract inter-pretation, and invariant analysis. In 7th International Workshop on Worst-Case Execution Time Analysis, (WCET’2007), Pisa, Italy, July 2007.
[14] Cormac Flanagan, K. Rustan M. Leino, Mark Lillibridge, Greg Nelson,James B. Saxe, and Raymie Stata. Extended static checking for Java.SIGPLAN Not., 37(5):234–245, May 2002.
[15] Jdrzej Fulara and Krzysztof Jakubczyk. Practically applicable formal meth-ods. In Jan Leeuwen, Anca Muscholl, David Peleg, Jaroslav Pokorn, andBernhard Rumpe, editors, SOFSEM 2010: Theory and Practice of Com-puter Science, volume 5901 of Lecture Notes in Computer Science, pages407–418. Springer Berlin Heidelberg, 2010.
[16] Sumit Gulwani, Sagar Jain, and Eric Koskinen. Control-flow refinementand progress invariants for bound analysis. SIGPLAN Not., 44(6):375–385,June 2009.
[17] Sumit Gulwani, Krishna K. Mehra, and Trishul Chilimbi. SPEED: pre-cise and efficient static estimation of program computational complexity.SIGPLAN Not., 44(1):127–139, January 2009.
[18] Sumit Gulwani and Florian Zuleger. The reachability-bound problem. SIG-PLAN Not., 45(6):292–304, June 2010.
[19] James J. Hunt, Isabel Tonin, and Fridtjof B. Siebert. Using global dataflow analysis on bytecode to aid worst case execution time analysis for real-time java programs. In Proceedings of the 6th international workshop onJava technologies for real-time and embedded systems, JTRES ’08, pages97–105, New York, NY, USA, 2008. ACM.
[20] Rody Kersten, Olha Shkaravska, Bernard van Gastel, Manuel Montenegro,and Marko van Eekelen. Making resource analysis practical for real-timeJava. In Proceedings of the 10th International Workshop on Java Tech-nologies for Real-time and Embedded Systems, JTRES ’12, pages 135–144,New York, NY, USA, 2012. ACM.
[21] Rody Kersten and Marko van Eekelen. Ranking functions for loops withdisjunctive exit-conditions. Technical report, Dept. Computer Systems andComputing Universidad Complutense de Madrid, 2011.
BIBLIOGRAPHY 77
[22] James C. King. Symbolic execution and program testing. Commun. ACM,19(7):385–394, July 1976.
[23] Paul Lokuciejewski, Daniel Cordes, Heiko Falk, and Peter Marwedel. A fastand precise static loop analysis based on abstract interpretation, programslicing and polytope models. In Proceedings of the 7th annual IEEE/ACMInternational Symposium on Code Generation and Optimization, CGO ’09,pages 136–146, Washington, DC, USA, 2009. IEEE Computer Society.
[24] Manuel Montenegro, Olha Shkaravska, Marko van Eekelen, and RicardoPena. Interpolation-based height analysis for improving a recurrence solver.In Proceedings of the 2nd International Workshop on Foundational Practi-cal Aspects of Resource Analysis, FOPARA’11. Springer, 2012.
[25] Andreas Podelski and Andrey Rybalchenko. A complete method for thesynthesis of linear ranking functions. In Bernhard Steffen and Giorgio Levi,editors, Verification, Model Checking, and Abstract Interpretation, volume2937 of Lecture Notes in Computer Science, pages 239–251. Springer BerlinHeidelberg, 2004.
[26] Dr. Clifford A. Shaffer. Data Structures and Algorithm Analysis. DoverPublications, 2011.
[27] Olha Shkaravska, Rody Kersten, and Marko Van Eekelen. Test-based infer-ence of polynomial loop-bound functions. In Andreas Krall and HanspeterMossenbock, editors, PPPJ’10: Proceedings of the 8th International Con-ference on the Principles and Practice of Programming in Java, ACM Dig-ital Proceedings Series, pages 99–108, 2010.
[28] Olha Shkaravska, Marko van Eekelen, and Alejandro Tamalet. Collectedsize semantics for functional programs over lists. In Proceedings of the20th international conference on Implementation and application of func-tional languages, IFL’08, pages 118–137, Berlin, Heidelberg, 2011. Springer-Verlag.
[29] Olha Shkaravska, Marko C. J. D. van Eekelen, and Ron van Kesteren.Polynomial size analysis of first-order shapely functions. Logical Methodsin Computer Science, 5, issue 2, paper 10:1–35, 2009. Special Issue withSelected Papers from TLCA 2007.
[30] Olha Shkaravska, Ron van Kesteren, and Marko C. J. D. van Eekelen.Polynomial size analysis of first-order functions. In TLCA, pages 351–365,2007.
[31] Alejandro Tamalet, Olha Shkaravska, and Marko van Eekelen. Size analysisof algebraic data types. In Peter Achten, Pieter Koopman, and Marco T.Morazan, editors, Trends in Functional Programming Volume 9 (TFP’08),pages 33–48. Intellect Publishers, 2009.
[32] M. van Eekelen, O. Shkaravska, R. van Kesteren, B. Jacobs, E. Poll, andS. Smetsers. AHA: Amortized Heap Space Usage Analysis. In MarcoMorazan, editor, Trends in Functional Programming Volume 8: Selected
78 BIBLIOGRAPHY
Papers of the 8th International Symposium on Trends in Functional Pro-gramming (TFP07), New York, USA, pages 36–53. Intellect Publishers,UK, 2008.
[33] R. van Kesteren, O. Shkaravska, and M. van Eekelen. Inferring staticnon-monotonically sized types through testing. In Revised Selected Papersof the 16th international Workshop on Functional and (Constraint) LogicProgramming (WFLP) 2007, ENTCS, pages 45–63. Elsevier, 2008.
Appendix A
Loops used in the detailedfeasibility study
In this chapter the loops that are used in the detailed evaluation (Section 4.2) arelisted. Some loops contain extra code for better understanding. Code directlyabove the loop is code in the same method as the loop, Code separated withwhite space is from the same class as the loop and if annotated the code is froma superclass.
1 private char [ ] fSmap ;2 private int fPo in t e r ;34 private char nextChar ( ) {5 i f (++fPo in t e r == fSmap . l ength ) {6 fEOF = true ;7 return ’ \000 ’ ;8 }9 fChar = fSmap [ fPo in t e r ] ;
1 int i = −1, l ength = s t r i n g . l ength ( ) ;2 char c ;3 while (++i < l ength && (( c = s t r i n g . charAt ( i ) ) == ’ ’ | | c == ’\ t ’ ) )4 ;
1 while ( contentView . l ength ( ) == 0 && ! ( i s S t a t e ( HttpParser .STATE END) | |i s S t a t e ( HttpParser .STATE SEEKING EOF) ) && endp !=null && endp .isOpen ( ) )
2 {3 i f ( ! endp . i sB l o ck ing ( ) )4 {5 i f ( parseNext ( )>0)6 continue ;78 i f ( ! endp . blockReadable (maxIdleTime ) )9 {
10 endp . c l o s e ( ) ;11 throw new EofException ( ” timeout ” ) ;12 }13 }1415 parseNext ( ) ;16 }
1 while (now<end && ( content !=null && content . l ength ( )>0 | | bu f f e r !=null &&bu f f e r . l ength ( )>0) && endp . isOpen ( )&& ! endp . isOutputShutdown ( ) )
2 {3 blockForOutput ( end−now) ;4 now=System . cur rentTimeMi l l i s ( ) ;5 }
1 do2 {3 l a s t f l u s h=t o f l u s h ;4 switch ( t o f l u s h )5 {6 case 7 :7 throw new I l l e g a l S t a t eEx c ep t i o n ( ) ; // should
never happen !8 case 6 :9 l en = endp . f l u s h ( header , bu f f e r , null ) ;
10 break ;11 case 5 :12 l en = endp . f l u s h ( header , content , null ) ;13 break ;14 case 4 :15 l en = endp . f l u s h ( header ) ;16 break ;17 case 3 :18 l en = endp . f l u s h ( bu f f e r , content , null ) ;19 break ;20 case 2 :21 l en = endp . f l u s h ( b u f f e r ) ;22 break ;23 case 1 :24 l en = endp . f l u s h ( content ) ;25 break ;26 case 0 :27 {28 l en =0;29 // Nothing more we can wr i t e now .
A.1. WHILE-LOOPS 81
30 i f ( header != null )31 header . c l e a r ( ) ;3233 bypass = fa l se ;34 bufferChunked = fa l se ;3536 i f ( b u f f e r != null )37 {38 bu f f e r . c l e a r ( ) ;39 i f ( contentLength == HttpTokens .
CHUNKEDCONTENT)40 {41 // r e s e r v e some space f o r the
chunk header42 bu f f e r . setPutIndex (CHUNK SPACE)
;43 bu f f e r . setGetIndex (CHUNK SPACE)
;4445 // Spe c i a l case handl ing f o r
smal l l e f t over bu f f e r from46 // an addContent that caused a
bu f f e r f l u s h .47 i f ( content != null && content
. l ength ( ) < bu f f e r . space ( )&& s t a t e !=
STATE FLUSHING)48 {49 bu f f e r . put ( content ) ;50 content . c l e a r ( ) ;51 content=null ;52 }53 }54 }5556 // Are we complete ly f i n i s h e d f o r now?57 i f ( ! needCRLF && ! needEOC && ( content==null
| | content . l ength ( )==0))58 {59 i f ( s t a t e == STATE FLUSHING)60 s t a t e = STATE END;6162 i f ( s t a t e==STATE END && pe r s i s t e n t !=
null && ! p e r s i s t e n t && s t a t u s!=100 && method==null )
63 endp . shutdownOutput ( ) ;64 }65 else66 // Try to prepare more to wr i t e .67 prepareBu f f e r s ( ) ;68 }6970 }7172 i f ( l en > 0)73 t o t a l+=len ;7475 t o f l u s h = flushMask ( ) ;76 }77 // loop whi le p rog r e s s i s being made (OR we have prepared some bu f f e r s
that might make prog r e s s )78 while ( len>0 | | ( t o f l u s h !=0 && l a s t f l u s h==0)) ;
1 while ( id==null | | id . l ength ( ) ==0|| idInUse ( id ) )2 {3 long r0= weakRandom4 ?( hashCode ( ) ˆRuntime . getRuntime ( ) . freeMemory ( ) ˆ random . next Int ( )
ˆ ( ( ( long ) r eques t . hashCode ( ) )<<32))5 : random . nextLong ( ) ;6 i f ( r0<0)
82 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
7 r0=−r0 ;8 long r1= weakRandom9 ?( hashCode ( ) ˆRuntime . getRuntime ( ) . freeMemory ( ) ˆ random . next Int ( )
ˆ ( ( ( long ) r eques t . hashCode ( ) )<<32))10 : random . nextLong ( ) ;11 i f ( r1<0)12 r1=−r1 ;13 id=Long . t oS t r i ng ( r0 , 3 6 )+Long . t oS t r i ng ( r1 , 3 6 ) ;1415 //add in the id o f the node to ensure unique id ac ro s s c l u s t e r16 //NOTE th i s i s d i f f e r e n t to the node s u f f i x which denotes which
node the reques t was r e c e i v ed on17 i f ( workerName!=null )18 id= workerName + id ;19 }
1 while ( cache . s i z e ( )>0 && ( cachedF i l e s . get ( )> maxCachedFiles | |cachedS i ze . get ( )> maxCacheSize ) )
2 {3 // Scan the e n t i r e cache and generate an ordered l i s t by l a s t
acce s s ed time .4 SortedSet<Content> so r t ed= new TreeSet<Content>(5 new Comparator<Content>()6 {7 public int compare ( Content c1 , Content
c2 )8 {9 i f ( c1 . l a s tAcce s s ed<c2 .
l a s tAcc e s s ed )10 return −1;1112 i f ( c1 . l a s tAcce s s ed>c2 .
l a s tAcc e s s ed )13 return 1 ;1415 i f ( c1 . l ength<c2 . l eng th )16 return −1;1718 return c1 . key . compareTo ( c2 . key
) ;19 }20 }) ;21 for ( Content content : cache . va lues ( ) )22 so r t ed . add ( content ) ;2324 // Inva l i d a t e l e a s t r e c en t l y used f i r s t25 for ( Content content : so r t ed )26 {27 i f ( c a chedF i l e s . get ( )<= maxCachedFiles && cachedS i ze .
get ( )<= maxCacheSize )28 break ;29 i f ( content== cache . remove ( content . getKey ( ) ) )30 content . i n v a l i d a t e ( ) ;31 }32 }
1 private List<Repos i toryDescr iptor> dest inat ionRepos = new ArrayList<Repos i toryDescr iptor >() ;
23 I t e r a t o r<Repos i toryDescr iptor> i t e r = dest inat ionRepos . i t e r a t o r ( ) ;4 while ( i t e r . hasNext ( ) && ( a r t i f a c tRepoDes c r i p t o r == null | |
metadataRepoDescriptor == null ) ) {5 Repos i to ryDesc r ip to r repo = i t e r . next ( ) ;6 i f ( repo . i s A r t i f a c t ( ) && ar t i f a c tRepoDes c r i p t o r == null )7 a r t i f a c tRepoDes c r i p t o r = repo ;8 i f ( repo . isMetadata ( ) && metadataRepoDescriptor == null )
1 private f ina l I t e r a t o r <? extends Object> i t e r a t o r I t e r a t o r ;2 private I t e r a t o r<T> c u r r e n t I t e r a t o r ;34 public CompoundIterator ( I t e r a t o r <? extends Object> i t e r a t o r ) {5 this . i t e r a t o r I t e r a t o r = i t e r a t o r ;6 }78 while ( c u r r e n t I t e r a t o r == null | | ! c u r r e n t I t e r a t o r . hasNext ( ) ) {9 i f ( ! i t e r a t o r I t e r a t o r . hasNext ( ) )
10 return fa l se ;1112 Object nex t I t o r = i t e r a t o r I t e r a t o r . next ( ) ;13 c u r r e n t I t e r a t o r = ( nex t I t o r instanceof I t e r a t o r <?>) ? ( I t e r a t o r<
T>) nex t I t o r : Repea tab l e I t e r a to r .<T> c r e a t e ( nex t I t o r ) ;14 }
1 //Def ined in sup e r c l a s s Express ionParser :2 protected St r ing expr e s s i on ;3 protected int tokenPos ;4 protected int currentToken ;5 protected void nextToken ( ) {6 tokenValue = null ;7 int top = expre s s i on . l ength ( ) ;8 char c = 0 ;9 while ( tokenPos < top ) {
10 c = expre s s i on . charAt ( tokenPos ) ;11 i f ( ! Character . i sWhitespace ( c ) )12 break ;13 ++tokenPos ;14 }15 i f ( tokenPos >= top ) {16 lastTokenPos = top ;17 currentToken = TOKENEND;18 return ;19 }2021 lastTokenPos = tokenPos ;22 switch ( c ) {23 case ’ | ’ :24 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’ | ’ ) {25 tokenValue = OPERATOROR;26 currentToken = TOKENOR;27 tokenPos += 2 ;28 } else {29 currentToken = TOKEN PIPE;30 ++tokenPos ;31 }32 break ;3334 case ’& ’ :35 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’&’ ) {36 tokenValue = OPERATORAND;37 currentToken = TOKENAND;38 tokenPos += 2 ;39 } else40 currentToken = TOKENERROR;41 break ;4243 case ’= ’ :44 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’=’ ) {
84 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
45 tokenValue = OPERATOREQUALS;46 currentToken = TOKENEQUAL;47 tokenPos += 2 ;48 } else49 currentToken = TOKENERROR;50 break ;5152 case ’ ! ’ :53 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’=’ ) {54 tokenValue = OPERATORNOT EQUALS;55 currentToken = TOKENNOT EQUAL;56 tokenPos += 2 ;57 } else {58 currentToken = TOKENNOT;59 ++tokenPos ;60 }61 break ;6263 case ’ ˜ ’ :64 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’=’ ) {65 tokenValue = OPERATORMATCHES;66 currentToken = TOKENMATCHES;67 tokenPos += 2 ;68 } else69 currentToken = TOKENERROR;70 break ;7172 case ’> ’ :73 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’=’ ) {74 tokenValue = OPERATORGTEQUAL;75 currentToken = TOKENGREATEREQUAL;76 tokenPos += 2 ;77 } else {78 currentToken = TOKENGREATER;79 ++tokenPos ;80 }81 break ;8283 case ’< ’ :84 i f ( tokenPos + 1 < top && expre s s i on . charAt (
115 currentToken = TOKEN LC;116 ++tokenPos ;117 break ;118119 case ’} ’ :120 currentToken = TOKENRC;121 ++tokenPos ;122 break ;123124 case ’ ( ’ :125 currentToken = TOKEN LP;126 ++tokenPos ;127 break ;128129 case ’ ) ’ :130 currentToken = TOKEN RP;131 ++tokenPos ;132 break ;133134 case ’ [ ’ :135 currentToken = TOKEN LB;136 ++tokenPos ;137 break ;138139 case ’ ] ’ :140 currentToken = TOKENRB;141 ++tokenPos ;142 break ;143144 case ’ , ’ :145 currentToken = TOKENCOMMA;146 ++tokenPos ;147 break ;148149 case ’ ” ’ :150 case ’ \ ’ ’ :151 par s eDe l im i t edSt r ing ( c ) ;152 break ;153154 case ’ / ’ :155 par s eDe l im i t edSt r ing ( c ) ;156 i f ( currentToken == TOKEN LITERAL)157 tokenValue = SimplePattern . compile ( (
S t r ing ) tokenValue ) ;158 break ;159160 default :161 i f ( Character . i sD i g i t ( c ) ) {162 int s t a r t = tokenPos++;163 while ( tokenPos < top && Character .
i sD i g i t ( exp r e s s i on . charAt ( tokenPos )) )
164 ++tokenPos ;165 tokenValue = In t eg e r . valueOf ( exp r e s s i on .
sub s t r i ng ( s ta r t , tokenPos ) ) ;166 currentToken = TOKEN LITERAL;167 break ;168 }169 i f ( Character . i s J a v a I d e n t i f i e r S t a r t ( c ) ) {170 int s t a r t = tokenPos++;171 while ( tokenPos < top && Character .
i s J a v a I d e n t i f i e rP a r t ( expr e s s i on .charAt ( tokenPos ) ) )
172 ++tokenPos ;173 St r ing word = expre s s i on . sub s t r i ng ( s ta r t
, tokenPos ) ;174 In t eg e r token = keywordToTokenMap ( ) . get (
word ) ;175 i f ( token == null )176 currentToken = TOKEN IDENTIFIER;177 else178 currentToken = token . intValue ( ) ;179 tokenValue = word ;180 break ;
86 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
181 }182 throw syntaxError ( ) ;183 }184 }185186 while ( currentToken == TOKENDOT | | currentToken == TOKEN LB) {187 int savePos = tokenPos ;188 int saveToken = currentToken ;189 Object saveTokenValue = tokenValue ;190 nextToken ( ) ;191 i f ( saveToken == TOKENDOT) {192 switch ( currentToken ) {193 case TOKEN IDENTIFIER :194 name = ( St r ing ) tokenValue ;195 nextToken ( ) ;196 i f ( currentToken == TOKEN LP) {197 nextToken ( ) ;198 IExpres s ion [ ] c a l lA rg s =
parseArray ( ) ;199 assertToken (TOKEN RP) ;200 nextToken ( ) ;201 expr = fa c t o ry . memberCall ( expr ,
name , ca l lA rg s ) ;202 } else203 expr = fa c t o ry .member( expr , name
) ;204 break ;205206 default :207 tokenPos = savePos ;208 currentToken = saveToken ;209 tokenValue = saveTokenValue ;210 return expr ;211 }212 } else {213 IExpres s ion atExpr = parseMember ( ) ;214 assertToken (TOKENRB) ;215 nextToken ( ) ;216 expr = fa c t o ry . at ( expr , atExpr ) ;217 }218 }
1 int begin = po s i t i o n ;2 int end = po s i t i o n ;3 char c = f i l t e r S t r i n g . charAt ( begin ) ;4 while ( ! ( c == ’ ˜ ’ | | c == ’< ’ | | c == ’> ’ | | c == ’=’ | | c == ’ ( ’ | | c
== ’ ) ’ ) ) {5 po s i t i o n++;6 i f ( ! Character . i sWhitespace ( c ) )7 end = po s i t i o n ;8 c = f i l t e r S t r i n g . charAt ( po s i t i o n ) ;9 }
1 protected St r ing expr e s s i on ;2 protected int tokenPos ;3 protected int currentToken ;4 protected void nextToken ( ) {5 tokenValue = null ;6 int top = expre s s i on . l ength ( ) ;7 char c = 0 ;8 while ( tokenPos < top ) {9 c = expre s s i on . charAt ( tokenPos ) ;
10 i f ( ! Character . i sWhitespace ( c ) )11 break ;12 ++tokenPos ;13 }
A.1. WHILE-LOOPS 87
14 i f ( tokenPos >= top ) {15 lastTokenPos = top ;16 currentToken = TOKENEND;17 return ;18 }1920 lastTokenPos = tokenPos ;21 switch ( c ) {22 case ’ | ’ :23 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’ | ’ ) {24 tokenValue = OPERATOROR;25 currentToken = TOKENOR;26 tokenPos += 2 ;27 } else {28 currentToken = TOKEN PIPE;29 ++tokenPos ;30 }31 break ;3233 case ’& ’ :34 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’&’ ) {35 tokenValue = OPERATORAND;36 currentToken = TOKENAND;37 tokenPos += 2 ;38 } else39 currentToken = TOKENERROR;40 break ;4142 case ’= ’ :43 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’=’ ) {44 tokenValue = OPERATOREQUALS;45 currentToken = TOKENEQUAL;46 tokenPos += 2 ;47 } else48 currentToken = TOKENERROR;49 break ;5051 case ’ ! ’ :52 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’=’ ) {53 tokenValue = OPERATORNOT EQUALS;54 currentToken = TOKENNOT EQUAL;55 tokenPos += 2 ;56 } else {57 currentToken = TOKENNOT;58 ++tokenPos ;59 }60 break ;6162 case ’ ˜ ’ :63 i f ( tokenPos + 1 < top && expre s s i on . charAt (
tokenPos + 1) == ’=’ ) {64 tokenValue = OPERATORMATCHES;65 currentToken = TOKENMATCHES;66 tokenPos += 2 ;67 } else68 currentToken = TOKENERROR;69 break ;7071 case ’> ’ :72 i f ( tokenPos + 1 < top && expre s s i on . charAt (
100 ++tokenPos ;101 break ;102103 case ’ . ’ :104 currentToken = TOKENDOT;105 ++tokenPos ;106 break ;107108 case ’ $ ’ :109 currentToken = TOKENDOLLAR;110 ++tokenPos ;111 break ;112113 case ’{ ’ :114 currentToken = TOKEN LC;115 ++tokenPos ;116 break ;117118 case ’} ’ :119 currentToken = TOKENRC;120 ++tokenPos ;121 break ;122123 case ’ ( ’ :124 currentToken = TOKEN LP;125 ++tokenPos ;126 break ;127128 case ’ ) ’ :129 currentToken = TOKEN RP;130 ++tokenPos ;131 break ;132133 case ’ [ ’ :134 currentToken = TOKEN LB;135 ++tokenPos ;136 break ;137138 case ’ ] ’ :139 currentToken = TOKENRB;140 ++tokenPos ;141 break ;142143 case ’ , ’ :144 currentToken = TOKENCOMMA;145 ++tokenPos ;146 break ;147148 case ’ ” ’ :149 case ’ \ ’ ’ :150 par s eDe l im i t edSt r ing ( c ) ;151 break ;152153 case ’ / ’ :154 par s eDe l im i t edSt r ing ( c ) ;
A.1. WHILE-LOOPS 89
155 i f ( currentToken == TOKEN LITERAL)156 tokenValue = SimplePattern . compile ( (
S t r ing ) tokenValue ) ;157 break ;158159 default :160 i f ( Character . i sD i g i t ( c ) ) {161 int s t a r t = tokenPos++;162 while ( tokenPos < top && Character .
i sD i g i t ( exp r e s s i on . charAt ( tokenPos )) )
163 ++tokenPos ;164 tokenValue = In t eg e r . valueOf ( exp r e s s i on .
sub s t r i ng ( s ta r t , tokenPos ) ) ;165 currentToken = TOKEN LITERAL;166 break ;167 }168 i f ( Character . i s J a v a I d e n t i f i e r S t a r t ( c ) ) {169 int s t a r t = tokenPos++;170 while ( tokenPos < top && Character .
i s J a v a I d e n t i f i e rP a r t ( expr e s s i on .charAt ( tokenPos ) ) )
171 ++tokenPos ;172 St r ing word = expre s s i on . sub s t r i ng ( s ta r t
, tokenPos ) ;173 In t eg e r token = keywordToTokenMap ( ) . get (
word ) ;174 i f ( token == null )175 currentToken = TOKEN IDENTIFIER;176 else177 currentToken = token . intValue ( ) ;178 tokenValue = word ;179 break ;180 }181 throw syntaxError ( ) ;182 }183 }184185 while ( currentToken == TOKENDOT | | currentToken == TOKEN LB) {186 int savePos = tokenPos ;187 int saveToken = currentToken ;188 Object saveTokenValue = tokenValue ;189 nextToken ( ) ;190 i f ( saveToken == TOKENDOT) {191 switch ( currentToken ) {192 case TOKEN IDENTIFIER :193 name = ( St r ing )
tokenValue ;194 nextToken ( ) ;195 expr = fa c t o ry .member(
1 while ( ! s e tRe su l t && ( delay > 0 | | timeout == 0) ) {
90 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
2 wait ( de lay ) ; // only wait f o r the s p e c i f i e d amount o f time3 i f ( t imeout > 0)4 delay −= (System . cur rentTimeMi l l i s ( ) − startTime ) ;5 }
1 public synchronized int read ( ) {2 while ( cur rent == null && bu f f e r . isEmpty ( ) && ! i sC lo s ed ) {3 try {4 wait ( ) ;5 } catch ( Inter ruptedExcept ion e ) {6 return −1;7 }8 }9 i f ( i sC lo s ed ) {
10 return −1;11 }1213 try {14 i f ( cur rent == null ) {15 cur rent = bu f f e r . remove (0) ;16 return cur rent [ pos++] & 0xFF ;17 } else {1819 return cur rent [ pos++] & 0xFF ;20 }21 } f ina l ly {22 i f ( cur rent != null ) {23 i f ( pos == current . l ength ) {24 cur rent = null ;25 pos = 0 ;26 }27 }28 }29 }3031 while ( ( pos > 0 | | ! b u f f e r . isEmpty ( ) ) && readCnt < l en ) {32 i = read ( ) ;33 i f ( i == −1) {34 return ( readCnt > 0) ? readCnt : i ;35 }36 b [ cur rOf f ] = (byte ) i ;37 cur rOf f++;38 readCnt++;39 }
1 while ( wr i t i ng != null | | wri te r sWait ing != 0) {2 try {3 i f ( wr i t i ng == Thread . currentThread ( ) )4 throw new I l l e g a l S t a t eEx c ep t i o n ( ”Attempted to
nest read lock i n s i d e a wr i t e l ock ” ) ; //$NON−NLS−1$
5 wait ( ) ;6 } catch ( Inter ruptedExcept ion e ) {7 // r e s e t i n t e r rup t ed s t a t e but keep wait ing8 Thread . currentThread ( ) . i n t e r r up t ( ) ;9 }
1 while ( wr i t i ng != null | | currentReaders . s i z e ( ) != 0) {2 try {
A.1. WHILE-LOOPS 91
3 i f ( wr i t i ng == Thread . currentThread ( ) | | currentReaders .conta in s (Thread . currentThread ( ) ) )
4 throw new I l l e g a l S t a t eEx c ep t i o n ( ”Attempted tonest wr i t e l ock i n s i d e a read or wr i t e l ock” ) ; //$NON−NLS−1$
5 wait ( ) ;6 } catch ( Inter ruptedExcept ion e ) {7 // r e s e t i n t e r rup t ed s t a t e but keep wai t ing8 Thread . currentThread ( ) . i n t e r r up t ( ) ;9 }
1 do {2 // w i l l be s e t to f a l s e i f we f i nd a prov ider with remaining3 // elements4 done = true ;5 for ( int i = 0 ; i < prov ide r s . l ength6 && ( showAllMatches | | countTotal < maxCount) ; i
++) {7 i f ( e n t r i e s [ i ] == null ) {8 e n t r i e s [ i ] = new ArrayList ( ) ;9 indexPerProvider [ i ] = 0 ;
10 }11 int count = 0 ;12 QuickAccessProvider prov ide r = prov ide r s [ i ] ;13 i f ( f i l t e r . l ength ( ) > 014 | | prov ide r . i sAlwaysPresent ( )15 | | showAllMatches ) {16 QuickAccessElement [ ] e lements = prov ide r17 . getElementsSorted ( ) ;18 int j = indexPerProvider [ i ] ;19 while ( j < e lements . l ength20 && ( showAllMatches | | ( count <
countPerProvider &&countTotal < maxCount) ) ) {
21 QuickAccessElement element = elements [ j] ;
22 QuickAccessEntry entry ;23 i f ( f i l t e r . l ength ( ) == 0) {24 i f ( i == 0 | | showAllMatches ) {25 entry = new
QuickAccessEntry (element , provider ,
26 new int[ 0 ] [ 0 ] ,
new
int[ 0 ] [ 0 ] );
27 } else {28 entry = null ;29 }30 } else {31 entry = element . match ( f i l t e r ,
p rov ide r ) ;32 }33 i f ( entry != null ) {34 e n t r i e s [ i ] . add ( entry ) ;35 count++;36 countTotal++;37 i f ( i == 0 && entry . element ==
perfectMatch ) {38 perfectMatchAdded = true
;39 maxCount =
MAXCOUNTTOTAL;40 }41 }
92 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
42 j++;43 }44 indexPerProvider [ i ] = j ;45 i f ( j < e lements . l ength ) {46 done = fa l se ;47 }48 }49 }50 // from now on , add one element per prov ider51 countPerProvider = 1 ;52 } while ( ( showAllMatches | | countTotal < maxCount) && ! done ) ;
1 IS t r u c tu r edSe l e c t i on s e l e c t i o n = ( IS t ru c tu r edSe l e c t i on ) getContext ( ) .g e t S e l e c t i o n ( ) ;
2 I t e r a t o r r e s ou r c e s = s e l e c t i o n . i t e r a t o r ( ) ;3 while ( r e s ou r c e s . hasNext ( ) && ( ! hasOpenProjects | | ! hasClosedPro j ec t s | |
hasBui lder | | i s P r o j e c t S e l e c t i o n ) ) {4 Object next = r e s ou r c e s . next ( ) ;5 IP ro j e c t p r o j e c t = null ;67 i f ( next instanceof IP ro j e c t ) {8 p r o j e c t = ( IP ro j e c t ) next ;9 } else i f ( next instanceof IAdaptable ) {
10 p r o j e c t = ( IP ro j e c t ) ( ( IAdaptable ) next ) . getAdapter (IP ro j e c t . class ) ;
11 }1213 i f ( p r o j e c t == null ) {14 i s P r o j e c t S e l e c t i o n = fa l se ;15 continue ;16 }17 i f ( p r o j e c t . isOpen ( ) ) {18 hasOpenProjects = true ;19 i f ( hasBui lder && ! hasBui lder ( p r o j e c t ) ) {20 hasBui lder = fa l se ;21 }22 } else {23 hasClosedPro j ec t s = true ;24 hasBui lder = fa l se ;25 }26 }
1 while ( te rmina l != ITerminalSymbols .TokenNameEOF && ! ( te rmina l ==ITerminalSymbols . TokenNameclass | | te rmina l == ITerminalSymbols .TokenNameinterface | | te rmina l == ITerminalSymbols . TokenNameenum | |( foundComment && ( termina l == ITerminalSymbols . TokenNameimport | |
te rmina l == ITerminalSymbols . TokenNamepackage ) ) ) ) {23 i f ( te rmina l == ITerminalSymbols .TokenNameCOMMENT JAVADOC | |
te rmina l == ITerminalSymbols .TokenNameCOMMENT BLOCK | |te rmina l == ITerminalSymbols .TokenNameCOMMENT LINE) {
1 //As de f ined in sup e r c l a s s Subst i tut ionTextReader :2 protected int nextChar ( ) throws IOException {3 this . fReadFromBuffer= ( this . fBu f f e r . l ength ( ) > 0) ;4 i f ( this . fReadFromBuffer ) {5 char ch= this . fBu f f e r . charAt ( this . f Index++) ;6 i f ( this . f Index >= this . fBu f f e r . l ength ( ) ) {7 this . fBu f f e r . setLength (0) ;8 this . f Index= 0 ;9 }
10 return ch ;11 } else {12 int ch= this . fCharAfterWhiteSpace ;13 i f ( ch == −1) {14 ch= this . fReader . read ( ) ;15 }16 i f ( this . fSkipWhiteSpace && ScannerHelper . i sWhitespace ( (
char ) ch ) ) {17 do {18 ch= this . fReader . read ( ) ;19 } while ( ScannerHelper . i sWhitespace ( ( char ) ch ) ) ;20 i f ( ch != −1) {21 this . fCharAfterWhiteSpace= ch ;22 return ’ ’ ;23 }24 } else {25 this . fCharAfterWhiteSpace= −1;26 }27 return ch ;28 }29 }3031 while ( ScannerHelper . i sL e t t e rOrD ig i t ( ( char ) ch ) | | ch == ’#’ ) {32 buf . append ( ( char ) ch ) ;33 ch= nextChar ( ) ;34 }
1 while ( idx<=this . s epa ra to r sPt r | | ( this . htmlNodesPtr != −1 && ptr <=this . htmlNodesPtr ) ) {
2 i f ( idx > this . s epa ra to r sPt r ) {3 // l a s t node4 FormatJavadocNode node = this . htmlNodes [ ptr++];5 node . toStringDebug ( bu f f e r , source ) ;6 return ;7 }8 int end = ( int ) ( this . s epa ra to r s [ idx ] >>> 32) ;9 i f ( this . htmlNodesPtr >= 0 && ptr <= this . htmlNodesPtr && end >
this . htmlNodes [ ptr ] . s ou r c eS ta r t ) {10 FormatJavadocNode node = this . htmlNodes [ ptr++];
94 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
11 node . toStringDebug ( bu f f e r , source ) ;12 } else {13 i f ( idx > 1 && source [ nextStar t ] != ’< ’ ) {14 bu f f e r . append ( ’\n ’ ) ;15 for ( int t=0; t<this . depth ; t++) bu f f e r . append ( ’
\ t ’ ) ;16 }17 bu f f e r . append ( source , nextStart , end − nextStar t + 1) ;18 }19 nextStar t = ( int ) this . s epa ra to r s [ idx++];20 }
1 do {2 i f ( f i e l d S t a r t < methodStart && f i e l d S t a r t < typeStar t ) {3 i f ( f i e l d . getKind ( ) == Abst rac tVar iab l eDec la ra t i on .
ENUMCONSTANT) {4 // f i l t e r out enum constants5 p r ev i ou sF i e l dS ta r t = f i e l d S t a r t ;6 i f (++f i e l d I nd e x < f i e ldCount ) { // f i nd next
f i e l d i f any7 f i e l d S t a r t = ( f i e l d = typeDec la rat ion .
f i e l d s [ f i e l d I nd e x ] ) .d e c l a r a t i onSou r c eS ta r t ;
8 } else {9 f i e l d S t a r t = In t eg e r .MAXVALUE;
10 }11 continue ;12 }13 // next member i s a f i e l d14 i f ( f i e l d S t a r t == prev i ou sF i e l dS ta r t ){15 ASTNode previousMember = members [ index − 1 ] ;16 i f ( previousMember instanceof
Mult iF i e ldDec la ra t i on ) {17 Mul t iF i e ldDec la ra t i on mul t iF i e ld = (
Mul t iF i e ldDec la ra t i on )previousMember ;
18 int l ength = mul t iF i e ld . d e c l a r a t i o n s .l ength ;
19 System . arraycopy ( mul t iF i e ld . d e c l a r a t i on s, 0 , mu l t iF i e ld . d e c l a r a t i o n s=newFi e ldDec l a r a t i on [ l ength +1] , 0 ,l ength ) ;
20 mul t iF i e ld . d e c l a r a t i o n s [ l ength ] = f i e l d ;21 } else {22 F i e l dDec l a ra t i on f i e l dD e c l a r a t i o n = (
F i e ldDec l a r a t i on ) previousMember ;23 f ina l Mult iF i e ldDec la ra t i on
mu l t iF i e l dDec l a ra t i on = newMult iF i e ldDec la ra t i on (newFi e ldDec l a r a t i on [ ] {f i e l dDe c l a r a t i o n , f i e l d }) ;
24 mu l t iF i e l dDec l a ra t i on . annotat ions =f i e l dDe c l a r a t i o n . annotat ions ;
25 members [ index − 1 ] =mul t iF i e l dDec l a ra t i on ;
26 }27 } else {28 members [ index++] = f i e l d ;29 }30 p r ev i ou sF i e l dS ta r t = f i e l d S t a r t ;31 i f (++f i e l d I nd e x < f i e ldCount ) { // f i nd next f i e l d i f
any32 f i e l d S t a r t = ( f i e l d = typeDec la rat ion . f i e l d s [
f i e l d I nd e x ] ) . d e c l a r a t i onSou r c eS ta r t ;33 } else {34 f i e l d S t a r t = In t eg e r .MAXVALUE;35 }36 } else i f ( methodStart < f i e l d S t a r t && methodStart < typeStar t )
{37 // next member i s a method
A.1. WHILE-LOOPS 95
38 i f ( ! method . i sDe fau l tCons t ruc to r ( ) && ! method . i s C l i n i t ( )) {
39 members [ index++] = method ;40 }41 i f (++methodIndex < methodCount ) { // f i nd next method
i f any42 methodStart = (method = typeDec la rat ion . methods [
methodIndex ] ) . d e c l a r a t i onSou r c eS ta r t ;43 } else {44 methodStart = In t eg e r .MAXVALUE;45 }46 } else {47 // next member i s a type48 members [ index++] = type ;49 i f (++typeIndex < typeCount ) { // f i nd next type i f any50 typeStar t = ( type = typeDec la rat ion . memberTypes [
typeIndex ] ) . d e c l a r a t i onSou r c eS ta r t ;51 } else {52 typeStar t = In t eg e r .MAXVALUE;53 }54 }55 } while ( ( f i e l d I nd e x < f i e ldCount ) | | ( typeIndex < typeCount ) | | (
1 //Def ined in the s up e r c l a s s Spe l lCheck I t e r a to r :2 protected f ina l St r ing fContent ;3 protected St r ing nextToken ( ) {45 St r ing token= null ;67 fPrev ious= fPrede c e s s o r ;8 f S ta r t sS en t enc e= fa l se ;9
10 nextBreak ( ) ;1112 boolean update= fa l se ;13 i f ( fNext − fPrev ious > 0) {1415 i f ( f Suc c e s s o r != Break I t e ra to r .DONE && fContent . charAt (
fPrev ious ) == IJavaDocTagConstants .JAVADOC TAG PREFIX) {
1617 nextBreak ( ) ;18 i f ( Character . i s L e t t e r ( fContent . charAt ( fPrev ious
+ 1) ) ) {19 update= true ;20 token= fContent . sub s t r i ng ( fPrev ious ,
fNext ) ;21 } else22 fPr edec e s s o r= fNext ;2324 } else i f ( f Suc c e s s o r != Break I t e ra to r .DONE && fContent .
charAt ( fPrev ious ) == IHtmlTagConstants .HTML TAG PREFIX && ( Character . i s L e t t e r ( fContent .charAt ( fNext ) ) | | fContent . charAt ( fNext ) == ’ / ’ ) ) {
2526 i f ( fContent . s tartsWith ( IHtmlTagConstants .
HTML CLOSE PREFIX, fPrev ious ) )27 nextBreak ( ) ;2829 nextBreak ( ) ;3031 i f ( f Suc c e s s o r != Break I t e ra to r .DONE && fContent
45 update= true ;46 } else47 token= fContent . sub s t r i ng (
fPrev ious , fNext ) ;48 } else49 token= fContent . sub s t r i ng ( fPrev ious ,
fNext ) ;5051 update= true ;52 } else i f ( ! i sWhitespace ( fPrev ious , fNext ) &&
isAlphaNumeric ( fPrev ious , fNext ) ) {5354 i f ( isUrlToken ( fPrev ious ) )55 skipTokens ( fPrev ious , WHITE SPACE TOKEN)
;56 else i f ( isToken ( IJavaDocTagConstants .
JAVADOCPARAMTAGS) )57 fLastToken= null ;58 else i f ( isToken ( IJavaDocTagConstants .
JAVADOC REFERENCE TAGS) ) {59 fLastToken= null ;60 skipTokens ( fPrev ious , fDe l im i t e r . charAt
(0) ) ;61 } else i f ( fNext − fPrev ious > 1 | |
i s S i n g l e L e t t e r ( fPrev ious ) && !f I s I g n o r i n g S i n g l e L e t t e r s )
62 token= fContent . sub s t r i ng ( fPrev ious ,fNext ) ;
6364 update= true ;65 }66 }6768 i f ( update && fSentenceBreaks . s i z e ( ) > 0) {6970 i f ( fPrev ious >= nextSentence ( ) ) {7172 while ( fSentenceBreaks . s i z e ( ) > 0 && fPrev ious
>= nextSentence ( ) )73 fSentenceBreaks . removeFirst ( ) ;7475 fS ta r t sSen t enc e= ( fLastToken == null ) | | ( token
!= null ) ;76 }77 }78 return token ;79 }8081 while ( f Suc c e s s o r != Break I t e ra to r .DONE && ( token == null | | fContent .
charAt ( fNext ) == ’&’ ) ) {82 i f ( token != null ) {83 i f ( prev ious == −1)84 prev ious= fPrev ious ;85 St r ing nextToken= nextToken ( ) ;86 i f ( nextToken != null )
A.1. WHILE-LOOPS 97
87 token= token + nextToken . sub s t r i ng (1) ;88 else89 token= token + ’&’ ;90 } else91 token= nextToken ( ) ;92 }
1 //As de f ined in sup e r c l a s s Subst i tut ionTextReader :2 protected int nextChar ( ) throws IOException {3 this . fReadFromBuffer= ( this . fBu f f e r . l ength ( ) > 0) ;4 i f ( this . fReadFromBuffer ) {5 char ch= this . fBu f f e r . charAt ( this . f Index++) ;6 i f ( this . f Index >= this . fBu f f e r . l ength ( ) ) {7 this . fBu f f e r . setLength (0) ;8 this . f Index= 0 ;9 }
10 return ch ;11 } else {12 int ch= this . fCharAfterWhiteSpace ;13 i f ( ch == −1) {14 ch= this . fReader . read ( ) ;15 }16 i f ( this . fSkipWhiteSpace && ScannerHelper . i sWhitespace ( (
char ) ch ) ) {17 do {18 ch= this . fReader . read ( ) ;19 } while ( ScannerHelper . i sWhitespace ( ( char ) ch ) ) ;20 i f ( ch != −1) {21 this . fCharAfterWhiteSpace= ch ;22 return ’ ’ ;23 }24 } else {25 this . fCharAfterWhiteSpace= −1;26 }27 return ch ;28 }29 }3031 while ( c == ’ . ’ | | c != −1 && Character . i s L e t t e r ( ( char ) c ) ) {32 bu f f e r . append ( ( char ) c ) ;33 c= nextChar ( ) ;34 }
1 //Def ined in the s up e r c l a s s JavaCodeReader2 public stat ic f ina l int EOF= −1;3 public int read ( ) throws IOException {4 try {5 return fForward ? readForwards ( ) : readBackwards ( ) ;6 } catch ( BadLocationException x ) {7 throw new IOException (x . getMessage ( ) ) ;8 }9 }
10 private int readForwards ( ) throws BadLocationException {11 while ( fO f f s e t < fEnd ) {12 char cur rent= fDocument . getChar ( fO f f s e t++) ;1314 switch ( cur rent ) {15 case ’ / ’ :16 i f ( fSkipComments && fO f f s e t < fEnd ) {17 char next= fDocument . getChar (
fO f f s e t ) ;18 i f ( next == ’∗ ’ ) {
98 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
19 // a comment s t a r t s ,advance to thecomment end
20 ++ fO f f s e t ;21 gotoCommentEnd ( ) ;22 continue ;23 } else i f ( next == ’ / ’ ) {24 // ’// ’−comment s t a r t s ,
advance to the l i n eend
25 gotoLineEnd ( ) ;26 continue ;27 }28 }29 return cur rent ;3031 case ’ ” ’ :32 case ’ \ ’ ’ :33 i f ( f Sk i pS t r i n g s ) {34 gotoStringEnd ( cur rent ) ;35 continue ;36 }37 return cur rent ;38 }39 return cur rent ;40 }41 return EOF;42 }43 private int readBackwards ( ) throws BadLocationException {44 while (0 < fO f f s e t ) {45 −− fO f f s e t ;4647 handleSingleLineComment ( ) ;4849 char cur rent= fDocument . getChar ( fO f f s e t ) ;50 switch ( cur rent ) {51 case ’ / ’ :52 i f ( fSkipComments && fO f f s e t > 1) {53 char next= fDocument . getChar (
fO f f s e t − 1) ;54 i f ( next == ’∗ ’ ) {55 // a comment ends ,
advance to thecomment s t a r t
56 fO f f s e t −= 2 ;57 gotoCommentStart ( ) ;58 continue ;59 }60 }61 return cur rent ;6263 case ’ ” ’ :64 case ’ \ ’ ’ :6566 i f ( f Sk i pS t r i n g s ) {67 −− fO f f s e t ;68 go toS t r i ngS ta r t ( cur rent ) ;69 continue ;70 }7172 return cur rent ;73 }74 return cur rent ;75 }76 return EOF;77 }78 }7980 while ( c != −1 && ( c == ’\ r ’ | | c == ’\n ’ ) ) {81 c= reader . read ( ) ;82 }
1 while ( l o c == Qual i f iedType .NAMEPROPERTY | | l o c == Qualif iedName .NAMEPROPERTY | | l o c == SimpleType .NAMEPROPERTY | | l o c ==ParameterizedType .TYPE PROPERTY) {
2 node= node . getParent ( ) ;3 l o c= node . getLocat ionInParent ( ) ;4 }
1 while ( node != null && ( r e l a t i v eO f f s e t == node . g e tS t a r tPo s i t i on ( ) | |r e l a t i v eO f f s e t == node . g e tS t a r tPo s i t i on ( ) + node . getLength ( ) ) )
1 //Def ined in the s up e r c l a s s JavaCodeReader2 public stat ic f ina l int EOF= −1;3 public int read ( ) throws IOException {4 try {5 return fForward ? readForwards ( ) : readBackwards ( ) ;6 } catch ( BadLocationException x ) {7 throw new IOException (x . getMessage ( ) ) ;8 }9 }
10 private int readForwards ( ) throws BadLocationException {11 while ( fO f f s e t < fEnd ) {12 char cur rent= fDocument . getChar ( fO f f s e t++) ;1314 switch ( cur rent ) {15 case ’ / ’ :16 i f ( fSkipComments && fO f f s e t < fEnd ) {17 char next= fDocument . getChar (
fO f f s e t ) ;18 i f ( next == ’∗ ’ ) {19 // a comment s t a r t s ,
advance to thecomment end
20 ++ fO f f s e t ;21 gotoCommentEnd ( ) ;22 continue ;23 } else i f ( next == ’ / ’ ) {24 // ’// ’−comment s t a r t s ,
advance to the l i n eend
25 gotoLineEnd ( ) ;26 continue ;27 }28 }29 return cur rent ;3031 case ’ ” ’ :32 case ’ \ ’ ’ :33 i f ( f Sk i pS t r i n g s ) {34 gotoStringEnd ( cur rent ) ;35 continue ;36 }37 return cur rent ;38 }39 return cur rent ;40 }41 return EOF;42 }43 private int readBackwards ( ) throws BadLocationException {44 while (0 < fO f f s e t ) {45 −− fO f f s e t ;46
100 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
47 handleSingleLineComment ( ) ;4849 char cur rent= fDocument . getChar ( fO f f s e t ) ;50 switch ( cur rent ) {51 case ’ / ’ :52 i f ( fSkipComments && fO f f s e t > 1) {53 char next= fDocument . getChar (
fO f f s e t − 1) ;54 i f ( next == ’∗ ’ ) {55 // a comment ends ,
advance to thecomment s t a r t
56 fO f f s e t −= 2 ;57 gotoCommentStart ( ) ;58 continue ;59 }60 }61 return cur rent ;6263 case ’ ” ’ :64 case ’ \ ’ ’ :6566 i f ( f Sk i pS t r i n g s ) {67 −− fO f f s e t ;68 go toS t r i ngS ta r t ( cur rent ) ;69 continue ;70 }7172 return cur rent ;73 }74 return cur rent ;75 }76 return EOF;77 }78 }7980 while ( c != −1 && ( c == ’\ r ’ | | c == ’\n ’ | | c == ’\ t ’ ) ) {81 c= reader . read ( ) ;82 }
1 while ( hasMoreVariables | | hasMoreScopes ) {2 i f ( hasMoreScopes3 && ( ! hasMoreVariables | | ( this . subscopes [ i s c ope ] .
s t a r t Index ( ) <= i l o c a l ) ) ) {4 // cons id e r subscope f i r s t5 i f ( this . subscopes [ i s c ope ] instanceof BlockScope ) {6 BlockScope subscope = ( BlockScope ) this .
subscopes [ i s c ope ] ;7 int subOf f s e t = subscope . s h i f t S c op e s == null ?
this . o f f s e t : subscope . maxShi f tedOf f set ( ) ;8 subscope . computeLoca lVar iab lePos i t ions (0 ,
subOffset , codeStream ) ;9 i f ( subscope . maxOffset > this . maxOffset )
10 this . maxOffset = subscope . maxOffset ;11 }12 hasMoreScopes = ++i s cope < maxScopes ;13 } else {1415 // cons id e r va r i ab l e f i r s t16 Loca lVar iab leBinding l o c a l = this . l o c a l s [ i l o c a l ] ; // i f
no l o c a l at a l l , w i l l be l o c a l s [ i l o c a l ]==nu l l1718 // check i f v a r i ab l e i s a c t ua l l y used , and may f o r c e i t
to be prese rved19 boolean generateCurrentLocalVar = ( l o c a l . useFlag >
Loca lVar iab leBinding .UNUSED && l o c a l . constant ( ) ==Constant . NotAConstant ) ;
2021 // do not r epor t fake used va r i ab l e22 i f ( l o c a l . useFlag == Loca lVar iab leBinding .UNUSED
A.1. WHILE-LOOPS 101
23 && ( l o c a l . d e c l a r a t i on != null ) // unused ( andnon s e c r e t ) l o c a l
24 && (( l o c a l . d e c l a r a t i on . b i t s & ASTNode .I sLoca lDec la ra t ionReachab l e ) != 0) ) { //de c l a r a t i on i s r eachab le
2526 i f ( ! ( l o c a l . d e c l a r a t i on instanceof Argument ) ) //
do not r epor t unused catch arguments27 problemReporter ( ) . unusedLocalVar iable (
l o c a l . d e c l a r a t i on ) ;28 }2930 // could be opt imized out , but does need to pre s e rve
unread va r i a b l e s ?31 i f ( ! generateCurrentLocalVar ) {32 i f ( l o c a l . d e c l a r a t i on != null && compi lerOptions
( ) . p r e s e rv eA l lLoca lVa r i ab l e s ) {33 generateCurrentLocalVar = true ; // f o r c e
i t to be prese rved in thegenerated code
34 i f ( l o c a l . useFlag ==Loca lVar iab leBinding .UNUSED)
35 l o c a l . useFlag =Loca lVar iab leBinding .USED;
36 }37 }3839 // a l l o c a t e va r i ab l e40 i f ( generateCurrentLocalVar ) {4142 i f ( l o c a l . d e c l a r a t i on != null ) {43 codeStream . record ( l o c a l ) ; // record user
−de f ined l o c a l v a r i a b l e s f o ra t t r i bu t e genera t i on
44 }45 // a s s i gn va r i ab l e p o s i t i o n46 l o c a l . r e s o l v edPo s i t i on = this . o f f s e t ;4748 i f ( ( l o c a l . type == TypeBinding .LONG) | | ( l o c a l .
type == TypeBinding .DOUBLE) ) {49 this . o f f s e t += 2 ;50 } else {51 this . o f f s e t++;52 }53 i f ( this . o f f s e t > 0xFFFF) { // no more than
65535 words o f l o c a l s54 problemReporter ( ) .
noMoreAvailableSpaceForLocal (55 l o ca l ,56 l o c a l . d e c l a r a t i on == null ? (
ASTNode)methodScope ( ) .r e f e r enceContext : l o c a l .d e c l a r a t i on ) ;
57 }58 } else {59 l o c a l . r e s o l v edPo s i t i on = −1; // not generated60 }61 hasMoreVariables = ++i l o c a l < maxLocals ;62 }63 }
1 while ( hasMoreVariables | | hasMoreScopes ) {2 i f ( hasMoreScopes3 && ( ! hasMoreVariables | | ( this . subscopes [ i s c ope ] .
s t a r t Index ( ) <= i l o c a l ) ) ) {4 // cons ide r subscope f i r s t5 Scope subscope = this . subscopes [ i s c ope ] ;6 i f ( subscope . kind == Scope .BLOCK SCOPE) { // do not dive
in nested types
102 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
7 l o c a lDe c l a r a t i o n s = ( ( BlockScope ) subscope ) .f i ndLoca lVa r i ab l eDec l a r a t i on s ( p o s i t i o n ) ;
8 i f ( l o c a lD e c l a r a t i o n s != null ) {9 return l o c a lD e c l a r a t i o n s ;
10 }11 }12 hasMoreScopes = ++i s cope < maxScopes ;13 } else {14 // cons id e r va r i ab l e f i r s t15 Loca lVar iab leBinding l o c a l = this . l o c a l s [ i l o c a l ] ; // i f
no l o c a l at a l l , w i l l be l o c a l s [ i l o c a l ]==nu l l16 i f ( l o c a l != null ) {17 Loca lDec la ra t i on l o c a lDe c l = l o c a l . d e c l a r a t i on ;18 i f ( l o c a lDe c l != null ) {19 i f ( l o c a lDe c l . d e c l a r a t i onSou r c eS ta r t <=
po s i t i o n ) {20 i f ( p o s i t i o n <= lo ca lDe c l .
dec larat ionSourceEnd ) {21 i f ( l o c a lD e c l a r a t i o n s ==
null ) {22 l o c a lD e c l a r a t i o n s
= newLoca lDec la ra t i on[ maxLocals] ;
23 }24 l o c a lDe c l a r a t i o n s [
dec lPtr++] =l o c a lDe c l ;
25 }26 } else {27 return l o c a lD e c l a r a t i o n s ;28 }29 }30 }31 hasMoreVariables = ++i l o c a l < maxLocals ;32 i f ( ! hasMoreVariables && l o c a lDe c l a r a t i o n s != null ) {33 return l o c a lD e c l a r a t i o n s ;34 }35 }36 }
1 while ( s ea rchForStar | | ! uncla imedAnnotat ions . isEmpty ( ) ) {2 Proce s s o r In f o p i = prov id e r . d i s coverNextProces so r ( ) ;3 i f ( null == pi ) {4 // There are no more p r o c e s s o r s to be d i s cove r ed .5 break ;6 }7 handleProcessor ( p i ) ;8 }
1 while ( ! contructorBind ing . i sVa l idBind ing ( ) && ( enclos ingTypeBinding .isMemberType ( ) | | enclos ingTypeBinding . i sLocalType ( ) ) ) {
1 while ( ! contructorBind ing . i sVa l idBind ing ( ) && ( enclos ingTypeBinding .isMemberType ( ) | | enclos ingTypeBinding . i sLocalType ( ) ) ) {
2 enclos ingTypeBinding = enclos ingTypeBinding . enc los ingType ( ) ;3 i f ( CharOperation . equa l s ( this . s e l e c t o r , enc los ingTypeBinding .
1 do {2 // ex t ra c t un i t s to proce s s3 int l ength = top − bottom ;4 Compi lat ionUnitDec larat ion [ ] cur rentUni t s = new
Compi lat ionUnitDec larat ion [ l ength ] ;5 int index = 0 ;6 for ( int i = bottom ; i < top ; i++) {7 Compi lat ionUnitDec larat ion currentUnit = this .
un i tsToProcess [ i ] ;8 i f ( ( currentUnit . b i t s & ASTNode . I s Imp l i c i tUn i t ) == 0) {9 cur rentUni t s [ index++] = currentUnit ;
10 }11 }12 i f ( index != length ) {13 System . arraycopy ( currentUnits , 0 , ( cur rentUni t s = new
Compi lat ionUnitDec larat ion [ index ] ) , 0 , index ) ;14 }15 this . annotat ionProcessorManager . processAnnotat ions ( currentUnits ,
binaryTypeBindingsTemp , fa l se ) ;16 ICompi lat ionUnit [ ] newUnits = this . annotat ionProcessorManager .
getNewUnits ( ) ;17 newUnitSize = newUnits . l ength ;18 ReferenceBinding [ ] newClassF i l e s = this .
annotat ionProcessorManager . getNewClassFi les ( ) ;19 binaryTypeBindingsTemp = newClassF i l e s ;20 newCla s sF i l e sS i z e = newClassF i l e s . l ength ;21 i f ( newUnitSize != 0) {22 ICompilat ionUnit [ ] newProcessedUnits = ( ICompilat ionUnit
[ ] ) newUnits . c l one ( ) ; // remember new un i t s in casea source type c o l l i s i o n occurs
23 try {24 this . lookupEnvironment . i sProce s s ingAnnota t i ons =
26 } catch ( SourceTypeCol l i s ionExcept ion e ) {27 e . newAnnotationProcessorUnits =
newProcessedUnits ;28 throw e ;29 } f ina l ly {30 this . lookupEnvironment . i sProce s s ingAnnota t i ons =
fa l se ;31 this . annotat ionProcessorManager . r e s e t ( ) ;32 }33 bottom = top ;34 top = this . t o t a lUn i t s ; // l a s t un i t added35 } else {36 bottom = top ;37 this . annotat ionProcessorManager . r e s e t ( ) ;38 }39 } while ( newUnitSize != 0 | | newClas sF i l e sS i z e != 0) ;
1 while ( ( this . cur rentCharacter != ’ / ’ ) | | ( ! s t a r ) ) {2 i f ( this . c u r r en tPo s i t i on >= this . e o fPo s i t i o n ) {3 throw new Inva l id InputExcept ion (UNTERMINATEDCOMMENT) ;4 }5 i f ( ( this . cur rentCharacter == ’\ r ’ ) | | ( this . cur rentCharacter ==
’\n ’ ) ) {6 i f ( this . r e cordL ineSeparator ) {7 i f ( i sUnicode ) {8 pushUnicodeLineSeparator ( ) ;9 } else {
10 pushLineSeparator ( ) ;11 }12 }13 }14 switch ( this . cur rentCharacter ) {15 case ’∗ ’ :16 s t a r = true ;17 break ;18 case ’@ ’ :19 i f ( f i r s tTag == 0 && this . i sF i r s tTag ( ) ) {20 f i r s tTag = prev ious ;21 }22 //$FALL−THROUGH$ de f au l t case to s e t s t a r to
f a l s e23 default :24 s t a r = fa l se ;25 }26 // get next char27 prev ious = this . c u r r en tPo s i t i on ;28 i f ( ( ( this . cur rentCharacter = this . source [ this . c u r r en tPo s i t i on
++]) == ’ \\ ’ )29 && ( this . source [ this . c u r r en tPo s i t i on ] == ’u ’ ) ) {30 //−−−−−−−−−−−−−unicode t ra i t ement −−−−−−−−−−−−31 getNextUnicodeChar ( ) ;32 i sUnicode = true ;33 } else {34 i sUnicode = fa l se ;35 }36 // handle the \\u case manually in to comment37 i f ( this . cur rentCharacter == ’ \\ ’ ) {38 i f ( this . source [ this . c u r r en tPo s i t i on ] == ’ \\ ’ )39 this . c u r r en tPo s i t i on++;40 } //jump over the \\41 }
1 while ( ( this . cur rentCharacter != ’ / ’ ) | | ( ! s t a r ) ) {2 i f ( this . c u r r en tPo s i t i on >= this . e o fPo s i t i o n ) {3 return ;4 }
A.1. WHILE-LOOPS 105
5 i f ( ( this . cur rentCharacter == ’\ r ’ ) | | ( this . cur rentCharacter ==’\n ’ ) ) {
6 i f ( this . r e cordL ineSeparator ) {7 i f ( i sUnicode ) {8 pushUnicodeLineSeparator ( ) ;9 } else {
10 pushLineSeparator ( ) ;11 }12 }13 }14 switch ( this . cur rentCharacter ) {15 case ’∗ ’ :16 s t a r = true ;17 break ;18 case ’@ ’ :19 i f ( f i r s tTag == 0 && this . i sF i r s tTag ( ) ) {20 f i r s tTag = prev ious ;21 }22 //$FALL−THROUGH$ de f au l t case to s e t s t a r to
f a l s e23 default :24 s t a r = fa l se ;25 }26 // get next char27 prev ious = this . c u r r en tPo s i t i on ;28 i f ( ( ( this . cur rentCharacter = this . source [ this . c u r r en tPo s i t i on
++]) == ’ \\ ’ )29 && ( this . source [ this . c u r r en tPo s i t i on ] == ’u ’ ) ) {30 getNextUnicodeChar ( ) ;31 i sUnicode = true ;32 } else {33 i sUnicode = fa l se ;34 }35 // handle the \\u case manually in to comment36 i f ( this . cur rentCharacter == ’ \\ ’ ) {37 i f ( this . source [ this . c u r r en tPo s i t i on ] == ’ \\ ’ )38 this . c u r r en tPo s i t i on++;39 } //jump over the \\40 }
1 while ( act > ERROR ACTION | | act < ACCEPT ACTION) { // SHIFT−REDUCEact i on or SHIFT act i on ?
2 this . nextStackTop = this . tempStackTop + 1 ;3 for ( int i = next pos + 1 ; i <= this . nextStackTop ; i++)4 this . nextStack [ i ] = this . tempStack [ i ] ;56 for ( int i = pos + 1 ; i <= this . nextStackTop ; i++) {7 this . l o ca t i onS tack [ i ] = this . l o ca t i onS tack [ this .
stateStackTop ] ;8 this . l o c a t i onS ta r tS t a ck [ i ] = this . l o c a t i onS ta r tS t a ck [
this . stateStackTop ] ;9 }
1011 //12 // I f we have a s h i f t−reduce , p roce s s i t as we l l as13 // the goto−reduce a c t i on s that f o l l ow i t .14 //15 i f ( act > ERROR ACTION) {16 act −= ERROR ACTION;17 do {18 this . nextStackTop −= ( Parser . rhs [ act ]−1) ;19 act = Parser . ntAction ( this . nextStack [ this .
nextStackTop ] , Parser . l h s [ act ] ) ;20 } while ( act <= NUM RULES) ;21 pos = pos < this . nextStackTop ? pos : this . nextStackTop ;22 }2324 i f ( this . nextStackTop + 1 >= this . stackLength )25 r e a l l o c a t e S t a c k s ( ) ;
106 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
2627 this . tempStackTop = this . nextStackTop ;28 this . nextStack[++this . nextStackTop ] = act ;29 next pos = this . nextStackTop ;3031 //32 // Simulate the par s e r through the next token without33 // de s t roy ing STACK or next s tack .34 //35 this . currentToken = this . lexStream . getToken ( ) ;36 tok = this . lexStream . kind ( this . currentToken ) ;37 act = Parser . tAct ion ( act , tok ) ;38 while ( act <= NUM RULES) {39 //40 // . . . Process a l l goto−reduce a c t i on s f o l l ow ing41 // reduct ion , u n t i l a goto ac t i on i s computed . . .42 //43 do {44 int lhs symbol = Parser . l h s [ act ] ;45 i f (DEBUG) {46 System . out . p r i n t l n ( Parser . name [ Parser .
non te rmina l index [ lhs symbol ] ] ) ;47 }48 this . tempStackTop −= ( Parser . rhs [ act ]−1) ;49 act = ( this . tempStackTop > next pos50 ? this . tempStack [ this .
tempStackTop ]51 : this . nextStack [ this .
tempStackTop ] ) ;52 act = Parser . ntAction ( act , lhs symbol ) ;53 } while ( act <= NUM RULES) ;5455 //56 // . . . Update the maximum us e f u l p o s i t i o n o f the57 // (STATE )STACK, push GOTO s ta t e in to stack , and58 // compute next ac t i on on cur rent symbol . . .59 //60 i f ( this . tempStackTop + 1 >= this . stackLength )61 r e a l l o c a t e S t a c k s ( ) ;6263 next pos = next pos < this . tempStackTop ? next pos :
this . tempStackTop ;64 this . tempStack [ this . tempStackTop + 1 ] = act ;65 act = Parser . tAct ion ( act , tok ) ;66 }6768 // i f ( ( tok != TokenNameRBRACE | | (
forceRecoveryToken != currentToken && ( lexStream . f l a g s ( currentToken) & LexStream .LBRACE MISSING) != 0) )
69 // && ( lexStream . f l a g s ( currentToken) & LexStream . IS AFTER JUMP) !=0) {
70 // act = ERROR ACTION;71 // i f ( forceRecoveryToken !=
forceRecoveryAfterLBracketMiss ing = true ;74 // forceRecoveryToken =
currentToken ;75 // }76 // }7778 //79 // No e r r o r was detected , Read next token in to80 // PREVTOK element , advance CURTOK po in t e r and81 // update s tack s .82 //83 i f ( act != ERROR ACTION) {84 this . prevStackTop = this . stateStackTop ;85 for ( int i = prev pos + 1 ; i <= this . prevStackTop ; i++)86 this . prevStack [ i ] = this . s tack [ i ] ;87 prev pos = pos ;88
A.1. WHILE-LOOPS 107
89 this . stateStackTop = this . nextStackTop ;90 for ( int i = pos + 1 ; i <= this . stateStackTop ; i++)91 this . s tack [ i ] = this . nextStack [ i ] ;92 this . l o ca t i onS tack [ this . stateStackTop ] = this .
currentToken ;93 this . l o c a t i onS ta r tS t a ck [ this . stateStackTop ] = this .
lexStream . s t a r t ( this . currentToken ) ;94 pos = next pos ;95 }96 }
1 while ( r e s u l t == this . readInProcessMarker | | r e s u l t == null ) {2 // l e t the readingThread know we ’ re wai t ing3 //System . out . p r i n t ( ’ | ’ ) ;4 this . contentsRead [ this . readyToReadPosition ] = null ;5 try {6 wait (250) ;7 } catch ( Inter ruptedExcept ion ignore ) { // ignore8 }9 i f ( this . caughtException != null ) {
10 // rethrow the caught except ion from the readingThreadsin the main compi ler thread
11 i f ( this . caughtException instanceof Error )12 throw ( Error ) this . caughtException ;13 throw ( RuntimeException ) this . caughtException ;14 }15 r e s u l t = this . contentsRead [ this . readyToReadPosition ] ;16 }
1 int l ength1 = currentMethodInfos == null ? 0 : currentMethodInfos . l ength;
2 int l ength2 = otherMethodInfos == null ? 0 : otherMethodInfos . l ength ;3 int index1 = 0 ;4 int index2 = 0 ;5 /∗ outer loop cond i t i on : ∗/ while ( index1 < l ength1 && index2 < l ength2 )
{6 while ( (m = otherMethodInfos [ index2 ] ) . i s S yn th e t i c ( ) | | m. i s C l i n i t ( ) ) {7 i f (++index2 >= length2 ) break end ;8 }
1 while ( ( this . cur rentCharacter != ’ / ’ ) | | ( ! s t a r ) ) {2 i f ( ( this . cur rentCharacter == ’\ r ’ ) | | ( this . cur rentCharacter ==
’\n ’ ) ) {3 // checkNonExterna l i zedStr ing ( ) ;4 i f ( this . r e cordL ineSeparator ) {5 i f ( ! i sUnicode ) {6 pushLineSeparator ( ) ;7 }8 }9 }
10 switch ( this . cur rentCharacter ) {11 case ’∗ ’ :12 s t a r = true ;13 break ;14 case ’@ ’ :15 i f ( f i r s tTag == 0 && this . i sF i r s tTag ( ) ) {16 f i r s tTag = prev ious ;17 }18 //$FALL−THROUGH$ de f au l t case to s e t s t a r to
f a l s e19 default :20 s t a r = fa l se ;21 }22 // get next char23 prev ious = this . c u r r en tPo s i t i on ;24 i f ( ( ( this . cur rentCharacter = this . source [ this . c u r r en tPo s i t i on
++]) == ’ \\ ’ )25 && ( this . source [ this . c u r r en tPo s i t i on ] == ’u ’ ) ) {26 //−−−−−−−−−−−−−unicode t ra i t ement −−−−−−−−−−−−27 getNextUnicodeChar ( ) ;28 i sUnicode = true ;29 } else {30 i sUnicode = fa l se ;31 }32 // handle the \\u case manually in to comment33 i f ( this . cur rentCharacter == ’ \\ ’ ) {34 i f ( this . source [ this . c u r r en tPo s i t i on ] == ’ \\ ’ )35 this . c u r r en tPo s i t i on++;36 } //jump over the \\37 }
1 while ( ( this . cur rentCharacter != ’ / ’ ) | | ( ! s t a r ) ) {2 i f ( this . c u r r en tPo s i t i on >= this . e o fPo s i t i o n ) {3 throw new Inva l id InputExcept ion (UNTERMINATEDCOMMENT) ;4 }5 i f ( ( this . cur rentCharacter == ’\ r ’ ) | | ( this . cur rentCharacter ==
’\n ’ ) ) {6 i f ( this . r e cordL ineSeparator ) {7 i f ( i sUnicode ) {8 pushUnicodeLineSeparator ( ) ;9 } else {
10 pushLineSeparator ( ) ;11 }12 }13 }14 switch ( this . cur rentCharacter ) {15 case ’∗ ’ :16 s t a r = true ;17 break ;18 case ’@ ’ :19 i f ( f i r s tTag == 0 && this . i sF i r s tTag ( ) ) {20 f i r s tTag = prev ious ;21 }22 //$FALL−THROUGH$ de f au l t case to s e t s t a r to
f a l s e23 default :24 s t a r = fa l se ;25 }26 // get next char27 prev ious = this . c u r r en tPo s i t i on ;28 i f ( ( ( this . cur rentCharacter = this . source [ this . c u r r en tPo s i t i on
++]) == ’ \\ ’ )29 && ( this . source [ this . c u r r en tPo s i t i on ] == ’u ’ ) ) {30 //−−−−−−−−−−−−−unicode t ra i t ement −−−−−−−−−−−−31 getNextUnicodeChar ( ) ;32 i sUnicode = true ;33 } else {34 i sUnicode = fa l se ;35 }36 // handle the \\u case manually in to comment37 i f ( this . cur rentCharacter == ’ \\ ’ ) {38 i f ( this . source [ this . c u r r en tPo s i t i on ] == ’ \\ ’ )39 this . c u r r en tPo s i t i on++;40 } //jump over the \\41 }
1 while ( ( this . cur rentCharacter != ’ / ’ ) | | ( ! s t a r ) ) {2 i f ( this . c u r r en tPo s i t i on >= this . e o fPo s i t i o n ) {3 return ;4 }
A.1. WHILE-LOOPS 111
5 i f ( ( this . cur rentCharacter == ’\ r ’ ) | | ( this . cur rentCharacter ==’\n ’ ) ) {
6 i f ( this . r e cordL ineSeparator ) {7 i f ( i sUnicode ) {8 pushUnicodeLineSeparator ( ) ;9 } else {
10 pushLineSeparator ( ) ;11 }12 }13 }14 switch ( this . cur rentCharacter ) {15 case ’∗ ’ :16 s t a r = true ;17 break ;18 case ’@ ’ :19 i f ( f i r s tTag == 0 && this . i sF i r s tTag ( ) ) {20 f i r s tTag = prev ious ;21 }22 //$FALL−THROUGH$ de f au l t case to s e t s t a r to
f a l s e23 default :24 s t a r = fa l se ;25 }26 // get next char27 prev ious = this . c u r r en tPo s i t i on ;28 i f ( ( ( this . cur rentCharacter = this . source [ this . c u r r en tPo s i t i on
++]) == ’ \\ ’ )29 && ( this . source [ this . c u r r en tPo s i t i on ] == ’u ’ ) ) {30 getNextUnicodeChar ( ) ;31 i sUnicode = true ;32 } else {33 i sUnicode = fa l se ;34 }35 // handle the \\u case manually in to comment36 i f ( this . cur rentCharacter == ’ \\ ’ ) {37 i f ( this . source [ this . c u r r en tPo s i t i on ] == ’ \\ ’ )38 this . c u r r en tPo s i t i on++;39 } //jump over the \\40 }
2 fromIndex = index + 1 ;34 int anchorEndStart = index + JavadocConstants .
ANCHOR PREFIX START LENGHT;56 this . tempLastAnchorFoundIndex = anchorEndStart ;78 i f ( CharOperation . p r e f i xEqua l s ( anchor , this . content , false ,
{3 int curr= 0 ;4 do {5 try {6 curr= fScanner . getNextToken ( ) ;7 } catch ( Inva l id InputExcept ion e ) {8 throw new CoreException ( c r ea t eEr ro r (
LEXICAL ERROR, e . getMessage ( ) , e ) ) ;9 }
10 } while ( ignoreComments && isComment ( curr ) ) ;11 return curr ;12 }1314 while ( curr == ITerminalSymbols .TokenNameCOMMENT LINE | | curr ==
ITerminalSymbols .TokenNameCOMMENT BLOCK) {15 int cu r rS ta r tL ine= getL ineOfOf f s e t ( g e tCur r en tS ta r tOf f s e t ( ) ) ;16 int l i n e sD i f f e r e n c e= cur rS ta r tL ine − prevEndLine ;1718 i f ( l i n e sD i f f e r e n c e > 1) {19 return prevEndPos ; // separated comments20 }2122 i f ( curr == ITerminalSymbols .TokenNameCOMMENT LINE) {23 prevEndPos= getLineEnd ( cur rS ta r tL ine ) ;24 prevEndLine= cur rS ta r tL ine ;25 } else {26 prevEndPos= getCurrentEndOffset ( ) ;27 prevEndLine= getL ineOfOf f s e t ( prevEndPos − 1) ;28 }29 i f ( sameLineComment ) {30 i f ( l i n e sD i f f e r e n c e == 0) {31 r e s= prevEndPos ;32 } else {33 sameLineComment= fa l se ;34 }35 }36 curr= readNextWithEOF( fa l se ) ;37 }
1 do {2 ICleanUp cleanUp= cleanUps [ i ] ;3 ICleanUpFix f i x ;4 i f ( slowCleanUps != null ) {5 long t imeBefore= System . cur rentTimeMi l l i s ( ) ;6 f i x= cleanUp . c r ea t eF ix ( context ) ;7 i f ( System . cur rentTimeMi l l i s ( ) − t imeBefore >
10 f i x= cleanUp . c r ea t eF ix ( context ) ;11 }12 i f ( f i x != null ) {13 CompilationUnitChange cur rent= f i x . createChange ( null ) ;14 TextEdit cur rentEd i t= current . getEdit ( ) ;1516 i f ( s o l u t i o n != null ) {17 i f ( TextEditUt i l . ove r l ap s ( currentEdit , s o l u t i o n .
FixMessages .CleanUpRefactor ing c lean up mult i chang name, context . getCompi lat ionUnit ( ) ) ;
21 merge . s e tEd i t ( TextEditUt i l . merge (currentEdit , s o l u t i o n . getEdit ( ) ) ) ;
2223 copyChangeGroups (merge , s o l u t i o n ) ;
A.1. WHILE-LOOPS 113
24 copyChangeGroups (merge , cur rent ) ;2526 s o l u t i o n= merge ;27 }28 } else {29 s o l u t i o n= new CleanUpChange ( cur rent . getName ( ) ,
context . getCompi lat ionUnit ( ) ) ;30 s o l u t i o n . s e tEd i t ( cur rentEd i t ) ;3132 copyChangeGroups ( so lu t i on , cur rent ) ;33 }34 }35 i++;36 } while ( i < cleanUps . l ength && ( context . getAST ( ) == null | | ! c leanUps [ i
1 do {2 i f ( conta ine r instanceof IFo lder )3 javaElem= JavaCore . c r e a t e ( ( IFo lder ) conta ine r ) ;4 i f ( conta ine r . getFul lPath ( ) . equa l s ( p r o j e c t . getPath ( ) ) ) {5 javaElem= pro j e c t ;6 break ;7 }8 conta ine r= conta ine r . getParent ( ) ;9 i f ( conta ine r == null )
1 do {2 id= Str ing . valueOf ( System . cur rentTimeMi l l i s ( ) ) ;3 } while (vmType . f indVMInsta l l ( id ) != null | | id . equa l s ( fgLastUsedID ) ) ;
1 while ( ( z e r o s < r | | dataUnit [ zzIndex ] != 0) && k <= end ) {2 i f ( dataUnit [ zzIndex ] != 0) {3 dataUnit [ zzIndex ] = ref ineAC ( dataUnit [ zzIndex ] ,
approxBit ) ;
114 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
4 } else {5 ze ro s++;6 }7 k++;8 zzIndex = ZigZag8x8 [ k ] ;9 }
1 while ( c i n f o . input scan number < c i n f o . output scan number | |2 ( c i n f o . input scan number == c i n f o . output scan number &&3 c i n f o . input iMCU row <= c i n f o . output iMCU row ) )4 {5 i f ( consume input ( c i n f o ) == JPEG SUSPENDED)6 return JPEG SUSPENDED;7 }
1 do {2 −− f i r s t ;3 i f ( f i r s t < 0)4 break ;56 p= category [ f i r s t ] ;78 } while (p . overlapsWith ( e . g e tO f f s e t ( ) , e . getLength ( ) ) | |9 ( e . g e tO f f s e t ( ) == fPreviousDocumentLength &&
10 (p . g e tO f f s e t ( ) + p . getLength ( ) ==fPreviousDocumentLength ) ) ) ;
1 while ( back >= 0 | | f o r th < s i z e ) {2 i f ( back >= 0) {3 i f ( p o s i t i o n == po s i t i o n s . get ( back ) ) {4 po s i t i o n s . remove ( back ) ;5 return ;6 }7 back−−;8 }9
10 i f ( f o r th < s i z e ) {11 i f ( p o s i t i o n == po s i t i o n s . get ( f o r th ) ) {12 po s i t i o n s . remove ( f o r th ) ;13 return ;14 }15 f o r th++;16 }17 }
2 for ( int i= 0 ; i < counts . l ength ; i++) {3 counts [ i ] [ 0 ]= counts [ i ] [ 1 ]= 0 ;4 }56 outer1 : while ( pos1 >= lowerBoundary && ! lowerFound ) {7 f ina l char c= doc . getChar ( pos1 ) ;8 int i= getCharacterIndex ( c , document , pos1 ) ;9 i f ( i != −1 && doc . i nPa r t i t i o n ( pos1 ) ) {
10 i f ( i % 2 == 0) {11 counts [ i / 2] [0]−− ; // s t a r t12 } else {13 counts [ i / 2 ] [ 0 ]++; //end14 }15 for ( int j= 0 ; j < counts . l ength ; j++) {16 i f ( counts [ j ] [ 0 ] == −1) {17 lowerFound= true ;18 break outer1 ;19 }20 }21 }22 pos1= doc . getNextPos i t ion ( pos1 , fa l se ) ;23 }2425 outer2 : while ( pos2 < upperBoundary && ! upperFound ) {26 f ina l char c= doc . getChar ( pos2 ) ;27 int i= getCharacterIndex ( c , document , pos2 ) ;28 i f ( i != −1 && doc . i nPa r t i t i o n ( pos2 ) ) {29 i f ( i % 2 == 0) {30 counts [ i / 2 ] [ 1 ]++; // s t a r t31 } else {32 counts [ i / 2] [1]−− ; //end33 }34 for ( int j= 0 ; j < counts . l ength ; j++) {35 i f ( counts [ j ] [ 1 ] == −1 && counts [ j ] [ 0 ]
== −1) {36 upperFound= true ;37 break outer2 ;38 }39 }40 }41 pos2= doc . getNextPos i t ion ( pos2 , true ) ;42 }4344 i f ( pos1 > s t a r t | | pos2 < end − 1) {45 //match i n s i d e s e l e c t i o n => d i s ca rd46 pos1= doc . getNextPos i t ion ( pos1 , fa l se ) ;47 pos2= doc . getNextPos i t ion ( pos2 , true ) ;48 lowerFound= fa l se ;49 upperFound= fa l se ;50 }51 }
1 while ( l >= min && in f o != null && ( i n f o . getChangeType ( ) ==IL i n eD i f f I n f o .CHANGED | | i n f o . getChangeType ( ) == IL i n eD i f f I n f o .ADDED) ) {
2 i n f o= d i f f e r . g e tL ine In f o(−− l ) ;3 }
1 while ( l <= max && in f o != null && ( i n f o . getChangeType ( ) ==IL i n eD i f f I n f o .CHANGED | | i n f o . getChangeType ( ) == IL i n eD i f f I n f o .ADDED) ) {
116 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
2 i n f o= d i f f e r . g e tL ine In f o(++l ) ;3 }
1 //As de f ined in sup e r c l a s s Subst i tut ionTextReader :2 protected int nextChar ( ) throws IOException {3 this . fReadFromBuffer= ( this . fBu f f e r . l ength ( ) > 0) ;4 i f ( this . fReadFromBuffer ) {5 char ch= this . fBu f f e r . charAt ( this . f Index++) ;6 i f ( this . f Index >= this . fBu f f e r . l ength ( ) ) {7 this . fBu f f e r . setLength (0) ;8 this . f Index= 0 ;9 }
10 return ch ;11 } else {12 int ch= this . fCharAfterWhiteSpace ;13 i f ( ch == −1) {14 ch= this . fReader . read ( ) ;15 }16 i f ( this . fSkipWhiteSpace && ScannerHelper . i sWhitespace ( (
char ) ch ) ) {17 do {18 ch= this . fReader . read ( ) ;19 } while ( ScannerHelper . i sWhitespace ( ( char ) ch ) ) ;20 i f ( ch != −1) {21 this . fCharAfterWhiteSpace= ch ;22 return ’ ’ ;23 }24 } else {25 this . fCharAfterWhiteSpace= −1;26 }27 return ch ;28 }29 }3031 while ( Character . i sL e t t e rOrD ig i t ( ( char ) ch ) | | ch == ’#’ ) {32 buf . append ( ( char ) ch ) ;33 ch= nextChar ( ) ;34 }
1 while ( f i r s tT ime | | tryAgain ) {2 tryAgain = fa l se ; // r e s e t the try again f l a g3 s e s s i o n = JSchSess ion . g e tSe s s i on ( l o ca t i on , l o c a t i o n . getUsername
( ) , password , l o c a t i o n . getHost ( ) , l o c a t i o n . getPort ( ) ,monitor ) ;
4 channel = s e s s i o n . g e tSe s s i on ( ) . openChannel ( ” exec ” ) ; //$NON−NLS−1$
5 ( ( ChannelExec ) channel ) . setCommand(COMMAND) ;6 channe l out = channel . getOutputStream ( ) ;7 channe l in = channel . getInputStream ( ) ;8 try {9 channel . connect ( ) ;
10 } catch ( JSchException ee ) {11 // This s t range l o g i c i s here due to how the JSch c l i e n t
share s s e s s i o n s .12 // I t i s p o s s i b l e that we have obtained a s e s s i o n that
th inks i t i s connected13 // but i s not . Channel connect ion only works i f the
s e s s i o n i s connected so the14 // above channel connect may f a i l because the s e s s i o n i s
down . For t h i s reason ,15 // we want to r e t r y i f the connect ion f a i l s .16 try {17 i f ( f i r s tT ime && ( isSess ionDownError ( ee ) | |
19 }20 i f ( ! tryAgain ) {21 throw ee ;22 }23 } f ina l ly {24 // Always d i spo s e o f the cur rent s e s s i o n when a
f a i l u r e occurs so we can s t a r t from sc ra t ch25 s e s s i o n . d i spo s e ( ) ;26 }27 }28 f i r s tT ime = fa l se ; // the f i r s t time i s done29 }
1 while ( c == ’=’ | | c == ’ : ’ ) {2 while ( c == ’ : ’ ) { // may not r e a l l y be a :=3 c = token i z e r . getChar ( ) ;4 i f ( c != ’=’ ) {5 St r ing restOfNext = token i z e r . getToken ( ”=:” ) ; //
$NON−NLS−1$6 i f ( restOfNext == null )7 throw new BundleException (NLS. bind (Msg .
8 next += ” : ” + c + restOfNext ; //$NON−NLS−1$9 c = token i z e r . getChar ( ) ;
10 } else11 d i r e c t i v e = true ;12 }13 // determine i f the a t t r i bu t e i s the form a t t r : L i s t<type>14 St r ing prese rveEscapes = null ;15 i f ( ! d i r e c t i v e && next . indexOf ( ” L i s t ” ) > 0) { //$NON−NLS−1$16 Tokenizer l i s tTok en i z e r = new Tokenizer ( next ) ;17 St r ing attrKey = l i s tTok en i z e r . getToken ( ” : ” ) ; //$NON−NLS
−1$18 i f ( attrKey != null && l i s tTok en i z e r . getChar ( ) == ’ : ’ &&
” L i s t ” . equa l s ( l i s tTok en i z e r . getToken ( ”<” ) ) ) { //$NON−NLS−1$//$NON−NLS−2$
19 // we assume we must pre s e rve escapes f o r , and”
20 prese rveEscapes = ”\\ , ” ; //$NON−NLS−1$21 }22 }23 St r ing va l = token i z e r . g e tS t r i ng ( ” ; , ” , prese rveEscapes ) ; //$NON−
NLS−1$24 i f ( va l == null )25 throw new BundleException (NLS. bind (Msg .
2627 i f (Debug .DEBUG MANIFEST)28 Debug . p r i n t ( ” ; ” + next + ”=” + val ) ; //$NON−NLS−1$ //
$NON−NLS−2$29 try {30 i f ( d i r e c t i v e )31 manifestElement . addDirect ive ( next , va l ) ;32 else33 manifestElement . addAttr ibute ( next , va l ) ;34 d i r e c t i v e = fa l se ;35 } catch ( Exception e ) {36 throw new BundleException (NLS. bind (Msg .
MANIFEST INVALID HEADER EXCEPTION, header , va lue ) ,BundleException .MANIFEST ERROR, e ) ;
118 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
37 }38 c = token i z e r . getChar ( ) ;39 i f ( c == ’ ; ’ ) /∗ more ∗/{40 next = token i z e r . getToken ( ”=:” ) ; //$NON−NLS−1$41 i f ( next == null )42 throw new BundleException (NLS. bind (Msg .
1 while ( f i l e == null | | f i l e . getType ( ) != IResource . FILE) {2 for ( int i = 0 ; i < names . l ength ; i++) {3 St r ing s t r i n g = names [ i ] ;4 f i l e= lpa r en t . findMember ( s t r i n g ) ;5 i f ( f i l e != null && f i l e . getType ( ) == IResource . FILE) {6 break ;7 }8 }9 lpa r en t = lpa r en t . getParent ( ) ;
10 i f ( l pa r en t == null ) {11 return null ;12 }13 }
1 while ( ( ( t e s t S h e l l != null && ! t e s t S h e l l . i sD i sposed ( ) ) | | ( ! theApp2 . getChi ldren ( ) . isEmpty ( ) && someAreVis ib le ( theApp3 . getChi ldren ( ) ) ) )4 && ! d i sp l ay . i sD i sposed ( ) ) {5 try {6 i f ( ! d i sp l ay . readAndDispatch ( ) ) {7 runContext . processWait ing ( ) ;8 i f ( spinOnce )9 return ;
10 adv i so r . eventLoopIdle ( d i sp l ay ) ;11 }12 } catch ( ThreadDeath th ) {13 throw th ;14 } catch ( Exception ex ) {15 handle ( ex , adv i so r ) ;16 } catch ( Error e r r ) {17 handle ( err , adv i so r ) ;18 }19 }
1 while ( myIter . fD i f f e r e n c e != null | | your I t e r . fD i f f e r e n c e != null ) {23 D i f f e r e n c e s I t e r a t o r startThread ;4 myIter . removeAll ( ) ;
A.1. WHILE-LOOPS 119
5 your I t e r . removeAll ( ) ;6 //7 // take the next d i f f that i s c l o s e r to the s t a r t8 //9 i f ( myIter . fD i f f e r e n c e == null )
10 startThread= your I t e r ;11 else i f ( you r I t e r . fD i f f e r e n c e == null )12 startThread= myIter ;13 else { // not at end o f both s c r i p t s take the lowest range14 i f ( myIter . fD i f f e r e n c e . l e f t S t a r t < your I t e r . fD i f f e r e n c e .
l e f t S t a r t ) { // 2 −> common ( Ancestor ) change range15 startThread= myIter ;16 } else i f ( myIter . fD i f f e r e n c e . l e f t S t a r t > your I t e r .
fD i f f e r e n c e . l e f t S t a r t ) {17 startThread= your I t e r ;18 } else {19 i f ( myIter . fD i f f e r e n c e . l e f tLeng th == 0 &&
your I t e r . fD i f f e r e n c e . l e f tLeng th == 0) {20 // i n s e r t i o n in to the same po s i t i o n i s
c o n f l i c t .21 changeRangeStart= myIter . fD i f f e r e n c e .
l e f t S t a r t ;22 changeRangeEnd= myIter . fD i f f e r e n c e .
l e f tEnd ( ) ;23 myIter . next ( ) ;24 your I t e r . next ( ) ;25 d i f f 3 . add ( c reateRangeDi f f e r ence3 ( fac tory
, myIter , your I te r , d i f f 3 , r i ght ,l e f t , changeRangeStart ,changeRangeEnd ) ) ;
26 continue ;27 } else i f ( myIter . fD i f f e r e n c e . l e f tLeng th == 0)
{28 // i n s e r t i o n in to a pos i t i on , and
mod i f i c a t i on to the next l i n e , i snot c o n f l i c t .
29 startThread= myIter ;30 } else i f ( you r I t e r . fD i f f e r e n c e . l e f tLeng th == 0)
{31 startThread = your I t e r ;32 } else {33 // mod i f i c a t i on s to over lapp ing l i n e s i s
c o n f l i c t .34 startThread= myIter ;35 }36 }3738 }39 changeRangeStart= startThread . fD i f f e r e n c e . l e f t S t a r t ;40 changeRangeEnd= startThread . fD i f f e r e n c e . l e f tEnd ( ) ;4142 startThread . next ( ) ;43 monitor . worked (1) ;44 //45 // check f o r over lapp ing changes with other thread46 // merge over lapp ing changes with t h i s range47 //48 D i f f e r e n c e s I t e r a t o r other= startThread . other ( myIter , you r I t e r ) ;49 while ( other . fD i f f e r e n c e != null && other . fD i f f e r e n c e . l e f t S t a r t
< changeRangeEnd ) {50 int newMax= other . fD i f f e r e n c e . l e f tEnd ( ) ;51 other . next ( ) ;52 monitor . worked (1) ;53 i f (newMax > changeRangeEnd ) {54 changeRangeEnd= newMax ;55 other= other . other ( myIter , you r I t e r ) ;56 }57 }58 d i f f 3 . add ( c rea teRangeDi f f e r ence3 ( fac tory , myIter , your I te r ,
d i f f 3 , r i ght , l e f t , changeRangeStart , changeRangeEnd ) ) ;59 }
1 while ( superName != null && ( ! Ut i l . i sJavaLangObject ( superName ) | |inc ludeObject ) ) {
2 superClass = superClass . g e tSupe r c l a s s ( ) ;3 int v i s i b i l i t y = V i s i b i l i t yMod i f i e r s .PRIVATE;4 IApiComponent superComponent = superClass . getApiComponent ( ) ;5 IAp iDesc r ip t i on ap iDe s c r i p t i on = superComponent .
ge tApiDescr ipt ion ( ) ;6 IApiAnnotations e l ementDescr ipt ion = ap iDes c r i p t i on .
r e so lveAnnotat ions ( superClass . getHandle ( ) ) ;7 i f ( e l ementDesc r ipt ion != null ) {8 v i s i b i l i t y = e lementDescr ipt ion . g e t V i s i b i l i t y ( ) ;9 }
10 i f ( i n c ludePr i va t e | | ( ( v i s i b i l i t y & v i s i b i l i t yM o d i f i e r s ) != 0) ){
11 l i s t . add ( superClass ) ;12 }13 superName = superClass . getSuperclassName ( ) ;14 }
1 do {2 s ta r tOfL ine = doc . g e tL ineOf f s e t ( l i n e ) ;3 newValue = doc . get ( o f f s e t , doc . getLineLength ( l i n e ) − o f f s e t +
star tOfL ine ) ;4 ++l i n e ;5 co lon = newValue . l a s t IndexOf ( ’ : ’ ) ;6 } while ( ( co lon == −1 | | ( newValue . l ength ( ) > co lon && newValue . charAt (
co lon + 1) == ’=’ ) ) && ( ent i reHeader | | newValue . indexOf ( ’ , ’ ) ==−1) && ! ( doc . getNumberOfLines ( ) == l i n e ) ) ;
1 while ( parentRequests == null | | parentRequests . isEmpty ( ) ) {2 parentPath = parentPath . getParentPath ( ) ;3 i f ( parentPath == null ) {4 // no running r eque s t s : s t a r t r eques t5 return fa l se ;6 }7 parentRequests = ( L i s t ) fReques t s InProgre s s . get ( parentPath ) ;8 }
1 while ( ( ! l i s t e n e r . fLabelUpdatesComplete | | ! l i s t e n e r .fViewerUpdatesComplete ) && ! l i s t e n e r . fProgressMonitor . i sCance l ed ( ) ){
1 while ( l i n e . indexOf ( ’=’ ) < 0 | | ( l i n e . l ength ( )>0 && ! Character .i s J a v a I d e n t i f i e r S t a r t ( l i n e . charAt (0) ) ) ) {
2 value += newLine + l i n e ;3 l i n e = reader . readLine ( ) ;4 i f ( l i n e == null ) {5 // i f next l i n e read i s the end o f the f i l e qu i t the loop6 break ;7 }8 }
1 protected synchronized St r ing [ ] getAllSortedConfigNames ( ) {2 i f ( fSortedConfigNames == null ) {3 ILaunchConf igurat ion [ ] c o n f i g s = getLaunchConf igurat ions
( ) ;4 fSortedConfigNames = new St r ing [ c on f i g s . l ength ] ;5 for ( int i = 0 ; i < c on f i g s . l ength ; i++) {6 fSortedConfigNames [ i ] = c on f i g s [ i ] . getName ( ) ;7 }8 Arrays . s o r t ( fSortedConfigNames ) ;9 }
10 return fSortedConfigNames ;11 }12 public boolean i sExist ingLaunchConf igurat ionName ( St r ing name) {13 St r ing [ ] sortedConfigNames = getAllSortedConfigNames ( ) ;14 int index = Arrays . b inarySearch ( sortedConfigNames , name) ;15 i f ( index < 0) {16 return fa l se ;17 }18 return true ;19 }2021 while ( isExist ingLaunchConf igurat ionName (newname) | | reservednames .
conta in s (newname) ) {22 bu f f e r = new St r i ngBu f f e r ( base ) ;23 bu f f e r . append ( ” ( ” ) ; //$NON−NLS−1$24 bu f f e r . append ( St r ing . valueOf ( index ) ) ;25 index++;
122 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
26 bu f f e r . append ( ’ ) ’ ) ;27 newname = bu f f e r . t oS t r i ng ( ) ;28 }
1 private JspReader reader ;23 do {4 // XXX could move t h i s l o g i c to JspReader5 currentChar = reader . nextChar ( ) ;6 i f ( currentChar == ’ \\ ’ && ( s ing leQuoted | | doubleQuoted ) ) {7 // sk ip charac t e r f o l l ow ing ’\ ’ with in quotes8 reader . nextChar ( ) ;9 currentChar = reader . nextChar ( ) ;
10 }11 i f ( currentChar == −1)12 e r r . j spEr ro r ( s ta r t , ” j sp . e r r o r . unterminated ” , typeEL ) ;13 i f ( currentChar == ’ ” ’ )14 doubleQuoted = ! doubleQuoted ;15 i f ( currentChar == ’ \ ’ ’ )16 s ing leQuoted = ! s ing leQuoted ;17 } while ( currentChar != ’} ’ | | ( s ing leQuoted | | doubleQuoted ) ) ;
1 while ( ! c l o s ed && (( s t a t e != null && ! s t a t e . i s I d l e ) | | pauseThreads != 0| | f lushPending | | abort ing ) ) {
2 try {3 wait ( ) ;4 } catch ( Inter ruptedExcept ion i e ) {5 // In 3 .0 we w i l l change t h i s to throw6 // Inter ruptedExcept ion in s t ead7 Thread . currentThread ( ) . i n t e r r up t ( ) ;8 throw new RuntimeException ( i e ) ;9 }
1 private boolean toSameDoc ( ) throws IOException {2 Arrays . s o r t ( subSpansByDoc , spanDocComparator ) ;3 int f i r s t I n d e x = 0 ;4 int maxDoc = subSpansByDoc [ subSpansByDoc . l ength − 1 ] . doc ( ) ;5 while ( subSpansByDoc [ f i r s t I n d e x ] . doc ( ) != maxDoc) {6 i f ( ! subSpansByDoc [ f i r s t I n d e x ] . skipTo (maxDoc) ) {7 more = fa l se ;8 inSameDoc = fa l se ;9 return fa l se ;
10 }
124 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
11 maxDoc = subSpansByDoc [ f i r s t I n d e x ] . doc ( ) ;12 i f (++f i r s t I n d e x == subSpansByDoc . l ength ) {13 f i r s t I n d e x = 0 ;14 }15 }16 for ( int i = 0 ; i < subSpansByDoc . l ength ; i++) {17 a s s e r t ( subSpansByDoc [ i ] . doc ( ) == maxDoc)18 : ” NearSpansOrdered . toSameDoc ( ) spans ” + subSpansByDoc [ 0 ]19 + ”\n at doc ” + subSpansByDoc [ i ] . doc ( )20 + ” , but should be at ” + maxDoc ;21 }22 inSameDoc = true ;23 return true ;24 }25 private boolean stretchToOrder ( ) throws IOException {26 matchDoc = subSpans [ 0 ] . doc ( ) ;27 for ( int i = 1 ; inSameDoc && ( i < subSpans . l ength ) ; i++) {28 while ( ! docSpansOrdered ( subSpans [ i −1] , subSpans [ i ] ) ) {29 i f ( ! subSpans [ i ] . next ( ) ) {30 inSameDoc = fa l se ;31 more = fa l se ;32 break ;33 } else i f (matchDoc != subSpans [ i ] . doc ( ) ) {34 inSameDoc = fa l se ;35 break ;36 }37 }38 }39 return inSameDoc ;40 }41 private boolean shr inkToAfterShortestMatch ( ) throws IOException {42 matchStart = subSpans [ subSpans . l ength − 1 ] . s t a r t ( ) ;43 matchEnd = subSpans [ subSpans . l ength − 1 ] . end ( ) ;44 Set poss ibleMatchPayloads = new HashSet ( ) ;45 i f ( subSpans [ subSpans . l ength − 1 ] . i sPay loadAva i l ab l e ( ) ) {46 poss ib leMatchPayloads . addAll ( subSpans [ subSpans . l ength −
1 ] . getPayload ( ) ) ;47 }4849 Co l l e c t i on pos s ib l ePay load = null ;5051 int matchSlop = 0 ;52 int l a s t S t a r t = matchStart ;53 int lastEnd = matchEnd ;54 for ( int i = subSpans . l ength − 2 ; i >= 0 ; i−−) {55 Spans prevSpans = subSpans [ i ] ;56 i f ( c o l l e c tPay l oad s && prevSpans . i sPay loadAva i l ab l e ( ) ) {57 Co l l e c t i on payload = prevSpans . getPayload ( ) ;58 pos s ib l ePay load = new ArrayList ( payload . s i z e ( ) ) ;59 pos s ib l ePay load . addAll ( payload ) ;60 }6162 int prevStar t = prevSpans . s t a r t ( ) ;63 int prevEnd = prevSpans . end ( ) ;64 while ( true ) { // Advance prevSpans un t i l a f t e r (
l a s t S t a r t , lastEnd )65 i f ( ! prevSpans . next ( ) ) {66 inSameDoc = fa l se ;67 more = fa l se ;68 break ; // Check remaining subSpans f o r
f i n a l match .69 } else i f (matchDoc != prevSpans . doc ( ) ) {70 inSameDoc = fa l se ; // The l a s t subSpans
i s not advanced here .71 break ; // Check remaining subSpans f o r
l a s t match in t h i s document .72 } else {73 int ppStart = prevSpans . s t a r t ( ) ;74 int ppEnd = prevSpans . end ( ) ; // Cannot
avoid invoking . end ( )75 i f ( ! docSpansOrdered ( ppStart , ppEnd ,
l a s t S t a r t , lastEnd ) ) {76 break ; // Check remaining
subSpans .
A.1. WHILE-LOOPS 125
77 } else { // prevSpans s t i l l b e f o r e (l a s t S t a r t , lastEnd )
78 prevStar t = ppStart ;79 prevEnd = ppEnd ;80 i f ( c o l l e c tPay l oad s && prevSpans
. i sPay loadAva i l ab l e ( ) ) {81 Co l l e c t i on payload =
prevSpans .getPayload ( ) ;
82 pos s ib l ePay load = newArrayList ( payload .s i z e ( ) ) ;
83 pos s ib l ePay load . addAll (payload ) ;
84 }85 }86 }87 }8889 i f ( c o l l e c tPay l oad s && poss ib l ePay load != null ) {90 poss ib leMatchPayloads . addAll ( pos s ib l ePay load ) ;91 }9293 a s s e r t prevStar t <= matchStart ;94 i f ( matchStart > prevEnd ) { // Only non over lapp ing
spans add to s l op .95 matchSlop += (matchStart − prevEnd ) ;96 }9798 /∗ Do not break on (matchSlop > a l lowedSlop ) here to
make sure99 ∗ that subSpans [ 0 ] i s advanced a f t e r the match , i f any .
100 ∗/101 matchStart = prevStar t ;102 l a s t S t a r t = prevStar t ;103 lastEnd = prevEnd ;104 }105106 boolean match = matchSlop <= al lowedSlop ;107108 i f ( c o l l e c tPay l oad s && match && poss ib leMatchPayloads . s i z e ( ) > 0) {109 matchPayload . addAll ( poss ib leMatchPayloads ) ;110 }111112 return match ; // ordered and al lowed s l op113 }114115 while (more && ( inSameDoc | | toSameDoc ( ) ) ) {116 i f ( stretchToOrder ( ) && shrinkToAfterShortestMatch ( ) ) {117 return true ;118 }119 }
1 do {2 bucketTable . f i r s t = null ;34 while ( cur rent != null ) { // more queued56 // check proh ib i t ed & requ i r ed7 i f ( ( cur rent . b i t s & prohibitedMask ) == 0 &&8 ( cur rent . b i t s & requiredMask ) == requiredMask ) {9
10 i f ( cur rent . doc >= max){11 tmp = current ;12 cur rent = current . next ;13 tmp . next = bucketTable . f i r s t ;14 bucketTable . f i r s t = tmp ;15 continue ;16 }17
126 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
18 i f ( cur rent . coord >= minNrShouldMatch ) {19 bs . s co r e = current . s co r e ∗ coordFactors [
cur rent . coord ] ;20 bs . doc = current . doc ;21 c o l l e c t o r . c o l l e c t ( cur rent . doc ) ;22 }23 }2425 cur rent = current . next ; // pop the queue26 }2728 i f ( bucketTable . f i r s t != null ){29 cur rent = bucketTable . f i r s t ;30 bucketTable . f i r s t = cur rent . next ;31 return true ;32 }3334 // r e f i l l the queue35 more = fa l se ;36 end += BucketTable . SIZE ;37 for ( SubScorer sub = s c o r e r s ; sub != null ; sub = sub . next ) {38 int subScorerDocID = sub . s c o r e r . docID ( ) ;39 i f ( subScorerDocID != NO MORE DOCS) {40 more |= sub . s c o r e r . s co r e ( sub . c o l l e c t o r , end ,
subScorerDocID ) ;41 }42 }43 cur rent = bucketTable . f i r s t ;44 } while ( cur rent != null | | more ) ;
1 do {2 while ( bucketTable . f i r s t != null ) { // more queued3 cur rent = bucketTable . f i r s t ;4 bucketTable . f i r s t = cur rent . next ; // pop the
queue56 // check proh ib i t ed & requi red , and minNrShouldMatch7 i f ( ( cur rent . b i t s & prohibitedMask ) == 0 && ( cur rent .
b i t s & requiredMask ) == requiredMask && current .coord >= minNrShouldMatch ) {
8 return doc = current . doc ;9 }
10 }1112 // r e f i l l the queue13 more = fa l se ;14 end += BucketTable . SIZE ;15 for ( SubScorer sub = s c o r e r s ; sub != null ; sub = sub . next ) {16 Scorer s c o r e r = sub . s c o r e r ;17 sub . c o l l e c t o r . s e t S co r e r ( s c o r e r ) ;18 int doc = s co r e r . docID ( ) ;19 while ( doc < end ) {20 sub . c o l l e c t o r . c o l l e c t ( doc ) ;21 doc = s c o r e r . nextDoc ( ) ;22 }23 more |= ( doc != NO MORE DOCS) ;24 }25 } while ( bucketTable . f i r s t != null | | more ) ;
1 do {2 i f ( updateCount != −1) {3 updateCountTotal += updateCount ;4 }5 i f ( r e t ) {6 r e s u l t S e t = getStatement ( ) . ge tResu l tSe t ( ) ;7 printWarnings ( r e s u l t S e t . getWarnings ( ) , fa l se ) ;8 r e s u l t S e t . c learWarnings ( ) ;9 i f ( p r i n t ) {
10 p r i n tRe su l t s ( r e su l tS e t , out ) ;11 }12 }13 r e t = getStatement ( ) . getMoreResults ( ) ;14 updateCount = getStatement ( ) . getUpdateCount ( ) ;15 } while ( r e t | | updateCount != −1) ;
1 while ( haveReadAhead | | s t . hasMoreTokens ( ) ) {2 St r ing currentToken = haveReadAhead ? cachedVers ion : s t .
nextToken ( ) ;3 haveReadAhead = fa l se ;4 i f ( currentToken . equa l s ( ” C l i en t : ” ) ) {5 c l i e n t = true ;6 } else i f ( currentToken . equa l s ( ” Server : ” ) ) {7 s e r v e r = true ;8 } else i f ( currentToken . startsWith ( ” (CVS” )9 && currentToken . endsWith ( ” ) ” ) ) {
11 }12 i f ( ! c l i e n t && ! s e r v e r && cvs != null13 && cachedVers ion == null && st . hasMoreTokens ( ) ) {14 cachedVers ion = s t . nextToken ( ) ;15 haveReadAhead = true ;16 } else i f ( c l i e n t && cvs != null ) {17 i f ( s t . hasMoreTokens ( ) ) {18 c l i e n tVe r s i o n = s t . nextToken ( ) + cvs ;19 }20 c l i e n t = fa l se ;21 cvs = null ;22 } else i f ( s e r v e r && cvs != null ) {23 i f ( s t . hasMoreTokens ( ) ) {24 s e rve rVer s i on = s t . nextToken ( ) + cvs ;25 }26 s e r v e r = fa l se ;27 cvs = null ;28 } else i f ( currentToken . equa l s ( ” ( c l i e n t / s e r v e r ) ” )29 && cvs != null && cachedVers ion != null30 && ! c l i e n t && ! s e r v e r ) {31 c l i e n t = s e rv e r = true ;32 c l i e n tVe r s i o n = se rve rVer s i on = cachedVers ion + cvs ;33 cachedVers ion = cvs = null ;34 }35 }
1 private I t e r a t o r readerSource s ;2 private Reader getReader ( ) throws IOException {3 i f ( reader == null && readerSources . hasNext ( ) ) {4 reader = fa c t o ry . getReader ( readerSource s . next ( ) ) ;5 Arrays . f i l l ( lastChars , ( char ) 0) ;6 }7 return reader ;8 }9
10 while ( getReader ( ) != null | | needAddSeparator ) {11 i f ( needAddSeparator ) {12 cbuf [ o f f ] = e o l S t r i n g . charAt ( l a s tPos++) ;13 i f ( l a s tPos >= eo l S t r i n g . l ength ( ) ) {14 la s tPos = 0 ;15 needAddSeparator = fa l se ;16 }17 len−−;18 o f f++;19 amountRead++;20 i f ( l en == 0) {21 return amountRead ;22 }23 continue ;24 }25 int nRead = getReader ( ) . read ( cbuf , o f f , l en ) ;26 i f (nRead == −1 | | nRead == 0) {27 nextReader ( ) ;28 i f ( i sF ixLas tL ine ( ) && isMiss ingEndOfLine ( ) ) {29 needAddSeparator = true ;30 l a s tPos = 0 ;31 }32 } else {33 i f ( i sF ixLas tL ine ( ) ) {34 for ( int i = nRead ;35 i > (nRead − l a s tChars . l ength ) ;36 −−i ) {37 i f ( i <= 0) {38 break ;39 }40 addLastChar ( cbuf [ o f f + i − 1 ] ) ;41 }42 }43 l en −= nRead ;44 o f f += nRead ;45 amountRead += nRead ;46 i f ( l en == 0) {47 return amountRead ;48 }49 }50 }
1 while ( l i n e == null | | l i n e . l ength ( ) == 0) {2 l i n e = l in eToken i z e r . getToken ( in ) ;3 l i n e = t a i l F i l t e r ( l i n e ) ;4 i f ( l i n e == null ) {5 return −1;6 }7 l inePos = 0 ;8 }
1 while ( l i n e == null | | l i n e . l ength ( ) == 0) {2 l i n e = l in eToken i z e r . getToken ( in ) ;3 i f ( l i n e == null ) {4 return −1;5 }6 l i n e = headF i l t e r ( l i n e ) ;
1 while ( l i n e == null | | l i n e . l ength ( ) == 0) {2 l i n e = token i z e r . getToken ( in ) ;3 i f ( l i n e == null ) {4 return −1;5 }6 for ( Enumeration e = f i l t e r s . e lements ( ) ; e . hasMoreElements ( ) ; ) {7 F i l t e r f i l t e r = ( F i l t e r ) e . nextElement ( ) ;8 l i n e = f i l t e r . f i l t e r ( l i n e ) ;9 i f ( l i n e == null ) {
10 break ;11 }12 }13 l inePos = 0 ;14 i f ( l i n e != null ) {15 i f ( t ok en i z e r . getPostToken ( ) . l ength ( ) != 0) {16 i f ( delimOutput != null ) {17 l i n e = l i n e + delimOutput ;18 } else {19 l i n e = l i n e + token i z e r . getPostToken ( ) ;20 }21 }22 }23 }
1 while ( ( ( prevCE & STRENGTH MASK [ s t r ength ] ) != (CE & STRENGTH MASK [s t r ength ] ) | | ( prevContCE & STRENGTH MASK [ s t r ength ] ) != ( contCE &STRENGTH MASK [ s t r ength ] ) )
1 while ( ( c e i << 1) < m ut i l I n tBu f f e r [ 0 ] | | c e i < m ut i l I n tBu f f e r [ 1 ]2 | | c e i < m ut i l I n tBu f f e r [ 2 ] ) {3 i f ( c e i > 0) {4 value = RuleBasedCol lator .CE CONTINUATION MARKER ;5 } else {6 value = 0 ;7 }
130 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
89 i f ( ( c e i << 1) < m ut i l I n tBu f f e r [ 0 ] ) {
10 value |= (( cepa r t s [ 0 ] >> (32 − ( ( c e i + 1) << 4) ) ) & 0xFFFF) << 16 ;
11 }12 i f ( c e i < m ut i l I n tBu f f e r [ 1 ] ) {13 value |= (( cepa r t s [ 1 ] >> (32 − ( ( c e i + 1) << 3) ) ) & 0xFF
) << 8 ;14 }1516 i f ( c e i < m ut i l I n tBu f f e r [ 2 ] ) {17 value |= (( cepa r t s [ 2 ] >> (32 − ( ( c e i + 1) << 3) ) ) & 0x3F
) ;18 }19 token .m CE [ c e i ] = value ;20 c e i++;21 }
1 while ( m opt ionarg < optionend && (UCharacter . i sWhitespace ( r u l e s . charAt( m opt ionarg ) ) | | UCharacterProperty . isRuleWhiteSpace ( r u l e s . charAt( m opt ionarg ) ) ) )
1 while ( ! bFinalStd | | ! bFinalDst ) {2 t z t = getNextTrans i t ion ( time , fa l se ) ;3 i f ( t z t == null ) {4 break ;5 }6 time = tz t . getTime ( ) ;78 TimeZoneRule toRule = t z t . getTo ( ) ;9 int ru l e Idx = 1 ;
10 for ( ; ru l e Idx < a l l . l ength ; ru l e Idx++) {11 i f ( a l l [ ru l e Idx ] . equa l s ( toRule ) ) {12 break ;13 }14 }15 i f ( ru l e Idx >= a l l . l ength ) {16 throw new I l l e g a l S t a t eEx c ep t i o n ( ”The ru l e was not found”
) ;17 }18 i f ( i sP ro c e s s ed . get ( ru l e Idx ) ) {19 continue ;20 }21 i f ( toRule instanceof TimeArrayTimeZoneRule ) {22 TimeArrayTimeZoneRule ta r = (TimeArrayTimeZoneRule )
toRule ;2324 // Get the prev ious raw o f f s e t and DST sav ings be f o r e
the very f i r s t s t a r t time25 long t = s t a r t ;26 while ( true ) {27 t z t = getNextTrans i t ion ( t , fa l se ) ;28 i f ( t z t == null ) {29 break ;30 }31 i f ( t z t . getTo ( ) . equa l s ( ta r ) ) {32 break ;33 }34 t = t z t . getTime ( ) ;35 }36 i f ( t z t != null ) {37 // Check i f the e n t i r e s t a r t t imes to be added38 Date f i r s t S t a r t = tar . g e tF i r s t S t a r t ( t z t . getFrom
( ) . getRawOffset ( ) ,
A.1. WHILE-LOOPS 131
39 t z t . getFrom ( ) . getDSTSavings ( ) ) ;40 i f ( f i r s t S t a r t . getTime ( ) > s t a r t ) {41 // Just add the ru l e as i s42 f i l t e r e dRu l e s . add ( ta r ) ;43 } else {44 // Co l l e c t t r a n s i t i o n s a f t e r the s t a r t
time45 long [ ] t imes = tar . getStartTimes ( ) ;46 int timeType = tar . getTimeType ( ) ;47 int idx ;48 for ( idx = 0 ; idx < t imes . l ength ; idx++)
{49 t = times [ idx ] ;50 i f ( timeType == DateTimeRule .
STANDARD TIME) {51 t −= tz t . getFrom ( ) .
getRawOffset ( ) ;52 }53 i f ( timeType == DateTimeRule .
WALL TIME) {54 t −= tz t . getFrom ( ) .
getDSTSavings ( ) ;55 }56 i f ( t > s t a r t ) {57 break ;58 }59 }60 int a s i z e = times . l ength − idx ;61 i f ( a s i z e > 0) {62 long [ ] newtimes = new long [ a s i z e
] ;63 System . arraycopy ( times , idx ,
newtimes , 0 , a s i z e ) ;64 TimeArrayTimeZoneRule newtar =
new TimeArrayTimeZoneRule (65 ta r . getName ( ) ,
ta r .getRawOffset( ) , ta r .getDSTSavings( ) ,
66 newtimes , ta r .getTimeType( ) ) ;
67 f i l t e r e dRu l e s . add ( newtar ) ;68 }69 }70 }71 } else i f ( toRule instanceof AnnualTimeZoneRule ) {72 AnnualTimeZoneRule ar = (AnnualTimeZoneRule ) toRule ;73 Date f i r s t S t a r t = ar . g e tF i r s t S t a r t ( t z t . getFrom ( ) .
getRawOffset ( ) ,74 t z t . getFrom ( ) . getDSTSavings ( ) ) ;75 i f ( f i r s t S t a r t . getTime ( ) == tz t . getTime ( ) ) {76 // Just add the ru l e as i s77 f i l t e r e dRu l e s . add ( ar ) ;78 } else {79 // Ca lcu la te the t r a n s i t i o n year80 int [ ] d f i e l d s = new int [ 6 ] ;81 Grego . t imeToFie lds ( t z t . getTime ( ) , d f i e l d s ) ;82 // Recreate the ru l e83 AnnualTimeZoneRule newar = new
AnnualTimeZoneRule ( ar . getName ( ) ,84 ar . getRawOffset ( ) , ar .
getDSTSavings ( ) ,85 ar . getRule ( ) , d f i e l d s [ 0 ] , ar .
getEndYear ( ) ) ;86 f i l t e r e dRu l e s . add ( newar ) ;87 }88 // Check i f t h i s i s a f i n a l r u l e89 i f ( ar . getEndYear ( ) == AnnualTimeZoneRule .MAXYEAR) {90 // After both f i n a l standard and dst ru l e are
processed ,91 // e x i t t h i s whi le loop .
132 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
92 i f ( ar . getDSTSavings ( ) == 0) {93 bFinalStd = true ;94 } else {95 bFinalDst = true ;96 }97 }98 }99 i sP roc e s s ed . s e t ( ru l e Idx ) ;
1 for ( I t e r a t o r i = changedItem . parent . ch i l d r en . i t e r a t o r ( ) ; i . hasNext ( ) &&( ! checkedFound | | ! uncheckedFound ) ; ) {
1 for ( int i = 0 ; i < prov ide r s . l ength && (message == null | | message .l ength ( ) == 0) ; i++) {
2 i f ( p rov ide r s [ i ] instanceof ICommonLabelProvider ) {3 message = ( ( ICommonLabelProvider ) p rov ide r s [ i ] )4 . g e tDe s c r i p t i on ( t a r g e t ) ;5 }6 }
1 for ( int idx=0, ptr=0; idx<=max | | ( t ext . htmlNodesPtr != −1 && ptr <=text . htmlNodesPtr ) ; idx++) {
23 // append text to bu f f e r r e a l i g n i n g with the l i n e l ength4 int end = ( idx > max) ? text . sourceEnd : ( int ) ( t ext . s epa ra to r s [
idx ] >>> 32) ;5 int nodeKind = 0 ; // text break6 i f ( t ext . htmlNodesPtr >= 0 && ptr <= text . htmlNodesPtr && end >
t ext . htmlNodes [ ptr ] . s ou r c eS ta r t ) {7 FormatJavadocNode node = text . htmlNodes [ ptr ] ;8 FormatJavadocText htmlTag = node . i sText ( ) ? (
FormatJavadocText ) node : null ;9 int newLines = htmlTag == null ? 0 : htmlTag . l i n e sB e f o r e
;10 i f ( l i n e sA f t e r > newLines ) {11 newLines = l i n e sA f t e r ;12 i f ( newLines > 1 && c learB lankL ines ) {13 i f ( idx < 2 | | ( t ext . htmlIndexes [ idx−2]
& JAVADOC TAGS ID MASK) !=JAVADOC CODE TAGS ID) {
14 newLines = 1 ;15 }16 }
A.2. FOR-LOOPS 133
17 }18 i f ( t ex tS ta r t < previousEnd ) {19 addReplaceEdit ( t extStar t , previousEnd , bu f f e r .
t oS t r i ng ( ) ) ;20 }21 boolean immutable = node . isImmutable ( ) ;22 i f ( newLines == 0) {23 newLines = printJavadocBlockNodesNewLines ( block ,
node , previousEnd ) ;24 }25 int nodeStart = node . s ou r c eS ta r t ;26 i f ( newLines > 0 | | ( idx > 1 && nodeStart > ( previousEnd
newLines , c l earBlankLines , false , null ) ;28 }29 i f ( newLines > 0) textOnNewLine = true ;30 bu f f e r . setLength (0) ;31 i f ( node . i sText ( ) ) {32 i f ( immutable ) {33 // do not change immutable tags , j u s t
increment column34 i f ( textOnNewLine && this .
commentIndentation != null ) {35 addInser tEd i t ( node . sourceStar t ,
this . commentIndentation ) ;36 this . column += this .
htmlTag ) ;40 l i n e sA f t e r = 0 ;41 } else {42 l i n e sA f t e r = printJavadocHtmlTag ( htmlTag
, block , textOnNewLine ) ;43 }44 nodeKind = 1 ; // text45 } else {46 i f ( textOnNewLine && this . commentIndentation !=
null ) {47 addInser tEd i t ( node . sourceStar t , this .
commentIndentation ) ;48 this . column += this . commentIndentation .
l ength ( ) ;49 }50 pr intJavadocBlock ( ( FormatJavadocBlock ) node ) ;51 l i n e sA f t e r = 0 ;52 nodeKind = 2 ; // block53 }54 t ex tS ta r t = node . sourceEnd+1;55 ptr++;56 i f ( idx > max) {57 return l i n e sA f t e r ;58 }59 } else {60 i f ( idx > 0 && l i n e sA f t e r > 0) {61 printJavadocGapLines ( previousEnd+1, nextStart −1,
l i n e sA f t e r , c l earBlankLines , false , b u f f e r) ;
62 textOnNewLine = true ;63 }64 boolean needIndentat ion = textOnNewLine ;65 i f ( idx > 0) {66 i f ( ! needIndentat ion && text .
isTextAfterHtmlSeparatorTag ( idx−1) ) {67 needIndentat ion = true ;68 }69 }70 this . needSpace = idx > 1 && ( previousEnd+1) < nextStar t ;
// There ’ s no space between text and html tag ori n l i n e block => do not i n s e r t space a the beg inning
134 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
o f the text71 printJavadocTextLine ( bu f f e r , nextStart , end , block , idx
==0, needIndentat ion , idx==0/∗ opening html tag ?∗/| | t ext . htmlIndexes [ idx−1] != −1) ;
72 l i n e sA f t e r = 0 ;73 i f ( idx==0) {74 i f ( isHtmlSeparatorTag ) {75 l i n e sA f t e r = 1 ;76 }77 } else i f ( t ext . htmlIndexes [ idx−1] ==
JAVADOC SINGLE BREAK TAG ID) {78 l i n e sA f t e r = 1 ;79 }80 }8182 // Replace with cur rent bu f f e r i f the re are s e v e r a l empty l i n e s
between text l i n e s83 nextStar t = ( int ) t ext . s epa ra to r s [ idx ] ;84 int endLine = Ut i l . getLineNumber ( end , this . l ineEnds , s ta r tL ine
−1, this . maxLines ) ;85 s t a r tL in e = Ut i l . getLineNumber ( nextStart , this . l ineEnds , endLine
−1, this . maxLines ) ;86 int l inesGap = s ta r tL in e − endLine ;87 i f ( l inesGap > 0) {88 i f ( c l ea rB lankL ines ) {89 // keep p r ev i ou s l y computed l i n e s a f t e r90 } else {91 i f ( idx==0 | | l inesGap > 1 | | ( idx < max &&
nodeKind==1 && ( text . htmlIndexes [ idx−1] &JAVADOC TAGS ID MASK) !=JAVADOC IMMUTABLE TAGS ID) ) {
92 i f ( l i n e sA f t e r < l inesGap ) {93 l i n e sA f t e r = l inesGap ;94 }95 }96 }97 }98 textOnNewLine = l i n e sA f t e r > 0 ;99
100 // pr in t <pre> tag101 i f ( isCode ) {102 int codeEnd = ( int ) ( t ext . s epa ra to r s [max ] >>> 32) ;103 i f ( codeEnd > end ) {104 i f ( this . f o rmatter . p r e f e r e n c e s .
comment format source ) {105 i f ( t ex tS ta r t < end ) addReplaceEdit (
t extStar t , end , bu f f e r . t oS t r i ng ( ) ) ;106 // See whether the re ’ s a space be f o r e
the code107 i f ( l inesGap > 0) {108 int l i n e S t a r t = this . scanner .
g e tL ineSta r t ( s t a r tL in e ) ;109 i f ( nextStar t > l i n e S t a r t ) { //
i f code s t a r t s at the l i n e ,then no l ead ing space i s
needed110 this . scanner . resetTo (
l i n eS t a r t ,nextStart −1) ;
111 try {112 int token = this
. scanner .getNextToken( ) ;
113 i f ( token ==TerminalTokens.TokenNameWHITESPACE) {
114 // sk ipindenta t i on
115 token =this
A.2. FOR-LOOPS 135
.scanner.getNextToken( ) ;
116 }117 i f ( token ==
TerminalTokens.TokenNameMULTIPLY) {
118 nextStar t=this.scanner.cu r r en tPo s i t i on;
119 }120 }121 catch (
Inva l id InputExcept ioni i e ) {
122 // sk ip123 }124 }125 }126 // Format gap l i n e s be f o r e code127 int newLines = l inesGap ;128 i f ( newLines == 0) newLines=1;129 this . needSpace = fa l se ;130 printJavadocGapLines ( end+1, nextStart −1,
newLines , fa l se /∗ c l e a r f i r s tblank l i n e s i n s i d e <pre> tag asdone by old formatter ∗/ , false ,null ) ;
131 // Format the code132 printCodeSnippet ( nextStart , codeEnd ,
l inesGap ) ;133 // Format the gap l i n e s a f t e r the code134 nextStar t = ( int ) t ext . s epa ra to r s [max ] ;135 printJavadocGapLines ( codeEnd+1,
nextStart −1, 1 , fa l se /∗ c l e a r blankl i n e s i n s i d e <pre> tag as done by
old formatter ∗/ , false , null ) ;136 return 2 ;137 }138 } else {139 nextStar t = ( int ) t ext . s epa ra to r s [max ] ;140 i f ( ( nextStart −1) > ( end+1) ) {141 int l i n e 1 = Ut i l . getLineNumber ( end+1,
this . l ineEnds , s ta r tL ine −1, this .maxLines ) ;
142 int l i n e 2 = Ut i l . getLineNumber ( nextStart−1, this . l ineEnds , l i n e1 −1, this .maxLines ) ;
143 int gapLines = l ine2−l i n e1 −1;144 printJavadocGapLines ( end+1, nextStart −1,
gapLines , fa l se /∗ never c l e a rblank l i n e s i n s i d e <pre> tag ∗/ ,false , null ) ;
145 i f ( gapLines > 0) textOnNewLine = true ;146 }147 }148 return 1 ;149 }150151 // s t o r e prev ious end152 previousEnd = end ;153 }
1 for ( int column = 0 ; column < columnCount | | column == 0 ; column++) {2 ViewerColumn columnViewer = getViewerColumn ( column ) ;3 ViewerCel l cel lToUpdate = updateCel l ( viewerRowFromItem ,4 column , element ) ;56 // I f the con t r o l i s v i r tua l , we cannot use the cached c e l l
ob j e c t . See bug 188663.7 i f ( i sV i r t u a l ) {8 cel lToUpdate = new ViewerCel l ( cel lToUpdate . getViewerRow
( ) , cel lToUpdate . getColumnIndex ( ) , element ) ;9 }
1011 columnViewer . r e f r e s h ( cel lToUpdate ) ;1213 // c l e a r c e l l ( s ee bug 201280)14 updateCel l (null , 0 , null ) ;1516 // As i t i s p o s s i b l e f o r user code to run the event17 // loop check here .18 i f ( item . i sD i sposed ( ) ) {19 unmapElement ( element , item ) ;20 return ;21 }2223 }
1 for ( int column = 0 ; column < columnCount | | column == 0 ; column++) {2 ViewerColumn columnViewer = getViewerColumn ( column ) ;3 ViewerCel l cel lToUpdate = updateCel l ( viewerRowFromItem ,4 column , element ) ;56 // I f the con t r o l i s v i r tua l , we cannot use the cached c e l l
ob j e c t . See bug 188663.7 i f ( i sV i r t u a l ) {8 cel lToUpdate = new ViewerCel l ( cel lToUpdate . getViewerRow
( ) , cel lToUpdate . getColumnIndex ( ) , element ) ;9 }
1011 columnViewer . r e f r e s h ( cel lToUpdate ) ;1213 // c l e a r c e l l ( s ee bug 201280)14 updateCel l (null , 0 , null ) ;1516 // As i t i s p o s s i b l e f o r user code to run the event17 // loop check here .18 i f ( item . i sD i sposed ( ) ) {19 unmapElement ( element , item ) ;20 return ;21 }2223 }
1 for ( int column = 0 ; column < columnCount | | column == 0 ; column++) {2 St r ing text = ”” ; //$NON−NLS−1$3 Image image = null ;4 i f ( tprov != null ) {5 text = tprov . getColumnText ( element , column ) ;6 image = tprov . getColumnImage ( element , column ) ;7 } else {8 i f ( column == 0) {9 ViewerLabel updateLabel = new ViewerLabel ( item .
getText ( ) ,10 item . getImage ( ) ) ;11 bu i ldLabe l ( updateLabel , element ) ;
A.2. FOR-LOOPS 137
1213 // As i t i s p o s s i b l e f o r user code to run the
event14 // loop check here .15 i f ( item . i sD i sposed ( ) ) {16 unmapElement ( element , item ) ;17 return ;18 }1920 text = updateLabel . getText ( ) ;21 image = updateLabel . getImage ( ) ;22 }23 }2425 // Avoid s e t t i n g text to nu l l26 i f ( t ext == null ) {27 text = ”” ; //$NON−NLS−1$28 }2930 t i . setText ( column , text ) ;31 // Apparently a problem to setImage to nu l l i f a l r eady nu l l32 i f ( t i . getImage ( column ) != image ) {33 t i . setImage ( column , image ) ;34 }3536 getColorAndFontCol lector ( ) . setFontsAndColors ( element ) ;37 getColorAndFontCol lector ( ) . applyFontsAndColors ( t i ) ;38 }
1 for ( int pos = s t a r t ; pos <= next | | ! t p sD i f f e r ; pos = pp . po s i t i o n ) {2 i f ( pos<=next && tp sD i f f e r )3 s t a r t = pos ; // advance pp to min
window4 i f ( ! pp . nextPos i t i on ( ) ) {5 done = true ; // ran out o f a term −− done
138 APPENDIX A. LOOPS USED IN THE DETAILED STUDY
6 break ;7 }8 PhrasePos i t i ons pp2 = null ;9 t p sD i f f e r = ! pp . r epea t s | | ( pp2 = te rmPos i t i on sD i f f e r (pp) )==null
;10 i f ( pp2!=null && pp2!=pp) {11 pp = f l i p (pp , pp2 ) ; // f l i p pp to pp212 }13 }